Gestion des référents depuis la fiche bénévole
Un poste avait bien un `lead_account_id`, lu par l'écran référent
(`/mobile-referent`) et par les droits d'écriture (`ensure_can_write_position`),
mais rien ne permettait de le renseigner : aucun écran ne l'exposait, et
l'API ne validait même pas que la valeur envoyée désignait un compte référent
existant de la bonne édition.
Backend :
- `PATCH /editions/{id}/accounts/{account_id}` (nouveau) : change le `role`
d'un compte, seulement entre LEAD et VOLUNTEER (lien magique dans les deux
cas) — 422 `account.role_change_not_allowed` dès que COORDINATOR est
impliqué (mot de passe en jeu, jamais touché ici). C'est ce qui permet de
faire passer le compte d'un bénévole en référent.
- `POST`/`PATCH /positions` : `lead_account_id` vérifié — doit désigner un
compte `Role.LEAD` de la même édition, sinon 422
`position.lead_must_be_referent_account` (silencieusement accepté
jusqu'ici, y compris un compte d'une autre édition ou du mauvais rôle).
Frontend (`ConfigVolunteers.tsx`) : nouvelle section « Référent des postes »
sur la fiche du bénévole, juste après l'accès de connexion — mêmes badges à
cocher que les vœux de poste/artiste. Cocher un poste crée ou met à niveau
(LEAD) l'accès de connexion du bénévole automatiquement ; décocher retire
seulement le poste, sans jamais rétrograder l'accès. Un bénévole dont le
compte est déjà COORDINATOR ne peut pas être désigné référent (il a déjà
accès à tout). Miroir complet côté mock (`accounts.update`,
`checkLeadAccount`) pour que la démonstration se comporte pareil.
Vérifié : 204 tests backend pertinents (14 nouveaux : 6 sur `PATCH accounts`,
8 sur la validation `lead_account_id`), ruff, alembic check ; typecheck/
lint/build/smoke frontend ; parcours complet testé en direct sur le jeu de
démo (création de compte, promotion LEAD, rejet COORDINATOR, affectation
référent) avant nettoyage des données de test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
db11d9a3ba
commit
8fcc22115f
@@ -9,7 +9,7 @@ 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.api.schemas import AccountCreate, AccountRead, AccountUpdate
|
||||
from app.auth.deps import require_coordinator
|
||||
from app.auth.passwords import MIN_LENGTH, hash_password
|
||||
from app.db import get_session
|
||||
@@ -85,6 +85,30 @@ def list_accounts(
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/{account_id}", response_model=AccountRead)
|
||||
def update_account(
|
||||
account_id: uuid.UUID,
|
||||
payload: AccountUpdate,
|
||||
edition: Edition = Depends(get_edition),
|
||||
_guard: Account = Depends(require_coordinator),
|
||||
session: Session = Depends(get_session),
|
||||
) -> Account:
|
||||
"""Seul le rôle change de main ici, et seulement entre LEAD et VOLUNTEER
|
||||
(lien magique dans les deux cas) : devenir référent d'un poste (voir
|
||||
`positions.py`) met à niveau le compte bénévole existant, sans toucher au
|
||||
mot de passe d'un compte COORDINATION."""
|
||||
account = owned_or_404(session.get(Account, account_id), edition.id)
|
||||
if payload.role is not None and payload.role != account.role:
|
||||
if Role.COORDINATOR in (account.role, payload.role):
|
||||
raise HTTPException(
|
||||
status_code=422, detail={"code": "account.role_change_not_allowed"}
|
||||
)
|
||||
account.role = payload.role
|
||||
session.commit()
|
||||
session.refresh(account)
|
||||
return account
|
||||
|
||||
|
||||
@router.delete("/{account_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_account(
|
||||
account_id: uuid.UUID,
|
||||
|
||||
Reference in New Issue
Block a user