41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
import re
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
from app.core.dto.user import UserRole
|
|
|
|
EMAIL_PATTERN = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
|
|
|
|
|
|
def _normalize_email(value: str) -> str:
|
|
value = value.strip().lower()
|
|
if not EMAIL_PATTERN.match(value) or len(value) > 254:
|
|
raise ValueError("invalid email")
|
|
return value
|
|
|
|
|
|
class UserCreate(BaseModel):
|
|
email: str
|
|
password: str = Field(min_length=8, max_length=128)
|
|
first_name: str = Field(default="", max_length=100)
|
|
last_name: str = Field(default="", max_length=100)
|
|
role: UserRole = UserRole.trainee
|
|
|
|
_email = field_validator("email")(_normalize_email)
|
|
|
|
|
|
class UserUpdate(BaseModel):
|
|
"""Partial update: only the fields that were sent are changed."""
|
|
|
|
email: Optional[str] = None
|
|
password: Optional[str] = Field(default=None, min_length=8, max_length=128)
|
|
first_name: Optional[str] = Field(default=None, max_length=100)
|
|
last_name: Optional[str] = Field(default=None, max_length=100)
|
|
role: Optional[UserRole] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
@field_validator("email")
|
|
@classmethod
|
|
def normalize_email(cls, value: Optional[str]) -> Optional[str]:
|
|
return None if value is None else _normalize_email(value)
|