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:
GGThed
2026-08-11 20:42:26 -04:00
co-authored by Claude Opus 5
parent 838b247649
commit 20dabecd67
8 changed files with 633 additions and 361 deletions
Binary file not shown.
+172 -164
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: team-tryouts VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-08-11 20:15-0400\n"
"POT-Creation-Date: 2026-08-11 20:39-0400\n"
"PO-Revision-Date: 2026-08-07 20:22-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n"
@@ -92,127 +92,135 @@ msgstr "Vous devez choisir un joueur."
msgid "Notes must be 2000 characters or less."
msgstr "Les notes ne doivent pas dépasser 2000 caractères."
#: app/validators.py:482
msgid "Date must be in YYYY-MM-DD format."
msgstr "La date doit être au format AAAA-MM-JJ."
#: app/validators.py:483
msgid "A date is required."
msgstr "Une date est requise."
#: app/validators.py:489 app/validators.py:554
msgid "Start time must be in HH:MM format."
msgstr "Lheure de début doit être au format HH:MM."
#: app/validators.py:490 app/validators.py:555
msgid "A start time is required."
msgstr "Une heure de début est requise."
#: app/validators.py:496
msgid "End time must be in HH:MM format."
msgstr "Lheure de fin doit être au format HH:MM."
#: app/validators.py:497
msgid "An end time is required."
msgstr "Une heure de fin est requise."
#: app/validators.py:501
msgid "Points must be 2000 characters or less."
msgstr "Les points ne doivent pas dépasser 2000 caractères."
#: app/validators.py:516
msgid "End time must be after start time."
msgstr "L'heure de fin doit être postérieure à l'heure de début."
#: app/validators.py:545 app/validators.py:547
msgid "Day must be 0 (Monday) to 6 (Sunday)."
msgstr "Le jour doit aller de 0 (lundi) à 6 (dimanche)."
#: app/validators.py:548
msgid "A day is required."
msgstr "Un jour est requis."
#: app/validators.py:583
msgid "Player selection is malformed."
msgstr "La sélection de joueurs est mal formée."
#: app/validators.py:609 app/validators.py:719
msgid "A title is required."
msgstr "Un titre est requis."
#: app/validators.py:618
msgid "Invalid date format."
msgstr "Format de date invalide."
#: app/validators.py:623 app/validators.py:630
msgid "Invalid time format."
msgstr "Format dheure invalide."
#: app/validators.py:624
msgid "Start time is required. Please select a time slot."
msgstr "Lheure de début est obligatoire. Choisissez une plage horaire."
#: app/validators.py:638
msgid "Unknown match status."
msgstr "Statut de match inconnu."
#: app/validators.py:654
msgid "The end time must come after the start time."
msgstr "L'heure de fin doit être postérieure à l'heure de début."
#: app/validators.py:668
msgid "Unknown match type."
msgstr "Type de match inconnu."
#: app/validators.py:680
msgid "A team cannot play against itself."
msgstr "Une équipe ne peut pas jouer contre elle-même."
#: app/validators.py:728
msgid "Unknown game."
msgstr "Jeu inconnu."
#: app/validators.py:733
msgid "Invalid start date format."
msgstr "Format de date de début invalide."
#: app/validators.py:734
msgid "A start date is required."
msgstr "Une date de début est requise."
#: app/validators.py:740
msgid "Invalid end date format."
msgstr "Format de date de fin invalide."
#: app/validators.py:748
msgid "A tryout must allow at least one player."
msgstr "Une sélection doit accepter au moins un joueur."
#: app/validators.py:751
msgid "The player limit must be a whole number."
msgstr "La limite de joueurs doit être un nombre entier."
#: app/validators.py:763
msgid "End date cannot be before start date."
msgstr "La date de fin ne peut pas précéder la date de début."
#: app/validators.py:790 app/validators.py:791
msgid "Team name is required."
msgstr "Le nom de l’équipe est obligatoire."
#: app/validators.py:797
#: app/validators.py:494 app/validators.py:853
msgid "Invalid coach selection."
msgstr "Sélection de coach invalide."
#: app/validators.py:803
#: app/validators.py:500 app/validators.py:859
msgid "Invalid manager selection."
msgstr "Sélection de gérant invalide."
#: app/validators.py:815
#: app/validators.py:511
msgid "Invalid player selection."
msgstr "Sélection de joueur invalide."
#: app/validators.py:515
msgid "Unknown roster status."
msgstr "Statut d'effectif inconnu."
#: app/validators.py:538
msgid "Date must be in YYYY-MM-DD format."
msgstr "La date doit être au format AAAA-MM-JJ."
#: app/validators.py:539
msgid "A date is required."
msgstr "Une date est requise."
#: app/validators.py:545 app/validators.py:610
msgid "Start time must be in HH:MM format."
msgstr "Lheure de début doit être au format HH:MM."
#: app/validators.py:546 app/validators.py:611
msgid "A start time is required."
msgstr "Une heure de début est requise."
#: app/validators.py:552
msgid "End time must be in HH:MM format."
msgstr "Lheure de fin doit être au format HH:MM."
#: app/validators.py:553
msgid "An end time is required."
msgstr "Une heure de fin est requise."
#: app/validators.py:557
msgid "Points must be 2000 characters or less."
msgstr "Les points ne doivent pas dépasser 2000 caractères."
#: app/validators.py:572
msgid "End time must be after start time."
msgstr "L'heure de fin doit être postérieure à l'heure de début."
#: app/validators.py:601 app/validators.py:603
msgid "Day must be 0 (Monday) to 6 (Sunday)."
msgstr "Le jour doit aller de 0 (lundi) à 6 (dimanche)."
#: app/validators.py:604
msgid "A day is required."
msgstr "Un jour est requis."
#: app/validators.py:639
msgid "Player selection is malformed."
msgstr "La sélection de joueurs est mal formée."
#: app/validators.py:665 app/validators.py:775
msgid "A title is required."
msgstr "Un titre est requis."
#: app/validators.py:674
msgid "Invalid date format."
msgstr "Format de date invalide."
#: app/validators.py:679 app/validators.py:686
msgid "Invalid time format."
msgstr "Format dheure invalide."
#: app/validators.py:680
msgid "Start time is required. Please select a time slot."
msgstr "Lheure de début est obligatoire. Choisissez une plage horaire."
#: app/validators.py:694
msgid "Unknown match status."
msgstr "Statut de match inconnu."
#: app/validators.py:710
msgid "The end time must come after the start time."
msgstr "L'heure de fin doit être postérieure à l'heure de début."
#: app/validators.py:724
msgid "Unknown match type."
msgstr "Type de match inconnu."
#: app/validators.py:736
msgid "A team cannot play against itself."
msgstr "Une équipe ne peut pas jouer contre elle-même."
#: app/validators.py:784
msgid "Unknown game."
msgstr "Jeu inconnu."
#: app/validators.py:789
msgid "Invalid start date format."
msgstr "Format de date de début invalide."
#: app/validators.py:790
msgid "A start date is required."
msgstr "Une date de début est requise."
#: app/validators.py:796
msgid "Invalid end date format."
msgstr "Format de date de fin invalide."
#: app/validators.py:804
msgid "A tryout must allow at least one player."
msgstr "Une sélection doit accepter au moins un joueur."
#: app/validators.py:807
msgid "The player limit must be a whole number."
msgstr "La limite de joueurs doit être un nombre entier."
#: app/validators.py:819
msgid "End date cannot be before start date."
msgstr "La date de fin ne peut pas précéder la date de début."
#: app/validators.py:846 app/validators.py:847
msgid "Team name is required."
msgstr "Le nom de l’équipe est obligatoire."
#: app/validators.py:871
msgid "Scores run from 1 to 10."
msgstr "Les notes vont de 1 à 10."
#: app/validators.py:816
#: app/validators.py:872
msgid "A score must be a whole number from 1 to 10."
msgstr "Une note doit être un nombre entier de 1 à 10."
@@ -313,12 +321,12 @@ msgstr "Évaluation enregistrée."
msgid "Evaluation updated!"
msgstr "Évaluation mise à jour."
#: app/routes/evaluations.py:210 app/routes/teams.py:305
#: app/routes/teams.py:346 app/routes/teams.py:387 app/routes/teams.py:412
#: app/routes/teams.py:437 app/routes/teams.py:472 app/routes/tryouts.py:437
#: app/routes/tryouts.py:453 app/routes/tryouts.py:473
#: app/routes/tryouts.py:512 app/routes/tryouts.py:548
#: app/routes/tryouts.py:567
#: app/routes/evaluations.py:210 app/routes/teams.py:341
#: app/routes/teams.py:384 app/routes/teams.py:427 app/routes/teams.py:455
#: app/routes/teams.py:483 app/routes/teams.py:520 app/routes/tryouts.py:444
#: app/routes/tryouts.py:460 app/routes/tryouts.py:480
#: app/routes/tryouts.py:519 app/routes/tryouts.py:555
#: app/routes/tryouts.py:574
msgid "Permission denied."
msgstr "Accès refusé."
@@ -377,130 +385,130 @@ msgstr "Utilisez « Mon ou mes équipes » pour consulter vos équipes."
msgid "You do not have permission to view teams."
msgstr "Vous navez pas les droits pour consulter les équipes."
#: app/routes/teams.py:74
#: app/routes/teams.py:79
msgid "This page is for players."
msgstr "Cette page est réservée aux joueurs."
#: app/routes/teams.py:150
#: app/routes/teams.py:186
msgid "You do not have permission to create teams."
msgstr "Vous navez pas les droits pour créer une équipe."
#: app/routes/teams.py:161 app/routes/teams.py:203
#: app/routes/teams.py:197 app/routes/teams.py:239
#, python-format
msgid "Team \"%(name)s\" already exists."
msgstr "L’équipe « %(name)s » existe déjà."
#: app/routes/teams.py:182
#: app/routes/teams.py:218
#, python-format
msgid "Team \"%(name)s\" created successfully!"
msgstr "Équipe « %(name)s » créée."
#: app/routes/teams.py:192
#: app/routes/teams.py:228
msgid "You do not have permission to edit this team."
msgstr "Vous navez pas les droits pour modifier cette équipe."
#: app/routes/teams.py:236
#: app/routes/teams.py:272
#, python-format
msgid "Team \"%(name)s\" updated successfully!"
msgstr "Équipe « %(name)s » mise à jour."
#: app/routes/teams.py:264
#: app/routes/teams.py:300
msgid "You do not have permission to delete teams."
msgstr "Vous navez pas les droits pour supprimer une équipe."
#: app/routes/teams.py:295
#: app/routes/teams.py:331
#, python-format
msgid "Team \"%(name)s\" deleted successfully."
msgstr "Équipe « %(name)s » supprimée."
#: app/routes/teams.py:310
#: app/routes/teams.py:348
msgid "Please select a coach."
msgstr "Veuillez choisir un coach."
#: app/routes/teams.py:315
#: app/routes/teams.py:353
msgid "Only coaches can be assigned as coach."
msgstr "Seuls les coachs peuvent être assignés comme coach."
#: app/routes/teams.py:321
#: app/routes/teams.py:359
#, python-format
msgid "%(username)s is already a coach of %(name)s."
msgstr "%(username)s est déjà coach de %(name)s."
#: app/routes/teams.py:334
#: app/routes/teams.py:372
#, python-format
msgid "%(username)s added as coach of %(name)s."
msgstr "%(username)s a été ajouté comme coach de %(name)s."
#: app/routes/teams.py:351
#: app/routes/teams.py:391
msgid "Please select a manager."
msgstr "Veuillez choisir un gérant."
#: app/routes/teams.py:356
#: app/routes/teams.py:396
msgid "Only managers can be assigned as manager."
msgstr "Seuls les gérants peuvent être assignés comme gérant."
#: app/routes/teams.py:362
#: app/routes/teams.py:402
#, python-format
msgid "%(username)s is already a manager of %(name)s."
msgstr "%(username)s est déjà gérant de %(name)s."
#: app/routes/teams.py:375
#: app/routes/teams.py:415
#, python-format
msgid "%(username)s added as manager of %(name)s."
msgstr "%(username)s a été ajouté comme gérant de %(name)s."
#: app/routes/teams.py:402
#: app/routes/teams.py:445
#, python-format
msgid "Coach removed from %(name)s."
msgstr "Coach retiré de %(name)s."
#: app/routes/teams.py:427
#: app/routes/teams.py:473
#, python-format
msgid "Manager removed from %(name)s."
msgstr "Gérant retiré de %(name)s."
#: app/routes/teams.py:443 app/routes/tryouts.py:477 app/routes/tryouts.py:578
#: app/routes/teams.py:490 app/routes/tryouts.py:484 app/routes/tryouts.py:585
msgid "Please select a player."
msgstr "Veuillez choisir un joueur."
#: app/routes/teams.py:448
#: app/routes/teams.py:496
msgid "Can only assign players to teams."
msgstr "Seuls des joueurs peuvent être assignés à une équipe."
#: app/routes/teams.py:454
#: app/routes/teams.py:502
#, python-format
msgid "%(username)s is already on %(name)s."
msgstr "%(username)s fait déjà partie de %(name)s."
#: app/routes/teams.py:462
#: app/routes/teams.py:510
#, python-format
msgid "%(username)s added to %(name)s!"
msgstr "%(username)s a été ajouté à %(name)s."
#: app/routes/teams.py:479 app/routes/teams.py:553
#: app/routes/teams.py:527 app/routes/teams.py:601
#, python-format
msgid "%(username)s is not on %(name)s."
msgstr "%(username)s ne fait pas partie de %(name)s."
#: app/routes/teams.py:487
#: app/routes/teams.py:535
#, python-format
msgid "%(username)s removed from %(name)s."
msgstr "%(username)s a été retiré de %(name)s."
#: app/routes/teams.py:524 app/routes/teams.py:542
#: app/routes/teams.py:572 app/routes/teams.py:590
msgid "You do not have permission to add notes to this team."
msgstr "Vous navez pas les droits pour ajouter des notes à cette équipe."
#: app/routes/teams.py:532
#: app/routes/teams.py:580
msgid "Team notes added successfully!"
msgstr "Notes d’équipe ajoutées."
#: app/routes/teams.py:547 app/routes/users/notes.py:207
#: app/routes/teams.py:595 app/routes/users/notes.py:207
#: app/routes/users/notes.py:250
msgid "Can only add notes for players."
msgstr "Il nest possible dajouter des notes que pour des joueurs."
#: app/routes/teams.py:563
#: app/routes/teams.py:611
#, python-format
msgid "Note added for %(username)s!"
msgstr "Note ajoutée pour %(username)s."
@@ -529,76 +537,76 @@ msgstr "Sélection mise à jour."
msgid "You do not have permission to view this tryout."
msgstr "Vous navez pas les droits pour consulter cette sélection."
#: app/routes/tryouts.py:404
#: app/routes/tryouts.py:411
msgid "Only players can register for tryouts."
msgstr "Seuls les joueurs peuvent sinscrire à une sélection."
#: app/routes/tryouts.py:408
#: app/routes/tryouts.py:415
msgid "This tryout is not accepting registrations."
msgstr "Cette sélection naccepte pas dinscriptions."
#: app/routes/tryouts.py:415
#: app/routes/tryouts.py:422
msgid "You are already registered for this tryout."
msgstr "Vous êtes déjà inscrit à cette sélection."
#: app/routes/tryouts.py:421 app/routes/tryouts.py:496
#: app/routes/tryouts.py:428 app/routes/tryouts.py:503
msgid "This tryout is full."
msgstr "Cette sélection est complète."
#: app/routes/tryouts.py:427
#: app/routes/tryouts.py:434
msgid "Successfully registered for tryout!"
msgstr "Inscription à la sélection réussie."
#: app/routes/tryouts.py:443
#: app/routes/tryouts.py:450
#, python-format
msgid "Tryout status updated to %(new_status)s."
msgstr "Statut de la sélection mis à jour : %(new_status)s."
#: app/routes/tryouts.py:463
#: app/routes/tryouts.py:470
msgid "Registration status updated."
msgstr "Statut dinscription mis à jour."
#: app/routes/tryouts.py:482
#: app/routes/tryouts.py:489
msgid "Can only register players."
msgstr "Seuls des joueurs peuvent être inscrits."
#: app/routes/tryouts.py:488
#: app/routes/tryouts.py:495
#, python-format
msgid "%(username)s is already registered for this tryout."
msgstr "%(username)s est déjà inscrit à cette sélection."
#: app/routes/tryouts.py:502
#: app/routes/tryouts.py:509
#, python-format
msgid "%(username)s registered for tryout!"
msgstr "%(username)s est inscrit à la sélection."
#: app/routes/tryouts.py:538
#: app/routes/tryouts.py:545
#, python-format
msgid "%(username)s removed from tryout."
msgstr "%(username)s a été retiré de la sélection."
#: app/routes/tryouts.py:556
#: app/routes/tryouts.py:563
#, python-format
msgid "Team \"%(team_name)s\" created!"
msgstr "Équipe « %(team_name)s » créée."
#: app/routes/tryouts.py:587
#: app/routes/tryouts.py:594
msgid "That player is not registered for this tryout."
msgstr "Ce joueur nest pas inscrit à cette sélection."
#: app/routes/tryouts.py:593
#: app/routes/tryouts.py:600
msgid "Player is already on this team."
msgstr "Ce joueur est déjà dans cette équipe."
#: app/routes/tryouts.py:598
#: app/routes/tryouts.py:605
msgid "Player added to team!"
msgstr "Joueur ajouté à l’équipe."
#: app/routes/tryouts.py:608
#: app/routes/tryouts.py:615
msgid "You do not have permission to delete this tryout."
msgstr "Vous navez pas les droits pour supprimer cette sélection."
#: app/routes/tryouts.py:644
#: app/routes/tryouts.py:651
msgid "Tryout deleted successfully."
msgstr "Sélection supprimée."