123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- import sys
- from django import forms
- from django.conf import settings
- from django.contrib import messages
- from django.contrib.auth import forms as auth_forms, hashers, tokens
- from django.contrib.sites import models as sites_models
- from django.template import loader
- from django.utils import http
- from django.utils.translation import ugettext_lazy as _
- import bson
- from . import backends, models
- class UserUsernameForm(forms.Form):
- """
- Class with username form.
- """
- username = forms.RegexField(
- label=_("Username"),
- max_length=30,
- min_length=4,
- regex=r'^' + models.USERNAME_REGEX + r'$',
- help_text=_("Minimal of 4 characters and maximum of 30. Letters, digits and @/./+/-/_ only."),
- error_messages={
- 'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters."),
- }
- )
- def clean_username(self):
- """
- This method checks whether the username exists in a case-insensitive manner.
- """
- username = self.cleaned_data['username']
- if backends.User.objects(username__iexact=username).count():
- raise forms.ValidationError(_("A user with that username already exists."), code='username_exists')
- return username
- class UserPasswordForm(forms.Form):
- """
- Class with user password form.
- """
- password1 = forms.CharField(
- label=_("Password"),
- min_length=6,
- widget=forms.PasswordInput,
- )
- password2 = forms.CharField(
- label=_("Password (repeat)"),
- widget=forms.PasswordInput,
- help_text=_("Enter the same password as above, for verification."),
- )
- def clean_password2(self):
- """
- This method checks whether the passwords match.
- """
- password1 = self.cleaned_data.get('password1')
- password2 = self.cleaned_data.get('password2')
- if password1 and password1 != password2:
- raise forms.ValidationError(_("The two password fields did not match."), code='password_mismatch')
- return password2
- class UserCurrentPasswordForm(forms.Form):
- """
- Class with user current password form.
- """
- current_password = forms.CharField(
- label=_("Current password"),
- widget=forms.PasswordInput,
- help_text=_("Enter your current password, for verification."),
- )
- def __init__(self, user, *args, **kwargs):
- self.user = user
- super(UserCurrentPasswordForm, self).__init__(*args, **kwargs)
- def clean_current_password(self):
- """
- This method checks if user password is correct.
- """
- password = self.cleaned_data['current_password']
- if not self.user.check_password(password):
- raise forms.ValidationError(_("Your current password was incorrect."), code='password_incorrect')
- return password
- class UserBasicInfoForm(forms.Form):
- """
- Class with user basic information form.
- """
- first_name = forms.CharField(label=_("First name"))
- last_name = forms.CharField(label=_("Last name"))
- email = forms.EmailField(label=_("E-mail"))
- class RegistrationForm(UserUsernameForm, UserPasswordForm, UserBasicInfoForm):
- """
- Class with registration form.
- """
- class AccountChangeForm(UserBasicInfoForm, UserCurrentPasswordForm):
- """
- Class with form for changing your account settings.
- """
- class PasswordChangeForm(UserCurrentPasswordForm, UserPasswordForm):
- """
- Class with form for changing password.
- """
- class EmailConfirmationSendTokenForm(forms.Form):
- """
- Form for sending an e-mail address confirmation token.
- """
- class EmailConfirmationProcessTokenForm(forms.Form):
- """
- Form for processing an e-mail address confirmation token.
- """
- confirmation_token = forms.CharField(
- label=_("Confirmation token"),
- min_length=20,
- max_length=20,
- required=True,
- help_text=_("Please enter the confirmation token you received to your e-mail address."),
- )
- def __init__(self, user, *args, **kwargs):
- self.user = user
- super(EmailConfirmationProcessTokenForm, self).__init__(*args, **kwargs)
- def clean_confirmation_token(self):
- """
- This method checks if user confirmation token is correct.
- """
- confirmation_token = self.cleaned_data['confirmation_token']
- if not self.user.email_confirmation_token.check_token(confirmation_token):
- raise forms.ValidationError(_("The confirmation token is invalid or has expired. Please retry."), code='confirmation_token_incorrect')
- return confirmation_token
- def objectid_to_base36(i):
- assert isinstance(i, bson.ObjectId), type(i)
- old_maxint = sys.maxint
- sys.maxint = old_maxint**2
- try:
- return http.int_to_base36(int(str(i), 16))
- finally:
- sys.maxint = old_maxint
- class PasswordResetForm(auth_forms.PasswordResetForm):
- def clean_email(self):
- email = self.cleaned_data["email"]
- self.users_cache = backends.User.objects.filter(email__iexact=email, is_active=True)
- if not len(self.users_cache):
- raise forms.ValidationError(self.error_messages['unknown'])
- # We use "all" instead of "any" and skip all users with unusable passwords in save
- if all((user.password == hashers.UNUSABLE_PASSWORD) for user in self.users_cache):
- raise forms.ValidationError(self.error_messages['unusable'])
- return email
- def save(self, domain_override=None, subject_template_name='mongo_auth/password_reset_subject.txt', email_template_name='mongo_auth/password_reset_email.html', use_https=False, token_generator=tokens.default_token_generator, from_email=None, request=None):
- for user in self.users_cache:
- if user.password == hashers.UNUSABLE_PASSWORD:
- continue
- if not domain_override:
- current_site = sites_models.get_current_site(request)
- site_name = current_site.name
- domain = current_site.domain
- else:
- site_name = domain = domain_override
- c = {
- 'PASSWORD_RESET_TIMEOUT_DAYS': settings.PASSWORD_RESET_TIMEOUT_DAYS,
- 'EMAIL_SUBJECT_PREFIX': settings.EMAIL_SUBJECT_PREFIX,
- 'SITE_NAME': getattr(settings, 'SITE_NAME', None),
- 'email': user.email,
- 'email_address': user.email,
- 'request': request,
- 'domain': domain,
- 'site_name': site_name,
- 'uid': objectid_to_base36(user.id),
- 'user': user,
- 'token': token_generator.make_token(user),
- 'protocol': use_https and 'https' or 'http',
- }
- subject = loader.render_to_string(subject_template_name, c)
- # Email subject *must not* contain newlines
- subject = ''.join(subject.splitlines())
- email = loader.render_to_string(email_template_name, c)
- user.email_user(subject, email, from_email)
- messages.success(request, _("We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly."))
|