128 lines
4.3 KiB
Python
Executable File
128 lines
4.3 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
|
|
|
|
|
|
class AddressResponse(BaseModel):
|
|
"""Beágyazott cím adatok a PersonResponse számára.
|
|
A mezőnevek address_ előtaggal egyeznek a frontend által várt PersonUpdate formátummal."""
|
|
address_zip: Optional[str] = None
|
|
address_city: Optional[str] = None
|
|
address_street_name: Optional[str] = None
|
|
address_street_type: Optional[str] = None
|
|
address_house_number: Optional[str] = None
|
|
address_stairwell: Optional[str] = None
|
|
address_floor: Optional[str] = None
|
|
address_door: Optional[str] = None
|
|
address_hrsz: Optional[str] = None
|
|
full_address_text: Optional[str] = None
|
|
latitude: Optional[float] = None
|
|
longitude: Optional[float] = None
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
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[AddressResponse] = 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
|
|
address_zip: Optional[str] = None
|
|
address_city: Optional[str] = None
|
|
address_street_name: Optional[str] = None
|
|
address_street_type: Optional[str] = None
|
|
address_house_number: Optional[str] = None
|
|
address_stairwell: Optional[str] = None
|
|
address_floor: Optional[str] = None
|
|
address_door: Optional[str] = None
|
|
address_hrsz: Optional[str] = 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"
|