import re from django.utils.text import slugify from django.core.validators import MinValueValidator, MaxValueValidator from rest_framework import serializers from rest_framework.exceptions import NotFound from django.contrib.auth import get_user_model from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from django.utils.translation import gettext_lazy as _ from django.utils.text import slugify from .permissions import * from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework.exceptions import PermissionDenied User = get_user_model() class CustomUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = [ "id", "username", "first_name", "last_name", "email", "role", "account_type", "email_verified", "phone_number", "create_time", "var_symbol", "bank_account", "ICO", "RC", "city", "street", "PSC", "GDPR", "is_active", ] read_only_fields = ["id", "create_time", "GDPR", "username"] # <-- removed "account_type" def update(self, instance, validated_data): user = self.context["request"].user staff_only_fields = ["role", "email_verified", "var_symbol", "is_active"] if user.role not in ["admin", "cityClerk"]: unauthorized = [f for f in staff_only_fields if f in validated_data] if unauthorized: raise PermissionDenied(f"You are not allowed to modify: {', '.join(unauthorized)}") return super().update(instance, validated_data) # Token obtaining Default Serializer class CustomTokenObtainPairSerializer(TokenObtainPairSerializer): username_field = User.USERNAME_FIELD def validate(self, attrs): login = attrs.get("username") password = attrs.get("password") # Allow login by username or email user = User.objects.filter(email__iexact=login).first() or \ User.objects.filter(username__iexact=login).first() if user is None or not user.check_password(password): raise serializers.ValidationError(_("No active account found with the given credentials")) # Call the parent validation to create token data = super().validate({ self.username_field: user.username, "password": password }) data["user_id"] = user.id data["username"] = user.username data["email"] = user.email return data # user creating section start ------------------------------------------ class UserRegistrationSerializer(serializers.ModelSerializer): password = serializers.CharField( write_only=True, help_text="Heslo musí mít alespoň 8 znaků, obsahovat velká a malá písmena a číslici." ) class Meta: model = User fields = [ 'first_name', 'last_name', 'email', 'phone_number', 'password', 'city', 'street', 'postal_code', 'gdpr' ] extra_kwargs = { 'first_name': {'required': True, 'help_text': 'Křestní jméno uživatele'}, 'last_name': {'required': True, 'help_text': 'Příjmení uživatele'}, 'email': {'required': True, 'help_text': 'Emailová adresa uživatele'}, 'phone_number': {'required': True, 'help_text': 'Telefonní číslo uživatele'}, 'city': {'required': True, 'help_text': 'Město uživatele'}, 'street': {'required': True, 'help_text': 'Ulice uživatele'}, 'postal_code': {'required': True, 'help_text': 'PSČ uživatele'}, 'gdpr': {'required': True, 'help_text': 'Souhlas se zpracováním osobních údajů'}, } def validate_password(self, value): if len(value) < 8: raise serializers.ValidationError("Password must be at least 8 characters long.") if not re.search(r"[A-Z]", value): raise serializers.ValidationError("Password must contain at least one uppercase letter.") if not re.search(r"[a-z]", value): raise serializers.ValidationError("Password must contain at least one lowercase letter.") if not re.search(r"\d", value): raise serializers.ValidationError("Password must contain at least one digit.") return value def validate(self, data): email = data.get("email") phone = data.get("phone_number") dgpr = data.get("GDPR") if not dgpr: raise serializers.ValidationError({"GDPR": "You must agree to the GDPR to register."}) if User.objects.filter(email=email).exists(): raise serializers.ValidationError({"email": "Account with this email already exists."}) if phone and User.objects.filter(phone_number=phone).exists(): raise serializers.ValidationError({"phone_number": "Account with this phone number already exists."}) return data def create(self, validated_data): password = validated_data.pop("password") username = validated_data.get("username", "") user = User.objects.create( username=username, is_active=False, #uživatel je defaultně deaktivovaný **validated_data ) user.set_password(password) user.save() return user class UserActivationSerializer(serializers.Serializer): user_id = serializers.IntegerField() var_symbol = serializers.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(9999999999)]) def save(self, **kwargs): try: user = User.objects.get(pk=self.validated_data['user_id']) except User.DoesNotExist: raise NotFound("User with this ID does not exist.") user.var_symbol = self.validated_data['var_symbol'] user.is_active = True user.save() return user def to_representation(self, instance): return { "id": instance.id, "email": instance.email, "var_symbol": instance.var_symbol, "is_active": instance.is_active, } class Meta: model = User fields = [ 'user_id', 'var_symbol' ] extra_kwargs = { 'user_id': {'required': True, 'help_text': 'ID uživatele'}, 'var_symbol': {'required': True, 'help_text': 'Variablní symbol, zadán úředníkem'}, } # user creating section end -------------------------------------------- class PasswordResetRequestSerializer(serializers.Serializer): email = serializers.EmailField( help_text="E-mail registrovaného a aktivního uživatele, na který bude zaslán reset hesla." ) def validate_email(self, value): if not User.objects.filter(email=value, is_active=True).exists(): raise serializers.ValidationError("Účet s tímto emailem neexistuje nebo není aktivní.") return value class PasswordResetConfirmSerializer(serializers.Serializer): password = serializers.CharField( write_only=True, help_text="Nové heslo musí mít alespoň 8 znaků, obsahovat velká a malá písmena a číslici." ) def validate_password(self, value): import re if len(value) < 8: raise serializers.ValidationError("Heslo musí mít alespoň 8 znaků.") if not re.search(r"[A-Z]", value): raise serializers.ValidationError("Musí obsahovat velké písmeno.") if not re.search(r"[a-z]", value): raise serializers.ValidationError("Musí obsahovat malé písmeno.") if not re.search(r"\d", value): raise serializers.ValidationError("Musí obsahovat číslici.") return value