diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ba35d31..4cf8dab9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ variables: GIT_SUBMODULE_STRATEGY: recursive # Ubuntu 22.04 -py310-django42: +py310-django52: stage: test image: ubuntu:22.04 before_script: @@ -22,10 +22,10 @@ py310-django42: python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache python3-bs4 python3-setuptools tox texlive-xetex - script: tox -e py310-django42 + script: tox -e py310-django52 # Debian Bookworm -py311-django42: +py311-django52: stage: test image: debian:bookworm before_script: @@ -37,7 +37,7 @@ py311-django42: python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache python3-bs4 python3-setuptools tox texlive-xetex - script: tox -e py311-django42 + script: tox -e py311-django52 linters: stage: quality-assurance diff --git a/apps/food/templates/food/food_list.html b/apps/food/templates/food/food_list.html index efc7a554..bd54ece9 100644 --- a/apps/food/templates/food/food_list.html +++ b/apps/food/templates/food/food_list.html @@ -7,7 +7,52 @@ SPDX-License-Identifier: GPL-3.0-or-later {% load i18n %} {% block content %} -{{ block.super }} +
+

+ {{ title }} +

+
+ +
+
+ + +
+
+
+
+ +
+ + {% block extra_inside_card %} + {% endblock %} + +
+ {% if table.data %} + {% render_table table %} + {% else %} +
+
+ {% trans "There is no results." %} +
+
+ {% endif %} +
+

@@ -68,4 +113,20 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endfor %} {% endif %}

-{% endblock %} + + + + +{% endblock %} \ No newline at end of file diff --git a/apps/food/urls.py b/apps/food/urls.py index 81acccdd..82a7f22e 100644 --- a/apps/food/urls.py +++ b/apps/food/urls.py @@ -18,4 +18,5 @@ urlpatterns = [ path('detail/basic/', views.BasicFoodDetailView.as_view(), name='basicfood_view'), path('detail/transformed/', views.TransformedFoodDetailView.as_view(), name='transformedfood_view'), path('add/ingredient/', views.AddIngredientView.as_view(), name='add_ingredient'), + path('redirect/', views.QRCodeRedirectView.as_view(), name='redirect_view'), ] diff --git a/apps/food/views.py b/apps/food/views.py index a5b86686..393e4072 100644 --- a/apps/food/views.py +++ b/apps/food/views.py @@ -10,6 +10,7 @@ from django.db.models import Q from django.http import HttpResponseRedirect, Http404 from django.views.generic import DetailView, UpdateView, CreateView from django.views.generic.list import ListView +from django.views.generic.base import RedirectView from django.urls import reverse_lazy from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -507,3 +508,14 @@ class TransformedFoodDetailView(FoodDetailView): if Food.objects.filter(pk=kwargs['pk']).count() == 1: kwargs['stop_redirect'] = (Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model == 'transformedfood') return super().get(*args, **kwargs) + + +class QRCodeRedirectView(RedirectView): + """ + Redirects to the QR code creation page from Food List + """ + def get_redirect_url(self, *args, **kwargs): + slug = self.request.GET.get('slug') + if slug: + return reverse_lazy('food:qrcode_create', kwargs={'slug': slug}) + return reverse_lazy('food:list') diff --git a/apps/member/tests/test_login.py b/apps/member/tests/test_login.py index b8873a14..ce5de1cf 100644 --- a/apps/member/tests/test_login.py +++ b/apps/member/tests/test_login.py @@ -44,7 +44,7 @@ class TemplateLoggedInTests(TestCase): self.assertRedirects(response, settings.LOGIN_REDIRECT_URL, 302, 302) def test_logout(self): - response = self.client.get(reverse("logout")) + response = self.client.post(reverse("logout")) self.assertEqual(response.status_code, 200) def test_admin_index(self): diff --git a/apps/note/api/urls.py b/apps/note/api/urls.py index 67d7371e..c50e68e4 100644 --- a/apps/note/api/urls.py +++ b/apps/note/api/urls.py @@ -13,7 +13,7 @@ def register_note_urls(router, path): router.register(path + '/note', NotePolymorphicViewSet) router.register(path + '/alias', AliasViewSet) router.register(path + '/trust', TrustViewSet) - router.register(path + '/consumer', ConsumerViewSet) + router.register(path + '/consumer', ConsumerViewSet, basename='alias2') router.register(path + '/transaction/category', TemplateCategoryViewSet) router.register(path + '/transaction/transaction', TransactionViewSet) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 0702aefa..2842546f 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -18,7 +18,18 @@ class PermissionScopes(BaseScopes): and can be useful to make queries through the API with limited privileges. """ - def get_all_scopes(self): + def get_all_scopes(self, **kwargs): + scopes = {} + if 'scopes' in kwargs: + for scope in kwargs['scopes']: + if scope == 'openid': + scopes['openid'] = "OpenID Connect" + else: + p = Permission.objects.get(id=scope.split('_')[0]) + club = Club.objects.get(id=scope.split('_')[1]) + scopes[scope] = f"{p.description} (club {club.name})" + return scopes + scopes = {f"{p.id}_{club.id}": f"{p.description} (club {club.name})" for p in Permission.objects.all() for club in Club.objects.all()} scopes['openid'] = "OpenID Connect" diff --git a/apps/permission/signals.py b/apps/permission/signals.py index 5ea04113..af5ab4ce 100644 --- a/apps/permission/signals.py +++ b/apps/permission/signals.py @@ -13,6 +13,7 @@ EXCLUDED = [ 'cas_server.serviceticket', 'cas_server.user', 'cas_server.userattributes', + 'constance.constance', 'contenttypes.contenttype', 'logs.changelog', 'migrations.migration', diff --git a/apps/permission/views.py b/apps/permission/views.py index 39e1f98c..30b13316 100644 --- a/apps/permission/views.py +++ b/apps/permission/views.py @@ -164,14 +164,24 @@ class ScopesView(LoginRequiredMixin, TemplateView): from oauth2_provider.models import Application from .scopes import PermissionScopes - scopes = PermissionScopes() + oidc = False context["scopes"] = {} - all_scopes = scopes.get_all_scopes() for app in Application.objects.filter(user=self.request.user).all(): - available_scopes = scopes.get_available_scopes(app) + available_scopes = PermissionScopes().get_available_scopes(app) context["scopes"][app] = OrderedDict() - items = [(k, v) for (k, v) in all_scopes.items() if k in available_scopes] - # items.sort(key=lambda x: (int(x[0].split("_")[1]), int(x[0].split("_")[0]))) + all_scopes = PermissionScopes().get_all_scopes(scopes=available_scopes) + scopes = {} + for scope in available_scopes: + scopes[scope] = all_scopes[scope] + # remove OIDC scope for sort + if 'openid' in scopes: + del scopes['openid'] + oidc = True + items = [(k, v) for (k, v) in scopes.items()] + items.sort(key=lambda x: (int(x[0].split("_")[1]), int(x[0].split("_")[0]))) + # add oidc if necessary + if oidc: + items.append(('openid', PermissionScopes().get_all_scopes(scopes=['openid'])['openid'])) for k, v in items: context["scopes"][app][k] = v diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 9832c986..29f72ecb 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-27 19:15+0200\n" +"POT-Creation-Date: 2025-07-11 16:10+0200\n" "PO-Revision-Date: 2022-04-11 22:05+0200\n" "Last-Translator: bleizi \n" "Language-Team: French \n" @@ -357,7 +357,7 @@ msgstr "Détails de l'activité" #: apps/note/models/transactions.py:261 #: apps/note/templates/note/transaction_form.html:17 #: apps/note/templates/note/transaction_form.html:152 -#: note_kfet/templates/base.html:78 +#: note_kfet/templates/base.html:79 msgid "Transfer" msgstr "Virement" @@ -474,7 +474,7 @@ msgstr "Inviter" msgid "Create new activity" msgstr "Créer une nouvelle activité" -#: apps/activity/views.py:71 note_kfet/templates/base.html:96 +#: apps/activity/views.py:71 note_kfet/templates/base.html:97 msgid "Activities" msgstr "Activités" @@ -563,7 +563,7 @@ msgstr "Nom" #, fuzzy #| msgid "QR-code number" msgid "QR code number" -msgstr "numéro de QR-code" +msgstr "Numéro de QR-code" #: apps/food/models.py:23 msgid "Allergen" @@ -597,7 +597,7 @@ msgstr "est prêt" msgid "order" msgstr "consigne" -#: apps/food/models.py:107 apps/food/views.py:34 +#: apps/food/models.py:107 apps/food/views.py:35 #: note_kfet/templates/base.html:72 msgid "Food" msgstr "Bouffe" @@ -657,61 +657,75 @@ msgstr "QR-codes" #: apps/food/models.py:286 #: apps/food/templates/food/transformedfood_update.html:24 msgid "QR-code number" -msgstr "numéro de QR-code" +msgstr "Numéro de QR-code" -#: apps/food/templates/food/food_detail.html:19 +#: apps/food/templates/food/food_detail.html:22 msgid "Contained in" msgstr "Contenu dans" -#: apps/food/templates/food/food_detail.html:26 +#: apps/food/templates/food/food_detail.html:29 msgid "Contain" msgstr "Contient" -#: apps/food/templates/food/food_detail.html:35 +#: apps/food/templates/food/food_detail.html:38 msgid "Update" msgstr "Modifier" -#: apps/food/templates/food/food_detail.html:40 +#: apps/food/templates/food/food_detail.html:43 msgid "Add to a meal" msgstr "Ajouter à un plat" -#: apps/food/templates/food/food_detail.html:45 +#: apps/food/templates/food/food_detail.html:48 msgid "Manage ingredients" msgstr "Gérer les ingrédients" -#: apps/food/templates/food/food_detail.html:49 +#: apps/food/templates/food/food_detail.html:52 msgid "Return to the food list" msgstr "Retour à la liste de nourriture" -#: apps/food/templates/food/food_list.html:14 +#: apps/food/templates/food/food_list.html:32 +msgid "View food" +msgstr "Voir l'aliment" + +#: apps/food/templates/food/food_list.html:37 +#: note_kfet/templates/base_search.html:15 +msgid "Search by attribute such as name..." +msgstr "Chercher par un attribut tel que le nom..." + +#: apps/food/templates/food/food_list.html:49 +#: note_kfet/templates/base_search.html:23 +msgid "There is no results." +msgstr "Il n'y a pas de résultat." + +#: apps/food/templates/food/food_list.html:58 msgid "Meal served" msgstr "Plat servis" -#: apps/food/templates/food/food_list.html:19 +#: apps/food/templates/food/food_list.html:63 msgid "New meal" msgstr "Nouveau plat" -#: apps/food/templates/food/food_list.html:28 +#: apps/food/templates/food/food_list.html:72 msgid "There is no meal served." msgstr "Il n'y a pas de plat servi." -#: apps/food/templates/food/food_list.html:35 +#: apps/food/templates/food/food_list.html:79 msgid "Free food" msgstr "Open" -#: apps/food/templates/food/food_list.html:42 +#: apps/food/templates/food/food_list.html:86 msgid "There is no free food." msgstr "Il n'y a pas de bouffe en open" -#: apps/food/templates/food/food_list.html:50 +#: apps/food/templates/food/food_list.html:94 msgid "Food of your clubs" msgstr "Bouffe de tes clubs" -#: apps/food/templates/food/food_list.html:56 +#: apps/food/templates/food/food_list.html:100 msgid "Food of club" msgstr "Bouffe du club" -#: apps/food/templates/food/food_list.html:63 +#: apps/food/templates/food/food_list.html:107 msgid "Yours club has not food yet." msgstr "Ton club n'a pas de bouffe pour l'instant" @@ -785,49 +799,49 @@ msgstr "semaines" msgid "and" msgstr "et" -#: apps/food/views.py:118 +#: apps/food/views.py:120 msgid "Add a new QRCode" msgstr "Ajouter un nouveau QR-code" -#: apps/food/views.py:167 +#: apps/food/views.py:169 msgid "Add an aliment" msgstr "Ajouter un nouvel aliment" -#: apps/food/views.py:235 +#: apps/food/views.py:228 msgid "Add a meal" msgstr "Ajouter un plat" -#: apps/food/views.py:275 +#: apps/food/views.py:259 msgid "Manage ingredients of:" msgstr "Gestion des ingrédienrs de :" -#: apps/food/views.py:289 apps/food/views.py:297 +#: apps/food/views.py:273 apps/food/views.py:281 #, python-brace-format msgid "Fully used in {meal}" msgstr "Aliment entièrement utilisé dans : {meal}" -#: apps/food/views.py:344 +#: apps/food/views.py:320 msgid "Add the ingredient:" msgstr "Ajouter l'ingrédient" -#: apps/food/views.py:370 +#: apps/food/views.py:346 #, python-brace-format msgid "Food fully used in : {meal.name}" msgstr "Aliment entièrement utilisé dans : {meal.name}" -#: apps/food/views.py:389 +#: apps/food/views.py:365 msgid "Update an aliment" msgstr "Modifier un aliment" -#: apps/food/views.py:437 +#: apps/food/views.py:413 msgid "Details of:" msgstr "Détails de :" -#: apps/food/views.py:447 apps/treasury/tables.py:149 +#: apps/food/views.py:423 apps/treasury/tables.py:149 msgid "Yes" msgstr "Oui" -#: apps/food/views.py:449 apps/member/models.py:99 apps/treasury/tables.py:149 +#: apps/food/views.py:425 apps/member/models.py:99 apps/treasury/tables.py:149 msgid "No" msgstr "Non" @@ -1962,8 +1976,8 @@ msgstr "" "mode de paiement et un⋅e utilisateur⋅rice ou un club" #: apps/note/models/transactions.py:357 apps/note/models/transactions.py:360 -#: apps/note/models/transactions.py:363 apps/wei/views.py:1097 -#: apps/wei/views.py:1101 +#: apps/note/models/transactions.py:363 apps/wei/views.py:1105 +#: apps/wei/views.py:1109 msgid "This field is required." msgstr "Ce champ est requis." @@ -2065,6 +2079,8 @@ msgstr "Historique des transactions récentes" #: apps/note/templates/note/mails/weekly_report.txt:32 #: apps/registration/templates/registration/mails/email_validation_email.html:40 #: apps/registration/templates/registration/mails/email_validation_email.txt:16 +#: apps/scripts/templates/scripts/food_report.html:48 +#: apps/scripts/templates/scripts/food_report.txt:14 msgid "Mail generated by the Note Kfet on the" msgstr "Mail généré par la Note Kfet le" @@ -2176,7 +2192,7 @@ msgstr "Chercher un bouton" msgid "Update button" msgstr "Modifier le bouton" -#: apps/note/views.py:156 note_kfet/templates/base.html:66 +#: apps/note/views.py:156 note_kfet/templates/base.html:67 msgid "Consumptions" msgstr "Consommations" @@ -2269,7 +2285,7 @@ msgstr "s'applique au club" msgid "role permissions" msgstr "permissions par rôles" -#: apps/permission/signals.py:73 +#: apps/permission/signals.py:75 #, python-brace-format msgid "" "You don't have the permission to change the field {field} on this instance " @@ -2278,7 +2294,7 @@ msgstr "" "Vous n'avez pas la permission de modifier le champ {field} sur l'instance du " "modèle {app_label}.{model_name}." -#: apps/permission/signals.py:83 apps/permission/views.py:104 +#: apps/permission/signals.py:85 apps/permission/views.py:104 #, python-brace-format msgid "" "You don't have the permission to add an instance of model {app_label}." @@ -2287,7 +2303,7 @@ msgstr "" "Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}." "{model_name}." -#: apps/permission/signals.py:112 +#: apps/permission/signals.py:114 #, python-brace-format msgid "" "You don't have the permission to delete this instance of model {app_label}." @@ -2375,7 +2391,7 @@ msgstr "" "Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » " "avec ces paramètres. Merci de les corriger et de réessayer." -#: apps/permission/views.py:111 note_kfet/templates/base.html:120 +#: apps/permission/views.py:111 note_kfet/templates/base.html:121 msgid "Rights" msgstr "Droits" @@ -2580,7 +2596,7 @@ msgstr "" msgid "Invalidate pre-registration" msgstr "Invalider l'inscription" -#: apps/treasury/apps.py:12 note_kfet/templates/base.html:102 +#: apps/treasury/apps.py:12 note_kfet/templates/base.html:103 msgid "Treasury" msgstr "Trésorerie" @@ -2996,7 +3012,7 @@ msgstr "Gérer les crédits de la Société générale" #: apps/wei/apps.py:10 apps/wei/models.py:42 apps/wei/models.py:43 #: apps/wei/models.py:67 apps/wei/models.py:192 -#: note_kfet/templates/base.html:108 +#: note_kfet/templates/base.html:109 msgid "WEI" msgstr "WEI" @@ -3041,7 +3057,7 @@ msgstr "Rôles au WEI" msgid "Select the roles that you are interested in." msgstr "Sélectionnez les rôles qui vous intéressent." -#: apps/wei/forms/registration.py:147 +#: apps/wei/forms/registration.py:160 msgid "This team doesn't belong to the given bus." msgstr "Cette équipe n'appartient pas à ce bus." @@ -3120,7 +3136,7 @@ msgstr "Rôle au WEI" msgid "Credit from Société générale" msgstr "Crédit de la Société générale" -#: apps/wei/models.py:202 apps/wei/views.py:984 +#: apps/wei/models.py:202 apps/wei/views.py:992 msgid "Caution check given" msgstr "Chèque de caution donné" @@ -3352,7 +3368,6 @@ msgid "View club" msgstr "Voir le club" #: apps/wei/templates/wei/bus_detail.html:26 -#| msgid "survey information" msgid "Edit information" msgstr "Modifier les informations" @@ -3373,8 +3388,8 @@ msgstr "Télécharger au format PDF" #: apps/wei/templates/wei/survey.html:11 #: apps/wei/templates/wei/survey_closed.html:11 -#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1159 -#: apps/wei/views.py:1214 apps/wei/views.py:1261 +#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1167 +#: apps/wei/views.py:1222 apps/wei/views.py:1269 msgid "Survey WEI" msgstr "Questionnaire WEI" @@ -3654,51 +3669,51 @@ msgstr "" msgid "Update WEI Registration" msgstr "Modifier l'inscription WEI" -#: apps/wei/views.py:810 +#: apps/wei/views.py:811 msgid "No membership found for this registration" msgstr "Pas d'adhésion trouvée pour cette inscription" -#: apps/wei/views.py:819 +#: apps/wei/views.py:820 msgid "You don't have the permission to update memberships" msgstr "" "Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}." "{model_name}." -#: apps/wei/views.py:825 +#: apps/wei/views.py:826 #, python-format msgid "You don't have the permission to update the field %(field)s" msgstr "Vous n'avez pas la permission de modifier le champ %(field)s" -#: apps/wei/views.py:870 +#: apps/wei/views.py:871 msgid "Delete WEI registration" msgstr "Supprimer l'inscription WEI" -#: apps/wei/views.py:881 +#: apps/wei/views.py:882 msgid "You don't have the right to delete this WEI registration." msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI." -#: apps/wei/views.py:899 +#: apps/wei/views.py:900 msgid "Validate WEI registration" msgstr "Valider l'inscription WEI" -#: apps/wei/views.py:985 +#: apps/wei/views.py:993 msgid "Please make sure the check is given before validating the registration" msgstr "" "Merci de vous assurer que le chèque a bien été donné avant de valider " "l'adhésion" -#: apps/wei/views.py:991 +#: apps/wei/views.py:999 msgid "Create deposit transaction" msgstr "Créer une transaction de caution" -#: apps/wei/views.py:992 +#: apps/wei/views.py:1000 #, python-format msgid "" "A transaction of %(amount).2f€ will be created from the user's Note account" msgstr "" "Un transaction de %(amount).2f€ va être créée depuis la note de l'utilisateur" -#: apps/wei/views.py:1087 +#: apps/wei/views.py:1095 #, python-format msgid "" "This user doesn't have enough money to join this club and pay the deposit. " @@ -3708,21 +3723,21 @@ msgstr "" "payer la cautionSolde actuel : %(balance)d€, crédit : %(credit)d€, requis : " "%(needed)d€" -#: apps/wei/views.py:1140 +#: apps/wei/views.py:1148 #, fuzzy, python-format #| msgid "total amount" msgid "Caution %(name)s" msgstr "montant total" -#: apps/wei/views.py:1354 +#: apps/wei/views.py:1362 msgid "Attribute buses to first year members" msgstr "Répartir les 1A dans les bus" -#: apps/wei/views.py:1380 +#: apps/wei/views.py:1388 msgid "Attribute bus" msgstr "Attribuer un bus" -#: apps/wei/views.py:1420 +#: apps/wei/views.py:1428 msgid "" "No first year student without a bus found. Either all of them have a bus, or " "none has filled the survey yet." @@ -3746,13 +3761,13 @@ msgstr "bde" #: apps/wrapped/models.py:65 msgid "data json" -msgstr "donnée json" +msgstr "données json" #: apps/wrapped/models.py:66 msgid "data in the wrapped and generated by the script generate_wrapped" msgstr "donnée dans le wrapped et générée par le script generate_wrapped" -#: apps/wrapped/models.py:70 note_kfet/templates/base.html:114 +#: apps/wrapped/models.py:70 note_kfet/templates/base.html:115 msgid "Wrapped" msgstr "Wrapped" @@ -3785,7 +3800,7 @@ msgid "Copy link" msgstr "Copier le lien" #: apps/wrapped/templates/wrapped/1/wrapped_base.html:16 -#: note_kfet/templates/base.html:14 +#: note_kfet/templates/base.html:15 msgid "The ENS Paris-Saclay BDE note." msgstr "La note du BDE de l'ENS Paris-Saclay." @@ -3888,7 +3903,7 @@ msgid "" "Do not forget to ask permission to people who are in your wrapped before to " "make them public" msgstr "" -"N'oublies pas de demander la permission des personnes apparaissant dans un " +"N'oublie pas de demander la permission des personnes apparaissant dans un " "wrapped avant de le rendre public" #: apps/wrapped/templates/wrapped/wrapped_list.html:40 @@ -3907,19 +3922,19 @@ msgstr "Le wrapped est public" msgid "List of wrapped" msgstr "Liste des wrapped" -#: note_kfet/settings/base.py:177 +#: note_kfet/settings/base.py:180 msgid "German" msgstr "Allemand" -#: note_kfet/settings/base.py:178 +#: note_kfet/settings/base.py:181 msgid "English" msgstr "Anglais" -#: note_kfet/settings/base.py:179 +#: note_kfet/settings/base.py:182 msgid "Spanish" msgstr "Espagnol" -#: note_kfet/settings/base.py:180 +#: note_kfet/settings/base.py:183 msgid "French" msgstr "Français" @@ -3980,34 +3995,34 @@ msgstr "" msgid "Reset" msgstr "Réinitialiser" -#: note_kfet/templates/base.html:84 +#: note_kfet/templates/base.html:85 msgid "Users" msgstr "Utilisateur·rices" -#: note_kfet/templates/base.html:90 +#: note_kfet/templates/base.html:91 msgid "Clubs" msgstr "Clubs" -#: note_kfet/templates/base.html:125 +#: note_kfet/templates/base.html:126 msgid "Admin" msgstr "Admin" -#: note_kfet/templates/base.html:139 +#: note_kfet/templates/base.html:140 msgid "My account" msgstr "Mon compte" -#: note_kfet/templates/base.html:142 +#: note_kfet/templates/base.html:145 msgid "Log out" msgstr "Se déconnecter" -#: note_kfet/templates/base.html:150 +#: note_kfet/templates/base.html:154 #: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:28 msgid "Sign up" msgstr "Inscription" -#: note_kfet/templates/base.html:157 +#: note_kfet/templates/base.html:161 #: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:38 @@ -4015,7 +4030,7 @@ msgstr "Inscription" msgid "Log in" msgstr "Se connecter" -#: note_kfet/templates/base.html:171 +#: note_kfet/templates/base.html:175 msgid "" "You are not a BDE member anymore. Please renew your membership if you want " "to use the note." @@ -4023,7 +4038,7 @@ msgstr "" "Vous n'êtes plus adhérent·e BDE. Merci de réadhérer si vous voulez profiter " "de la note." -#: note_kfet/templates/base.html:177 +#: note_kfet/templates/base.html:181 msgid "" "Your e-mail address is not validated. Please check your mail inbox and click " "on the validation link." @@ -4031,7 +4046,7 @@ msgstr "" "Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail " "et de cliquer sur le lien de validation." -#: note_kfet/templates/base.html:183 +#: note_kfet/templates/base.html:187 msgid "" "You declared that you opened a bank account in the Société générale. The " "bank did not validate the creation of the account to the BDE, so the " @@ -4045,22 +4060,38 @@ msgstr "" "vérification peut durer quelques jours. Merci de vous assurer de bien aller " "au bout de vos démarches." -#: note_kfet/templates/base.html:206 +#: note_kfet/templates/base.html:214 msgid "Contact us" msgstr "Nous contacter" -#: note_kfet/templates/base.html:208 +#: note_kfet/templates/base.html:216 msgid "Technical Support" msgstr "Support technique" -#: note_kfet/templates/base.html:210 +#: note_kfet/templates/base.html:218 msgid "Charte Info (FR)" msgstr "Charte Info (FR)" -#: note_kfet/templates/base.html:212 +#: note_kfet/templates/base.html:220 msgid "FAQ (FR)" msgstr "FAQ (FR)" +#: note_kfet/templates/base.html:222 +msgid "Managed by BDE" +msgstr "Gérer par le BDE" + +#: note_kfet/templates/base.html:224 +msgid "Hosted by Cr@ns" +msgstr "Hébergé par le Cr@ans" + +#: note_kfet/templates/base.html:266 +msgid "The note is not available for now" +msgstr "La note est indisponible pour le moment" + +#: note_kfet/templates/base.html:268 +msgid "Thank you for your understanding -- The Respos Info of BDE" +msgstr "Merci de votre compréhension -- Les Respos Info du BDE" + #: note_kfet/templates/base_search.html:15 msgid "Search by attribute such as name..." msgstr "Chercher par un attribut tel que le nom..." @@ -4069,6 +4100,41 @@ msgstr "Chercher par un attribut tel que le nom..." msgid "There is no results." msgstr "Il n'y a pas de résultat." +#: note_kfet/templates/cas/logged.html:8 +msgid "" +"

Log In Successful

You have successfully logged into the Central " +"Authentication Service.
For security reasons, please Log Out and Exit " +"your web browser when you are done accessing services that require " +"authentication!" +msgstr "" +"

Connection réussie

Vous vous êtes bien connecté au Service Central d'Authentification." +"
Pour des raisons de sécurité, veuillez vous déconnecter et fermer votre navigateur internet " +"une fois que vous aurez fini d'accéder aux services qui requiert une authentification !" + +#: note_kfet/templates/cas/logged.html:14 +msgid "Log me out from all my sessions" +msgstr "Me déconnecter de toutes mes sessions" + +#: note_kfet/templates/cas/logged.html:20 +msgid "Forget the identity provider" +msgstr "Oublier le fournisseur d'identité" + +#: note_kfet/templates/cas/logged.html:24 +msgid "Logout" +msgstr "Déconnexion" + +#: note_kfet/templates/cas/login.html:11 +msgid "Please log in" +msgstr "Veuillez vous connecter" + +#: note_kfet/templates/cas/login.html:23 +msgid "Login" +msgstr "Connexion" + +#: note_kfet/templates/cas/warn.html:14 +msgid "Connect to the service" +msgstr "Connexion au service" + #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 msgid "Are you sure to delete the application" msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application" @@ -4289,10 +4355,86 @@ msgstr "" "d'adhésion. Vous devez également valider votre adresse email en suivant le " "lien que vous avez reçu." -#, fuzzy, python-format -#~| msgid "Creation date" -#~ msgid "Deposit %(name)s" -#~ msgstr "Caution %(name)s" +#, fuzzy +#~| msgid "QR-code" +#~ msgid "Go to QR-code" +#~ msgstr "QR-code" + +#, python-brace-format +#~ msgid "QR-code number {qr_code_number}" +#~ msgstr "Numéro du QR-code {qr_code_number}" + +#~ msgid "was eaten" +#~ msgstr "a été mangé" + +#~ msgid "is active" +#~ msgstr "est en cours" + +#~ msgid "foods" +#~ msgstr "bouffes" + +#~ msgid "Arrival date" +#~ msgstr "Date d'arrivée" + +#~ msgid "Active" +#~ msgstr "Actif" + +#~ msgid "Eaten" +#~ msgstr "Mangé" + +#~ msgid "number" +#~ msgstr "numéro" + +#~ msgid "View details" +#~ msgstr "Voir plus" + +#~ msgid "Ready" +#~ msgstr "Prêt" + +#~ msgid "Creation date" +#~ msgstr "Date de création" + +#~ msgid "Ingredients" +#~ msgstr "Ingrédients" + +#~ msgid "Open" +#~ msgstr "Open" + +#~ msgid "All meals" +#~ msgstr "Tout les plats" + +#~ msgid "There is no meal." +#~ msgstr "Il n'y a pas de plat" + +#~ msgid "The product is already prepared" +#~ msgstr "Le produit est déjà prêt" + +#~ msgid "Add a new basic food with QRCode" +#~ msgstr "Ajouter un nouvel ingrédient avec un QR-code" + +#~ msgid "QRCode" +#~ msgstr "QR-code" + +#~ msgid "Add a new meal" +#~ msgstr "Ajouter un nouveau plat" + +#~ msgid "Update a meal" +#~ msgstr "Modifier le plat" + +#, fuzzy +#~| msgid "invalidate" +#~ msgid "Enter a valid color." +#~ msgstr "dévalider" + +#, fuzzy +#~| msgid "invalidate" +#~ msgid "Enter a valid value." +#~ msgstr "dévalider" + +#, fuzzy +#~| msgid "Invitation" +#~ msgid "Syndication" +#~ msgstr "Invitation" #, fuzzy #~| msgid "There is no results." @@ -4706,7 +4848,7 @@ msgstr "" #, python-brace-format #~ msgid "QR-code number {qr_code_number}" -#~ msgstr "numéro du QR-code {qr_code_number}" +#~ msgstr "Numéro du QR-code {qr_code_number}" #~ msgid "was eaten" #~ msgstr "a été mangé" diff --git a/note.cron b/note.cron index fb45a4b3..6c2b94c6 100644 --- a/note.cron +++ b/note.cron @@ -27,5 +27,6 @@ MAILTO=notekfet2020@lists.crans.org # Vider les tokens Oauth2 00 6 * * * root cd /var/www/note_kfet && env/bin/python manage.py cleartokens -v 0 # Envoyer la liste des abonnés à la NL BDA - 00 10 * * 0 root cd /var/www/note_kfet && env/bin/python manage.py extract_ml_registrations -t art -e "bda.ensparissaclay@gmail.com" - \ No newline at end of file + 00 10 * * 0 root cd /var/www/note_kfet && env/bin/python manage.py extract_ml_registrations -t art -e "bda.ensparissaclay@gmail.com" +# Envoyer la liste de la bouffe au club et aux GCKs + 00 8 * * 1 root cd /var/www/note_kfet && env/bin/python manage.py send_mail_for_food --report --club diff --git a/note_kfet/admin.py b/note_kfet/admin.py index 6bda409f..7f4effe3 100644 --- a/note_kfet/admin.py +++ b/note_kfet/admin.py @@ -56,3 +56,8 @@ if "cas_server" in settings.INSTALLED_APPS: from cas_server.models import * admin_site.register(ServicePattern, ServicePatternAdmin) admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin) + +if "constance" in settings.INSTALLED_APPS: + from constance.admin import * + from constance.models import * + admin_site.register([Config], ConstanceAdmin) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 2f7965d8..1fa0a0ea 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -39,7 +39,9 @@ SECURE_HSTS_PRELOAD = True INSTALLED_APPS = [ # External apps 'bootstrap_datepicker_plus', + 'cas_server', 'colorfield', + 'constance', 'crispy_bootstrap4', 'crispy_forms', # 'django_htcpcp_tea', @@ -111,6 +113,7 @@ TEMPLATES = [ 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ + 'constance.context_processors.config', 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', @@ -307,6 +310,30 @@ PHONENUMBER_DEFAULT_REGION = 'FR' # We add custom information to CAS, in order to give a normalized name to other services CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' +CAS_LOGIN_TEMPLATE = 'cas/login.html' +CAS_LOGOUT_TEMPLATE = 'cas/logout.html' +CAS_WARN_TEMPLATE = 'cas/warn.html' +CAS_LOGGED_TEMPLATE = 'cas/logged.html' # Default field for primary key DEFAULT_AUTO_FIELD = "django.db.models.AutoField" + +# Constance settings +CONSTANCE_ADDITIONAL_FIELDS = { + 'banner_type': ['django.forms.fields.ChoiceField', { + 'widget': 'django.forms.Select', + 'choices': (('info', 'Info'), ('success', 'Success'), ('warning', 'Warning'), ('danger', 'Danger')) + }], +} +CONSTANCE_CONFIG = { + 'BANNER_MESSAGE': ('', 'Some message', str), + 'BANNER_TYPE': ('info', 'Banner type', 'banner_type'), + 'MAINTENANCE': (False, 'check for mainteance mode', bool), + 'MAINTENANCE_MESSAGE': ('', 'Some maintenance message', str), +} +CONSTANCE_CONFIG_FIELDSETS = { + 'Maintenance': ('MAINTENANCE_MESSAGE', 'MAINTENANCE'), + 'Banner': ('BANNER_MESSAGE', 'BANNER_TYPE'), +} +CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend' +CONSTANCE_SUPERUSER_ONLY = True diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html index 1c601c50..b6762c9b 100644 --- a/note_kfet/templates/base.html +++ b/note_kfet/templates/base.html @@ -5,6 +5,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %} +{% if not config.MAINTENANCE %} @@ -138,9 +139,12 @@ SPDX-License-Identifier: GPL-3.0-or-later {% trans "My account" %} - - {% trans "Log out" %} - +
+ {% csrf_token %} + +
{% else %} @@ -188,7 +192,11 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblocktrans %} {% endif %} - {# TODO Add banners #} + {% if config.BANNER_MESSAGE and user.is_authenticated %} +
+ {{ config.BANNER_MESSAGE }} +
+ {% endif %} {% block content %}

Default content...

@@ -210,6 +218,10 @@ SPDX-License-Identifier: GPL-3.0-or-later class="text-muted">{% trans "Charte Info (FR)" %} — {% trans "FAQ (FR)" %} — + {% trans "Managed by BDE" %} — + {% trans "Hosted by Cr@ns" %} — {% csrf_token %} {% trans "Log me out from all my sessions" %} + + + {% if settings.CAS_FEDERATE and request.COOKIES.remember_provider %} +
+ +
+ {% endif %} + + + + +{% endblock %} diff --git a/note_kfet/templates/cas/login.html b/note_kfet/templates/cas/login.html new file mode 100644 index 00000000..84fd0cf8 --- /dev/null +++ b/note_kfet/templates/cas/login.html @@ -0,0 +1,42 @@ +{% extends "base.html" %} +{% comment %} +Copyright (C) by BDE ENS-Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block ante_messages %} + {% if auto_submit %}{% endif %} +{% endblock %} + +{% block content %} +
+
+
+ +
+ +{% endblock %} + +{% block javascript_inline %} +jQuery(function( $ ){ + $("#id_warn").click(function(e){ + if($("#id_warn").is(':checked')){ + createCookie("warn", "on", 10 * 365); + } else { + eraseCookie("warn"); + } + }); +}); +{% if auto_submit %}document.getElementById('login_form').submit(); // SUBMIT FORM{% endif %} +{% endblock %} diff --git a/note_kfet/templates/cas/logout.html b/note_kfet/templates/cas/logout.html new file mode 100644 index 00000000..814f7d33 --- /dev/null +++ b/note_kfet/templates/cas/logout.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% comment %} +Copyright (C) by BDE ENS-Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n static %} +{% block content %} + +{% endblock %} + diff --git a/note_kfet/templates/cas/warn.html b/note_kfet/templates/cas/warn.html new file mode 100644 index 00000000..89ee1815 --- /dev/null +++ b/note_kfet/templates/cas/warn.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% comment %} +Copyright (C) by BDE ENS-Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n static %} + +{% block content %} +
+
+ +
+
+{% endblock %} + diff --git a/requirements.txt b/requirements.txt index f4a32c97..c40bf0bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,21 @@ -beautifulsoup4~=4.12.3 -crispy-bootstrap4~=2023.1 -Django~=4.2.9 +beautifulsoup4~=4.13.4 +crispy-bootstrap4~=2025.6 +Django~=5.2.4 django-bootstrap-datepicker-plus~=5.0.5 -#django-cas-server~=2.0.0 -django-colorfield~=0.11.0 -django-crispy-forms~=2.1.0 -django-extensions>=3.2.3 -django-filter~=23.5 +django-cas-server~=3.1.0 +django-colorfield~=0.14.0 +django-constance~=4.3.2 +django-crispy-forms~=2.4.0 +django-extensions>=4.1.0 +django-filter~=25.1 #django-htcpcp-tea~=0.8.1 -django-mailer~=2.3.1 -django-oauth-toolkit~=2.3.0 -django-phonenumber-field~=7.3.0 +django-mailer~=2.3.2 +django-oauth-toolkit~=3.0.1 +django-phonenumber-field~=8.1.0 django-polymorphic~=3.1.0 -djangorestframework~=3.14.0 +djangorestframework~=3.16.0 django-rest-polymorphic~=0.1.10 -django-tables2~=2.7.0 +django-tables2~=2.7.5 python-memcached~=1.62 -phonenumbers~=8.13.28 -Pillow>=10.2.0 +phonenumbers~=9.0.8 +Pillow>=11.3.0 diff --git a/tox.ini b/tox.ini index 1bfeb593..1fa7cf7a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,13 @@ [tox] envlist = # Ubuntu 22.04 Python - py310-django42 + py310-django52 # Debian Bookworm Python - py311-django42 + py311-django52 # Ubuntu 24.04 Python - py312-django42 + py312-django52 linters skipsdist = True @@ -32,8 +32,7 @@ deps = pep8-naming pyflakes commands = - flake8 apps --extend-exclude apps/scripts,apps/wrapped/management/commands - flake8 apps/wrapped/management/commands --extend-ignore=C901 + flake8 apps --extend-exclude apps/scripts [flake8] ignore = W503, I100, I101, B019