Photo du bénévole ajoutée par la coordination
ci-cd / build-backend (push) Successful in 33s
ci-cd / build-frontend (push) Successful in 20s
ci-cd / deploy (push) Successful in 14s

Section « Photo » sur la fiche bénévole (ajouter / remplacer / retirer),
PUT/DELETE /editions/{id}/volunteers/{vid}/photo (COORDINATION),
validation de l'image partagée avec le formulaire public (read_photo).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-27 18:17:25 +01:00
co-authored by Claude Opus 5.5
parent 54cba467fc
commit 6892e0307d
12 changed files with 288 additions and 64 deletions
+40 -1
View File
@@ -5,12 +5,13 @@ L'email n'est pas unique : plusieurs bénévoles peuvent en partager un même
import uuid
from fastapi import APIRouter, Depends, HTTPException, Response, status
from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile, status
from sqlalchemy.orm import aliased
from sqlmodel import Session, select
from app.api._common import (
owned_or_404,
read_photo,
replace_links,
resolve_owned_ids,
set_artists,
@@ -342,6 +343,44 @@ def get_volunteer_photo(
)
@router.put("/{volunteer_id}/photo", response_model=VolunteerRead)
async def set_volunteer_photo(
volunteer_id: uuid.UUID,
file: UploadFile = File(...),
edition: Edition = Depends(get_edition),
_guard: Account = Depends(require_coordinator),
session: Session = Depends(get_session),
) -> VolunteerRead:
"""Ajout (ou remplacement) de la photo par la coordination, depuis la
fiche — pour un bénévole qui n'en a pas envoyé au formulaire public ou
ajouté à la main. Même validation que le formulaire (`read_photo`)."""
volunteer = owned_or_404(session.get(Volunteer, volunteer_id), edition.id)
photo = await read_photo(file)
if photo is None:
raise HTTPException(status_code=400, detail={"code": "volunteer.empty_photo"})
volunteer.photo, volunteer.photo_content_type = photo
session.add(volunteer)
session.commit()
session.refresh(volunteer)
return _read(session, volunteer)
@router.delete("/{volunteer_id}/photo", response_model=VolunteerRead)
def delete_volunteer_photo(
volunteer_id: uuid.UUID,
edition: Edition = Depends(get_edition),
_guard: Account = Depends(require_coordinator),
session: Session = Depends(get_session),
) -> VolunteerRead:
volunteer = owned_or_404(session.get(Volunteer, volunteer_id), edition.id)
volunteer.photo = None
volunteer.photo_content_type = None
session.add(volunteer)
session.commit()
session.refresh(volunteer)
return _read(session, volunteer)
@router.patch("/{volunteer_id}", response_model=VolunteerRead)
def update_volunteer(
volunteer_id: uuid.UUID,