from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from typing import List, Optional from datetime import datetime import uuid from app.core.database import get_db from app.models.system import System from app.models.user import User from app.api import deps from app.api.schemas.system import SystemCreate, SystemUpdate, SystemResponse router = APIRouter() # =================================== # ENDPOINTS # =================================== @router.get("/", response_model=List[SystemResponse]) async def read_systems( skip: int = 0, limit: int = 100, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) # ✅ CORREGIDO: Type hint + no solo superuser ): """ Listar sistemas del tenant del usuario actual. ✅ Implementa multi-tenancy: solo muestra sistemas del tenant del usuario. """ # ✅ CORREGIDO: Filtrar por tenant_id query = select(System).where( System.tenant_id == current_user.tenant_id ).offset(skip).limit(limit) result = await db.execute(query) return result.scalars().all() @router.post("/", response_model=SystemResponse, status_code=status.HTTP_201_CREATED) async def create_system( system: SystemCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) # ✅ CORREGIDO: Type hint ): """ Crear nuevo sistema en el tenant del usuario actual. ✅ Implementa multi-tenancy: asigna automáticamente tenant_id del usuario. """ # ✅ CORREGIDO: Asignar tenant_id del usuario actual db_system = System( **system.model_dump(), tenant_id=current_user.tenant_id # ✅ Multi-tenancy automático ) db.add(db_system) await db.commit() await db.refresh(db_system) return db_system @router.get("/{system_id}", response_model=SystemResponse) async def read_system( system_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): """ Obtener un sistema específico del tenant. ✅ Implementa multi-tenancy: solo permite acceso a sistemas del propio tenant. """ query = select(System).where( System.id == system_id, System.tenant_id == current_user.tenant_id # ✅ Seguridad multi-tenant ) result = await db.execute(query) system = result.scalar_one_or_none() if not system: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="System not found" ) return system @router.put("/{system_id}", response_model=SystemResponse) async def update_system( system_id: uuid.UUID, system_update: SystemUpdate, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): """ Actualizar sistema del tenant. ✅ Implementa multi-tenancy: solo permite actualizar sistemas del propio tenant. """ query = select(System).where( System.id == system_id, System.tenant_id == current_user.tenant_id ) result = await db.execute(query) db_system = result.scalar_one_or_none() if not db_system: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="System not found" ) # Actualizar campos update_data = system_update.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(db_system, field, value) await db.commit() await db.refresh(db_system) return db_system @router.delete("/{system_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_system( system_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): """ Desactivar sistema del tenant (soft delete). ✅ Implementa multi-tenancy: solo permite desactivar sistemas del propio tenant. """ query = select(System).where( System.id == system_id, System.tenant_id == current_user.tenant_id ) result = await db.execute(query) db_system = result.scalar_one_or_none() if not db_system: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="System not found" ) # Soft delete db_system.is_active = False await db.commit() return None