auth.py 5.5 KB

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