Source code for shoop.front.apps.auth.forms

# -*- coding: utf-8 -*-
# This file is part of Shoop.
#
# Copyright (c) 2012-2016, Shoop Ltd. All rights reserved.
#
# This source code is licensed under the AGPLv3 license found in the
# LICENSE file in the root directory of this source tree.
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.tokens import default_token_generator
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.mail import send_mail
from django.db.models import Q
from django.template import loader
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.utils.translation import ugettext as _

from shoop.core.models import get_person_contact


[docs]class EmailAuthenticationForm(AuthenticationForm): error_messages = { 'invalid_login': _("Please enter a correct %(username)s and password. " "Note that both fields may be case-sensitive. " "In case of multiple accounts with same email only username can be used to login."), 'inactive': _("This account is inactive."), } def __init__(self, *args, **kwargs): super(EmailAuthenticationForm, self).__init__(*args, **kwargs) self.fields['username'].label = _("Username or email address")
[docs] def clean_username(self): username = self.data['username'] user_model = get_user_model() # Note: Always search by username AND by email prevent timing attacks try: user_by_name = user_model._default_manager.get_by_natural_key(username) except ObjectDoesNotExist: user_by_name = None try: user_by_email = user_model._default_manager.get(email=username) except (ObjectDoesNotExist, MultipleObjectsReturned): user_by_email = None if not user_by_name and user_by_email: return getattr(user_by_email, user_model.USERNAME_FIELD) return username
[docs] def confirm_login_allowed(self, user): """ Do not let user with inactive person contact to login. """ if not get_person_contact(user).is_active: raise forms.ValidationError( self.error_messages['inactive'], code='inactive', ) super(EmailAuthenticationForm, self).confirm_login_allowed(user)
[docs]class RecoverPasswordForm(forms.Form): username = forms.CharField(label=_("Username"), max_length=254, required=False) email = forms.EmailField(label=_("Email"), max_length=254, required=False) token_generator = default_token_generator subject_template_name = "shoop/user/recover_password_mail_subject.jinja", email_template_name = "shoop/user/recover_password_mail_content.jinja" from_email = None
[docs] def clean(self): data = self.cleaned_data username = data["username"] email = data["email"] if username and email: msg = _("Please provide either username or email, not both.") self.add_error("username", msg) self.add_error("email", msg) if not (username or email): msg = _("Please provide either username or email.") self.add_error("username", msg) self.add_error("email", msg) return data
[docs] def save(self, request): self.request = request user_model = get_user_model() username = self.cleaned_data["username"] email = self.cleaned_data["email"] active_users = user_model.objects.filter( Q(username__iexact=username) | Q(email__iexact=email), Q(is_active=True) ) for user in active_users: self.process_user(user)
[docs] def process_user(self, user_to_recover): if not user_to_recover.has_usable_password() or not hasattr(user_to_recover, 'email'): return False context = { 'site_name': getattr(self.request, "shop", _("shop")), 'uid': urlsafe_base64_encode(force_bytes(user_to_recover.pk)), 'user_to_recover': user_to_recover, 'token': self.token_generator.make_token(user_to_recover), 'request': self.request, } subject = loader.render_to_string(self.subject_template_name, context) subject = ''.join(subject.splitlines()) # Email subject *must not* contain newlines email = loader.render_to_string(self.email_template_name, context, request=self.request) send_mail(subject, email, self.from_email, [user_to_recover.email]) return True