323 lines
9.8 KiB
Python
323 lines
9.8 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,
|
|
SageGatewayListResponse,
|
|
SageGatewayHealthCheck,
|
|
SageGatewayTestRequest,
|
|
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=SageGatewayListResponse)
|
|
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 SageGatewayListResponse(
|
|
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: SageGatewayTestRequest,
|
|
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",
|
|
}
|