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
@@ -0,0 +1,51 @@
|
||||
import uuid
|
||||
|
||||
from app.models import Role
|
||||
|
||||
|
||||
def _url(edition, suffix=""):
|
||||
return f"/editions/{edition.id}/accounts{suffix}"
|
||||
|
||||
|
||||
def test_promotes_a_volunteer_account_to_lead(client, edition, make_account):
|
||||
account = make_account(Role.VOLUNTEER, email="v@ex.fr")
|
||||
resp = client.patch(_url(edition, f"/{account.id}"), json={"role": "LEAD"})
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["role"] == "LEAD"
|
||||
assert resp.json()["auth_method"] == "magic_link"
|
||||
|
||||
|
||||
def test_demotes_a_lead_account_to_volunteer(client, edition, make_account):
|
||||
account = make_account(Role.LEAD, email="l@ex.fr")
|
||||
resp = client.patch(_url(edition, f"/{account.id}"), json={"role": "VOLUNTEER"})
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["role"] == "VOLUNTEER"
|
||||
|
||||
|
||||
def test_cannot_change_role_of_a_coordinator_account(client, edition, make_account):
|
||||
account = make_account(Role.COORDINATOR, email="c@ex.fr", password="password123")
|
||||
resp = client.patch(_url(edition, f"/{account.id}"), json={"role": "LEAD"})
|
||||
assert resp.status_code == 422
|
||||
assert resp.json()["detail"]["code"] == "account.role_change_not_allowed"
|
||||
|
||||
|
||||
def test_cannot_promote_a_volunteer_to_coordinator(client, edition, make_account):
|
||||
account = make_account(Role.VOLUNTEER, email="v2@ex.fr")
|
||||
resp = client.patch(_url(edition, f"/{account.id}"), json={"role": "COORDINATOR"})
|
||||
assert resp.status_code == 422
|
||||
assert resp.json()["detail"]["code"] == "account.role_change_not_allowed"
|
||||
|
||||
|
||||
def test_unknown_account_is_404(client, edition):
|
||||
assert (
|
||||
client.patch(_url(edition, f"/{uuid.uuid4()}"), json={"role": "LEAD"}).status_code
|
||||
== 404
|
||||
)
|
||||
|
||||
|
||||
def test_volunteer_role_forbidden(edition, make_account, as_account):
|
||||
volunteer_account = make_account(Role.VOLUNTEER, email="v3@ex.fr")
|
||||
other = make_account(Role.VOLUNTEER, email="v4@ex.fr")
|
||||
api = as_account(volunteer_account)
|
||||
resp = api.patch(_url(edition, f"/{other.id}"), json={"role": "LEAD"})
|
||||
assert resp.status_code == 403
|
||||
Reference in New Issue
Block a user