"""Gestion des comptes par la coordination (créer un référent, un bénévole connecté…).""" import uuid from fastapi import APIRouter, Depends, HTTPException, Response, status from sqlalchemy.exc import IntegrityError from sqlmodel import Session, select from app.api._common import owned_or_404 from app.api.deps import get_edition from app.api.schemas import AccountCreate, AccountRead from app.auth.deps import require_coordinator from app.auth.passwords import MIN_LENGTH, hash_password from app.db import get_session from app.models import Account, Edition, Role, Volunteer router = APIRouter( prefix="/editions/{edition_id}/accounts", tags=["accounts"] ) @router.post("", response_model=AccountRead, status_code=status.HTTP_201_CREATED) def create_account( payload: AccountCreate, edition: Edition = Depends(get_edition), _guard: Account = Depends(require_coordinator), session: Session = Depends(get_session), ) -> Account: if payload.volunteer_id is not None: volunteer = session.get(Volunteer, payload.volunteer_id) if volunteer is None or volunteer.edition_id != edition.id: raise HTTPException( status_code=422, detail={"code": "account.volunteer_wrong_edition"} ) # Deux systèmes de connexion : mot de passe pour la COORDINATION, # lien magique pour les autres. if payload.role is Role.COORDINATOR: if not payload.password or len(payload.password) < MIN_LENGTH: raise HTTPException( status_code=422, detail={"code": "account.password_required", "min": MIN_LENGTH}, ) password_hash = hash_password(payload.password) else: if payload.password is not None: raise HTTPException( status_code=422, detail={"code": "account.password_not_allowed"}, ) password_hash = None account = Account( edition_id=edition.id, email=payload.email.strip(), role=payload.role, volunteer_id=payload.volunteer_id, password_hash=password_hash, ) session.add(account) try: session.commit() except IntegrityError as exc: session.rollback() raise HTTPException( status_code=409, detail={"code": "account.duplicate"} ) from exc session.refresh(account) return account @router.get("", response_model=list[AccountRead]) def list_accounts( edition: Edition = Depends(get_edition), _guard: Account = Depends(require_coordinator), session: Session = Depends(get_session), ) -> list[Account]: return list( session.exec( select(Account) .where(Account.edition_id == edition.id) .order_by(Account.email) ) ) @router.delete("/{account_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_account( account_id: uuid.UUID, edition: Edition = Depends(get_edition), _guard: Account = Depends(require_coordinator), session: Session = Depends(get_session), ) -> Response: account = owned_or_404(session.get(Account, account_id), edition.id) session.delete(account) session.commit() return Response(status_code=status.HTTP_204_NO_CONTENT)