Spaces:
Sleeping
Sleeping
| 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() | |
| def get_user(self, obj): | |
| return UserSerializer(obj).data | |
| def get_profile(self, obj): | |
| try: | |
| return UserProfileSerializer(obj.profile).data | |
| except UserProfile.DoesNotExist: | |
| return {} | |
| def get_skills(self, obj): | |
| user_skills = UserSkill.objects.filter(user=obj).select_related('skill') | |
| return UserSkillSerializer(user_skills, many=True).data | |