From 89cc03141bf49a9a97dba2c43dd925b84d97c969 Mon Sep 17 00:00:00 2001 From: quark Date: Thu, 12 Jun 2025 18:48:29 +0200 Subject: [PATCH 01/22] allow search with club name --- apps/food/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/food/views.py b/apps/food/views.py index d9556ef6..f8c7977d 100644 --- a/apps/food/views.py +++ b/apps/food/views.py @@ -63,7 +63,8 @@ class FoodListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, Li valid_regex = is_regex(pattern) suffix = '__iregex' if valid_regex else '__istartswith' prefix = '^' if valid_regex else '' - qs = qs.filter(Q(**{f'name{suffix}': prefix + pattern})) + qs = qs.filter(Q(**{f'name{suffix}': prefix + pattern}) + | Q(**{f'owner__name{suffix}': prefix + pattern})) else: qs = qs.none() search_table = qs.filter(PermissionBackend.filter_queryset(self.request, Food, 'view')) From d71105976f58628c90d730ab991e8b2c96704edd Mon Sep 17 00:00:00 2001 From: quark Date: Sat, 14 Jun 2025 18:01:42 +0200 Subject: [PATCH 02/22] oidc --- apps/permission/scopes.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 6ee5818f..29b04217 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -3,6 +3,7 @@ from oauth2_provider.oauth2_validators import OAuth2Validator from oauth2_provider.scopes import BaseScopes from member.models import Club +from note.models import Alias from note_kfet.middlewares import get_current_request from .backends import PermissionBackend @@ -35,7 +36,18 @@ class PermissionScopes(BaseScopes): class PermissionOAuth2Validator(OAuth2Validator): - oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 + oidc_claim_scope = OAuth2Validator.oidc_claim_scope + oidc_claim_scope.update({"name": 'openid', + "normalized_name": 'openid', + "email": 'openid', + }) + + def get_additional_claims(self, request): + return { + "name": request.user.username, + "normalized_name": Alias.normalize(request.user.username), + "email": request.user.email, + } def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): """ From 97621e8704bd3e99987d813cc73f595c27d7b2d9 Mon Sep 17 00:00:00 2001 From: thomasl Date: Sat, 14 Jun 2025 20:07:29 +0200 Subject: [PATCH 03/22] Update doc about scripts --- docs/scripts.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/scripts.rst b/docs/scripts.rst index fc85468c..7ddda96d 100644 --- a/docs/scripts.rst +++ b/docs/scripts.rst @@ -136,7 +136,7 @@ de diffusion utiles. Faîtes attention, donc où la sortie est stockée. -Il prend 2 options : +Il prend 4 options : * ``--type``, qui prend en argument ``members`` (défaut), ``clubs``, ``events``, ``art``, ``sport``, qui permet respectivement de sortir la liste des adresses mails des adhérent⋅es @@ -149,7 +149,10 @@ Il prend 2 options : pour la ML Adhérents, pour exporter les mails des adhérents au BDE pendant n'importe laquelle des ``n+1`` dernières années. -Le script sort sur la sortie standard la liste des adresses mails à inscrire. +* ``--email``, qui prend en argument une chaine de caractère contenant une adresse email. + +Si aucun email n'est renseigné, le script sort sur la sortie standard la liste des adresses mails à inscrire. +Dans le cas contraire, la liste est envoyée à l'adresse passée en argument. Attention : il y a parfois certains cas particuliers à prendre en compte, il n'est malheureusement pas aussi simple que de simplement supposer que ces listes sont exhaustives. From 092cc37320a996aabf865412d5fe6d812c66c2c7 Mon Sep 17 00:00:00 2001 From: quark Date: Tue, 17 Jun 2025 00:26:13 +0200 Subject: [PATCH 04/22] OIDC 0 Quark 1 --- apps/permission/scopes.py | 29 ++++++++++++++++++++--------- apps/permission/signals.py | 1 + apps/permission/views.py | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 29b04217..7d2619c1 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -18,22 +18,27 @@ class PermissionScopes(BaseScopes): """ def get_all_scopes(self): - return {f"{p.id}_{club.id}": f"{p.description} (club {club.name})" - for p in Permission.objects.all() for club in Club.objects.all()} + 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" + return scopes def get_available_scopes(self, application=None, request=None, *args, **kwargs): if not application: return [] - return [f"{p.id}_{p.membership.club.id}" - for t in Permission.PERMISSION_TYPES - for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0])] + scopes = [f"{p.id}_{p.membership.club.id}" + for t in Permission.PERMISSION_TYPES + for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0])] + scopes.append('openid') + return scopes def get_default_scopes(self, application=None, request=None, *args, **kwargs): if not application: return [] - return [f"{p.id}_{p.membership.club.id}" - for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')] - + scopes = [f"{p.id}_{p.membership.club.id}" + for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')] + scopes.append('openid') + return scopes class PermissionOAuth2Validator(OAuth2Validator): oidc_claim_scope = OAuth2Validator.oidc_claim_scope @@ -49,6 +54,10 @@ class PermissionOAuth2Validator(OAuth2Validator): "email": request.user.email, } + def get_discovery_claims(self, request): + claims = super().get_discovery_claims(self) + return claims + ["name", "normalized_name", "email"] + def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): """ User can request as many scope as he wants, including invalid scopes, @@ -65,7 +74,9 @@ class PermissionOAuth2Validator(OAuth2Validator): scope = f"{p.id}_{p.membership.club.id}" if scope in scopes: valid_scopes.add(scope) + + if 'openid' in scopes: + valid_scopes.add('openid') request.scopes = valid_scopes - return valid_scopes diff --git a/apps/permission/signals.py b/apps/permission/signals.py index b2394c6f..5ea04113 100644 --- a/apps/permission/signals.py +++ b/apps/permission/signals.py @@ -19,6 +19,7 @@ EXCLUDED = [ 'oauth2_provider.accesstoken', 'oauth2_provider.grant', 'oauth2_provider.refreshtoken', + 'oauth2_provider.idtoken', 'sessions.session', ] diff --git a/apps/permission/views.py b/apps/permission/views.py index e7de920e..39e1f98c 100644 --- a/apps/permission/views.py +++ b/apps/permission/views.py @@ -171,7 +171,7 @@ class ScopesView(LoginRequiredMixin, TemplateView): available_scopes = scopes.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]))) + # items.sort(key=lambda x: (int(x[0].split("_")[1]), int(x[0].split("_")[0]))) for k, v in items: context["scopes"][app][k] = v From df0d886db97ce55088f71e4bb192a47e12182f24 Mon Sep 17 00:00:00 2001 From: quark Date: Tue, 17 Jun 2025 11:46:33 +0200 Subject: [PATCH 05/22] linters --- apps/permission/scopes.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 7d2619c1..0702aefa 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -1,5 +1,6 @@ # Copyright (C) 2018-2025 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later + from oauth2_provider.oauth2_validators import OAuth2Validator from oauth2_provider.scopes import BaseScopes from member.models import Club @@ -19,7 +20,7 @@ class PermissionScopes(BaseScopes): def get_all_scopes(self): scopes = {f"{p.id}_{club.id}": f"{p.description} (club {club.name})" - for p in Permission.objects.all() for club in Club.objects.all()} + for p in Permission.objects.all() for club in Club.objects.all()} scopes['openid'] = "OpenID Connect" return scopes @@ -27,8 +28,8 @@ class PermissionScopes(BaseScopes): if not application: return [] scopes = [f"{p.id}_{p.membership.club.id}" - for t in Permission.PERMISSION_TYPES - for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0])] + for t in Permission.PERMISSION_TYPES + for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0])] scopes.append('openid') return scopes @@ -36,10 +37,11 @@ class PermissionScopes(BaseScopes): if not application: return [] scopes = [f"{p.id}_{p.membership.club.id}" - for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')] + for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')] scopes.append('openid') return scopes + class PermissionOAuth2Validator(OAuth2Validator): oidc_claim_scope = OAuth2Validator.oidc_claim_scope oidc_claim_scope.update({"name": 'openid', @@ -74,7 +76,7 @@ class PermissionOAuth2Validator(OAuth2Validator): scope = f"{p.id}_{p.membership.club.id}" if scope in scopes: valid_scopes.add(scope) - + if 'openid' in scopes: valid_scopes.add('openid') From cdc6f0a3f8cbc9baaa9c71899d3f332692069c0e Mon Sep 17 00:00:00 2001 From: quark Date: Fri, 27 Jun 2025 12:13:54 +0200 Subject: [PATCH 06/22] Fix jwks.json --- .env_example | 3 +++ README.md | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.env_example b/.env_example index 7e1dbd3b..5257e83c 100644 --- a/.env_example +++ b/.env_example @@ -21,3 +21,6 @@ EMAIL_PASSWORD=CHANGE_ME # Wiki configuration WIKI_USER=NoteKfet2020 WIKI_PASSWORD= + +# OIDC +OIDC_RSA_PRIVATE_KEY= diff --git a/README.md b/README.md index 4ba19356..c340d58c 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ Bien que cela permette de créer une instance sur toutes les distributions, 6. (Optionnel) **Création d'une clé privée OpenID Connect** Pour activer le support d'OpenID Connect, il faut générer une clé privée, par -exemple avec openssl (`openssl genrsa -out oidc.key 4096`), et renseigner son -emplacement dans `OIDC_RSA_PRIVATE_KEY` (par défaut `/var/secrets/oidc.key`). +exemple avec openssl (`openssl genrsa -out oidc.key 4096`), et copier la clé dans .env dans le champ +`OIDC_RSA_PRIVATE_KEY`. 7. Enjoy : @@ -237,8 +237,8 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous. 7. **Création d'une clé privée OpenID Connect** Pour activer le support d'OpenID Connect, il faut générer une clé privée, par -exemple avec openssl (`openssl genrsa -out oidc.key 4096`), et renseigner son -emplacement dans `OIDC_RSA_PRIVATE_KEY` (par défaut `/var/secrets/oidc.key`). +exemple avec openssl (`openssl genrsa -out oidc.key 4096`), et renseigner le champ +`OIDC_RSA_PRIVATE_KEY` dans le .env (par défaut `/var/secrets/oidc.key`). 8. *Enjoy \o/* From c411197af3a3240ba23376b10b9863600b64a8db Mon Sep 17 00:00:00 2001 From: quark Date: Fri, 27 Jun 2025 22:13:43 +0200 Subject: [PATCH 07/22] multiline support for RSA key in env --- .env_example | 2 +- note_kfet/settings/base.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env_example b/.env_example index 5257e83c..da0b4efa 100644 --- a/.env_example +++ b/.env_example @@ -23,4 +23,4 @@ WIKI_USER=NoteKfet2020 WIKI_PASSWORD= # OIDC -OIDC_RSA_PRIVATE_KEY= +OIDC_RSA_PRIVATE_KEY=CHANGE_ME diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 0f3a757c..2f7965d8 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -270,7 +270,7 @@ OAUTH2_PROVIDER = { 'PKCE_REQUIRED': False, # PKCE (fix a breaking change of django-oauth-toolkit 2.0.0) 'OIDC_ENABLED': True, 'OIDC_RSA_PRIVATE_KEY': - os.getenv('OIDC_RSA_PRIVATE_KEY', '/var/secrets/oidc.key'), + os.getenv('OIDC_RSA_PRIVATE_KEY', 'CHANGE_ME_IN_ENV_SETTINGS').replace('\\n', '\n'), # for multilines 'SCOPES': { 'openid': "OpenID Connect scope" }, } From 6edef619aa7b79ca3f1d1a62b3de631a67458adb Mon Sep 17 00:00:00 2001 From: quark Date: Thu, 3 Jul 2025 11:37:07 +0200 Subject: [PATCH 08/22] change requirements.txt --- apps/note/api/urls.py | 2 +- note_kfet/settings/base.py | 1 + requirements.txt | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 16 deletions(-) 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/note_kfet/settings/base.py b/note_kfet/settings/base.py index 2f7965d8..779ee23d 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -39,6 +39,7 @@ SECURE_HSTS_PRELOAD = True INSTALLED_APPS = [ # External apps 'bootstrap_datepicker_plus', + 'cas_server', 'colorfield', 'crispy_bootstrap4', 'crispy_forms', diff --git a/requirements.txt b/requirements.txt index f4a32c97..1d6f5063 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ -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-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 From f54dd3048207fef48999dafd2cb13c6a2a34cd52 Mon Sep 17 00:00:00 2001 From: quark Date: Thu, 3 Jul 2025 15:18:29 +0200 Subject: [PATCH 09/22] fix logout test --- apps/member/tests/test_login.py | 2 +- note_kfet/templates/base.html | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) 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/note_kfet/templates/base.html b/note_kfet/templates/base.html index 1c601c50..3dbfa901 100644 --- a/note_kfet/templates/base.html +++ b/note_kfet/templates/base.html @@ -138,9 +138,12 @@ SPDX-License-Identifier: GPL-3.0-or-later {% trans "My account" %} - - {% trans "Log out" %} - +
+ {% csrf_token %} + +
{% else %} From 85ea43a7cf9e62b1cc6add430bb266baa7d0f6db Mon Sep 17 00:00:00 2001 From: quark Date: Fri, 4 Jul 2025 16:26:40 +0200 Subject: [PATCH 10/22] change pipeline --- .gitlab-ci.yml | 8 ++++---- tox.ini | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) 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/tox.ini b/tox.ini index 1bfeb593..8ad79854 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 From b7c0986a5f358863714f24d75ea264487147fae5 Mon Sep 17 00:00:00 2001 From: quark Date: Fri, 4 Jul 2025 17:14:12 +0200 Subject: [PATCH 11/22] cron and linters --- note.cron | 5 +++-- tox.ini | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) 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/tox.ini b/tox.ini index 8ad79854..1fa7cf7a 100644 --- a/tox.ini +++ b/tox.ini @@ -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 From 4cc43fe4b62e936b1bb9b169b4286dc504694c08 Mon Sep 17 00:00:00 2001 From: quark Date: Fri, 4 Jul 2025 22:11:47 +0200 Subject: [PATCH 12/22] traduction, resolve #133 --- locale/fr/LC_MESSAGES/django.po | 113 +++++++++++++++++--------------- note_kfet/templates/base.html | 4 ++ 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 9832c986..9f9fb04f 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-04 21:47+0200\n" "PO-Revision-Date: 2022-04-11 22:05+0200\n" "Last-Translator: bleizi \n" "Language-Team: French \n" @@ -785,49 +785,49 @@ msgstr "semaines" msgid "and" msgstr "et" -#: apps/food/views.py:118 +#: apps/food/views.py:119 msgid "Add a new QRCode" msgstr "Ajouter un nouveau QR-code" -#: apps/food/views.py:167 +#: apps/food/views.py:168 msgid "Add an aliment" msgstr "Ajouter un nouvel aliment" -#: apps/food/views.py:235 +#: apps/food/views.py:236 msgid "Add a meal" msgstr "Ajouter un plat" -#: apps/food/views.py:275 +#: apps/food/views.py:276 msgid "Manage ingredients of:" msgstr "Gestion des ingrédienrs de :" -#: apps/food/views.py:289 apps/food/views.py:297 +#: apps/food/views.py:290 apps/food/views.py:298 #, python-brace-format msgid "Fully used in {meal}" msgstr "Aliment entièrement utilisé dans : {meal}" -#: apps/food/views.py:344 +#: apps/food/views.py:345 msgid "Add the ingredient:" msgstr "Ajouter l'ingrédient" -#: apps/food/views.py:370 +#: apps/food/views.py:371 #, 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:390 msgid "Update an aliment" msgstr "Modifier un aliment" -#: apps/food/views.py:437 +#: apps/food/views.py:438 msgid "Details of:" msgstr "Détails de :" -#: apps/food/views.py:447 apps/treasury/tables.py:149 +#: apps/food/views.py:448 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:450 apps/member/models.py:99 apps/treasury/tables.py:149 msgid "No" msgstr "Non" @@ -1962,8 +1962,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 +2065,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" @@ -2269,7 +2271,7 @@ msgstr "s'applique au club" msgid "role permissions" msgstr "permissions par rôles" -#: apps/permission/signals.py:73 +#: apps/permission/signals.py:74 #, python-brace-format msgid "" "You don't have the permission to change the field {field} on this instance " @@ -2278,7 +2280,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:84 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 +2289,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:113 #, python-brace-format msgid "" "You don't have the permission to delete this instance of model {app_label}." @@ -3041,7 +3043,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 +3122,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 +3354,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 +3374,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 +3655,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 +3709,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,7 +3747,7 @@ 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" @@ -3888,7 +3889,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 +3908,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:178 msgid "German" msgstr "Allemand" -#: note_kfet/settings/base.py:178 +#: note_kfet/settings/base.py:179 msgid "English" msgstr "Anglais" -#: note_kfet/settings/base.py:179 +#: note_kfet/settings/base.py:180 msgid "Spanish" msgstr "Espagnol" -#: note_kfet/settings/base.py:180 +#: note_kfet/settings/base.py:181 msgid "French" msgstr "Français" @@ -3996,18 +3997,18 @@ msgstr "Admin" msgid "My account" msgstr "Mon compte" -#: note_kfet/templates/base.html:142 +#: note_kfet/templates/base.html:144 msgid "Log out" msgstr "Se déconnecter" -#: note_kfet/templates/base.html:150 +#: note_kfet/templates/base.html:153 #: 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:160 #: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:38 @@ -4015,7 +4016,7 @@ msgstr "Inscription" msgid "Log in" msgstr "Se connecter" -#: note_kfet/templates/base.html:171 +#: note_kfet/templates/base.html:174 msgid "" "You are not a BDE member anymore. Please renew your membership if you want " "to use the note." @@ -4023,7 +4024,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:180 msgid "" "Your e-mail address is not validated. Please check your mail inbox and click " "on the validation link." @@ -4031,7 +4032,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:186 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 +4046,30 @@ 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:209 msgid "Contact us" msgstr "Nous contacter" -#: note_kfet/templates/base.html:208 +#: note_kfet/templates/base.html:211 msgid "Technical Support" msgstr "Support technique" -#: note_kfet/templates/base.html:210 +#: note_kfet/templates/base.html:213 msgid "Charte Info (FR)" msgstr "Charte Info (FR)" -#: note_kfet/templates/base.html:212 +#: note_kfet/templates/base.html:215 msgid "FAQ (FR)" msgstr "FAQ (FR)" +#: note_kfet/templates/base.html:217 +msgid "Managed by BDE" +msgstr "Gérer par le BDE" + +#: note_kfet/templates/base.html:219 +msgid "Hosted by Cr@ns" +msgstr "Hébergé par le Cr@ans" + #: note_kfet/templates/base_search.html:15 msgid "Search by attribute such as name..." msgstr "Chercher par un attribut tel que le nom..." diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html index 3dbfa901..70e55f90 100644 --- a/note_kfet/templates/base.html +++ b/note_kfet/templates/base.html @@ -213,6 +213,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" %} &mdahs; {% csrf_token %} {% blocktrans %}

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!{% endblocktrans %} +
+
+ +
+
+{% 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 %} + From c36f8c25a288c7d1c1e7c8aaad699feee1e9615c Mon Sep 17 00:00:00 2001 From: quark Date: Sat, 5 Jul 2025 18:26:31 +0200 Subject: [PATCH 14/22] Add banner #80 (with django-constance --- apps/permission/signals.py | 1 + note_kfet/admin.py | 5 +++++ note_kfet/settings/base.py | 19 +++++++++++++++++++ note_kfet/templates/base.html | 6 +++++- requirements.txt | 1 + 5 files changed, 31 insertions(+), 1 deletion(-) 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/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 8a0fc738..dc954453 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ 'bootstrap_datepicker_plus', 'cas_server', 'colorfield', + 'constance', 'crispy_bootstrap4', 'crispy_forms', # 'django_htcpcp_tea', @@ -112,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', @@ -315,3 +317,20 @@ 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'), +} +CONSTANCE_CONFIG_FIELDSETS = { + '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 45dcdfe7..f7794222 100644 --- a/note_kfet/templates/base.html +++ b/note_kfet/templates/base.html @@ -191,7 +191,11 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblocktrans %} {% endif %} - {# TODO Add banners #} + {% if config.BANNER_MESSAGE %} +
+ {{ config.BANNER_MESSAGE }} +
+ {% endif %} {% block content %}

Default content...

diff --git a/requirements.txt b/requirements.txt index 1d6f5063..c40bf0bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ Django~=5.2.4 django-bootstrap-datepicker-plus~=5.0.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 From 883589e08c8eed7cd71b1849fca9221e6a115ad3 Mon Sep 17 00:00:00 2001 From: quark Date: Sun, 6 Jul 2025 16:17:13 +0200 Subject: [PATCH 15/22] django-constance and traduction --- locale/fr/LC_MESSAGES/django.po | 109 ++++++++++++++++++++++---------- note_kfet/settings/base.py | 5 +- note_kfet/templates/base.html | 14 +++- 3 files changed, 93 insertions(+), 35 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 9f9fb04f..a2973d1c 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-07-04 21:47+0200\n" +"POT-Creation-Date: 2025-07-06 16:04+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" @@ -598,7 +598,7 @@ msgid "order" msgstr "consigne" #: apps/food/models.py:107 apps/food/views.py:34 -#: note_kfet/templates/base.html:72 +#: note_kfet/templates/base.html:73 msgid "Food" msgstr "Bouffe" @@ -2178,7 +2178,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" @@ -2271,7 +2271,7 @@ msgstr "s'applique au club" msgid "role permissions" msgstr "permissions par rôles" -#: apps/permission/signals.py:74 +#: apps/permission/signals.py:75 #, python-brace-format msgid "" "You don't have the permission to change the field {field} on this instance " @@ -2280,7 +2280,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:84 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}." @@ -2289,7 +2289,7 @@ msgstr "" "Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}." "{model_name}." -#: apps/permission/signals.py:113 +#: apps/permission/signals.py:114 #, python-brace-format msgid "" "You don't have the permission to delete this instance of model {app_label}." @@ -2377,7 +2377,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" @@ -2582,7 +2582,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" @@ -2998,7 +2998,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" @@ -3753,7 +3753,7 @@ msgstr "données json" 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" @@ -3786,7 +3786,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." @@ -3908,19 +3908,19 @@ msgstr "Le wrapped est public" msgid "List of wrapped" msgstr "Liste des wrapped" -#: note_kfet/settings/base.py:178 +#: note_kfet/settings/base.py:180 msgid "German" msgstr "Allemand" -#: note_kfet/settings/base.py:179 +#: note_kfet/settings/base.py:181 msgid "English" msgstr "Anglais" -#: note_kfet/settings/base.py:180 +#: note_kfet/settings/base.py:182 msgid "Spanish" msgstr "Espagnol" -#: note_kfet/settings/base.py:181 +#: note_kfet/settings/base.py:183 msgid "French" msgstr "Français" @@ -3981,34 +3981,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:144 +#: note_kfet/templates/base.html:145 msgid "Log out" msgstr "Se déconnecter" -#: note_kfet/templates/base.html:153 +#: 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:160 +#: 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 @@ -4016,7 +4016,7 @@ msgstr "Inscription" msgid "Log in" msgstr "Se connecter" -#: note_kfet/templates/base.html:174 +#: 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." @@ -4024,7 +4024,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:180 +#: 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." @@ -4032,7 +4032,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:186 +#: 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 " @@ -4046,30 +4046,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:209 +#: note_kfet/templates/base.html:214 msgid "Contact us" msgstr "Nous contacter" -#: note_kfet/templates/base.html:211 +#: note_kfet/templates/base.html:216 msgid "Technical Support" msgstr "Support technique" -#: note_kfet/templates/base.html:213 +#: note_kfet/templates/base.html:218 msgid "Charte Info (FR)" msgstr "Charte Info (FR)" -#: note_kfet/templates/base.html:215 +#: note_kfet/templates/base.html:220 msgid "FAQ (FR)" msgstr "FAQ (FR)" -#: note_kfet/templates/base.html:217 +#: note_kfet/templates/base.html:222 msgid "Managed by BDE" msgstr "Gérer par le BDE" -#: note_kfet/templates/base.html:219 +#: 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..." @@ -4078,6 +4086,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" diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index dc954453..1fa0a0ea 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -327,9 +327,12 @@ CONSTANCE_ADDITIONAL_FIELDS = { } CONSTANCE_CONFIG = { 'BANNER_MESSAGE': ('', 'Some message', str), - 'BANNER_TYPE': ('Info', 'Banner type', 'banner_type'), + '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' diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html index f7794222..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 %} @@ -191,7 +192,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblocktrans %} {% endif %} - {% if config.BANNER_MESSAGE %} + {% if config.BANNER_MESSAGE and user.is_authenticated %}
{{ config.BANNER_MESSAGE }}
@@ -257,4 +258,15 @@ SPDX-License-Identifier: GPL-3.0-or-later {% block extrajavascript %}{% endblock %} +{% endif %} +{% if config.MAINTENANCE %} + +
+
+ {% trans "The note is not available for now" %}

+ {{ config.MAINTENANCE_MESSAGE }}

+ {% trans "Thank you for your understanding -- The Respos Info of BDE" %} +
+ +{% endif %} From 432f50e49abe6c2d8726fa2f636a51dd1784c0ab Mon Sep 17 00:00:00 2001 From: quark Date: Wed, 9 Jul 2025 00:15:33 +0200 Subject: [PATCH 16/22] propose fix for #134 (partially tested) --- entrypoint.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/entrypoint.sh b/entrypoint.sh index 7f19eb59..e09832f9 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,6 +11,10 @@ else sed -i -e "s/REPLACEME/La Note Kfet \\\\ud83c\\\\udf7b/g" /var/www/note_kfet/note_kfet/fixtures/cas.json fi +# fix lag issues with django-oauth-toolkit (cf https://gitlab.crans.org/bde/nk20/issues/134 ) +sed -i -e "s/all_scopes =/# all_scopes =/g" /var/www/note_kfet/env/lib/python3.11/site-packages/oauth2_provider/views/base.py +sed -i -e 's/kwargs\["scopes_descriptions"\] =/# kwargs\["scopes_descriptions"\] =/g' /var/www/note_kfet/env/lib/python3.11/site-packages/oauth2_provider/views/base.py + # Set up Django project python3 manage.py collectstatic --noinput python3 manage.py compilemessages From cf9d208586832b156eb94db4cc981b456fffbddb Mon Sep 17 00:00:00 2001 From: quark Date: Wed, 9 Jul 2025 15:29:50 +0200 Subject: [PATCH 17/22] scopes --- apps/permission/scopes.py | 13 ++++++++++++- apps/permission/views.py | 22 ++++++++++++++++------ entrypoint.sh | 4 ---- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 0702aefa..b1fbad78 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/views.py b/apps/permission/views.py index 39e1f98c..469cdf99 100644 --- a/apps/permission/views.py +++ b/apps/permission/views.py @@ -163,15 +163,25 @@ 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/entrypoint.sh b/entrypoint.sh index e09832f9..7f19eb59 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,10 +11,6 @@ else sed -i -e "s/REPLACEME/La Note Kfet \\\\ud83c\\\\udf7b/g" /var/www/note_kfet/note_kfet/fixtures/cas.json fi -# fix lag issues with django-oauth-toolkit (cf https://gitlab.crans.org/bde/nk20/issues/134 ) -sed -i -e "s/all_scopes =/# all_scopes =/g" /var/www/note_kfet/env/lib/python3.11/site-packages/oauth2_provider/views/base.py -sed -i -e 's/kwargs\["scopes_descriptions"\] =/# kwargs\["scopes_descriptions"\] =/g' /var/www/note_kfet/env/lib/python3.11/site-packages/oauth2_provider/views/base.py - # Set up Django project python3 manage.py collectstatic --noinput python3 manage.py compilemessages From 82a06c29ddea4d7ec0075914c3de21e4dd62684d Mon Sep 17 00:00:00 2001 From: quark Date: Wed, 9 Jul 2025 16:12:55 +0200 Subject: [PATCH 18/22] linters --- apps/permission/scopes.py | 2 +- apps/permission/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index b1fbad78..2842546f 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -22,7 +22,7 @@ class PermissionScopes(BaseScopes): scopes = {} if 'scopes' in kwargs: for scope in kwargs['scopes']: - if scope == 'openid' : + if scope == 'openid': scopes['openid'] = "OpenID Connect" else: p = Permission.objects.get(id=scope.split('_')[0]) diff --git a/apps/permission/views.py b/apps/permission/views.py index 469cdf99..30b13316 100644 --- a/apps/permission/views.py +++ b/apps/permission/views.py @@ -163,7 +163,7 @@ class ScopesView(LoginRequiredMixin, TemplateView): from oauth2_provider.models import Application from .scopes import PermissionScopes - + oidc = False context["scopes"] = {} for app in Application.objects.filter(user=self.request.user).all(): From 608804db307319ab415c8af184b215017c797bc5 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Thu, 10 Jul 2025 20:05:27 +0200 Subject: [PATCH 19/22] Bugs fixed --- apps/food/forms.py | 2 +- apps/food/templates/food/food_detail.html | 3 +++ apps/food/views.py | 2 ++ apps/permission/fixtures/initial.json | 4 ++-- locale/fr/LC_MESSAGES/django.po | 6 +++--- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/food/forms.py b/apps/food/forms.py index dfa32008..13c5cba3 100644 --- a/apps/food/forms.py +++ b/apps/food/forms.py @@ -145,7 +145,7 @@ class AddIngredientForms(forms.ModelForm): polymorphic_ctype__model="transformedfood", is_ready=False, end_of_life='', - ).filter(PermissionBackend.filter_queryset(get_current_request(), TransformedFood, "change")).exclude(pk=pk) + ).filter(PermissionBackend.filter_queryset(get_current_request(), Food, "change")).exclude(pk=pk) class Meta: model = TransformedFood diff --git a/apps/food/templates/food/food_detail.html b/apps/food/templates/food/food_detail.html index 9343f6d1..2d805d6b 100644 --- a/apps/food/templates/food/food_detail.html +++ b/apps/food/templates/food/food_detail.html @@ -12,6 +12,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
    + {% if QR_code %} +
  • {{QR_code}}
  • + {% endif %} {% for field, value in fields %}
  • {{ field }} : {{ value }}
  • {% endfor %} diff --git a/apps/food/views.py b/apps/food/views.py index f8c7977d..b6aa2caa 100644 --- a/apps/food/views.py +++ b/apps/food/views.py @@ -428,6 +428,8 @@ class FoodDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): context["fields"] = [( Food._meta.get_field(field).verbose_name.capitalize(), value) for field, value in fields.items()] + if self.object.QR_code.exists(): + context["QR_code"] = self.object.QR_code.first() context["meals"] = self.object.transformed_ingredient_inv.all() context["update"] = PermissionBackend.check_perm(self.request, "food.change_food") context["add_ingredient"] = (self.object.end_of_life == '' and PermissionBackend.check_perm(self.request, "food.change_transformedfood")) diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json index f1f01dcc..a33a3fcf 100644 --- a/apps/permission/fixtures/initial.json +++ b/apps/permission/fixtures/initial.json @@ -3479,11 +3479,11 @@ "food", "food" ], - "query": "{\"end_of_life\": \"\"}", + "query": "[\"AND\", {\"end_of_life\": \"\"}, [\"OR\", {\"expiry_date__lte\": [\"today\"]}, {\"is_ready\": true}]]", "type": "view", "mask": 1, "permanent": false, - "description": "Voir la bouffe servie" + "description": "Voir la bouffe servie ou en open" } }, { diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 23ba06dd..3e5001c5 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -529,7 +529,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" @@ -623,7 +623,7 @@ 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 msgid "Contained in" @@ -4163,7 +4163,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é" From 5989721bc9de75d96ec19a0e1e2d18fd177558fc Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Fri, 11 Jul 2025 16:35:49 +0200 Subject: [PATCH 20/22] Easier access to food details --- apps/food/templates/food/food_list.html | 65 +++++++++++++++++++- apps/food/urls.py | 1 + apps/food/views.py | 12 ++++ locale/fr/LC_MESSAGES/django.po | 81 ++++++++++++++----------- 4 files changed, 122 insertions(+), 37 deletions(-) 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 b6aa2caa..892df728 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 _ @@ -483,3 +484,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/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 3e5001c5..efbdf0da 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-04-30 11:44+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" @@ -563,7 +563,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" @@ -625,59 +625,73 @@ msgstr "QR-codes" msgid "QR-code number" 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" @@ -751,49 +765,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:226 +#: apps/food/views.py:228 msgid "Add a meal" msgstr "Ajouter un plat" -#: apps/food/views.py:262 +#: apps/food/views.py:259 msgid "Manage ingredients of:" msgstr "Gestion des ingrédienrs de :" -#: apps/food/views.py:276 apps/food/views.py:284 +#: 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:323 +#: apps/food/views.py:320 msgid "Add the ingredient:" msgstr "Ajouter l'ingrédient" -#: apps/food/views.py:349 +#: 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:368 +#: apps/food/views.py:365 msgid "Update an aliment" msgstr "Modifier un aliment" -#: apps/food/views.py:416 +#: apps/food/views.py:413 msgid "Details of:" msgstr "Détails de :" -#: apps/food/views.py:426 apps/treasury/tables.py:149 +#: apps/food/views.py:423 apps/treasury/tables.py:149 msgid "Yes" msgstr "Oui" -#: apps/food/views.py:428 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" @@ -3933,14 +3947,6 @@ msgstr "Charte Info (FR)" msgid "FAQ (FR)" msgstr "FAQ (FR)" -#: note_kfet/templates/base_search.html:15 -msgid "Search by attribute such as name..." -msgstr "Chercher par un attribut tel que le nom..." - -#: note_kfet/templates/base_search.html:23 -msgid "There is no results." -msgstr "Il n'y a pas de résultat." - #: 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" @@ -4161,6 +4167,11 @@ msgstr "" "d'adhésion. Vous devez également valider votre adresse email en suivant le " "lien que vous avez reçu." +#, 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}" From b97b79e2ea523a4f782cbdc305a586f93d2010cb Mon Sep 17 00:00:00 2001 From: quark Date: Sat, 12 Jul 2025 14:05:53 +0200 Subject: [PATCH 21/22] translation --- locale/fr/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 29f72ecb..76bc8fa7 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -4078,7 +4078,7 @@ msgstr "FAQ (FR)" #: note_kfet/templates/base.html:222 msgid "Managed by BDE" -msgstr "Gérer par le BDE" +msgstr "Géré par le BDE" #: note_kfet/templates/base.html:224 msgid "Hosted by Cr@ns" From 0a261e6ad5514eb458cce1db68d9f147dae6b8c5 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Sun, 13 Jul 2025 16:38:39 +0200 Subject: [PATCH 22/22] Bugs fixed again (lost in beta) --- apps/food/forms.py | 2 +- apps/food/templates/food/food_detail.html | 33 ++++++++++++----------- apps/food/views.py | 2 ++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/food/forms.py b/apps/food/forms.py index dfa32008..13c5cba3 100644 --- a/apps/food/forms.py +++ b/apps/food/forms.py @@ -145,7 +145,7 @@ class AddIngredientForms(forms.ModelForm): polymorphic_ctype__model="transformedfood", is_ready=False, end_of_life='', - ).filter(PermissionBackend.filter_queryset(get_current_request(), TransformedFood, "change")).exclude(pk=pk) + ).filter(PermissionBackend.filter_queryset(get_current_request(), Food, "change")).exclude(pk=pk) class Meta: model = TransformedFood diff --git a/apps/food/templates/food/food_detail.html b/apps/food/templates/food/food_detail.html index 9343f6d1..e82cc907 100644 --- a/apps/food/templates/food/food_detail.html +++ b/apps/food/templates/food/food_detail.html @@ -12,18 +12,21 @@ SPDX-License-Identifier: GPL-3.0-or-later
      + {% if QR_code %} +
    • {{QR_code}}
    • + {% endif %} {% for field, value in fields %}
    • {{ field }} : {{ value }}
    • {% endfor %} {% if meals %} -
    • {% trans "Contained in" %} : +
    • {% trans "Contained in" %} : {% for meal in meals %} - {{ meal.name }}{% if not forloop.last %},{% endif %} + {{ meal.name }}{% if not forloop.last %},{% endif %} {% endfor %}
    • {% endif %} {% if foods %} -
    • {% trans "Contain" %} : +
    • {% trans "Contain" %} : {% for food in foods %} {{ food.name }}{% if not forloop.last %},{% endif %} {% endfor %} @@ -31,23 +34,23 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %}
    {% if update %} - - {% trans "Update" %} - + + {% trans "Update" %} + {% endif %} {% if add_ingredient %} - - {% trans "Add to a meal" %} - + + {% trans "Add to a meal" %} + {% endif %} {% if manage_ingredients %} - {% trans "Manage ingredients" %} - + {% trans "Manage ingredients" %} + {% endif %} - - {% trans "Return to the food list" %} - + + {% trans "Return to the food list" %} +
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/apps/food/views.py b/apps/food/views.py index 393e4072..bebf1939 100644 --- a/apps/food/views.py +++ b/apps/food/views.py @@ -455,6 +455,8 @@ class FoodDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): context["fields"] = [( Food._meta.get_field(field).verbose_name.capitalize(), value) for field, value in fields.items()] + if self.object.QR_code.exists(): + context["QR_code"] = self.object.QR_code.first() context["meals"] = self.object.transformed_ingredient_inv.all() context["update"] = PermissionBackend.check_perm(self.request, "food.change_food") context["add_ingredient"] = (self.object.end_of_life == '' and PermissionBackend.check_perm(self.request, "food.change_transformedfood"))