223 lines
7.2 KiB
Python
223 lines
7.2 KiB
Python
"""Common account serializers"""
|
|
from django.conf import settings
|
|
from django.contrib.auth import password_validation as password_validators
|
|
from fcm_django.models import FCMDevice
|
|
from rest_framework import exceptions
|
|
from rest_framework import serializers
|
|
from rest_framework import validators as rest_validators
|
|
|
|
from account import models, tasks
|
|
from utils import exceptions as utils_exceptions
|
|
from utils import methods as utils_methods
|
|
|
|
|
|
# User serializers
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
"""User serializer."""
|
|
# RESPONSE
|
|
email_confirmed = serializers.BooleanField(read_only=True)
|
|
fullname = serializers.CharField(source='get_full_name', read_only=True)
|
|
|
|
# REQUEST
|
|
username = serializers.CharField(
|
|
validators=(rest_validators.UniqueValidator(queryset=models.User.objects.all()),),
|
|
required=False)
|
|
first_name = serializers.CharField(required=False, write_only=True)
|
|
last_name = serializers.CharField(required=False, write_only=True)
|
|
image = serializers.ImageField(required=False)
|
|
cropped_image = serializers.ImageField(required=False)
|
|
email = serializers.EmailField(
|
|
validators=(rest_validators.UniqueValidator(queryset=models.User.objects.all()),),
|
|
required=False)
|
|
newsletter = serializers.BooleanField(required=False)
|
|
|
|
class Meta:
|
|
model = models.User
|
|
fields = [
|
|
'username',
|
|
'first_name',
|
|
'last_name',
|
|
'fullname',
|
|
'cropped_image',
|
|
'image',
|
|
'email',
|
|
'email_confirmed',
|
|
'newsletter',
|
|
]
|
|
|
|
def validate_email(self, value):
|
|
"""Validate email value"""
|
|
if value == self.instance.email:
|
|
raise serializers.ValidationError()
|
|
return value
|
|
|
|
def validate_username(self, value):
|
|
"""Custom username validation"""
|
|
valid = utils_methods.username_validator(username=value)
|
|
if not valid:
|
|
raise utils_exceptions.NotValidUsernameError()
|
|
return value
|
|
|
|
def validate(self, attrs):
|
|
if ('cropped_image' in attrs or 'image' in attrs) and \
|
|
('cropped_image' not in attrs or 'image' not in attrs):
|
|
raise utils_exceptions.UserUpdateUploadImageError()
|
|
return attrs
|
|
|
|
def update(self, instance, validated_data):
|
|
"""
|
|
Override update method
|
|
"""
|
|
if 'email' in validated_data:
|
|
validated_data['email_confirmed'] = False
|
|
instance = super().update(instance, validated_data)
|
|
# 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)
|
|
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 = (
|
|
'email',
|
|
)
|
|
|
|
def validate_email(self, value):
|
|
"""Validate email value"""
|
|
if value == self.instance.email:
|
|
raise serializers.ValidationError()
|
|
return value
|
|
|
|
def validate(self, attrs):
|
|
"""Override validate method"""
|
|
email_confirmed = self.instance.email_confirmed
|
|
if not email_confirmed:
|
|
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)
|
|
return instance
|
|
|
|
|
|
class ConfirmEmailSerializer(serializers.ModelSerializer):
|
|
"""Confirm user email serializer"""
|
|
|
|
class Meta:
|
|
"""Meta class"""
|
|
model = models.User
|
|
fields = (
|
|
'email',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
"""Override validate method"""
|
|
email_confirmed = self.instance.email_confirmed
|
|
if email_confirmed:
|
|
raise serializers.ValidationError()
|
|
return attrs
|
|
|
|
def update(self, instance, validated_data):
|
|
"""
|
|
Override update method
|
|
"""
|
|
# 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)
|
|
return instance
|
|
|
|
|
|
# Firebase Cloud Messaging serializers
|
|
class FCMDeviceSerializer(serializers.ModelSerializer):
|
|
"""FCM Device model serializer"""
|
|
class Meta:
|
|
model = FCMDevice
|
|
fields = ('id', 'name', 'registration_id', 'device_id',
|
|
'active', 'date_created', 'type')
|
|
read_only_fields = ('id', 'date_created',)
|
|
extra_kwargs = {'active': {'default': True}}
|
|
|
|
def validate(self, attrs):
|
|
regid = attrs.get('registration_id')
|
|
dtype = attrs.get('type')
|
|
if regid and dtype and self.Meta.model.objects.filter(
|
|
registration_id=regid).exclude(type=dtype).count():
|
|
raise exceptions.ValidationError(
|
|
{'registration_id': 'This field must be unique.'})
|
|
return attrs
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(FCMDeviceSerializer, self).__init__(*args, **kwargs)
|
|
self.fields['type'].help_text = (
|
|
'Should be one of ["%s"]' %
|
|
'", "'.join([i for i in self.fields['type'].choices]))
|
|
|
|
def create(self, validated_data):
|
|
user = self.context['request'].user
|
|
if not user.is_anonymous:
|
|
validated_data['user'] = user
|
|
device = FCMDevice.objects.create(**validated_data)
|
|
return device
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
if not user.is_anonymous:
|
|
instance.user = user
|
|
instance.save()
|
|
else:
|
|
instance.user = None
|
|
instance.save()
|
|
return instance
|