uktrade/directory-sso

View on GitHub
sso/user/serializers.py

Summary

Maintainability
A
0 mins
Test Coverage
from django.contrib.auth import password_validation
from django.db import transaction
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from rest_framework import serializers

from sso.user import utils
from sso.user.models import User, UserAnswer, UserProfile
from sso.verification import helpers
from sso.verification.models import VerificationCode


class VerificationCodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = VerificationCode
        fields = (
            'code',
            'expiration_date',
        )


class LastLoginSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = (
            'id',
            'last_login',
        )


class PasswordCheckSerializer(serializers.Serializer):
    password = serializers.CharField(style={'input_type': 'password'})
    session_key = serializers.CharField(style={'input_type': 'password'})


class CreateUserSerializer(serializers.ModelSerializer):
    verification_code = VerificationCodeSerializer(read_only=True)
    uidb64 = serializers.SerializerMethodField()
    verification_token = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = (
            'email',
            'password',
            'uidb64',
            'verification_token',
            'verification_code',
        )
        extra_kwargs = {
            'password': {'write_only': True},
        }

    def get_uidb64(self, obj):
        return urlsafe_base64_encode(force_bytes(obj.pk))

    def get_verification_token(self, obj):
        return helpers.verification_token.make_token(obj)

    def validate_password(self, value):
        password_validation.validate_password(value)
        return value

    @transaction.atomic
    def create(self, validated_data):
        instance = User.objects.create_user(**validated_data)
        VerificationCode.objects.create(user=instance)
        return instance


class UserProfileSerializer(serializers.ModelSerializer):
    profile_image = serializers.SerializerMethodField()
    social_account = serializers.SerializerMethodField()

    class Meta:
        model = UserProfile
        fields = (
            'first_name',
            'last_name',
            'job_title',
            'mobile_phone_number',
            'segment',
            'profile_image',
            'social_account',
        )

    def get_profile_image(self, obj):
        account = obj.user.socialaccount_set.first()
        if account:
            return utils.get_social_account_image(account)

    def get_social_account(self, obj):
        account = obj.user.socialaccount_set.first()
        return account.provider if account else 'email'

    def to_internal_value(self, data):
        return {**data, 'user_id': self.context['request'].user.pk}


class UserSerializer(serializers.ModelSerializer):
    user_profile = UserProfileSerializer()
    social_login = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = (
            'id',
            'email',
            'hashed_uuid',
            'social_login',
            'user_profile',
        )

    def get_social_login(self, obj):
        return bool(obj.socialaccount_set.all())


class ActivityStreamUsersSerializer(serializers.ModelSerializer):
    telephone = serializers.CharField(source='user_profile.mobile_phone_number')

    class Meta:
        model = User
        fields = ('id', 'hashed_uuid', 'email', 'telephone', 'date_joined', 'modified', 'last_login')


class ActivityStreamUserAnswerSerializer(serializers.ModelSerializer):
    question_title = serializers.CharField(source='question.title')
    answer_label = serializers.SerializerMethodField()
    hashed_uuid = serializers.CharField(source='user.hashed_uuid')

    class Meta:
        model = UserAnswer
        fields = ('id', 'user_id', 'hashed_uuid', 'answer', 'modified', 'question_id', 'question_title', 'answer_label')

    def get_answer_label(self, obj):
        if obj.question.question_type in ['SELECT', 'RADIO']:
            return self.get_choice_value(obj.answer, obj.question.to_dict()['choices']) or ''

        elif obj.question.question_type == 'MULTI_SELECT':
            answer_list = [
                self.get_choice_value(
                    answer,
                    obj.question.to_dict()['choices'],
                )
                or ''
                for answer in obj.answer
            ]
            return answer_list

    def get_choice_value(self, value, choices_array):
        choices_list = choices_array if isinstance(choices_array, list) else choices_array.get('options', choices_array)
        for c in choices_list:
            if c.get('value') == value:
                return c.get('label')