gapguide-api / apps /accounts /serializers.py
arifRB's picture
Deploy GapGuide backend (Docker)
ffd36e0 verified
Raw
History Blame Contribute Delete
4.08 kB
from django.contrib.auth import authenticate
from django.contrib.auth.password_validation import validate_password as django_validate_password
from django.core.exceptions import ValidationError as DjangoValidationError
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from .models import User, UserProfile
from apps.skills.models import UserSkill
from apps.skills.serializers import UserSkillSerializer
class RegisterSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['name', 'email', 'password', 'password_confirm']
extra_kwargs = {
'password': {'write_only': True},
}
def validate(self, attrs):
if attrs['password'] != attrs['password_confirm']:
raise serializers.ValidationError({"password": "Passwords do not match."})
return attrs
def validate_email(self, value):
# Case-insensitive uniqueness: store lowercase so `Foo@X.com` and
# `foo@x.com` cannot both register, and login is case-insensitive too.
normalized = value.strip().lower()
if User.objects.filter(email__iexact=normalized).exists():
raise serializers.ValidationError("A user with this email already exists.")
return normalized
def validate_password(self, value):
# Run Django's configured AUTH_PASSWORD_VALIDATORS (min-length, common,
# numeric, user-similarity). Without this call the settings list is dead
# config.
try:
django_validate_password(value)
except DjangoValidationError as exc:
raise serializers.ValidationError(list(exc.messages))
return value
def create(self, validated_data):
validated_data.pop('password_confirm')
email = validated_data['email']
user = User.objects.create_user(
username=email,
email=email,
name=validated_data.get('name', ''),
password=validated_data['password'],
role_type='STUDENT'
)
return user
class LoginSerializer(serializers.Serializer):
email = serializers.EmailField(write_only=True)
password = serializers.CharField(write_only=True)
def validate(self, attrs):
# Normalize to match the lowercase username stored at registration.
email = (attrs.get('email') or '').strip().lower()
user = authenticate(
request=self.context.get('request'),
username=email,
password=attrs.get('password')
)
if not user:
raise serializers.ValidationError("Invalid credentials.")
if not user.is_active:
raise serializers.ValidationError("User account is disabled.")
return user
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'role_type', 'created_at']
read_only_fields = ['id', 'name', 'email', 'role_type', 'created_at']
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['degree', 'semester', 'interests', 'bio', 'updated_at']
read_only_fields = ['updated_at']
class ProfileWithSkillsSerializer(serializers.Serializer):
user = serializers.SerializerMethodField()
profile = serializers.SerializerMethodField()
skills = serializers.SerializerMethodField()
@extend_schema_field(UserSerializer)
def get_user(self, obj):
return UserSerializer(obj).data
@extend_schema_field(UserProfileSerializer)
def get_profile(self, obj):
try:
return UserProfileSerializer(obj.profile).data
except UserProfile.DoesNotExist:
return {}
@extend_schema_field(UserSkillSerializer(many=True))
def get_skills(self, obj):
user_skills = UserSkill.objects.filter(user=obj).select_related('skill')
return UserSkillSerializer(user_skills, many=True).data