fix(authz): finir SEC-16, que mon propre correctif avait laisse a moitie
La vague K a pose un schema sur create_team et edit_team et a laisse cinq routes soeurs du meme fichier lire int(request.form.get(...)) : add_coach, add_manager, remove_coach, remove_manager et add_player. Un identifiant non numerique y etait un 500 dans chacune. C'est exactement la lecon que ce projet repete depuis la vague D -- corriger un motif fautif dans une seule couche le laisse dans les autres -- et cette fois c'est le correctif lui-meme qui l'a commise. Notee comme telle. Deux defauts de plus, trouves en finissant. add_player ecrivait status tel quel dans une colonne NOT NULL String(20). Et toggle_player_status lit "substitute si status == starter, sinon starter" : une valeur inconnue devenait donc starter a la premiere bascule, c'est-a-dire promouvait son porteur. Liste blanche dans TEAM_PLAYER_STATUSES. Et aucune de ces routes ne regardait is_active_account. La requete qui alimente la liste deroulante des joueurs ne le filtrait pas non plus, alors que les deux requetes juste au-dessus, coachs et gerants, le posaient -- deux lignes d'ecart, meme fichier. Un compte desactive etait donc propose et accepte, alors que is_active_account est precisement ce qui dit que la personne a quitte le club. Meme oubli dans tryouts.py. _staff_member delegue desormais a _assignable au lieu de repeter isinstance : deux fonctions du meme fichier repondant differemment a "ce compte peut-il prendre ce role" est la forme de tous les defauts qu'a eus ce module. Verifie par mutation : retirer le controle d'activite ou la liste blanche fait tomber trois tests. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -460,6 +460,62 @@ class UploadContractSchema(StripMixin):
|
||||
)
|
||||
|
||||
|
||||
#: Where a player stands on a team roster.
|
||||
#:
|
||||
#: `TeamPlayer.status` is a NOT NULL String(20) that `add_player` filled from
|
||||
#: `request.form.get('status', 'starter')` with no check at all, so a forged
|
||||
#: submission stored any string it liked. It then survived until someone
|
||||
#: pressed the toggle, which reads `'substitute' if status == 'starter' else
|
||||
#: 'starter'` — so an unknown value silently became `starter`, i.e. promoted
|
||||
#: whoever held it (SEC-16).
|
||||
TEAM_PLAYER_STATUSES = ('starter', 'substitute')
|
||||
|
||||
|
||||
class TeamStaffSchema(StripMixin):
|
||||
"""One staff id, posted by the add/remove coach and manager forms.
|
||||
|
||||
Both ids are optional here even though each route needs exactly one:
|
||||
`remove_coach` treats an absent id as "remove every coach", and the add
|
||||
routes already carry their own translated "Please select a coach."
|
||||
message. Making the field required would replace that message with a
|
||||
generic one for no gain.
|
||||
|
||||
What this schema is for is the conversion. Wave K closed `create_team`
|
||||
and `edit_team` and left five sibling routes reading `int(...)` straight
|
||||
off the form — a non-numeric id was a 500 in each. Fixing a pattern in
|
||||
one place and not its neighbours is the mistake this project keeps
|
||||
making; this is the same mistake, made by the fix for it.
|
||||
"""
|
||||
|
||||
coach_id = fields.Integer(
|
||||
allow_none=True,
|
||||
load_default=None,
|
||||
validate=validate.Range(min=1),
|
||||
error_messages={'invalid': _l('Invalid coach selection.')},
|
||||
)
|
||||
manager_id = fields.Integer(
|
||||
allow_none=True,
|
||||
load_default=None,
|
||||
validate=validate.Range(min=1),
|
||||
error_messages={'invalid': _l('Invalid manager selection.')},
|
||||
)
|
||||
|
||||
|
||||
class TeamPlayerSchema(StripMixin):
|
||||
"""A player being put on a team roster, and where they stand on it."""
|
||||
|
||||
player_id = fields.Integer(
|
||||
allow_none=True,
|
||||
load_default=None,
|
||||
validate=validate.Range(min=1),
|
||||
error_messages={'invalid': _l('Invalid player selection.')},
|
||||
)
|
||||
status = fields.String(
|
||||
load_default='starter',
|
||||
validate=validate.OneOf(TEAM_PLAYER_STATUSES, error=_l('Unknown roster status.')),
|
||||
)
|
||||
|
||||
|
||||
class OneOnOneRequestSchema(StripMixin):
|
||||
"""A player asking their coach for a session (MNT-12).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user