Files
plantillas-proyectos/backend/api/v1/modules/a76/tenants/dto.py
acazares 52b8fcd434 feat: Implement multi-tenancy support in middleware and security layers
- Enhanced TenantMiddleware to validate tenant information from JWT tokens.
- Added LicenseValidationMiddleware to check tenant licenses before processing requests.
- Updated security utilities to extract tenant information from tokens and validate company access.
- Introduced CompanyStore to manage active company state and handle company switching in the frontend.
- Modified API routes to include company_id in requests for better resource management.
- Improved logging and error handling throughout the middleware and API layers.
- Updated frontend components to reflect changes in company management and selection.
- Added new API route for fetching user's companies with proper authentication handling.
2025-11-11 14:15:31 -06:00

116 lines
3.3 KiB
Python

"""
DTOs (Data Transfer Objects) para módulo de tenants
Reemplaza schemas.py siguiendo enfoque DDD y estilo NestJS
"""
from pydantic import BaseModel, Field, EmailStr
from typing import Optional
from datetime import datetime
from enum import Enum
class TenantTypeDTO(str, Enum):
"""Tipo de tenant"""
SHARED = "shared"
DEDICATED = "dedicated"
class TenantCreateDTO(BaseModel):
"""DTO para crear un nuevo tenant"""
name: str = Field(
..., min_length=3, max_length=255, description="Nombre del tenant"
)
slug: str = Field(
..., min_length=3, max_length=100, description="Identificador único del tenant"
)
keycloak_realm: str = Field(
..., min_length=3, max_length=255, description="Nombre del realm en Keycloak"
)
type: TenantTypeDTO = Field(
default=TenantTypeDTO.SHARED, description="Tipo de tenant"
)
contact_name: Optional[str] = Field(
None, max_length=255, description="Nombre de contacto"
)
contact_email: Optional[EmailStr] = Field(None, description="Email de contacto")
contact_phone: Optional[str] = Field(
None, max_length=50, description="Teléfono de contacto"
)
class Config:
json_schema_extra = {
"example": {
"name": "Empresa ABC S.A. de C.V.",
"slug": "empresa-abc",
"keycloak_realm": "empresa-abc-realm",
"type": "shared",
"contact_name": "Juan Pérez",
"contact_email": "juan.perez@empresa-abc.com",
"contact_phone": "+52 55 1234 5678",
}
}
class TenantUpdateDTO(BaseModel):
"""DTO para actualizar un tenant"""
name: Optional[str] = Field(None, min_length=3, max_length=255)
contact_name: Optional[str] = Field(None, max_length=255)
contact_email: Optional[EmailStr] = None
contact_phone: Optional[str] = Field(None, max_length=50)
is_active: Optional[bool] = None
class Config:
json_schema_extra = {
"example": {
"name": "Empresa ABC S.A. de C.V. - Actualizado",
"contact_email": "nuevo@empresa-abc.com",
}
}
class TenantResponseDTO(BaseModel):
"""DTO para respuesta de tenant"""
id: int
name: str
slug: str
type: TenantTypeDTO
keycloak_realm: str
contact_name: Optional[str]
contact_email: Optional[str]
contact_phone: Optional[str]
is_active: bool
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
json_schema_extra = {
"example": {
"id": 1,
"name": "Empresa ABC S.A. de C.V.",
"slug": "empresa-abc",
"type": "shared",
"keycloak_realm": "empresa-abc-realm",
"contact_name": "Juan Pérez",
"contact_email": "juan.perez@empresa-abc.com",
"contact_phone": "+52 55 1234 5678",
"is_active": True,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z",
}
}
class TenantListResponseDTO(BaseModel):
"""DTO para lista de tenants"""
tenants: list[TenantResponseDTO]
total: int
page: int
page_size: int