auth.py 5.8 KB

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