""" Serializers for user-related models. """ from rest_framework import serializers from django.contrib.auth import authenticate from django.contrib.auth.password_validation import validate_password from .models import User, UserProfile, APIKey import secrets class UserRegistrationSerializer(serializers.ModelSerializer): """Serializer for user registration.""" password = serializers.CharField(write_only=True, validators=[validate_password]) password_confirm = serializers.CharField(write_only=True) class Meta: model = User fields = ('username', 'email', 'password', 'password_confirm', 'first_name', 'last_name', 'company_name', 'phone_number') def validate(self, attrs): if attrs['password'] != attrs['password_confirm']: raise serializers.ValidationError("Passwords don't match.") return attrs def create(self, validated_data): validated_data.pop('password_confirm') user = User.objects.create_user(**validated_data) return user class UserLoginSerializer(serializers.Serializer): """Serializer for user login.""" email = serializers.EmailField() password = serializers.CharField() def validate(self, attrs): email = attrs.get('email') password = attrs.get('password') if email and password: user = authenticate(username=email, password=password) if not user: raise serializers.ValidationError('Invalid credentials.') if not user.is_active: raise serializers.ValidationError('User account is disabled.') attrs['user'] = user return attrs else: raise serializers.ValidationError('Must include email and password.') class UserSerializer(serializers.ModelSerializer): """Serializer for user details.""" profile = serializers.SerializerMethodField() usage_limits = serializers.SerializerMethodField() class Meta: model = User fields = ( 'id', 'username', 'email', 'first_name', 'last_name', 'subscription_type', 'is_api_enabled', 'company_name', 'phone_number', 'is_verified', 'date_joined', 'last_login', 'profile', 'usage_limits' ) read_only_fields = ('id', 'date_joined', 'last_login') def get_profile(self, obj): try: profile = obj.profile return UserProfileSerializer(profile).data except UserProfile.DoesNotExist: return None def get_usage_limits(self, obj): return obj.get_usage_limits() class UserProfileSerializer(serializers.ModelSerializer): """Serializer for user profile.""" class Meta: model = UserProfile fields = ( 'avatar', 'bio', 'website', 'location', 'timezone', 'language', 'notification_preferences', 'created_at', 'updated_at' ) read_only_fields = ('created_at', 'updated_at') class UserUpdateSerializer(serializers.ModelSerializer): """Serializer for updating user information.""" class Meta: model = User fields = ('first_name', 'last_name', 'company_name', 'phone_number') def update(self, instance, validated_data): for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() return instance class PasswordChangeSerializer(serializers.Serializer): """Serializer for password change.""" old_password = serializers.CharField() new_password = serializers.CharField(validators=[validate_password]) new_password_confirm = serializers.CharField() def validate(self, attrs): if attrs['new_password'] != attrs['new_password_confirm']: raise serializers.ValidationError("New passwords don't match.") return attrs def validate_old_password(self, value): user = self.context['request'].user if not user.check_password(value): raise serializers.ValidationError('Old password is incorrect.') return value class APIKeySerializer(serializers.ModelSerializer): """Serializer for API keys.""" class Meta: model = APIKey fields = ('id', 'name', 'key', 'is_active', 'last_used', 'created_at', 'expires_at') read_only_fields = ('id', 'key', 'last_used', 'created_at') def create(self, validated_data): validated_data['key'] = secrets.token_urlsafe(32) return super().create(validated_data) class APIKeyCreateSerializer(serializers.ModelSerializer): """Serializer for creating API keys.""" class Meta: model = APIKey fields = ('name', 'expires_at') def create(self, validated_data): validated_data['user'] = self.context['request'].user validated_data['key'] = secrets.token_urlsafe(32) return super().create(validated_data) class SubscriptionUpdateSerializer(serializers.Serializer): """Serializer for updating user subscription.""" subscription_type = serializers.ChoiceField(choices=[ ('free', 'Free'), ('paid', 'Paid'), ('premium', 'Premium'), ]) def validate_subscription_type(self, value): user = self.context['request'].user if user.subscription_type == value: raise serializers.ValidationError('User already has this subscription type.') return value