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 .email 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', 'account_type', 'password','city', 'street', 'PSC', 'bank_account', 'RC', 'ICO', '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'}, 'account_type': {'required': True, 'help_text': 'Typ účtu'}, 'city': {'required': True, 'help_text': 'Město uživatele'}, 'street': {'required': True, 'help_text': 'Ulice uživatele'}, 'PSC': {'required': True, 'help_text': 'Poštovní směrovací číslo'}, 'bank_account': {'required': True, 'help_text': 'Číslo bankovního účtu'}, 'RC': {'required': True, 'help_text': 'Rodné číslo'}, 'ICO': {'required': True, 'help_text': 'Identifikační číslo organizace'}, '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("Heslo musí mít alespoň 8 znaků.") if not re.search(r"[A-Z]", value): raise serializers.ValidationError("Heslo musí obsahovat alespoň jedno velké písmeno.") if not re.search(r"[a-z]", value): raise serializers.ValidationError("Heslo musí obsahovat alespoň jedno malé písmeno.") if not re.search(r"\d", value): raise serializers.ValidationError("Heslo musí obsahovat alespoň jednu číslici.") 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": "Pro registraci musíte souhlasit s GDPR"}) if User.objects.filter(email=email).exists(): raise serializers.ValidationError({"email": "Účet s tímto emailem již existuje."}) if phone and User.objects.filter(phone_number=phone).exists(): raise serializers.ValidationError({"phone_number": "Účet s tímto telefonem již existuje."}) return data def generate_username(self, first_name, last_name): # Převod na ascii (bez diakritiky) base_login = slugify(f"{last_name}{first_name[:2]}") login = base_login counter = 1 while User.objects.filter(username=login).exists(): login = f"{base_login}{counter}" counter += 1 return login def create(self, validated_data): password = validated_data.pop("password") first_name = validated_data.get("first_name", "") last_name = validated_data.get("last_name", "") username = self.generate_username(first_name, last_name) 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("Uživatel s tímto ID neexistuje.") 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