gault-millau/apps/account/serializers/web.py
2019-09-02 15:44:37 +03:00

207 lines
6.5 KiB
Python

"""Serializers for account web"""
from django.conf import settings
from django.contrib.auth import password_validation as password_validators
from rest_framework_simplejwt import tokens
from django.db.models import Q
from rest_framework import serializers
from account import models
from account import tasks
from utils import exceptions as utils_exceptions
class PasswordResetSerializer(serializers.ModelSerializer):
"""Serializer from model PasswordReset"""
username_or_email = serializers.CharField(required=False,
write_only=True,)
class Meta:
"""Meta class"""
model = models.ResetPasswordToken
fields = (
'username_or_email',
)
def validate(self, attrs):
"""Override validate method"""
user = self.context.get('request').user
username_or_email = attrs.pop('username_or_email')
if user.is_anonymous:
# Check user in DB
user_qs = models.User.objects.filter(Q(email=username_or_email) |
Q(username=username_or_email))
if user_qs.exists():
attrs['user'] = user_qs.first()
else:
raise utils_exceptions.UserNotFoundError()
else:
attrs['user'] = user
return attrs
def create(self, validated_data, *args, **kwargs):
"""Override create method"""
user = validated_data.pop('user')
ip_address = self.context.get('request').META.get('REMOTE_ADDR')
obj = models.ResetPasswordToken.objects.create(
user=user,
ip_address=ip_address,
source=models.ResetPasswordToken.WEB
)
if settings.USE_CELERY:
tasks.send_reset_password_email.delay(obj.id)
else:
tasks.send_reset_password_email(obj.id)
return obj
class PasswordResetConfirmSerializer(serializers.ModelSerializer):
"""Serializer for model User"""
password = serializers.CharField(write_only=True)
class Meta:
"""Meta class"""
model = models.ResetPasswordToken
fields = ('password', )
def validate(self, attrs):
"""Override validate method"""
user = self.instance.user
password = attrs.get('password')
try:
# Compare new password with the old ones
if user.check_password(raw_password=password):
raise utils_exceptions.PasswordsAreEqual()
# Validate password
password_validators.validate_password(password=password)
except serializers.ValidationError as e:
raise serializers.ValidationError(str(e))
else:
return attrs
def update(self, instance, validated_data):
"""Override update method"""
# Update user password from instance
instance.user.set_password(validated_data.get('password'))
instance.user.save()
# Overdue instance
instance.overdue()
return instance
class ChangePasswordSerializer(serializers.ModelSerializer):
"""Serializer for model User."""
password = serializers.CharField(write_only=True)
class Meta:
"""Meta class"""
model = models.User
fields = ('password', )
def validate(self, attrs):
"""Override validate method"""
password = attrs.get('password')
try:
# Compare new password with the old ones
if self.instance.check_password(raw_password=password):
raise utils_exceptions.PasswordsAreEqual()
# Validate password
password_validators.validate_password(password=password)
except serializers.ValidationError as e:
raise serializers.ValidationError(str(e))
else:
return attrs
def update(self, instance, validated_data):
"""Override update method"""
# Update user password from instance
instance.set_password(validated_data.get('password'))
instance.save()
return instance
class ChangeEmailSerializer(serializers.ModelSerializer):
"""Change user email serializer"""
class Meta:
"""Meta class"""
model = models.User
fields = (
'id',
'email',
)
read_only_fields = (
'id',
)
def validate_email(self, value):
"""Validate email value"""
if value == self.instance.email:
# todo: add custom exception
raise serializers.ValidationError()
return value
def validate(self, attrs):
"""Override validate method"""
email_confirmed = self.instance.email_confirmed
if not email_confirmed:
# todo: add custom exception
raise serializers.ValidationError()
return attrs
def update(self, instance, validated_data):
"""
Override update method
"""
instance.email = validated_data.get('email')
instance.email_confirmed = False
instance.save()
# Send verification link on user email for change email address
if settings.USE_CELERY:
tasks.confirm_new_email_address.delay(instance.id)
else:
tasks.confirm_new_email_address(instance.id)
instance.revoke_access_token()
return instance
class RefreshTokenSerializer(serializers.Serializer):
"""Serializer for refresh token view"""
refresh_token = serializers.CharField(read_only=True)
access_token = serializers.CharField(read_only=True)
def get_request(self):
"""Return request"""
return self.context.get('request')
def validate(self, attrs):
"""Override validate method"""
refresh_token = self.get_request().COOKIES.get('refresh_token')
if not refresh_token:
raise utils_exceptions.NotValidRefreshTokenError()
token = tokens.RefreshToken(token=refresh_token)
data = {'access_token': str(token.access_token)}
if settings.SIMPLE_JWT.get('ROTATE_REFRESH_TOKENS'):
if settings.SIMPLE_JWT.get('BLACKLIST_AFTER_ROTATION'):
try:
# Attempt to blacklist the given refresh token
token.blacklist()
except AttributeError:
# If blacklist app not installed, `blacklist` method will
# not be present
pass
token.set_jti()
token.set_exp()
data['refresh_token'] = str(token)
return data