From cc5df9b171561d8205dd2753a2511952283a1ece Mon Sep 17 00:00:00 2001 From: Sli Date: Tue, 27 Aug 2024 17:05:37 +0200 Subject: [PATCH 1/9] Better form for user submiting images, fix potential attack vector on bad file being resized and treated as an image --- core/templates/core/user_edit.jinja | 1 + core/views/forms.py | 37 ++-- locale/fr/LC_MESSAGES/django.po | 312 ++++++++++++++-------------- 3 files changed, 179 insertions(+), 171 deletions(-) diff --git a/core/templates/core/user_edit.jinja b/core/templates/core/user_edit.jinja index 69df1778..37acfbe7 100644 --- a/core/templates/core/user_edit.jinja +++ b/core/templates/core/user_edit.jinja @@ -61,6 +61,7 @@

{{ form[field_name].label }}

+ {{ form[field_name].errors }} {%- else -%} {% trans %}To edit your profile picture, ask a member of the AE{% endtrans %} {%- endif -%} diff --git a/core/views/forms.py b/core/views/forms.py index 9f565529..baf6b20e 100644 --- a/core/views/forms.py +++ b/core/views/forms.py @@ -201,10 +201,7 @@ class RegisteringForm(UserCreationForm): class UserProfileForm(forms.ModelForm): - """Form handling the user profile, managing the files - This form is actually pretty bad and was made in the rush before the migration. It should be refactored. - TODO: refactor this form. - """ + """Form handling the user profile, managing the files""" class Meta: model = User @@ -237,25 +234,35 @@ class UserProfileForm(forms.ModelForm): ] widgets = { "date_of_birth": SelectDate, - "profile_pict": forms.ClearableFileInput, - "avatar_pict": forms.ClearableFileInput, - "scrub_pict": forms.ClearableFileInput, "phone": RegionalPhoneNumberWidget, "parent_phone": RegionalPhoneNumberWidget, "quote": forms.Textarea, } - labels = { - "profile_pict": _( - "Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)" - ), - "avatar_pict": _("Avatar: used on the forum"), - "scrub_pict": _("Scrub: let other know how your scrub looks like!"), - } def generate_name(self, field_name, f): field_name = field_name[:-4] return field_name + str(self.instance.id) + "." + f.content_type.split("/")[-1] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Image fields are injected here to override the file field provided by the model + # This would be better if we could have a SithImage sort of model input instead of a generic SithFile + self.fields["profile_pict"] = forms.ImageField( + required=False, + label=_( + "Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)" + ), + ) + self.fields["avatar_pict"] = forms.ImageField( + required=False, + label=_("Avatar: used on the forum"), + ) + self.fields["scrub_pict"] = forms.ImageField( + required=False, + label=_("Scrub: let other know how your scrub looks like!"), + ) + def process(self, files): avatar = self.instance.avatar_pict profile = self.instance.profile_pict @@ -305,7 +312,7 @@ class UserProfileForm(forms.ModelForm): % { "file_name": f, "msg": _( - "Bad image format, only jpeg, png, and gif are accepted" + "Bad image format, only jpeg, png, webp and gif are accepted" ), }, ) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 313807bd..e27b63b8 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-08-21 15:30+0200\n" +"POT-Creation-Date: 2024-08-27 17:02+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -219,7 +219,7 @@ msgstr "Compte" msgid "Company" msgstr "Entreprise" -#: accounting/models.py:312 core/models.py:311 sith/settings.py:404 +#: accounting/models.py:312 core/models.py:311 sith/settings.py:413 #: stock/templates/stock/shopping_list_items.jinja:37 msgid "Other" msgstr "Autre" @@ -370,17 +370,17 @@ msgstr "Compte en banque : " #: core/templates/core/user_account_detail.jinja:66 #: core/templates/core/user_clubs.jinja:34 #: core/templates/core/user_clubs.jinja:63 -#: core/templates/core/user_edit.jinja:53 +#: core/templates/core/user_edit.jinja:57 #: core/templates/core/user_preferences.jinja:48 #: counter/templates/counter/last_ops.jinja:35 #: counter/templates/counter/last_ops.jinja:65 #: election/templates/election/election_detail.jinja:187 #: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:134 #: launderette/templates/launderette/launderette_admin.jinja:16 -#: launderette/views.py:217 pedagogy/templates/pedagogy/guide.jinja:95 -#: pedagogy/templates/pedagogy/guide.jinja:110 +#: launderette/views.py:217 pedagogy/templates/pedagogy/guide.jinja:96 +#: pedagogy/templates/pedagogy/guide.jinja:111 #: pedagogy/templates/pedagogy/uv_detail.jinja:185 -#: sas/templates/sas/album.jinja:32 sas/templates/sas/moderation.jinja:18 +#: sas/templates/sas/album.jinja:33 sas/templates/sas/moderation.jinja:18 #: sas/templates/sas/picture.jinja:48 #: stock/templates/stock/stock_shopping_list.jinja:43 #: stock/templates/stock/stock_shopping_list.jinja:69 @@ -433,10 +433,10 @@ msgstr "Nouveau compte club" #: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62 #: forum/templates/forum/macros.jinja:128 #: launderette/templates/launderette/launderette_list.jinja:16 -#: pedagogy/templates/pedagogy/guide.jinja:94 -#: pedagogy/templates/pedagogy/guide.jinja:109 +#: pedagogy/templates/pedagogy/guide.jinja:95 +#: pedagogy/templates/pedagogy/guide.jinja:110 #: pedagogy/templates/pedagogy/uv_detail.jinja:184 -#: sas/templates/sas/album.jinja:31 trombi/templates/trombi/detail.jinja:9 +#: sas/templates/sas/album.jinja:32 trombi/templates/trombi/detail.jinja:9 #: trombi/templates/trombi/edit_profile.jinja:34 msgid "Edit" msgstr "Éditer" @@ -526,7 +526,7 @@ msgid "Effective amount" msgstr "Montant effectif" #: accounting/templates/accounting/club_account_details.jinja:36 -#: sith/settings.py:450 +#: sith/settings.py:459 msgid "Closed" msgstr "Fermé" @@ -1162,7 +1162,7 @@ msgid "There are no members in this club." msgstr "Il n'y a pas de membres dans ce club." #: club/templates/club/club_members.jinja:80 -#: core/templates/core/file_detail.jinja:19 core/views/forms.py:332 +#: core/templates/core/file_detail.jinja:19 core/views/forms.py:339 #: launderette/views.py:217 trombi/templates/trombi/detail.jinja:19 msgid "Add" msgstr "Ajouter" @@ -1587,7 +1587,7 @@ msgstr "Type" #: com/templates/com/weekmail.jinja:19 com/templates/com/weekmail.jinja:48 #: forum/templates/forum/forum.jinja:28 forum/templates/forum/forum.jinja:47 #: forum/templates/forum/main.jinja:30 forum/views.py:246 -#: pedagogy/templates/pedagogy/guide.jinja:88 +#: pedagogy/templates/pedagogy/guide.jinja:89 msgid "Title" msgstr "Titre" @@ -2387,7 +2387,7 @@ msgstr "403, Non autorisé" msgid "404, Not Found" msgstr "404. Non trouvé" -#: core/templates/core/500.jinja:12 +#: core/templates/core/500.jinja:11 msgid "500, Server Error" msgstr "500, Erreur Serveur" @@ -2479,7 +2479,7 @@ msgstr "Photos" #: eboutic/templates/eboutic/eboutic_main.jinja:22 #: eboutic/templates/eboutic/eboutic_makecommand.jinja:16 #: eboutic/templates/eboutic/eboutic_payment_result.jinja:4 -#: sith/settings.py:403 sith/settings.py:411 +#: sith/settings.py:412 sith/settings.py:420 msgid "Eboutic" msgstr "Eboutic" @@ -2621,20 +2621,20 @@ msgstr "Propriétés" msgid "Owner: " msgstr "Propriétaire : " -#: core/templates/core/file_detail.jinja:26 sas/templates/sas/album.jinja:46 +#: core/templates/core/file_detail.jinja:26 sas/templates/sas/album.jinja:47 #: sas/templates/sas/main.jinja:49 msgid "Clear clipboard" msgstr "Vider le presse-papier" -#: core/templates/core/file_detail.jinja:27 sas/templates/sas/album.jinja:33 +#: core/templates/core/file_detail.jinja:27 sas/templates/sas/album.jinja:34 msgid "Cut" msgstr "Couper" -#: core/templates/core/file_detail.jinja:28 sas/templates/sas/album.jinja:34 +#: core/templates/core/file_detail.jinja:28 sas/templates/sas/album.jinja:35 msgid "Paste" msgstr "Coller" -#: core/templates/core/file_detail.jinja:31 sas/templates/sas/album.jinja:40 +#: core/templates/core/file_detail.jinja:31 sas/templates/sas/album.jinja:41 #: sas/templates/sas/main.jinja:43 msgid "Clipboard: " msgstr "Presse-papier : " @@ -2696,7 +2696,7 @@ msgid "Edit group" msgstr "Éditer le groupe" #: core/templates/core/group_edit.jinja:9 -#: core/templates/core/user_edit.jinja:235 +#: core/templates/core/user_edit.jinja:268 #: core/templates/core/user_group.jinja:13 #: pedagogy/templates/pedagogy/uv_edit.jinja:36 msgid "Update" @@ -2771,23 +2771,23 @@ msgstr "Créneau" msgid "Tokens" msgstr "Jetons" -#: core/templates/core/macros.jinja:123 core/templates/core/macros.jinja:125 +#: core/templates/core/macros.jinja:163 core/templates/core/macros.jinja:165 msgid "Previous" msgstr "Précédent" -#: core/templates/core/macros.jinja:129 +#: core/templates/core/macros.jinja:169 msgid "current" msgstr "actuel" -#: core/templates/core/macros.jinja:135 core/templates/core/macros.jinja:137 +#: core/templates/core/macros.jinja:175 core/templates/core/macros.jinja:177 msgid "Next" msgstr "Suivant" -#: core/templates/core/macros.jinja:153 +#: core/templates/core/macros.jinja:193 msgid "Select All" msgstr "Tout sélectionner" -#: core/templates/core/macros.jinja:154 +#: core/templates/core/macros.jinja:194 msgid "Unselect All" msgstr "Tout désélectionner" @@ -3194,31 +3194,31 @@ msgstr "Activer la caméra" msgid "Take a picture" msgstr "Prendre une photo" -#: core/templates/core/user_edit.jinja:60 +#: core/templates/core/user_edit.jinja:64 msgid "To edit your profile picture, ask a member of the AE" msgstr "Pour changer votre photo de profil, demandez à un membre de l'AE" -#: core/templates/core/user_edit.jinja:142 +#: core/templates/core/user_edit.jinja:173 msgid "captured" msgstr "capturé" -#: core/templates/core/user_edit.jinja:163 +#: core/templates/core/user_edit.jinja:196 msgid "Edit user profile" msgstr "Éditer le profil de l'utilisateur" -#: core/templates/core/user_edit.jinja:225 +#: core/templates/core/user_edit.jinja:258 msgid "Change my password" msgstr "Changer mon mot de passe" -#: core/templates/core/user_edit.jinja:230 +#: core/templates/core/user_edit.jinja:263 msgid "Change user password" msgstr "Changer le mot de passe" -#: core/templates/core/user_edit.jinja:240 +#: core/templates/core/user_edit.jinja:273 msgid "Username:" msgstr "Nom d'utilisateur : " -#: core/templates/core/user_edit.jinja:243 +#: core/templates/core/user_edit.jinja:276 msgid "Account number:" msgstr "Numéro de compte : " @@ -3308,12 +3308,12 @@ msgstr "Photos de %(user_name)s" msgid "Download all my pictures" msgstr "Télécharger toutes mes photos" -#: core/templates/core/user_pictures.jinja:49 sas/templates/sas/album.jinja:74 +#: core/templates/core/user_pictures.jinja:49 sas/templates/sas/album.jinja:75 #: sas/templates/sas/macros.jinja:16 msgid "To be moderated" msgstr "A modérer" -#: core/templates/core/user_pictures.jinja:130 +#: core/templates/core/user_pictures.jinja:136 msgid "pictures" msgstr "photos" @@ -3508,12 +3508,12 @@ msgid "Moderate pictures" msgstr "Modérer les photos" #: core/templates/core/user_tools.jinja:173 -#: pedagogy/templates/pedagogy/guide.jinja:21 +#: pedagogy/templates/pedagogy/guide.jinja:22 msgid "Create UV" msgstr "Créer UV" #: core/templates/core/user_tools.jinja:174 -#: pedagogy/templates/pedagogy/guide.jinja:24 +#: pedagogy/templates/pedagogy/guide.jinja:25 #: trombi/templates/trombi/detail.jinja:10 msgid "Moderate comments" msgstr "Modérer les commentaires" @@ -3538,7 +3538,7 @@ msgstr "Autres outils" msgid "Trombi tools" msgstr "Outils Trombi" -#: core/templatetags/renderer.py:84 +#: core/templatetags/renderer.py:89 #, python-format msgid "%(nb_days)d day, %(remainder)s" msgid_plural "%(nb_days)d days, %(remainder)s" @@ -3554,7 +3554,7 @@ msgstr "Ajouter un nouveau dossier" msgid "Error creating folder %(folder_name)s: %(msg)s" msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" -#: core/views/files.py:154 core/views/forms.py:297 core/views/forms.py:304 +#: core/views/files.py:154 core/views/forms.py:304 core/views/forms.py:311 #: sas/views.py:81 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" @@ -3652,7 +3652,7 @@ msgstr "Choisir un utilisateur" msgid "Username, email, or account number" msgstr "Nom d'utilisateur, email, ou numéro de compte AE" -#: core/views/forms.py:249 +#: core/views/forms.py:254 msgid "" "Profile: you need to be visible on the picture, in order to be recognized (e." "g. by the barmen)" @@ -3660,36 +3660,36 @@ msgstr "" "Photo de profil: vous devez être visible sur la photo afin d'être reconnu " "(par exemple par les barmen)" -#: core/views/forms.py:251 +#: core/views/forms.py:259 msgid "Avatar: used on the forum" msgstr "Avatar : utilisé sur le forum" -#: core/views/forms.py:252 +#: core/views/forms.py:263 msgid "Scrub: let other know how your scrub looks like!" msgstr "Blouse : montrez aux autres à quoi ressemble votre blouse !" -#: core/views/forms.py:308 -msgid "Bad image format, only jpeg, png, and gif are accepted" -msgstr "Mauvais format d'image, seuls les jpeg, png, et gif sont acceptés" +#: core/views/forms.py:315 +msgid "Bad image format, only jpeg, png, webp and gif are accepted" +msgstr "Mauvais format d'image, seuls les jpeg, png, webp et gif sont acceptés" -#: core/views/forms.py:329 +#: core/views/forms.py:336 msgid "Godfather / Godmother" msgstr "Parrain / Marraine" -#: core/views/forms.py:330 +#: core/views/forms.py:337 msgid "Godchild" msgstr "Fillot / Fillote" -#: core/views/forms.py:335 counter/forms.py:67 trombi/views.py:149 +#: core/views/forms.py:342 counter/forms.py:67 trombi/views.py:149 msgid "Select user" msgstr "Choisir un utilisateur" -#: core/views/forms.py:348 core/views/forms.py:366 election/models.py:22 +#: core/views/forms.py:355 core/views/forms.py:373 election/models.py:22 #: election/views.py:147 msgid "edit groups" msgstr "groupe d'édition" -#: core/views/forms.py:351 core/views/forms.py:369 election/models.py:29 +#: core/views/forms.py:358 core/views/forms.py:376 election/models.py:29 #: election/views.py:150 msgid "view groups" msgstr "groupe de vue" @@ -3710,7 +3710,7 @@ msgstr "Nous n'avons pas réussi à vérifier que cette adresse mail existe." msgid "Family" msgstr "Famille" -#: core/views/user.py:207 sas/templates/sas/album.jinja:63 +#: core/views/user.py:207 sas/templates/sas/album.jinja:64 #: trombi/templates/trombi/export.jinja:25 #: trombi/templates/trombi/user_profile.jinja:11 msgid "Pictures" @@ -3889,8 +3889,8 @@ msgstr "quantité" msgid "Sith account" msgstr "Compte utilisateur" -#: counter/models.py:683 sith/settings.py:396 sith/settings.py:401 -#: sith/settings.py:421 +#: counter/models.py:683 sith/settings.py:405 sith/settings.py:410 +#: sith/settings.py:430 msgid "Credit card" msgstr "Carte bancaire" @@ -4926,12 +4926,12 @@ msgid "Washing and drying" msgstr "Lavage et séchage" #: launderette/templates/launderette/launderette_book.jinja:27 -#: sith/settings.py:635 +#: sith/settings.py:644 msgid "Washing" msgstr "Lavage" #: launderette/templates/launderette/launderette_book.jinja:31 -#: sith/settings.py:635 +#: sith/settings.py:644 msgid "Drying" msgstr "Séchage" @@ -5127,30 +5127,30 @@ msgstr "signalant" msgid "reason" msgstr "raison" -#: pedagogy/templates/pedagogy/guide.jinja:4 +#: pedagogy/templates/pedagogy/guide.jinja:5 msgid "UV Guide" msgstr "Guide des UVs" -#: pedagogy/templates/pedagogy/guide.jinja:55 +#: pedagogy/templates/pedagogy/guide.jinja:56 #, python-format msgid "%(display_name)s" msgstr "%(display_name)s" -#: pedagogy/templates/pedagogy/guide.jinja:69 +#: pedagogy/templates/pedagogy/guide.jinja:70 #, python-format msgid "%(credit_type)s" msgstr "%(credit_type)s" -#: pedagogy/templates/pedagogy/guide.jinja:87 +#: pedagogy/templates/pedagogy/guide.jinja:88 #: pedagogy/templates/pedagogy/moderation.jinja:12 msgid "UV" msgstr "UE" -#: pedagogy/templates/pedagogy/guide.jinja:89 +#: pedagogy/templates/pedagogy/guide.jinja:90 msgid "Department" msgstr "Département" -#: pedagogy/templates/pedagogy/guide.jinja:90 +#: pedagogy/templates/pedagogy/guide.jinja:91 msgid "Credit type" msgstr "Type de crédit" @@ -5335,20 +5335,20 @@ msgstr "Utilisateur à sélectionner" msgid "picture" msgstr "photo" -#: sas/templates/sas/album.jinja:9 sas/templates/sas/main.jinja:8 +#: sas/templates/sas/album.jinja:10 sas/templates/sas/main.jinja:8 #: sas/templates/sas/main.jinja:17 sas/templates/sas/picture.jinja:8 msgid "SAS" msgstr "SAS" -#: sas/templates/sas/album.jinja:52 sas/templates/sas/moderation.jinja:10 +#: sas/templates/sas/album.jinja:53 sas/templates/sas/moderation.jinja:10 msgid "Albums" msgstr "Albums" -#: sas/templates/sas/album.jinja:117 +#: sas/templates/sas/album.jinja:97 msgid "Upload" msgstr "Envoyer" -#: sas/templates/sas/album.jinja:124 +#: sas/templates/sas/album.jinja:104 msgid "Template generation time: " msgstr "Temps de génération du template : " @@ -5401,380 +5401,380 @@ msgstr "Erreur de création de l'album %(album)s : %(msg)s" msgid "Add user" msgstr "Ajouter une personne" -#: sith/settings.py:247 sith/settings.py:458 +#: sith/settings.py:247 sith/settings.py:467 msgid "English" msgstr "Anglais" -#: sith/settings.py:247 sith/settings.py:457 +#: sith/settings.py:247 sith/settings.py:466 msgid "French" msgstr "Français" -#: sith/settings.py:377 +#: sith/settings.py:386 msgid "TC" msgstr "TC" -#: sith/settings.py:378 +#: sith/settings.py:387 msgid "IMSI" msgstr "IMSI" -#: sith/settings.py:379 +#: sith/settings.py:388 msgid "IMAP" msgstr "IMAP" -#: sith/settings.py:380 +#: sith/settings.py:389 msgid "INFO" msgstr "INFO" -#: sith/settings.py:381 +#: sith/settings.py:390 msgid "GI" msgstr "GI" -#: sith/settings.py:382 sith/settings.py:468 +#: sith/settings.py:391 sith/settings.py:477 msgid "E" msgstr "E" -#: sith/settings.py:383 +#: sith/settings.py:392 msgid "EE" msgstr "EE" -#: sith/settings.py:384 +#: sith/settings.py:393 msgid "GESC" msgstr "GESC" -#: sith/settings.py:385 +#: sith/settings.py:394 msgid "GMC" msgstr "GMC" -#: sith/settings.py:386 +#: sith/settings.py:395 msgid "MC" msgstr "MC" -#: sith/settings.py:387 +#: sith/settings.py:396 msgid "EDIM" msgstr "EDIM" -#: sith/settings.py:388 +#: sith/settings.py:397 msgid "Humanities" msgstr "Humanités" -#: sith/settings.py:389 +#: sith/settings.py:398 msgid "N/A" msgstr "N/A" -#: sith/settings.py:393 sith/settings.py:400 sith/settings.py:419 +#: sith/settings.py:402 sith/settings.py:409 sith/settings.py:428 msgid "Check" msgstr "Chèque" -#: sith/settings.py:394 sith/settings.py:402 sith/settings.py:420 +#: sith/settings.py:403 sith/settings.py:411 sith/settings.py:429 msgid "Cash" msgstr "Espèces" -#: sith/settings.py:395 +#: sith/settings.py:404 msgid "Transfert" msgstr "Virement" -#: sith/settings.py:408 +#: sith/settings.py:417 msgid "Belfort" msgstr "Belfort" -#: sith/settings.py:409 +#: sith/settings.py:418 msgid "Sevenans" msgstr "Sevenans" -#: sith/settings.py:410 +#: sith/settings.py:419 msgid "Montbéliard" msgstr "Montbéliard" -#: sith/settings.py:438 +#: sith/settings.py:447 msgid "Free" msgstr "Libre" -#: sith/settings.py:439 +#: sith/settings.py:448 msgid "CS" msgstr "CS" -#: sith/settings.py:440 +#: sith/settings.py:449 msgid "TM" msgstr "TM" -#: sith/settings.py:441 +#: sith/settings.py:450 msgid "OM" msgstr "OM" -#: sith/settings.py:442 +#: sith/settings.py:451 msgid "QC" msgstr "QC" -#: sith/settings.py:443 +#: sith/settings.py:452 msgid "EC" msgstr "EC" -#: sith/settings.py:444 +#: sith/settings.py:453 msgid "RN" msgstr "RN" -#: sith/settings.py:445 +#: sith/settings.py:454 msgid "ST" msgstr "ST" -#: sith/settings.py:446 +#: sith/settings.py:455 msgid "EXT" msgstr "EXT" -#: sith/settings.py:451 +#: sith/settings.py:460 msgid "Autumn" msgstr "Automne" -#: sith/settings.py:452 +#: sith/settings.py:461 msgid "Spring" msgstr "Printemps" -#: sith/settings.py:453 +#: sith/settings.py:462 msgid "Autumn and spring" msgstr "Automne et printemps" -#: sith/settings.py:459 +#: sith/settings.py:468 msgid "German" msgstr "Allemand" -#: sith/settings.py:460 +#: sith/settings.py:469 msgid "Spanish" msgstr "Espagnol" -#: sith/settings.py:464 +#: sith/settings.py:473 msgid "A" msgstr "A" -#: sith/settings.py:465 +#: sith/settings.py:474 msgid "B" msgstr "B" -#: sith/settings.py:466 +#: sith/settings.py:475 msgid "C" msgstr "C" -#: sith/settings.py:467 +#: sith/settings.py:476 msgid "D" msgstr "D" -#: sith/settings.py:469 +#: sith/settings.py:478 msgid "FX" msgstr "FX" -#: sith/settings.py:470 +#: sith/settings.py:479 msgid "F" msgstr "F" -#: sith/settings.py:471 +#: sith/settings.py:480 msgid "Abs" msgstr "Abs" -#: sith/settings.py:475 +#: sith/settings.py:484 msgid "Selling deletion" msgstr "Suppression de vente" -#: sith/settings.py:476 +#: sith/settings.py:485 msgid "Refilling deletion" msgstr "Suppression de rechargement" -#: sith/settings.py:513 +#: sith/settings.py:522 msgid "One semester" msgstr "Un semestre, 20 €" -#: sith/settings.py:514 +#: sith/settings.py:523 msgid "Two semesters" msgstr "Deux semestres, 35 €" -#: sith/settings.py:516 +#: sith/settings.py:525 msgid "Common core cursus" msgstr "Cursus tronc commun, 60 €" -#: sith/settings.py:520 +#: sith/settings.py:529 msgid "Branch cursus" msgstr "Cursus branche, 60 €" -#: sith/settings.py:521 +#: sith/settings.py:530 msgid "Alternating cursus" msgstr "Cursus alternant, 30 €" -#: sith/settings.py:522 +#: sith/settings.py:531 msgid "Honorary member" msgstr "Membre honoraire, 0 €" -#: sith/settings.py:523 +#: sith/settings.py:532 msgid "Assidu member" msgstr "Membre d'Assidu, 0 €" -#: sith/settings.py:524 +#: sith/settings.py:533 msgid "Amicale/DOCEO member" msgstr "Membre de l'Amicale/DOCEO, 0 €" -#: sith/settings.py:525 +#: sith/settings.py:534 msgid "UT network member" msgstr "Cotisant du réseau UT, 0 €" -#: sith/settings.py:526 +#: sith/settings.py:535 msgid "CROUS member" msgstr "Membres du CROUS, 0 €" -#: sith/settings.py:527 +#: sith/settings.py:536 msgid "Sbarro/ESTA member" msgstr "Membre de Sbarro ou de l'ESTA, 20 €" -#: sith/settings.py:529 +#: sith/settings.py:538 msgid "One semester Welcome Week" msgstr "Un semestre Welcome Week" -#: sith/settings.py:533 +#: sith/settings.py:542 msgid "One month for free" msgstr "Un mois gratuit" -#: sith/settings.py:534 +#: sith/settings.py:543 msgid "Two months for free" msgstr "Deux mois gratuits" -#: sith/settings.py:535 +#: sith/settings.py:544 msgid "Eurok's volunteer" msgstr "Bénévole Eurockéennes" -#: sith/settings.py:537 +#: sith/settings.py:546 msgid "Six weeks for free" msgstr "6 semaines gratuites" -#: sith/settings.py:541 +#: sith/settings.py:550 msgid "One day" msgstr "Un jour" -#: sith/settings.py:542 +#: sith/settings.py:551 msgid "GA staff member" msgstr "Membre staff GA (2 semaines), 1 €" -#: sith/settings.py:545 +#: sith/settings.py:554 msgid "One semester (-20%)" msgstr "Un semestre (-20%), 12 €" -#: sith/settings.py:550 +#: sith/settings.py:559 msgid "Two semesters (-20%)" msgstr "Deux semestres (-20%), 22 €" -#: sith/settings.py:555 +#: sith/settings.py:564 msgid "Common core cursus (-20%)" msgstr "Cursus tronc commun (-20%), 36 €" -#: sith/settings.py:560 +#: sith/settings.py:569 msgid "Branch cursus (-20%)" msgstr "Cursus branche (-20%), 36 €" -#: sith/settings.py:565 +#: sith/settings.py:574 msgid "Alternating cursus (-20%)" msgstr "Cursus alternant (-20%), 24 €" -#: sith/settings.py:571 +#: sith/settings.py:580 msgid "One year for free(CA offer)" msgstr "Une année offerte (Offre CA)" -#: sith/settings.py:591 +#: sith/settings.py:600 msgid "President" msgstr "Président⸱e" -#: sith/settings.py:592 +#: sith/settings.py:601 msgid "Vice-President" msgstr "Vice-Président⸱e" -#: sith/settings.py:593 +#: sith/settings.py:602 msgid "Treasurer" msgstr "Trésorier⸱e" -#: sith/settings.py:594 +#: sith/settings.py:603 msgid "Communication supervisor" msgstr "Responsable communication" -#: sith/settings.py:595 +#: sith/settings.py:604 msgid "Secretary" msgstr "Secrétaire" -#: sith/settings.py:596 +#: sith/settings.py:605 msgid "IT supervisor" msgstr "Responsable info" -#: sith/settings.py:597 +#: sith/settings.py:606 msgid "Board member" msgstr "Membre du bureau" -#: sith/settings.py:598 +#: sith/settings.py:607 msgid "Active member" msgstr "Membre actif⸱ve" -#: sith/settings.py:599 +#: sith/settings.py:608 msgid "Curious" msgstr "Curieux⸱euse" -#: sith/settings.py:639 +#: sith/settings.py:648 msgid "A new poster needs to be moderated" msgstr "Une nouvelle affiche a besoin d'être modérée" -#: sith/settings.py:640 +#: sith/settings.py:649 msgid "A new mailing list needs to be moderated" msgstr "Une nouvelle mailing list a besoin d'être modérée" -#: sith/settings.py:643 +#: sith/settings.py:652 msgid "A new pedagogy comment has been signaled for moderation" msgstr "" "Un nouveau commentaire de la pédagogie a été signalé pour la modération" -#: sith/settings.py:645 +#: sith/settings.py:654 #, python-format msgid "There are %s fresh news to be moderated" msgstr "Il y a %s nouvelles toutes fraîches à modérer" -#: sith/settings.py:646 +#: sith/settings.py:655 msgid "New files to be moderated" msgstr "Nouveaux fichiers à modérer" -#: sith/settings.py:647 +#: sith/settings.py:656 #, python-format msgid "There are %s pictures to be moderated in the SAS" msgstr "Il y a %s photos à modérer dans le SAS" -#: sith/settings.py:648 +#: sith/settings.py:657 msgid "You've been identified on some pictures" msgstr "Vous avez été identifié sur des photos" -#: sith/settings.py:649 +#: sith/settings.py:658 #, python-format msgid "You just refilled of %s €" msgstr "Vous avez rechargé votre compte de %s€" -#: sith/settings.py:650 +#: sith/settings.py:659 #, python-format msgid "You just bought %s" msgstr "Vous avez acheté %s" -#: sith/settings.py:651 +#: sith/settings.py:660 msgid "You have a notification" msgstr "Vous avez une notification" -#: sith/settings.py:663 +#: sith/settings.py:672 msgid "Success!" msgstr "Succès !" -#: sith/settings.py:664 +#: sith/settings.py:673 msgid "Fail!" msgstr "Échec !" -#: sith/settings.py:665 +#: sith/settings.py:674 msgid "You successfully posted an article in the Weekmail" msgstr "Article posté avec succès dans le Weekmail" -#: sith/settings.py:666 +#: sith/settings.py:675 msgid "You successfully edited an article in the Weekmail" msgstr "Article édité avec succès dans le Weekmail" -#: sith/settings.py:667 +#: sith/settings.py:676 msgid "You successfully sent the Weekmail" msgstr "Weekmail envoyé avec succès" -#: sith/settings.py:675 +#: sith/settings.py:684 msgid "AE tee-shirt" msgstr "Tee-shirt AE" From e82acdabb0ba00d78b165c7c2694a260d93d3633 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Thu, 29 Aug 2024 11:48:26 +0200 Subject: [PATCH 2/9] remove sentry deployment CI (until Sentry is repaired) --- .github/workflows/deploy.yml | 18 ------------------ .github/workflows/taiste.yml | 18 ------------------ 2 files changed, 36 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca9fac48..5c783a12 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -44,21 +44,3 @@ jobs: poetry run ./manage.py compilemessages sudo systemctl restart uwsgi - - sentry: - runs-on: ubuntu-latest - environment: production - timeout-minutes: 30 - needs: deployment - steps: - - uses: actions/checkout@v3 - - - name: Sentry Release - uses: getsentry/action-release@v1.2.0 - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - SENTRY_URL: ${{ secrets.SENTRY_URL }} - with: - environment: production diff --git a/.github/workflows/taiste.yml b/.github/workflows/taiste.yml index cfecf289..bf0da234 100644 --- a/.github/workflows/taiste.yml +++ b/.github/workflows/taiste.yml @@ -43,21 +43,3 @@ jobs: poetry run ./manage.py compilemessages sudo systemctl restart uwsgi - - sentry: - runs-on: ubuntu-latest - environment: taiste - timeout-minutes: 30 - needs: deployment - steps: - - uses: actions/checkout@v3 - - - name: Sentry Release - uses: getsentry/action-release@v1.2.0 - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - SENTRY_URL: ${{ secrets.SENTRY_URL }} - with: - environment: taiste From cc1d700f7d92b308766918e8402438ff1e9d9095 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Thu, 29 Aug 2024 11:54:32 +0200 Subject: [PATCH 3/9] add forgotten migration --- sas/migrations/0003_sasfile.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 sas/migrations/0003_sasfile.py diff --git a/sas/migrations/0003_sasfile.py b/sas/migrations/0003_sasfile.py new file mode 100644 index 00000000..a66b7e25 --- /dev/null +++ b/sas/migrations/0003_sasfile.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.14 on 2024-08-29 09:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0038_alter_preferences_receive_weekmail"), + ("sas", "0002_auto_20161119_1241"), + ] + + operations = [ + migrations.CreateModel( + name="SasFile", + fields=[], + options={ + "proxy": True, + "indexes": [], + "constraints": [], + }, + bases=("core.sithfile",), + ), + ] From fbff38c5c3d2efb7e646ad1b2ee09762a0f96861 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Thu, 29 Aug 2024 11:42:21 +0200 Subject: [PATCH 4/9] repair name of protected files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depuis l'implémentation de l'envoi des fichiers par le reverse-proxy, le nom des fichiers n'était plus envoyé. --- core/views/files.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/core/views/files.py b/core/views/files.py index 064b9aaa..fca46c7e 100644 --- a/core/views/files.py +++ b/core/views/files.py @@ -58,30 +58,28 @@ def send_file( if not can_view(f, request.user) and not is_logged_in_counter(request): raise PermissionDenied name = getattr(f, file_attr).name - filepath = settings.MEDIA_ROOT / name - - # check if file exists on disk - if not filepath.exists(): - raise Http404 + response = HttpResponse( + headers={"Content-Disposition": f'inline; filename="{quote(name)}"'} + ) if not settings.DEBUG: # When receiving a response with the Accel-Redirect header, # the reverse proxy will automatically handle the file sending. # This is really hard to test (thus isn't tested) # so please do not mess with this. - response = HttpResponse(status=200) - response["Content-Type"] = "" + response["Content-Type"] = "" # automatically set by nginx response["X-Accel-Redirect"] = quote(urljoin(settings.MEDIA_URL, name)) return response + filepath = settings.MEDIA_ROOT / name + # check if file exists on disk + if not filepath.exists(): + raise Http404 with open(filepath, "rb") as filename: - wrapper = FileWrapper(filename) - response = HttpResponse(wrapper, content_type=f.mime_type) + response.content = FileWrapper(filename) + response["Content-Type"] = f.mime_type response["Last-Modified"] = http_date(f.date.timestamp()) response["Content-Length"] = filepath.stat().st_size - response["Content-Disposition"] = ('inline; filename="%s"' % f.name).encode( - "utf-8" - ) return response From 85a99fc8fa512eb50f55d9dcba712f3d3e396f79 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Sun, 1 Sep 2024 12:33:49 +0200 Subject: [PATCH 5/9] fix promo img on clicks --- core/templates/core/macros.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/templates/core/macros.jinja b/core/templates/core/macros.jinja index 11014a64..2f3d84b8 100644 --- a/core/templates/core/macros.jinja +++ b/core/templates/core/macros.jinja @@ -64,7 +64,7 @@ {% endif %} - {% if user.promo %} + {% if user.promo and user.promo_has_logo() %}
Promo {{ user.promo }}
From 352b09d9cd448da7084911af6c00caa0d647d294 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Sun, 1 Sep 2024 15:07:30 +0200 Subject: [PATCH 6/9] fix subscription form translation --- locale/fr/LC_MESSAGES/django.po | 20 ++++++++++---------- subscription/views.py | 26 +++++--------------------- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index e27b63b8..9d414839 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-08-27 17:02+0200\n" +"POT-Creation-Date: 2024-09-01 15:19+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -2265,11 +2265,11 @@ msgstr "miniature" msgid "owner" msgstr "propriétaire" -#: core/models.py:896 core/models.py:1240 core/views/files.py:231 +#: core/models.py:896 core/models.py:1240 core/views/files.py:229 msgid "edit group" msgstr "groupe d'édition" -#: core/models.py:899 core/models.py:1243 core/views/files.py:234 +#: core/models.py:899 core/models.py:1243 core/views/files.py:232 msgid "view group" msgstr "groupe de vue" @@ -2499,7 +2499,7 @@ msgid "Launderette" msgstr "Laverie" #: core/templates/core/base.jinja:227 core/templates/core/file.jinja:20 -#: core/views/files.py:117 +#: core/views/files.py:115 msgid "Files" msgstr "Fichiers" @@ -3545,22 +3545,22 @@ msgid_plural "%(nb_days)d days, %(remainder)s" msgstr[0] "" msgstr[1] "" -#: core/views/files.py:114 +#: core/views/files.py:112 msgid "Add a new folder" msgstr "Ajouter un nouveau dossier" -#: core/views/files.py:134 +#: core/views/files.py:132 #, python-format msgid "Error creating folder %(folder_name)s: %(msg)s" msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" -#: core/views/files.py:154 core/views/forms.py:304 core/views/forms.py:311 +#: core/views/files.py:152 core/views/forms.py:304 core/views/forms.py:311 #: sas/views.py:81 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" msgstr "Erreur d'envoi du fichier %(file_name)s : %(msg)s" -#: core/views/files.py:236 sas/views.py:359 +#: core/views/files.py:234 sas/views.py:359 msgid "Apply rights recursively" msgstr "Appliquer les droits récursivement" @@ -6013,11 +6013,11 @@ msgid "Eboutic is reserved to specific users. In doubt, don't use it." msgstr "" "Eboutic est réservé à des cas particuliers. Dans le doute, ne l'utilisez pas." -#: subscription/views.py:93 +#: subscription/views.py:78 msgid "A user with that email address already exists" msgstr "Un utilisateur avec cette adresse email existe déjà" -#: subscription/views.py:116 +#: subscription/views.py:101 msgid "You must either choose an existing user or create a new one properly" msgstr "" "Vous devez soit choisir un utilisateur existant, soit en créer un proprement" diff --git a/subscription/views.py b/subscription/views.py index 5dddcf84..c77aee0d 100644 --- a/subscription/views.py +++ b/subscription/views.py @@ -48,26 +48,11 @@ class SubscriptionForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Add fields to allow basic user creation - self.fields["last_name"] = forms.CharField( - max_length=User._meta.get_field("last_name").max_length + self.fields |= forms.fields_for_model( + User, + fields=["first_name", "last_name", "email", "date_of_birth"], + widgets={"date_of_birth": SelectDate}, ) - self.fields["first_name"] = forms.CharField( - max_length=User._meta.get_field("first_name").max_length - ) - self.fields["email"] = forms.EmailField() - self.fields["date_of_birth"] = forms.DateField(widget=SelectDate) - - self.field_order = [ - "member", - "last_name", - "first_name", - "email", - "date_of_birth", - "subscription_type", - "payment_method", - "location", - ] def clean_member(self): subscriber = self.cleaned_data.get("member") @@ -124,9 +109,8 @@ class NewSubscription(CreateView): form_class = SubscriptionForm def dispatch(self, request, *arg, **kwargs): - res = super().dispatch(request, *arg, **kwargs) if request.user.can_create_subscription: - return res + return super().dispatch(request, *arg, **kwargs) raise PermissionDenied def get_initial(self): From b3e59b3829f3e84be3a64cf71b5a9c43e70a0451 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Sun, 1 Sep 2024 18:49:50 +0200 Subject: [PATCH 7/9] remove unused view `GET user//profile_upload` --- core/urls.py | 5 ----- core/views/user.py | 41 ++--------------------------------------- 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/core/urls.py b/core/urls.py index 5a62ed65..32f81a2b 100644 --- a/core/urls.py +++ b/core/urls.py @@ -127,11 +127,6 @@ urlpatterns = [ UserUpdateProfileView.as_view(), name="user_edit", ), - path( - "user//profile_upload/", - UserUploadProfilePictView.as_view(), - name="user_profile_upload", - ), path("user//clubs/", UserClubView.as_view(), name="user_clubs"), path( "user//prefs/", diff --git a/core/views/user.py b/core/views/user.py index 27602d22..0c695e8c 100644 --- a/core/views/user.py +++ b/core/views/user.py @@ -31,7 +31,7 @@ from django.conf import settings from django.contrib.auth import login, views from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.mixins import LoginRequiredMixin -from django.core.exceptions import PermissionDenied, ValidationError +from django.core.exceptions import PermissionDenied from django.forms import CheckboxSelectMultiple from django.forms.models import modelform_factory from django.http import Http404, HttpResponse @@ -52,7 +52,7 @@ from django.views.generic.dates import MonthMixin, YearMixin from django.views.generic.edit import FormView, UpdateView from honeypot.decorators import check_honeypot -from core.models import Gift, Preferences, SithFile, User +from core.models import Gift, Preferences, User from core.views import ( CanEditMixin, CanEditPropMixin, @@ -561,43 +561,6 @@ class UserListView(ListView, CanEditPropMixin): template_name = "core/user_list.jinja" -class UserUploadProfilePictView(CanEditMixin, DetailView): - """Handle the upload of the profile picture taken with webcam in navigator.""" - - model = User - pk_url_kwarg = "user_id" - template_name = "core/user_edit.jinja" - - def post(self, request, *args, **kwargs): - from io import BytesIO - - from PIL import Image - - from core.utils import resize_image - - self.object = self.get_object() - if self.object.profile_pict: - raise ValidationError(_("User already has a profile picture")) - f = request.FILES["new_profile_pict"] - parent = SithFile.objects.filter(parent=None, name="profiles").first() - name = str(self.object.id) + "_profile.jpg" # Webcamejs uploads JPGs - im = Image.open(BytesIO(f.read())) - new_file = SithFile( - parent=parent, - name=name, - file=resize_image(im, 400, f.content_type.split("/")[-1]), - owner=self.object, - is_folder=False, - mime_type=f.content_type, - size=f.size, - ) - new_file.file.name = name - new_file.save() - self.object.profile_pict = new_file - self.object.save() - return redirect("core:user_edit", user_id=self.object.id) - - class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView): """Edit a user's profile.""" From dd07c374d742675eabd21d4238d04b1139c971b1 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Sun, 1 Sep 2024 19:05:54 +0200 Subject: [PATCH 8/9] convert uploaded images to webp --- core/management/commands/populate.py | 24 ++++++++++++------------ core/templates/core/user_edit.jinja | 6 +++--- core/utils.py | 10 +++++++--- core/views/files.py | 3 ++- core/views/forms.py | 10 +++------- sas/models.py | 22 ++++++++++++++-------- 6 files changed, 41 insertions(+), 34 deletions(-) diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py index 8bd53c6f..77131c98 100644 --- a/core/management/commands/populate.py +++ b/core/management/commands/populate.py @@ -234,10 +234,10 @@ Welcome to the wiki page! skia_profile = SithFile( parent=profiles_root, name=name, - file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), + file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"), owner=skia, is_folder=False, - mime_type="image/jpeg", + mime_type="image/webp", size=skia_profile_path.stat().st_size, ) skia_profile.file.name = name @@ -368,10 +368,10 @@ Welcome to the wiki page! richard_profile = SithFile( parent=profiles_root, name=name, - file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), + file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"), owner=richard, is_folder=False, - mime_type="image/jpeg", + mime_type="image/webp", size=richard_profile_path.stat().st_size, ) richard_profile.file.name = name @@ -853,10 +853,10 @@ Welcome to the wiki page! sli_profile = SithFile( parent=profiles_root, name=name, - file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), + file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"), owner=sli, is_folder=False, - mime_type="image/jpeg", + mime_type="image/webp", size=sli_profile_path.stat().st_size, ) sli_profile.file.name = name @@ -887,10 +887,10 @@ Welcome to the wiki page! krophil_profile = SithFile( parent=profiles_root, name=name, - file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), + file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"), owner=krophil, is_folder=False, - mime_type="image/jpeg", + mime_type="image/webp", size=krophil_profile_path.stat().st_size, ) krophil_profile.file.name = name @@ -1217,13 +1217,13 @@ Welcome to the wiki page! parent=album, name=p.name, file=resize_image( - Image.open(BytesIO(p.read_bytes())), 1000, "JPEG" + Image.open(BytesIO(p.read_bytes())), 1000, "WEBP" ), owner=root, is_folder=False, is_in_sas=True, is_moderated=True, - mime_type="image/jpeg", + mime_type="image/webp", size=p.stat().st_size, ) pict.file.name = p.name @@ -1252,10 +1252,10 @@ Welcome to the wiki page! skia_profile = SithFile( parent=profiles_root, name=name, - file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), + file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"), owner=skia, is_folder=False, - mime_type="image/jpeg", + mime_type="image/webp", size=skia_profile_path.stat().st_size, ) skia_profile.file.name = name diff --git a/core/templates/core/user_edit.jinja b/core/templates/core/user_edit.jinja index 37acfbe7..8cb8719b 100644 --- a/core/templates/core/user_edit.jinja +++ b/core/templates/core/user_edit.jinja @@ -164,7 +164,7 @@ /* Stop camera */ this.video.pause() this.video.srcObject.getTracks().forEach((track) => { - if (track.readyState == 'live') { + if (track.readyState === 'live') { track.stop(); } }); @@ -172,8 +172,8 @@ canvas.toBlob((blob) => { let file = new File( [blob], - "{% trans %}captured{% endtrans %}.png", - { type: "image/jpeg" }, + "{% trans %}captured{% endtrans %}.webp", + { type: "image/webp" }, ); let list = new DataTransfer(); diff --git a/core/utils.py b/core/utils.py index 5ed6cb1b..55e6afdd 100644 --- a/core/utils.py +++ b/core/utils.py @@ -102,13 +102,17 @@ def scale_dimension(width, height, long_edge): def resize_image(im, edge, img_format): (w, h) = im.size (width, height) = scale_dimension(w, h, long_edge=edge) + img_format = img_format.upper() content = BytesIO() # use the lanczos filter for antialiasing and discard the alpha channel - im = im.resize((width, height), Resampling.LANCZOS).convert("RGB") + im = im.resize((width, height), Resampling.LANCZOS) + if img_format == "JPEG": + # converting an image with an alpha channel to jpeg would cause a crash + im = im.convert("RGB") try: im.save( fp=content, - format=img_format.upper(), + format=img_format, quality=90, optimize=True, progressive=True, @@ -117,7 +121,7 @@ def resize_image(im, edge, img_format): PIL.ImageFile.MAXBLOCK = im.size[0] * im.size[1] im.save( fp=content, - format=img_format.upper(), + format=img_format, quality=90, optimize=True, progressive=True, diff --git a/core/views/files.py b/core/views/files.py index fca46c7e..3d1151d0 100644 --- a/core/views/files.py +++ b/core/views/files.py @@ -12,6 +12,7 @@ # OR WITHIN THE LOCAL FILE "LICENSE" # # +import mimetypes from urllib.parse import quote, urljoin # This file contains all the views that concern the page model @@ -77,7 +78,7 @@ def send_file( raise Http404 with open(filepath, "rb") as filename: response.content = FileWrapper(filename) - response["Content-Type"] = f.mime_type + response["Content-Type"] = mimetypes.guess_type(filepath)[0] response["Last-Modified"] = http_date(f.date.timestamp()) response["Content-Length"] = filepath.stat().st_size return response diff --git a/core/views/forms.py b/core/views/forms.py index baf6b20e..8bf12912 100644 --- a/core/views/forms.py +++ b/core/views/forms.py @@ -239,10 +239,6 @@ class UserProfileForm(forms.ModelForm): "quote": forms.Textarea, } - def generate_name(self, field_name, f): - field_name = field_name[:-4] - return field_name + str(self.instance.id) + "." + f.content_type.split("/")[-1] - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -278,11 +274,11 @@ class UserProfileForm(forms.ModelForm): im = Image.open(BytesIO(f.read())) new_file = SithFile( parent=parent, - name=self.generate_name(field, f), - file=resize_image(im, 400, f.content_type.split("/")[-1]), + name=f"{field.removesuffix('_pict')}_{self.instance.id}.webp", + file=resize_image(im, 400, "webp"), owner=self.instance, is_folder=False, - mime_type=f.content_type, + mime_type="image/wepb", size=f.size, moderator=self.instance, is_moderated=True, diff --git a/sas/models.py b/sas/models.py index af1b30ff..fbe10223 100644 --- a/sas/models.py +++ b/sas/models.py @@ -110,19 +110,25 @@ class Picture(SasFile): im = exif_auto_rotate(im) except: pass - file = resize_image(im, max(im.size), self.mime_type.split("/")[-1]) - thumb = resize_image(im, 200, self.mime_type.split("/")[-1]) - compressed = resize_image(im, 1200, self.mime_type.split("/")[-1]) + # convert the compressed image and the thumbnail into webp + # The original image keeps its original type, because it's not + # meant to be shown on the website, but rather to keep the real image + # for less frequent cases (like downloading the pictures of an user) + extension = self.mime_type.split("/")[-1] + file = resize_image(im, max(im.size), extension) + thumb = resize_image(im, 200, "webp") + compressed = resize_image(im, 1200, "webp") if overwrite: self.file.delete() self.thumbnail.delete() self.compressed.delete() + new_extension_name = self.name.removesuffix(extension) + "webp" self.file = file self.file.name = self.name self.thumbnail = thumb - self.thumbnail.name = self.name + self.thumbnail.name = new_extension_name self.compressed = compressed - self.compressed.name = self.name + self.compressed.name = new_extension_name self.save() def rotate(self, degree): @@ -224,9 +230,9 @@ class Album(SasFile): .first() ) if p and p.file: - im = Image.open(BytesIO(p.file.read())) - self.file = resize_image(im, 200, "jpeg") - self.file.name = self.name + "/thumb.jpg" + image = resize_image(Image.open(BytesIO(p.file.read())), 200, "webp") + self.file = image + self.file.name = f"{self.name}/thumb.webp" self.save() From cf46c3800f9fa17ecc3c48f79d8303eb82309585 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Sun, 1 Sep 2024 10:38:57 +0200 Subject: [PATCH 9/9] remove sith version from the footer --- com/models.py | 2 - core/templates/core/base.jinja | 5 -- core/utils.py | 12 ---- locale/fr/LC_MESSAGES/django.po | 108 +++++++++++++++----------------- 4 files changed, 50 insertions(+), 77 deletions(-) diff --git a/com/models.py b/com/models.py index 1cbfbfec..5c1466ca 100644 --- a/com/models.py +++ b/com/models.py @@ -34,7 +34,6 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from club.models import Club -from core import utils from core.models import Notification, Preferences, RealGroup, User @@ -44,7 +43,6 @@ class Sith(models.Model): alert_msg = models.TextField(_("alert message"), default="", blank=True) info_msg = models.TextField(_("info message"), default="", blank=True) weekmail_destinations = models.TextField(_("weekmail destinations"), default="") - version = utils.get_git_revision_short_hash() def __str__(self): return "⛩ Sith ⛩" diff --git a/core/templates/core/base.jinja b/core/templates/core/base.jinja index d5a8b2a0..5eb2a682 100644 --- a/core/templates/core/base.jinja +++ b/core/templates/core/base.jinja @@ -290,11 +290,6 @@ {% endblock %}
- - {% cache 1000 "sith_version" %} - {% trans %}Sith version:{% endtrans %} {{ get_sith().version }} - {% endcache %} - {% endif %} diff --git a/core/utils.py b/core/utils.py index 55e6afdd..ef748b80 100644 --- a/core/utils.py +++ b/core/utils.py @@ -13,7 +13,6 @@ # # -import subprocess from datetime import date # Image utils @@ -29,17 +28,6 @@ from PIL import ExifTags from PIL.Image import Resampling -def get_git_revision_short_hash() -> str: - """Return the short hash of the current commit.""" - try: - output = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]) - if isinstance(output, bytes): - return output.decode("ascii").strip() - return output.strip() - except subprocess.CalledProcessError: - return "" - - def get_start_of_semester(today: Optional[date] = None) -> date: """Return the date of the start of the semester of the given date. If no date is given, return the start date of the current semester. diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 9d414839..cb902675 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-01 15:19+0200\n" +"POT-Creation-Date: 2024-09-01 23:45+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -17,8 +17,8 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: accounting/models.py:50 accounting/models.py:91 accounting/models.py:124 -#: accounting/models.py:191 club/models.py:52 com/models.py:276 -#: com/models.py:295 counter/models.py:208 counter/models.py:239 +#: accounting/models.py:191 club/models.py:52 com/models.py:274 +#: com/models.py:293 counter/models.py:208 counter/models.py:239 #: counter/models.py:370 forum/models.py:59 launderette/models.py:29 #: launderette/models.py:84 launderette/models.py:122 stock/models.py:36 #: stock/models.py:57 stock/models.py:97 stock/models.py:125 @@ -66,7 +66,7 @@ msgid "account number" msgstr "numéro de compte" #: accounting/models.py:97 accounting/models.py:128 club/models.py:344 -#: com/models.py:76 com/models.py:261 com/models.py:301 counter/models.py:257 +#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:257 #: counter/models.py:372 trombi/models.py:210 msgid "club" msgstr "club" @@ -1059,7 +1059,7 @@ msgstr "Un club avec ce nom UNIX existe déjà." #: club/models.py:336 counter/models.py:844 counter/models.py:880 #: eboutic/models.py:53 eboutic/models.py:169 election/models.py:183 -#: launderette/models.py:136 launderette/models.py:198 sas/models.py:248 +#: launderette/models.py:136 launderette/models.py:198 sas/models.py:254 #: trombi/models.py:206 msgid "user" msgstr "nom d'utilisateur" @@ -1084,11 +1084,11 @@ msgid "Enter a valid address. Only the root of the address is needed." msgstr "" "Entrez une adresse valide. Seule la racine de l'adresse est nécessaire." -#: club/models.py:428 com/models.py:84 com/models.py:311 core/models.py:905 +#: club/models.py:428 com/models.py:82 com/models.py:309 core/models.py:905 msgid "is moderated" msgstr "est modéré" -#: club/models.py:432 com/models.py:88 com/models.py:315 +#: club/models.py:432 com/models.py:86 com/models.py:313 msgid "moderator" msgstr "modérateur" @@ -1162,7 +1162,7 @@ msgid "There are no members in this club." msgstr "Il n'y a pas de membres dans ce club." #: club/templates/club/club_members.jinja:80 -#: core/templates/core/file_detail.jinja:19 core/views/forms.py:339 +#: core/templates/core/file_detail.jinja:19 core/views/forms.py:335 #: launderette/views.py:217 trombi/templates/trombi/detail.jinja:19 msgid "Add" msgstr "Ajouter" @@ -1397,108 +1397,108 @@ msgstr "Liste d'affiches" msgid "Props" msgstr "Propriétés" -#: com/models.py:44 +#: com/models.py:43 msgid "alert message" msgstr "message d'alerte" -#: com/models.py:45 +#: com/models.py:44 msgid "info message" msgstr "message d'info" -#: com/models.py:46 +#: com/models.py:45 msgid "weekmail destinations" msgstr "destinataires du weekmail" -#: com/models.py:59 +#: com/models.py:57 msgid "Notice" msgstr "Information" -#: com/models.py:60 +#: com/models.py:58 msgid "Event" msgstr "Événement" -#: com/models.py:61 +#: com/models.py:59 msgid "Weekly" msgstr "Hebdomadaire" -#: com/models.py:62 +#: com/models.py:60 msgid "Call" msgstr "Appel" -#: com/models.py:69 com/models.py:176 com/models.py:250 election/models.py:12 +#: com/models.py:67 com/models.py:174 com/models.py:248 election/models.py:12 #: election/models.py:114 election/models.py:152 forum/models.py:255 #: forum/models.py:309 pedagogy/models.py:96 msgid "title" msgstr "titre" -#: com/models.py:70 +#: com/models.py:68 msgid "summary" msgstr "résumé" -#: com/models.py:71 com/models.py:251 trombi/models.py:189 +#: com/models.py:69 com/models.py:249 trombi/models.py:189 msgid "content" msgstr "contenu" -#: com/models.py:73 core/models.py:1474 launderette/models.py:92 +#: com/models.py:71 core/models.py:1474 launderette/models.py:92 #: launderette/models.py:130 launderette/models.py:181 stock/models.py:74 #: stock/models.py:129 msgid "type" msgstr "type" -#: com/models.py:81 com/models.py:255 pedagogy/models.py:56 +#: com/models.py:79 com/models.py:253 pedagogy/models.py:56 #: pedagogy/models.py:199 trombi/models.py:179 msgid "author" msgstr "auteur" -#: com/models.py:155 +#: com/models.py:153 msgid "news_date" msgstr "date de la nouvelle" -#: com/models.py:158 +#: com/models.py:156 msgid "start_date" msgstr "date de début" -#: com/models.py:159 +#: com/models.py:157 msgid "end_date" msgstr "date de fin" -#: com/models.py:177 +#: com/models.py:175 msgid "intro" msgstr "intro" -#: com/models.py:178 +#: com/models.py:176 msgid "joke" msgstr "blague" -#: com/models.py:179 +#: com/models.py:177 msgid "protip" msgstr "astuce" -#: com/models.py:180 +#: com/models.py:178 msgid "conclusion" msgstr "conclusion" -#: com/models.py:181 +#: com/models.py:179 msgid "sent" msgstr "envoyé" -#: com/models.py:246 +#: com/models.py:244 msgid "weekmail" msgstr "weekmail" -#: com/models.py:264 +#: com/models.py:262 msgid "rank" msgstr "rang" -#: com/models.py:297 core/models.py:870 core/models.py:920 +#: com/models.py:295 core/models.py:870 core/models.py:920 msgid "file" msgstr "fichier" -#: com/models.py:309 +#: com/models.py:307 msgid "display time" msgstr "temps d'affichage" -#: com/models.py:340 +#: com/models.py:338 msgid "Begin date should be before end date" msgstr "La date de début doit être avant celle de fin" @@ -2265,11 +2265,11 @@ msgstr "miniature" msgid "owner" msgstr "propriétaire" -#: core/models.py:896 core/models.py:1240 core/views/files.py:229 +#: core/models.py:896 core/models.py:1240 core/views/files.py:230 msgid "edit group" msgstr "groupe d'édition" -#: core/models.py:899 core/models.py:1243 core/views/files.py:232 +#: core/models.py:899 core/models.py:1243 core/views/files.py:233 msgid "view group" msgstr "groupe de vue" @@ -2499,7 +2499,7 @@ msgid "Launderette" msgstr "Laverie" #: core/templates/core/base.jinja:227 core/templates/core/file.jinja:20 -#: core/views/files.py:115 +#: core/views/files.py:116 msgid "Files" msgstr "Fichiers" @@ -2555,10 +2555,6 @@ msgstr "R&D" msgid "Site created by the IT Department of the AE" msgstr "Site réalisé par le Pôle Informatique de l'AE" -#: core/templates/core/base.jinja:295 -msgid "Sith version:" -msgstr "Version du site :" - #: core/templates/core/create.jinja:4 core/templates/core/create.jinja:8 #, python-format msgid "Create %(name)s" @@ -3545,22 +3541,22 @@ msgid_plural "%(nb_days)d days, %(remainder)s" msgstr[0] "" msgstr[1] "" -#: core/views/files.py:112 +#: core/views/files.py:113 msgid "Add a new folder" msgstr "Ajouter un nouveau dossier" -#: core/views/files.py:132 +#: core/views/files.py:133 #, python-format msgid "Error creating folder %(folder_name)s: %(msg)s" msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" -#: core/views/files.py:152 core/views/forms.py:304 core/views/forms.py:311 +#: core/views/files.py:153 core/views/forms.py:300 core/views/forms.py:307 #: sas/views.py:81 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" msgstr "Erreur d'envoi du fichier %(file_name)s : %(msg)s" -#: core/views/files.py:234 sas/views.py:359 +#: core/views/files.py:235 sas/views.py:359 msgid "Apply rights recursively" msgstr "Appliquer les droits récursivement" @@ -3652,7 +3648,7 @@ msgstr "Choisir un utilisateur" msgid "Username, email, or account number" msgstr "Nom d'utilisateur, email, ou numéro de compte AE" -#: core/views/forms.py:254 +#: core/views/forms.py:250 msgid "" "Profile: you need to be visible on the picture, in order to be recognized (e." "g. by the barmen)" @@ -3660,36 +3656,36 @@ msgstr "" "Photo de profil: vous devez être visible sur la photo afin d'être reconnu " "(par exemple par les barmen)" -#: core/views/forms.py:259 +#: core/views/forms.py:255 msgid "Avatar: used on the forum" msgstr "Avatar : utilisé sur le forum" -#: core/views/forms.py:263 +#: core/views/forms.py:259 msgid "Scrub: let other know how your scrub looks like!" msgstr "Blouse : montrez aux autres à quoi ressemble votre blouse !" -#: core/views/forms.py:315 +#: core/views/forms.py:311 msgid "Bad image format, only jpeg, png, webp and gif are accepted" msgstr "Mauvais format d'image, seuls les jpeg, png, webp et gif sont acceptés" -#: core/views/forms.py:336 +#: core/views/forms.py:332 msgid "Godfather / Godmother" msgstr "Parrain / Marraine" -#: core/views/forms.py:337 +#: core/views/forms.py:333 msgid "Godchild" msgstr "Fillot / Fillote" -#: core/views/forms.py:342 counter/forms.py:67 trombi/views.py:149 +#: core/views/forms.py:338 counter/forms.py:67 trombi/views.py:149 msgid "Select user" msgstr "Choisir un utilisateur" -#: core/views/forms.py:355 core/views/forms.py:373 election/models.py:22 +#: core/views/forms.py:351 core/views/forms.py:369 election/models.py:22 #: election/views.py:147 msgid "edit groups" msgstr "groupe d'édition" -#: core/views/forms.py:358 core/views/forms.py:376 election/models.py:29 +#: core/views/forms.py:354 core/views/forms.py:372 election/models.py:29 #: election/views.py:150 msgid "view groups" msgstr "groupe de vue" @@ -3720,10 +3716,6 @@ msgstr "Photos" msgid "Galaxy" msgstr "Galaxie" -#: core/views/user.py:580 -msgid "User already has a profile picture" -msgstr "L'utilisateur a déjà une photo de profil" - #: counter/apps.py:30 counter/models.py:396 counter/models.py:850 #: counter/models.py:886 launderette/models.py:32 stock/models.py:39 msgid "counter" @@ -5331,7 +5323,7 @@ msgstr "Utilisateur qui sera supprimé" msgid "User to be selected" msgstr "Utilisateur à sélectionner" -#: sas/models.py:256 +#: sas/models.py:262 msgid "picture" msgstr "photo"