Sage100-vps/routes/sage_gateway.py

323 lines
9.7 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
import logging
from database import get_session, User
from core.dependencies import get_current_user
from services.sage_gateway import (
SageGatewayService,
gateway_response_from_model,
)
from schemas import (
SageGatewayCreate,
SageGatewayUpdate,
SageGatewayResponse,
SageGatewayList,
SageGatewayHealthCheck,
SageGatewayTest,
SageGatewayStatsResponse,
CurrentGatewayInfo,
)
from config.config import settings
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/sage-gateways", tags=["Sage Gateways"])
@router.post(
"", response_model=SageGatewayResponse, status_code=status.HTTP_201_CREATED
)
async def create_gateway(
data: SageGatewayCreate,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateway = await service.create(user.id, data.model_dump())
logger.info(f"Gateway créée: {gateway.name} par {user.email}")
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.get("", response_model=SageGatewayList)
async def list_gateways(
include_deleted: bool = Query(False, description="Inclure les gateways supprimées"),
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateways = await service.list_for_user(user.id, include_deleted)
active = await service.get_active_gateway(user.id)
items = [SageGatewayResponse(**gateway_response_from_model(g)) for g in gateways]
return SageGatewayList(
items=items,
total=len(items),
active_gateway=SageGatewayResponse(**gateway_response_from_model(active))
if active
else None,
using_fallback=active is None,
)
@router.get("/current", response_model=CurrentGatewayInfo)
async def get_current_gateway(
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
url, token, gateway_id = await service.get_effective_gateway_config(user.id)
if gateway_id:
gateway = await service.get_by_id(gateway_id, user.id)
return CurrentGatewayInfo(
source="user_config",
gateway_id=gateway_id,
gateway_name=gateway.name if gateway else None,
gateway_url=url,
is_healthy=gateway.last_health_status if gateway else None,
user_id=user.id,
)
else:
return CurrentGatewayInfo(
source="fallback",
gateway_id=None,
gateway_name="Configuration .env (défaut)",
gateway_url=url,
is_healthy=None,
user_id=user.id,
)
@router.get("/stats", response_model=SageGatewayStatsResponse)
async def get_gateway_stats(
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
stats = await service.get_stats(user.id)
return SageGatewayStatsResponse(**stats)
@router.get("/{gateway_id}", response_model=SageGatewayResponse)
async def get_gateway(
gateway_id: str,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateway = await service.get_by_id(gateway_id, user.id)
if not gateway:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.put("/{gateway_id}", response_model=SageGatewayResponse)
async def update_gateway(
gateway_id: str,
data: SageGatewayUpdate,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
update_data = {k: v for k, v in data.model_dump().items() if v is not None}
if not update_data:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail="Aucun champ à modifier"
)
gateway = await service.update(gateway_id, user.id, update_data)
if not gateway:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
logger.info(f"Gateway mise à jour: {gateway.name} par {user.email}")
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.delete("/{gateway_id}")
async def delete_gateway(
gateway_id: str,
hard_delete: bool = Query(False, description="Suppression définitive"),
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
success = await service.delete(gateway_id, user.id, hard_delete)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
logger.info(
f"Gateway supprimée: {gateway_id} par {user.email} (hard={hard_delete})"
)
return {
"success": True,
"message": f"Gateway supprimée {'définitivement' if hard_delete else '(soft delete)'}",
}
@router.post("/{gateway_id}/activate", response_model=SageGatewayResponse)
async def activate_gateway(
gateway_id: str,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateway = await service.activate(gateway_id, user.id)
if not gateway:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
logger.info(f"Gateway activée: {gateway.name} par {user.email}")
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.post("/{gateway_id}/deactivate", response_model=SageGatewayResponse)
async def deactivate_gateway(
gateway_id: str,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateway = await service.deactivate(gateway_id, user.id)
if not gateway:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
logger.info(f"Gateway désactivée: {gateway.name} - fallback actif")
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.post("/deactivate-all")
async def deactivate_all_gateways(
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
await service._deactivate_all_for_user(user.id)
await session.commit()
logger.info(
f"Toutes les gateways désactivées pour {user.email} - fallback .env actif"
)
return {
"success": True,
"message": "Toutes les gateways désactivées. Le fallback .env est maintenant utilisé.",
"fallback_url": settings.sage_gateway_url,
}
@router.post("/{gateway_id}/health-check", response_model=SageGatewayHealthCheck)
async def check_gateway_health(
gateway_id: str,
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
from datetime import datetime
service = SageGatewayService(session)
gateway = await service.get_by_id(gateway_id, user.id)
if not gateway:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gateway {gateway_id} introuvable",
)
result = await service.health_check(gateway_id, user.id)
return SageGatewayHealthCheck(
gateway_id=gateway_id,
gateway_name=gateway.name,
status=result.get("status", "unknown"),
response_time_ms=result.get("response_time_ms"),
sage_version=result.get("sage_version"),
error=result.get("error"),
checked_at=datetime.now(),
)
@router.post("/test", response_model=dict)
async def test_gateway_config(
data: SageGatewayTest,
user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
):
service = SageGatewayService(session)
result = await service.test_gateway(data.gateway_url, data.gateway_token)
return {"tested_url": data.gateway_url, "result": result}
@router.post("/health-check-all")
async def check_all_gateways_health(
session: AsyncSession = Depends(get_session),
user: User = Depends(get_current_user),
):
service = SageGatewayService(session)
gateways = await service.list_for_user(user.id)
results = []
for gateway in gateways:
result = await service.health_check(gateway.id, user.id)
results.append(
{
"gateway_id": gateway.id,
"gateway_name": gateway.name,
"is_active": gateway.is_active,
**result,
}
)
healthy_count = sum(1 for r in results if r.get("status") == "healthy")
return {
"total": len(results),
"healthy": healthy_count,
"unhealthy": len(results) - healthy_count,
"results": results,
}
@router.get("/fallback/info")
async def get_fallback_info(
user: User = Depends(get_current_user),
):
return {
"source": ".env",
"gateway_url": settings.sage_gateway_url,
"token_configured": bool(settings.sage_gateway_token),
"token_preview": f"****{settings.sage_gateway_token[-4:]}"
if settings.sage_gateway_token
else None,
"description": "Configuration par défaut utilisée quand aucune gateway utilisateur n'est active",
}