Files
service-finder/backend/app/schemas/user.py
2026-07-01 19:49:58 +00:00

103 lines
3.4 KiB
Python
Executable File

# /opt/docker/dev/service_finder/backend/app/schemas/user.py
import uuid
from pydantic import BaseModel, EmailStr, field_validator, ConfigDict
from typing import Optional, Any, Dict
from datetime import date, datetime
from app.schemas.address import AddressIn, AddressOut
class PersonResponse(BaseModel):
"""Beágyazott személyes adatok a UserResponse számára."""
id: int
id_uuid: uuid.UUID
first_name: Optional[str] = None
last_name: Optional[str] = None
phone: Optional[str] = None
mothers_last_name: Optional[str] = None
mothers_first_name: Optional[str] = None
birth_place: Optional[str] = None
birth_date: Optional[datetime] = None
identity_docs: Optional[Any] = None
ice_contact: Optional[Any] = None
is_active: bool = True
address: Optional[AddressOut] = None
model_config = ConfigDict(from_attributes=True)
class UserBase(BaseModel):
email: EmailStr
first_name: Optional[str] = None
last_name: Optional[str] = None
is_active: bool = True
region_code: str = "HU"
class UserResponse(UserBase):
id: int
person_id: Optional[int] = None
role: str
subscription_plan: str
subscription_expires_at: Optional[datetime] = None
# P0: Real subscription limits from the assigned subscription_tier JSONB rules
max_vehicles: int = 1
max_garages: int = 1
scope_level: str
scope_id: Optional[str] = None
ui_mode: str = "personal"
visual_settings: Optional[dict] = {"theme": "default", "primary_color": None, "wall_logo_url": None}
active_organization_id: Optional[int] = None
preferred_language: str = "hu"
# Beágyazott személyes adatok (Person + Address)
person: Optional[PersonResponse] = None
# Utolsó admin flag (ha a user az egyetlen aktív admin bármely szervezetében)
is_last_admin: bool = False
# RBAC Phase 3: Rendszerszintű képességek (a SYSTEM_CAPABILITIES_MATRIX-ból)
system_capabilities: Dict[str, bool] = {}
# RBAC Phase 3: Szervezeti szintű képességek (org_id -> capability -> bool)
org_capabilities: Dict[str, Dict[str, bool]] = {}
model_config = ConfigDict(from_attributes=True)
class PersonUpdate(BaseModel):
"""PUT /users/me/person séma - a személyes adatok szerkesztéséhez."""
first_name: Optional[str] = None
last_name: Optional[str] = None
phone: Optional[str] = None
mothers_last_name: Optional[str] = None
mothers_first_name: Optional[str] = None
birth_place: Optional[str] = None
birth_date: Optional[date] = None
# Okmány adatok (identity_docs)
identity_docs: Optional[Any] = None
# Cím adatok — egységes AddressIn séma
address: Optional[AddressIn] = None
class ChangePasswordRequest(BaseModel):
"""PUT /users/me/password séma - jelszó módosításhoz."""
current_password: str
new_password: str
class UserUpdate(BaseModel):
first_name: Optional[str] = None
last_name: Optional[str] = None
preferred_language: Optional[str] = None
ui_mode: Optional[str] = None
visual_settings: Optional[dict] = None
class ActiveOrganizationUpdate(BaseModel):
organization_id: Optional[int] = None # Integer ID or None to revert to personal mode
class UserWithTokenResponse(BaseModel):
"""User response with new JWT token for organization switching"""
user: UserResponse
access_token: str
token_type: str = "bearer"