/
auth.py
148 lines (110 loc) · 5.15 KB
/
auth.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from django import forms
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.translation import ugettext_lazy as _
from misago.users.bans import get_user_ban
UserModel = get_user_model()
class MisagoAuthMixin(object):
error_messages = {
'empty_data': _("Fill out both fields."),
'invalid_login': _("Login or password is incorrect."),
'inactive_user': _("You have to activate your account before you will be able to sign in."),
'inactive_admin': _(
"Your account has to be activated by Administrator before you will be able to sign in."
),
}
def confirm_user_active(self, user):
if user.requires_activation_by_admin:
raise ValidationError(self.error_messages['inactive_admin'], code='inactive_admin')
if user.requires_activation_by_user:
raise ValidationError(self.error_messages['inactive_user'], code='inactive_user')
def confirm_user_not_banned(self, user):
if not user.is_staff:
self.user_ban = get_user_ban(user)
if self.user_ban:
raise ValidationError('', code='banned')
def get_errors_dict(self):
error = self.errors.as_data()['__all__'][0]
if error.code == 'banned':
error.message = self.user_ban.ban.get_serialized_message()
else:
error.message = error.messages[0]
return {'detail': error.message, 'code': error.code}
class AuthenticationForm(MisagoAuthMixin, BaseAuthenticationForm):
"""
Base class for authenticating users, Floppy-forms and
Misago login field compliant
"""
username = forms.CharField(label=_("Username or e-mail"), required=False, max_length=254)
password = forms.CharField(label=_("Password"), required=False, widget=forms.PasswordInput)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None or not self.user_cache.is_active:
raise ValidationError(self.error_messages['invalid_login'], code='invalid_login')
else:
self.confirm_login_allowed(self.user_cache)
else:
raise ValidationError(self.error_messages['empty_data'], code='empty_data')
return self.cleaned_data
def confirm_login_allowed(self, user):
self.confirm_user_active(user)
self.confirm_user_not_banned(user)
class AdminAuthenticationForm(AuthenticationForm):
required_css_class = 'required'
def __init__(self, *args, **kwargs):
self.error_messages.update({
'not_staff': _("Your account does not have admin privileges."),
})
super(AdminAuthenticationForm, self).__init__(*args, **kwargs)
def confirm_login_allowed(self, user):
if not user.is_staff:
raise forms.ValidationError(self.error_messages['not_staff'], code='not_staff')
class GetUserForm(MisagoAuthMixin, forms.Form):
email = forms.CharField()
def clean(self):
data = super(GetUserForm, self).clean()
email = data.get('email')
if not email or len(email) > 250:
raise forms.ValidationError(_("Enter e-mail address."), code='empty_email')
try:
validate_email(email)
except forms.ValidationError:
raise forms.ValidationError(_("Entered e-mail is invalid."), code='invalid_email')
try:
user = UserModel.objects.get_by_email(data['email'])
if not user.is_active:
raise UserModel.DoesNotExist()
self.user_cache = user
except UserModel.DoesNotExist:
raise forms.ValidationError(_("No user with this e-mail exists."), code='not_found')
self.confirm_allowed(user)
return data
def confirm_allowed(self, user):
"""override this method to include additional checks"""
class ResendActivationForm(GetUserForm):
def confirm_allowed(self, user):
username_format = {'user': user.username}
if not user.requires_activation:
message = _("%(user)s, your account is already active.")
raise forms.ValidationError(message % username_format, code='already_active')
if user.requires_activation_by_admin:
message = _("%(user)s, only administrator may activate your account.")
raise forms.ValidationError(message % username_format, code='inactive_admin')
class ResetPasswordForm(GetUserForm):
error_messages = {
'inactive_user': _(
"You have to activate your account before "
"you will be able to request new password."
),
'inactive_admin': _(
"Administrator has to activate your account before "
"you will be able to request new password."
),
}
def confirm_allowed(self, user):
self.confirm_user_active(user)