Source code for rest_auth.users.serializers

# -*- coding: utf-8 -*-
from django.conf import settings
from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMultiAlternatives
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_lazy as _
from rest_framework import serializers

UserModel = get_user_model()


[docs]class UserSerializer(serializers.ModelSerializer): """User serializer for rest_framework & AUTH_USER_MODEL. Fields & methods are built on a django's defualt ``User`` model. Extend this serializer if you need your custom user model. (Even if ``AUTH_USER_MODEL`` is can be customized, this is recommended that You don't change & use customized user model. using custom user model is very complex.) :param username: ``USERNAME_FIELD`` of ``AUTH_USER_MODEL`` :param email: ``User.get_email_field_name()`` :param password1: password of a user (write_only, used only when created) :param password2: password confirmation (write_only) :TODO: Serializer Only implements creating. list/get are need to be implmtd """ password1 = serializers.CharField( label=_('Password'), validators=[password_validation.validate_password], help_text=password_validation.password_validators_help_text_html(), write_only=True, style={'input_type': 'password'}, ) password2 = serializers.CharField( label=_('Password Confirmation'), help_text=_('Enter the same password as before, for verification.'), write_only=True, style={'input_type': 'password'}, ) default_error_messages = { 'password_mismatch': _('2 passwords should be equal'), } EMAIL_FIELD_NAME = UserModel.get_email_field_name() class Meta: model = UserModel fields = ( UserModel.USERNAME_FIELD, UserModel.get_email_field_name(), 'password1', 'password2', ) extra_kwargs = { UserModel.get_email_field_name(): { 'required': True, 'allow_blank': False, }, }
[docs] def validate(self, data): """Vaildates if two passwords are equal. :exception ValidationError: when 2 passwds are different """ password1 = data.get('password1') password2 = data.get('password2') data['password2'] = self._validate_password2(password1, password2) return data
def _validate_password2(self, password1, password2): if password1 != password2: raise serializers.ValidationError( self.error_messages['password_mismatch'], code='password_mismatch', ) return password2
[docs] def create(self, validated_data): """Creates user instance CAVEAT: A clear difference between django's ``ModelForm`` and rest_framework's ``ModelSerializer`` is that, model serializer's ``save`` method doesn't respect form's ``commit=True``. Inside ``super().create``, a query is fired to create user, and inside this, additional query is fired to save hashed password. It's because ``ModelSerializer``'s ``create`` method uses default manager's create function, ``Model._default_manager.create()`` (User model creation is recommended by calling ``UserManager``'s ``create_user`` method) :param validated_data: validated data created after ``self.vaildate`` """ password = validated_data.pop('password1') email_opts = validated_data.pop('email_opts', {}) validated_data.pop('password2') # NOTE We should set user's password manually because # ModelSerializer.create calls model._default_manager.save(). user = super(UserSerializer, self).create(validated_data) user.set_password(password) # user activation through email confirmation. require_email_confirmation =\ settings.REST_AUTH_SIGNUP_REQUIRE_EMAIL_CONFIRMATION update_fields = ['password'] if require_email_confirmation: user, new_update_fields = self.set_user_as_unverified(user) update_fields.extend(new_update_fields) self.send_mail(user, **email_opts) user.save(update_fields=update_fields) return user
def set_user_as_unverified(self, user): user.is_active = False return user, ['is_active']
[docs] def send_mail(self, user, domain_override=None, subject_template_name='registration/verify_email.txt', email_template_name='registration/verify_email.html', use_https=False, token_generator=default_token_generator, from_email=None, request=None, html_email_template_name=None, extra_email_context=None): """Send verification mail to newbie. """ email = self.validated_data[self.EMAIL_FIELD_NAME] if domain_override: site_name = domain = domain_override else: current_site = get_current_site(request) site_name = current_site.name domain = current_site.domain protocol = 'https' if use_https else 'http' context = { 'email': email, 'domain': domain, 'site_name': site_name, 'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(), 'user': user, 'token': token_generator.make_token(user), 'protocol': protocol, } if extra_email_context is not None: context.update(extra_email_context) subject = loader.render_to_string(subject_template_name, context) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) body = loader.render_to_string(email_template_name, context) email_message = EmailMultiAlternatives( subject, body, from_email, [email] ) if html_email_template_name is not None: html_email = loader.render_to_string( html_email_template_name, context ) email_message.attach_alternative(html_email, 'text/html') email_message.send()