"""Pydantic-scheman för request/response-validering.""" from datetime import datetime from typing import Optional from uuid import UUID from pydantic import BaseModel, EmailStr, Field, ConfigDict from app.models import UserRole, UserStatus # ─── Shared ─────────────────────────────────────────── class UserBase(BaseModel): email: EmailStr first_name: str = Field(..., min_length=1, max_length=100) last_name: str = Field(..., min_length=1, max_length=100) role: UserRole = UserRole.VIEWER class TenantBase(BaseModel): name: str = Field(..., min_length=1, max_length=255) slug: str = Field(..., min_length=1, max_length=100) description: Optional[str] = None # ─── Tenant ─────────────────────────────────────────── class TenantCreate(TenantBase): pass class TenantUpdate(BaseModel): name: Optional[str] = Field(None, min_length=1, max_length=255) description: Optional[str] = None class TenantOut(TenantBase): model_config = ConfigDict(from_attributes=True) id: UUID created_at: datetime updated_at: datetime # ─── User ───────────────────────────────────────────── class UserCreate(UserBase): password: Optional[str] = Field(None, min_length=8) tenant_id: Optional[UUID] = None class UserUpdate(BaseModel): email: Optional[EmailStr] = None first_name: Optional[str] = Field(None, min_length=1, max_length=100) last_name: Optional[str] = Field(None, min_length=1, max_length=100) role: Optional[UserRole] = None status: Optional[UserStatus] = None tenant_id: Optional[UUID] = None class UserOut(UserBase): model_config = ConfigDict(from_attributes=True) id: UUID status: UserStatus is_superuser: bool last_login_at: Optional[datetime] = None tenant_id: Optional[UUID] = None created_at: datetime updated_at: datetime class UserDetailOut(UserOut): tenant: Optional[TenantOut] = None class UserListOut(BaseModel): items: list[UserOut] total: int # ─── Auth ───────────────────────────────────────────── class Token(BaseModel): access_token: str refresh_token: str token_type: str = "bearer" expires_in: int class TokenPayload(BaseModel): sub: Optional[str] = None type: Optional[str] = None class LoginRequest(BaseModel): email: EmailStr password: str class RefreshRequest(BaseModel): refresh_token: str class ChangePasswordRequest(BaseModel): current_password: str new_password: str = Field(..., min_length=8) # ─── Invitation ─────────────────────────────────────── class InvitationCreate(BaseModel): email: EmailStr role: UserRole = UserRole.VIEWER tenant_id: Optional[UUID] = None class InvitationOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: UUID email: str role: UserRole token: str expires_at: datetime accepted_at: Optional[datetime] = None created_at: datetime invited_by_id: UUID tenant_id: Optional[UUID] = None class AcceptInvitationRequest(BaseModel): token: str first_name: str = Field(..., min_length=1, max_length=100) last_name: str = Field(..., min_length=1, max_length=100) password: str = Field(..., min_length=8) # ─── Password reset (future) ────────────────────────── class PasswordResetRequest(BaseModel): email: EmailStr class PasswordResetConfirm(BaseModel): token: str new_password: str = Field(..., min_length=8)