"""User management schemas for web API.""" from __future__ import annotations from datetime import datetime from typing import Optional from pydantic import BaseModel, ConfigDict, EmailStr, Field from backend.constants.roles import DEFAULT_USER_ROLE, UserRole class UserResponse(BaseModel): """User DTO returned from API.""" model_config = ConfigDict(from_attributes=True, protected_namespaces=()) id: int username: str email: Optional[str] = None full_name: Optional[str] = None is_active: bool is_admin: bool role: UserRole password_change_required: bool created_date: datetime last_login: Optional[datetime] = None class UserCreateRequest(BaseModel): """Request payload to create a new user.""" model_config = ConfigDict(protected_namespaces=()) username: str = Field(..., min_length=1, max_length=100) password: str = Field(..., min_length=6, description="Password (minimum 6 characters)") email: EmailStr = Field(..., description="Email address (required)") full_name: str = Field(..., min_length=1, max_length=200, description="Full name (required)") is_active: bool = True is_admin: bool = False role: UserRole = Field( DEFAULT_USER_ROLE, description="Role for feature-level access; also controls admin status where applicable", ) give_frontend_permission: bool = Field(False, description="Create user in auth database for frontend access") class UserUpdateRequest(BaseModel): """Request payload to update a user.""" model_config = ConfigDict(protected_namespaces=()) password: Optional[str] = Field(None, min_length=6, description="New password (minimum 6 characters, leave empty to keep current)") email: EmailStr = Field(..., description="Email address (required)") full_name: str = Field(..., min_length=1, max_length=200, description="Full name (required)") is_active: Optional[bool] = None is_admin: Optional[bool] = None role: Optional[UserRole] = Field( None, description="Updated role; determines admin status when provided", ) give_frontend_permission: Optional[bool] = Field( None, description="Create user in auth database for frontend access if True", ) class UsersListResponse(BaseModel): """List of users.""" model_config = ConfigDict(protected_namespaces=()) items: list[UserResponse] total: int