fix(security): verifier les fichiers televerses et retirer un intent Discord
SEC-021 -- rien ne validait le contrat signe upload_signed_contract se contentait d un nom de fichier non vide. ALLOWED_SIGNED_EXTENSIONS etait declaree juste a cote et jamais lue. Le fichier atterrissait sur le disque sous un nom que download_signed_contract sert ensuite : ce qu un joueur televerse est ce qu un gerant ouvre. Le nom seul ne suffisait pas non plus cote upload_contract, qui verifiait `.pdf` en fin de chaine -- payload.pdf ne dit rien des octets. pdf_upload_error() couvre les deux routes : extension dans la liste, puis signature %PDF- en tete de flux. Le flux est rembobine, l appelant enregistre toujours le fichier entier. OPS-014 -- intent Discord privilegie inutile Le bot demandait GUILD_MEMBERS et ne s en servait pas : rien n enumere ni ne recherche de membre de serveur, les personnes sont jointes par le discord_user_id enregistre sur leur compte. Retire. message_content reste : on_raw_reaction_add lit le texte de la reponse d un coach pour consigner un motif de refus. CI-003 et CI-005 sont deja appliques (permissions: contents: read, checkout@v4, exclusions de deploiement). L epinglage par SHA des actions n est pas fait : ce sont des actions GitHub de premiere partie, et l epingler sans Dependabot echange une exposition contre une autre. 11 tests, dont deux verifient que signer un contrat marche toujours et qu un autre joueur ne peut pas le faire. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -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-08 14:58-0400\n"
|
||||
"POT-Creation-Date: 2026-08-08 15:07-0400\n"
|
||||
"PO-Revision-Date: 2026-08-07 20:22-0400\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
@@ -100,22 +100,22 @@ msgstr "Points must be 2000 characters or less."
|
||||
msgid "Day must be 0 (Monday) to 6 (Sunday)."
|
||||
msgstr "Day must be 0 (Monday) to 6 (Sunday)."
|
||||
|
||||
#: app/routes/auth.py:169 app/routes/auth.py:297 app/routes/users.py:49
|
||||
#: app/routes/users.py:653
|
||||
#: app/routes/auth.py:186 app/routes/auth.py:314 app/routes/users.py:83
|
||||
#: app/routes/users.py:687
|
||||
#, python-format
|
||||
msgid "%(field)s: %(msg)s"
|
||||
msgstr "%(field)s: %(msg)s"
|
||||
|
||||
#: app/routes/auth.py:187
|
||||
#: app/routes/auth.py:204
|
||||
msgid "This account has been deactivated."
|
||||
msgstr "This account has been deactivated."
|
||||
|
||||
#: app/routes/auth.py:225
|
||||
#: app/routes/auth.py:242
|
||||
#, python-format
|
||||
msgid "Welcome back, %(username)s!"
|
||||
msgstr "Welcome back, %(username)s!"
|
||||
|
||||
#: app/routes/auth.py:246
|
||||
#: app/routes/auth.py:263
|
||||
msgid ""
|
||||
"Login unsuccessful. Please check your username and password, or ask a "
|
||||
"president for help."
|
||||
@@ -123,27 +123,27 @@ msgstr ""
|
||||
"Login unsuccessful. Please check your username and password, or ask a "
|
||||
"president for help."
|
||||
|
||||
#: app/routes/auth.py:278
|
||||
#: app/routes/auth.py:295
|
||||
msgid "Incorrect CAPTCHA answer. Please try again."
|
||||
msgstr "Incorrect CAPTCHA answer. Please try again."
|
||||
|
||||
#: app/routes/auth.py:320 app/routes/users.py:336
|
||||
#: app/routes/auth.py:337 app/routes/users.py:370
|
||||
msgid "Username already exists."
|
||||
msgstr "Username already exists."
|
||||
|
||||
#: app/routes/auth.py:332 app/routes/users.py:340
|
||||
#: app/routes/auth.py:349 app/routes/users.py:374
|
||||
msgid "Email already registered."
|
||||
msgstr "Email already registered."
|
||||
|
||||
#: app/routes/auth.py:378
|
||||
#: app/routes/auth.py:395
|
||||
msgid "Your account has been created! You can now log in."
|
||||
msgstr "Your account has been created! You can now log in."
|
||||
|
||||
#: app/routes/auth.py:404
|
||||
#: app/routes/auth.py:421
|
||||
msgid "Discord OAuth2 is not configured."
|
||||
msgstr "Discord OAuth2 is not configured."
|
||||
|
||||
#: app/routes/auth.py:444
|
||||
#: app/routes/auth.py:461
|
||||
msgid ""
|
||||
"Discord authorization could not be verified. Please start the connection "
|
||||
"again from this page."
|
||||
@@ -151,27 +151,27 @@ msgstr ""
|
||||
"Discord authorization could not be verified. Please start the connection "
|
||||
"again from this page."
|
||||
|
||||
#: app/routes/auth.py:452
|
||||
#: app/routes/auth.py:469
|
||||
msgid "Discord authorization failed. No code received."
|
||||
msgstr "Discord authorization failed. No code received."
|
||||
|
||||
#: app/routes/auth.py:476
|
||||
#: app/routes/auth.py:493
|
||||
msgid "Failed to connect to Discord. Please try again."
|
||||
msgstr "Failed to connect to Discord. Please try again."
|
||||
|
||||
#: app/routes/auth.py:480
|
||||
#: app/routes/auth.py:497
|
||||
msgid "Failed to obtain Discord access token."
|
||||
msgstr "Failed to obtain Discord access token."
|
||||
|
||||
#: app/routes/auth.py:495
|
||||
#: app/routes/auth.py:512
|
||||
msgid "Failed to fetch Discord user profile."
|
||||
msgstr "Failed to fetch Discord user profile."
|
||||
|
||||
#: app/routes/auth.py:542
|
||||
#: app/routes/auth.py:559
|
||||
msgid "Discord account connected! Your profile has been pre-filled."
|
||||
msgstr "Discord account connected! Your profile has been pre-filled."
|
||||
|
||||
#: app/routes/auth.py:565
|
||||
#: app/routes/auth.py:587
|
||||
msgid "You have been logged out."
|
||||
msgstr "You have been logged out."
|
||||
|
||||
@@ -408,7 +408,7 @@ msgstr "You do not have permission to add notes to this team."
|
||||
msgid "Team notes added successfully!"
|
||||
msgstr "Team notes added successfully!"
|
||||
|
||||
#: app/routes/teams.py:444 app/routes/users.py:1241 app/routes/users.py:1283
|
||||
#: app/routes/teams.py:444 app/routes/users.py:1266 app/routes/users.py:1308
|
||||
msgid "Can only add notes for players."
|
||||
msgstr "Can only add notes for players."
|
||||
|
||||
@@ -526,23 +526,35 @@ msgstr "You do not have permission to delete this tryout."
|
||||
msgid "Tryout deleted successfully."
|
||||
msgstr "Tryout deleted successfully."
|
||||
|
||||
#: app/routes/users.py:119
|
||||
#: app/routes/users.py:61
|
||||
msgid "No file selected."
|
||||
msgstr "No file selected."
|
||||
|
||||
#: app/routes/users.py:65
|
||||
msgid "Only PDF files are allowed for contracts."
|
||||
msgstr "Only PDF files are allowed for contracts."
|
||||
|
||||
#: app/routes/users.py:70
|
||||
msgid "That file is not a PDF, whatever its name says."
|
||||
msgstr "That file is not a PDF, whatever its name says."
|
||||
|
||||
#: app/routes/users.py:153
|
||||
msgid "Only the president can manage users."
|
||||
msgstr "Only the president can manage users."
|
||||
|
||||
#: app/routes/users.py:131
|
||||
#: app/routes/users.py:165
|
||||
msgid "Only the president can edit users."
|
||||
msgstr "Only the president can edit users."
|
||||
|
||||
#: app/routes/users.py:168
|
||||
#: app/routes/users.py:202
|
||||
msgid "Email already in use by another account."
|
||||
msgstr "Email already in use by another account."
|
||||
|
||||
#: app/routes/users.py:178
|
||||
#: app/routes/users.py:212
|
||||
msgid "You cannot change your own role. Ask another president to do it."
|
||||
msgstr "You cannot change your own role. Ask another president to do it."
|
||||
|
||||
#: app/routes/users.py:189
|
||||
#: app/routes/users.py:223
|
||||
msgid ""
|
||||
"This is the last active president. Promote another account before "
|
||||
"changing this one."
|
||||
@@ -550,181 +562,172 @@ msgstr ""
|
||||
"This is the last active president. Promote another account before "
|
||||
"changing this one."
|
||||
|
||||
#: app/routes/users.py:251
|
||||
#: app/routes/users.py:285
|
||||
#, python-format
|
||||
msgid "User %(username)s updated successfully!"
|
||||
msgstr "User %(username)s updated successfully!"
|
||||
|
||||
#: app/routes/users.py:266
|
||||
#: app/routes/users.py:300
|
||||
msgid "Only the president can delete users."
|
||||
msgstr "Only the president can delete users."
|
||||
|
||||
#: app/routes/users.py:270
|
||||
#: app/routes/users.py:304
|
||||
msgid "You cannot delete your own account."
|
||||
msgstr "You cannot delete your own account."
|
||||
|
||||
#: app/routes/users.py:307
|
||||
#: app/routes/users.py:341
|
||||
#, python-format
|
||||
msgid "User %(deleted_username)s has been removed."
|
||||
msgstr "User %(deleted_username)s has been removed."
|
||||
|
||||
#: app/routes/users.py:316
|
||||
#: app/routes/users.py:350
|
||||
msgid "Only the president can create users."
|
||||
msgstr "Only the president can create users."
|
||||
|
||||
#: app/routes/users.py:355
|
||||
#: app/routes/users.py:389
|
||||
#, python-format
|
||||
msgid "User %(full_name)s created as %(role)s!"
|
||||
msgstr "User %(full_name)s created as %(role)s!"
|
||||
|
||||
#: app/routes/users.py:412
|
||||
#: app/routes/users.py:446
|
||||
msgid "Username already taken."
|
||||
msgstr "Username already taken."
|
||||
|
||||
#: app/routes/users.py:418
|
||||
#: app/routes/users.py:452
|
||||
msgid "Email already in use."
|
||||
msgstr "Email already in use."
|
||||
|
||||
#: app/routes/users.py:443
|
||||
#: app/routes/users.py:477
|
||||
msgid "Profile updated successfully!"
|
||||
msgstr "Profile updated successfully!"
|
||||
|
||||
#: app/routes/users.py:641
|
||||
#: app/routes/users.py:675
|
||||
msgid "Only presidents, managers, and coaches can upload contracts."
|
||||
msgstr "Only presidents, managers, and coaches can upload contracts."
|
||||
|
||||
#: app/routes/users.py:660
|
||||
#: app/routes/users.py:694
|
||||
msgid "You do not have permission to upload a contract for this player."
|
||||
msgstr "You do not have permission to upload a contract for this player."
|
||||
|
||||
#: app/routes/users.py:664 app/routes/users.py:669 app/routes/users.py:721
|
||||
#: app/routes/users.py:726
|
||||
msgid "No file selected."
|
||||
msgstr "No file selected."
|
||||
|
||||
#: app/routes/users.py:672
|
||||
msgid "Only PDF files are allowed for contracts."
|
||||
msgstr "Only PDF files are allowed for contracts."
|
||||
|
||||
#: app/routes/users.py:705
|
||||
#: app/routes/users.py:733
|
||||
#, python-format
|
||||
msgid "Contract uploaded successfully for %(username)s!"
|
||||
msgstr "Contract uploaded successfully for %(username)s!"
|
||||
|
||||
#: app/routes/users.py:717
|
||||
#: app/routes/users.py:745
|
||||
msgid "Only the player can upload their signed contract."
|
||||
msgstr "Only the player can upload their signed contract."
|
||||
|
||||
#: app/routes/users.py:737
|
||||
#: app/routes/users.py:762
|
||||
msgid "Signed contract uploaded successfully!"
|
||||
msgstr "Signed contract uploaded successfully!"
|
||||
|
||||
#: app/routes/users.py:747 app/routes/users.py:758
|
||||
#: app/routes/users.py:772 app/routes/users.py:783
|
||||
msgid "You do not have permission to download this contract."
|
||||
msgstr "You do not have permission to download this contract."
|
||||
|
||||
#: app/routes/users.py:761
|
||||
#: app/routes/users.py:786
|
||||
msgid "No signed contract available."
|
||||
msgstr "No signed contract available."
|
||||
|
||||
#: app/routes/users.py:828
|
||||
#: app/routes/users.py:853
|
||||
msgid "Only players can request One on One sessions."
|
||||
msgstr "Only players can request One on One sessions."
|
||||
|
||||
#: app/routes/users.py:841
|
||||
#: app/routes/users.py:866
|
||||
msgid "You do not have a coach assigned to your team."
|
||||
msgstr "You do not have a coach assigned to your team."
|
||||
|
||||
#: app/routes/users.py:868
|
||||
#: app/routes/users.py:893
|
||||
msgid "Cannot request One on One - no coach assigned."
|
||||
msgstr "Cannot request One on One - no coach assigned."
|
||||
|
||||
#: app/routes/users.py:876
|
||||
#: app/routes/users.py:901
|
||||
msgid "Invalid date or time format."
|
||||
msgstr "Invalid date or time format."
|
||||
|
||||
#: app/routes/users.py:890
|
||||
#: app/routes/users.py:915
|
||||
msgid "The requested time is not within the coach's availability."
|
||||
msgstr "The requested time is not within the coach's availability."
|
||||
|
||||
#: app/routes/users.py:913
|
||||
#: app/routes/users.py:938
|
||||
msgid "Your One on One request has been submitted!"
|
||||
msgstr "Your One on One request has been submitted!"
|
||||
|
||||
#: app/routes/users.py:948
|
||||
#: app/routes/users.py:973
|
||||
msgid "Only coaches can accept One on One requests."
|
||||
msgstr "Only coaches can accept One on One requests."
|
||||
|
||||
#: app/routes/users.py:954 app/routes/users.py:995
|
||||
#: app/routes/users.py:979 app/routes/users.py:1020
|
||||
msgid "This request is not for you."
|
||||
msgstr "This request is not for you."
|
||||
|
||||
#: app/routes/users.py:958 app/routes/users.py:999
|
||||
#: app/routes/users.py:983 app/routes/users.py:1024
|
||||
msgid "This request has already been processed."
|
||||
msgstr "This request has already been processed."
|
||||
|
||||
#: app/routes/users.py:980
|
||||
#: app/routes/users.py:1005
|
||||
#, python-format
|
||||
msgid "One on One request from %(player)s has been approved!"
|
||||
msgstr "One on One request from %(player)s has been approved!"
|
||||
|
||||
#: app/routes/users.py:989
|
||||
#: app/routes/users.py:1014
|
||||
msgid "Only coaches can reject One on One requests."
|
||||
msgstr "Only coaches can reject One on One requests."
|
||||
|
||||
#: app/routes/users.py:1026
|
||||
#: app/routes/users.py:1051
|
||||
#, python-format
|
||||
msgid "One on One request from %(player)s has been rejected."
|
||||
msgstr "One on One request from %(player)s has been rejected."
|
||||
|
||||
#: app/routes/users.py:1039
|
||||
#: app/routes/users.py:1064
|
||||
msgid "This page is for players only."
|
||||
msgstr "This page is for players only."
|
||||
|
||||
#: app/routes/users.py:1070
|
||||
#: app/routes/users.py:1095
|
||||
msgid "Only coaches can manage availability."
|
||||
msgstr "Only coaches can manage availability."
|
||||
|
||||
#: app/routes/users.py:1132
|
||||
#: app/routes/users.py:1157
|
||||
msgid "Only coaches can access the notes dashboard."
|
||||
msgstr "Only coaches can access the notes dashboard."
|
||||
|
||||
#: app/routes/users.py:1196
|
||||
#: app/routes/users.py:1221
|
||||
msgid "Only coaches can manage team notes."
|
||||
msgstr "Only coaches can manage team notes."
|
||||
|
||||
#: app/routes/users.py:1202
|
||||
#: app/routes/users.py:1227
|
||||
msgid "You are not assigned to a team."
|
||||
msgstr "You are not assigned to a team."
|
||||
|
||||
#: app/routes/users.py:1215
|
||||
#: app/routes/users.py:1240
|
||||
msgid "Team notes saved successfully!"
|
||||
msgstr "Team notes saved successfully!"
|
||||
|
||||
#: app/routes/users.py:1229
|
||||
#: app/routes/users.py:1254
|
||||
msgid "Only coaches can manage personal notes."
|
||||
msgstr "Only coaches can manage personal notes."
|
||||
|
||||
#: app/routes/users.py:1236 app/routes/users.py:1278 app/routes/users.py:1328
|
||||
#: app/routes/users.py:1379
|
||||
#: app/routes/users.py:1261 app/routes/users.py:1303 app/routes/users.py:1353
|
||||
#: app/routes/users.py:1404
|
||||
msgid "Player and content are required."
|
||||
msgstr "Player and content are required."
|
||||
|
||||
#: app/routes/users.py:1245 app/routes/users.py:1287 app/routes/users.py:1332
|
||||
#: app/routes/users.py:1383
|
||||
#: app/routes/users.py:1270 app/routes/users.py:1312 app/routes/users.py:1357
|
||||
#: app/routes/users.py:1408
|
||||
msgid "You can only write notes about players you work with."
|
||||
msgstr "You can only write notes about players you work with."
|
||||
|
||||
#: app/routes/users.py:1255 app/routes/users.py:1300
|
||||
#: app/routes/users.py:1280 app/routes/users.py:1325
|
||||
#, python-format
|
||||
msgid "Note added for %(username)s."
|
||||
msgstr "Note added for %(username)s."
|
||||
|
||||
#: app/routes/users.py:1268 app/routes/users.py:1313 app/routes/users.py:1363
|
||||
#: app/routes/users.py:1293 app/routes/users.py:1338 app/routes/users.py:1388
|
||||
msgid "Only coaches can add personal notes."
|
||||
msgstr "Only coaches can add personal notes."
|
||||
|
||||
#: app/routes/users.py:1343 app/routes/users.py:1394
|
||||
#: app/routes/users.py:1368 app/routes/users.py:1419
|
||||
msgid "Note added successfully."
|
||||
msgstr "Note added successfully."
|
||||
|
||||
@@ -845,7 +848,7 @@ msgstr "Try Again"
|
||||
msgid "Language"
|
||||
msgstr "Language"
|
||||
|
||||
#: app/templates/layouts/base.html:33 app/templates/layouts/base.html:133
|
||||
#: app/templates/layouts/base.html:33 app/templates/layouts/base.html:139
|
||||
#: app/templates/pages/dashboard.html:2 app/templates/pages/dashboard.html:3
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
@@ -904,19 +907,19 @@ msgstr "Contracts"
|
||||
msgid "My Profile"
|
||||
msgstr "My Profile"
|
||||
|
||||
#: app/templates/layouts/base.html:117
|
||||
#: app/templates/layouts/base.html:122
|
||||
msgid "Logout"
|
||||
msgstr "Logout"
|
||||
|
||||
#: app/templates/layouts/base.html:137
|
||||
#: app/templates/layouts/base.html:143
|
||||
msgid "Toggle dark mode"
|
||||
msgstr "Toggle dark mode"
|
||||
|
||||
#: app/templates/layouts/base.html:149 app/templates/layouts/base.html:168
|
||||
#: app/templates/layouts/base.html:155 app/templates/layouts/base.html:174
|
||||
msgid "Dismiss"
|
||||
msgstr "Dismiss"
|
||||
|
||||
#: app/templates/layouts/base.html:178
|
||||
#: app/templates/layouts/base.html:184
|
||||
msgid "Team Tryout Management System"
|
||||
msgstr "Team Tryout Management System"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user