init
This commit is contained in:
224
backend/account/serializers.py
Normal file
224
backend/account/serializers.py
Normal file
@@ -0,0 +1,224 @@
|
||||
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
|
||||
Reference in New Issue
Block a user