auth.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. from django.core.exceptions import ValidationError
  2. from django.contrib.auth import authenticate, get_user_model
  3. from django.contrib.auth.forms import (AuthenticationForm as
  4. BaseAuthenticationForm)
  5. from django.template.defaultfilters import date as format_date
  6. from django.utils.translation import ugettext_lazy as _
  7. from misago.core import forms
  8. from misago.users.bans import get_user_ban
  9. from misago.users.validators import validate_password
  10. class MisagoAuthMixin(object):
  11. error_messages = {
  12. 'empty_data': _("You have to fill out both fields."),
  13. 'invalid_login': _("Your login or password is incorrect."),
  14. 'inactive_user': _("You have to activate your account before "
  15. "you will be able to sign in."),
  16. 'inactive_admin': _("Administrator has to activate your account "
  17. "before you will be able 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. if self.user_ban.valid_until:
  34. if self.user_ban.user_message:
  35. message = _("%(user)s, your account is "
  36. "banned until %(date)s for:")
  37. else:
  38. message = _("%(user)s, your account "
  39. "is banned until %(date)s.")
  40. date_format = {'date': format_date(self.user_ban.valid_until)}
  41. message = message % date_format
  42. else:
  43. if self.user_ban.user_message:
  44. message = _("%(user)s, your account is banned for:")
  45. else:
  46. message = _("%(user)s, your account is banned.")
  47. raise ValidationError(
  48. message % {'user': self.user_cache.username},
  49. code='banned',
  50. )
  51. class AuthenticationForm(MisagoAuthMixin, forms.Form, BaseAuthenticationForm):
  52. """
  53. Base class for authenticating users, Floppy-forms and
  54. Misago login field comliant
  55. """
  56. username = forms.CharField(label=_("Username or e-mail"),
  57. required=False,
  58. max_length=254)
  59. password = forms.CharField(label=_("Password"), required=False,
  60. widget=forms.PasswordInput)
  61. def clean(self):
  62. username = self.cleaned_data.get('username')
  63. password = self.cleaned_data.get('password')
  64. if username and password:
  65. self.user_cache = authenticate(username=username,
  66. password=password)
  67. if self.user_cache is None or not self.user_cache.is_active:
  68. raise ValidationError(
  69. self.error_messages['invalid_login'],
  70. code='invalid_login',
  71. )
  72. else:
  73. self.confirm_login_allowed(self.user_cache)
  74. else:
  75. raise ValidationError(
  76. self.error_messages['empty_data'],
  77. code='empty_data',
  78. )
  79. return self.cleaned_data
  80. def confirm_login_allowed(self, user):
  81. self.confirm_user_active(user)
  82. self.confirm_user_not_banned(user)
  83. class AdminAuthenticationForm(AuthenticationForm):
  84. required_css_class = 'required'
  85. def __init__(self, *args, **kwargs):
  86. self.error_messages.update({
  87. 'not_staff': _("Your account does not have admin privileges.")
  88. })
  89. super(AdminAuthenticationForm, self).__init__(*args, **kwargs)
  90. def confirm_login_allowed(self, user):
  91. if not user.is_staff:
  92. raise forms.ValidationError(
  93. self.error_messages['not_staff'],
  94. code='not_staff',
  95. )
  96. class GetUserForm(MisagoAuthMixin, forms.Form):
  97. username = forms.CharField(label=_("Username or e-mail"))
  98. def clean(self):
  99. data = super(GetUserForm, self).clean()
  100. credential = data.get('username')
  101. if not credential or len(credential) > 250:
  102. raise forms.ValidationError(_("You have to fill out form."))
  103. try:
  104. User = get_user_model()
  105. user = User.objects.get_by_username_or_email(data['username'])
  106. self.user_cache = user
  107. except User.DoesNotExist:
  108. raise forms.ValidationError(_("Invalid username or e-mail."))
  109. self.confirm_allowed(user)
  110. return data
  111. def confirm_allowed(self, user):
  112. raise NotImplementedError("confirm_allowed method must be defined "
  113. "by inheriting classes")
  114. class ResendActivationForm(GetUserForm):
  115. def confirm_allowed(self, user):
  116. self.confirm_user_not_banned(user)
  117. username_format = {'user': user.username}
  118. if not user.requires_activation:
  119. message = _("%(user)s, your account is already active.")
  120. raise forms.ValidationError(message % username_format)
  121. if user.requires_activation_by_admin:
  122. message = _("%(user)s, only administrator may activate "
  123. "your account.")
  124. raise forms.ValidationError(message % username_format)
  125. class ResetPasswordForm(GetUserForm):
  126. error_messages = {
  127. 'inactive_user': _("You have to activate your account before "
  128. "you will be able to request new password."),
  129. 'inactive_admin': _("Administrator has to activate your account "
  130. "before you will be able to request "
  131. "new password."),
  132. }
  133. def confirm_allowed(self, user):
  134. self.confirm_user_not_banned(user)
  135. self.confirm_user_active(user)
  136. class SetNewPasswordForm(MisagoAuthMixin, forms.Form):
  137. new_password = forms.CharField(label=_("New password"),
  138. widget=forms.PasswordInput)
  139. def clean(self):
  140. data = super(SetNewPasswordForm, self).clean()
  141. new_password = data.get('new_password')
  142. if not new_password or len(new_password) > 250:
  143. raise forms.ValidationError(_("You have to fill out form."))
  144. validate_password(new_password)
  145. return data