Files
plantillas-proyectos/backend/api/v1/modules/a76/tenants/routes.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

133 lines
3.5 KiB
Python

"""
Endpoints API para gestión de tenants
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List
from core.database import get_core_db
from core.security import get_current_user, has_role
from .dto import (
TenantCreateDTO,
TenantUpdateDTO,
TenantResponseDTO,
TenantListResponseDTO,
)
from .service import TenantService
router = APIRouter(prefix="/tenants")
@router.post("/", response_model=TenantResponseDTO, status_code=201)
async def create_tenant(
tenant_data: TenantCreateDTO,
db: Session = Depends(get_core_db),
current_user: dict = Depends(has_role("admin")),
):
"""
Crea un nuevo tenant en el sistema
Requiere rol: admin
"""
service = TenantService(db)
return service.create_tenant(tenant_data)
@router.get("/", response_model=TenantListResponseDTO)
async def list_tenants(
page: int = Query(1, ge=1, description="Número de página"),
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
active_only: bool = Query(False, description="Solo tenants activos"),
db: Session = Depends(get_core_db),
current_user: dict = Depends(has_role("admin")),
):
"""
Lista todos los tenants
Requiere rol: admin
"""
service = TenantService(db)
skip = (page - 1) * page_size
tenants = service.list_tenants(skip=skip, limit=page_size, active_only=active_only)
# Contar total
from .models import Tenant
query = db.query(Tenant)
if active_only:
query = query.filter(Tenant.is_active == True)
total = query.count()
return TenantListResponseDTO(
tenants=tenants, total=total, page=page, page_size=page_size
)
@router.get("/{tenant_id}", response_model=TenantResponseDTO)
async def get_tenant(
tenant_id: int,
db: Session = Depends(get_core_db),
current_user: dict = Depends(get_current_user),
):
"""
Obtiene información de un tenant por ID
"""
service = TenantService(db)
tenant = service.get_tenant(tenant_id)
if not tenant:
raise HTTPException(status_code=404, detail="Tenant not found")
return tenant
@router.put("/{tenant_id}", response_model=TenantResponseDTO)
async def update_tenant(
tenant_id: int,
tenant_data: TenantUpdateDTO,
db: Session = Depends(get_core_db),
current_user: dict = Depends(has_role("admin")),
):
"""
Actualiza un tenant
Requiere rol: admin
"""
service = TenantService(db)
tenant = service.update_tenant(tenant_id, tenant_data)
if not tenant:
raise HTTPException(status_code=404, detail="Tenant not found")
return tenant
@router.delete("/{tenant_id}", status_code=204)
async def delete_tenant(
tenant_id: int,
db: Session = Depends(get_core_db),
current_user: dict = Depends(has_role("admin")),
):
"""
Elimina (desactiva) un tenant
Requiere rol: admin
"""
service = TenantService(db)
if not service.delete_tenant(tenant_id):
raise HTTPException(status_code=404, detail="Tenant not found")
return None
@router.get("/slug/{slug}", response_model=TenantResponseDTO)
async def get_tenant_by_slug(
slug: str,
db: Session = Depends(get_core_db),
current_user: dict = Depends(get_current_user),
):
"""
Obtiene un tenant por su slug
"""
service = TenantService(db)
tenant = service.get_tenant_by_slug(slug)
if not tenant:
raise HTTPException(status_code=404, detail="Tenant not found")
return tenant