171 lines
5.7 KiB
Python
171 lines
5.7 KiB
Python
"""Routes d'administration reservees au sysadmin."""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import func, select
|
|
from pydantic import BaseModel
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import create_token, get_current_membre, is_sysadmin, verify_pin
|
|
from app.services.admin_database import (
|
|
creer_groupe,
|
|
initialiser_demo,
|
|
modifier_groupe,
|
|
reinitialiser_groupe,
|
|
reinitialiser_demo,
|
|
supprimer_groupe,
|
|
)
|
|
from app.models.groupe import Groupe
|
|
from app.models.membre import Membre
|
|
from app.models.reunion import Reunion
|
|
from app.models.historique_modification import HistoriqueModification
|
|
|
|
router = APIRouter(prefix="/admin", tags=["Administration"])
|
|
|
|
|
|
class SysadminLoginRequest(BaseModel):
|
|
pin: str
|
|
|
|
|
|
class GroupeAdminRequest(BaseModel):
|
|
nom: str
|
|
district: str = "87-16"
|
|
adresse_local: str | None = None
|
|
jour_reunion: str | None = "mardi"
|
|
heure_reunion: str | None = "19:30"
|
|
assemblee_affaires_ordre: str = "premiere"
|
|
format_reunion: str | None = "Discussion ouverte"
|
|
lien_aa87: str = "https://aa87.org"
|
|
|
|
|
|
async def require_sysadmin(membre=Depends(get_current_membre)):
|
|
if not is_sysadmin(membre):
|
|
raise HTTPException(status_code=403, detail="Réservé au sysadmin")
|
|
return membre
|
|
|
|
|
|
@router.post("/sysadmin-login")
|
|
async def sysadmin_login(req: SysadminLoginRequest, db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(select(Membre).where(Membre.courriel == "sysadmin", Membre.actif == True))
|
|
for membre in result.scalars().all():
|
|
if verify_pin(req.pin, membre.pin_hash):
|
|
token = create_token(str(membre.id), None, expire_jours=1)
|
|
return {
|
|
"access_token": token,
|
|
"token_type": "bearer",
|
|
"sysadmin_instance": True,
|
|
"membre": {
|
|
"id": str(membre.id),
|
|
"prenom": "Sysadmin",
|
|
"courriel": "sysadmin",
|
|
"groupe_id": None,
|
|
"date_abstinence": None,
|
|
"is_sysadmin": True,
|
|
},
|
|
}
|
|
raise HTTPException(status_code=401, detail="PIN Sysadmin invalide")
|
|
|
|
|
|
@router.post("/demo")
|
|
async def demo_database(
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await initialiser_demo(db)
|
|
|
|
|
|
@router.post("/demo/reset")
|
|
async def reset_demo_database(
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await reinitialiser_demo(db)
|
|
|
|
|
|
@router.post("/groupes/{groupe_id}/reset")
|
|
async def reset_groupe_admin(
|
|
groupe_id: str,
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
try:
|
|
return await reinitialiser_groupe(db, groupe_id)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
|
|
|
|
@router.get("/groupes")
|
|
async def liste_groupes_admin(
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
await initialiser_demo(db)
|
|
groupes = (await db.execute(select(Groupe))).scalars().all()
|
|
groupes.sort(key=lambda g: (g.nom == "Groupe Démonstration", g.nom.lower()))
|
|
out = []
|
|
for groupe in groupes:
|
|
nb_membres = (await db.execute(
|
|
select(func.count()).select_from(Membre).where(Membre.groupe_id == groupe.id)
|
|
)).scalar_one()
|
|
nb_reunions = (await db.execute(
|
|
select(func.count()).select_from(Reunion).where(Reunion.groupe_id == groupe.id)
|
|
)).scalar_one()
|
|
nb_traces = (await db.execute(
|
|
select(func.count()).select_from(HistoriqueModification).where(HistoriqueModification.groupe_id == groupe.id)
|
|
)).scalar_one()
|
|
out.append({
|
|
"id": str(groupe.id),
|
|
"nom": groupe.nom,
|
|
"district": groupe.district,
|
|
"adresse_local": groupe.adresse_local,
|
|
"jour_reunion": groupe.jour_reunion,
|
|
"heure_reunion": groupe.heure_reunion.strftime("%H:%M") if groupe.heure_reunion else None,
|
|
"assemblee_affaires_ordre": groupe.assemblee_affaires_ordre,
|
|
"format_reunion": groupe.format_reunion,
|
|
"lien_aa87": groupe.lien_aa87,
|
|
"cree_le": groupe.cree_le,
|
|
"membres": nb_membres,
|
|
"reunions": nb_reunions,
|
|
"traces": nb_traces,
|
|
"demo": groupe.nom == "Groupe Démonstration",
|
|
"protege": groupe.nom == "Groupe Démonstration",
|
|
})
|
|
return out
|
|
|
|
|
|
@router.post("/groupes")
|
|
async def creer_groupe_admin(
|
|
req: GroupeAdminRequest,
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
try:
|
|
groupe = await creer_groupe(db, req.model_dump())
|
|
return {"message": "Groupe créé", "id": str(groupe.id)}
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
|
|
|
|
@router.patch("/groupes/{groupe_id}")
|
|
async def modifier_groupe_admin(
|
|
groupe_id: str,
|
|
req: GroupeAdminRequest,
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
try:
|
|
groupe = await modifier_groupe(db, groupe_id, req.model_dump())
|
|
return {"message": "Groupe modifié", "id": str(groupe.id)}
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
|
|
|
|
@router.delete("/groupes/{groupe_id}")
|
|
async def supprimer_groupe_admin(
|
|
groupe_id: str,
|
|
_sysadmin=Depends(require_sysadmin),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
try:
|
|
return await supprimer_groupe(db, groupe_id)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc))
|