From e9f18c3ed9956bec07d6b71e391f7e275534663b Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 24 Jan 2024 19:18:02 +0100 Subject: [PATCH 01/14] migrate to django 4.2 (LTS), change requirement and tests. remove depreciated ifnotequal --- .gitlab-ci.yml | 34 +++++++++--------- apps/note/templates/note/amount_input.html | 2 +- note_kfet/templates/autocomplete_model.html | 2 +- requirements.txt | 38 ++++++++++----------- tox.ini | 6 ++-- 5 files changed, 42 insertions(+), 40 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 97110ecd..98fbac88 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,21 +7,6 @@ stages: variables: GIT_SUBMODULE_STRATEGY: recursive -# Debian Buster -py37-django22: - stage: test - image: debian:buster-backports - before_script: - - > - apt-get update && - apt-get install --no-install-recommends -t buster-backports -y - python3-django python3-django-crispy-forms - python3-django-extensions python3-django-filters python3-django-polymorphic - 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 py37-django22 - # Ubuntu 20.04 py38-django22: stage: test @@ -54,9 +39,26 @@ py39-django22: python3-bs4 python3-setuptools tox texlive-xetex script: tox -e py39-django22 +# Debian Bookworm +py311-django42: + stage: test + image: debian:bookworm + before_script: + - > + apt-get update && + apt-get install --no-install-recommends -y + python3-django python3-django-crispy-forms + python3-django-extensions python3-django-filters python3-django-polymorphic + 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 + + + linters: stage: quality-assurance - image: debian:buster-backports + image: debian:bookworm before_script: - apt-get update && apt-get install -y tox script: tox -e linters diff --git a/apps/note/templates/note/amount_input.html b/apps/note/templates/note/amount_input.html index d4873115..cbe9d160 100644 --- a/apps/note/templates/note/amount_input.html +++ b/apps/note/templates/note/amount_input.html @@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later name="{{ widget.name }}" {# Other attributes are loaded #} {% for name, value in widget.attrs.items %} - {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %} + {% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %} {% endfor %}>
diff --git a/note_kfet/templates/autocomplete_model.html b/note_kfet/templates/autocomplete_model.html index fa24213f..5ffe971d 100644 --- a/note_kfet/templates/autocomplete_model.html +++ b/note_kfet/templates/autocomplete_model.html @@ -8,7 +8,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %} name="{{ widget.name }}_name" autocomplete="off" {% for name, value in widget.attrs.items %} - {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %} + {% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %} {% endfor %} aria-describedby="{{widget.attrs.id}}_tooltip"> {% if widget.resetable %} diff --git a/requirements.txt b/requirements.txt index f4ece220..5548fd4b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,19 @@ -beautifulsoup4~=4.7.1 -Django~=2.2.15 -django-bootstrap-datepicker-plus~=3.0.5 -django-cas-server~=1.2.0 -django-colorfield~=0.3.2 -django-crispy-forms~=1.7.2 -django-extensions>=2.1.4 -django-filter~=2.1 -django-htcpcp-tea~=0.3.1 -django-mailer~=2.0.1 -django-oauth-toolkit~=1.3.3 -django-phonenumber-field~=5.0.0 -django-polymorphic>=2.0.3,<3.0.0 -djangorestframework>=3.9.0,<3.13.0 -django-rest-polymorphic~=0.1.9 -django-tables2~=2.3.1 -python-memcached~=1.59 -phonenumbers~=8.9.10 -Pillow>=5.4.1 +beautifulsoup4~=4.12.3 +Django~=4.2.9 +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-htcpcp-tea~=0.8.1 +django-mailer~=2.3.1 +django-oauth-toolkit~=2.3.0 +django-phonenumber-field~=7.3.0 +django-polymorphic~=3.1.0 +djangorestframework~=3.14.0 +django-rest-polymorphic~=0.1.10 +django-tables2~=2.7.0 +python-memcached~=1.62 +phonenumbers~=8.13.28 +Pillow>=10.2.0 diff --git a/tox.ini b/tox.ini index ad3c6798..0526236f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,14 @@ [tox] envlist = - # Debian Buster Python - py37-django22 - # Ubuntu 20.04 Python py38-django22 # Debian Bullseye Python py39-django22 + # Debian Bookworm Python + py311-django42 + linters skipsdist = True From 2f8c9b54e7c42bbd62dca80d658832c77f36f992 Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 24 Jan 2024 19:58:55 +0100 Subject: [PATCH 02/14] Remove importation of django-cas-server which is not compatible with django 4.2 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5548fd4b..7af89d9f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ beautifulsoup4~=4.12.3 Django~=4.2.9 django-bootstrap-datepicker-plus~=5.0.5 -django-cas-server~=2.0.0 +#django-cas-server~=2.0.0 django-colorfield~=0.11.0 django-crispy-forms~=2.1.0 django-extensions>=3.2.3 From 516a7f4be57360e917143c35abd7b21996999e6d Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 24 Jan 2024 20:14:32 +0100 Subject: [PATCH 03/14] Remove importation of django-htcpcp-tea which is not compatible with django 4.2 --- note_kfet/settings/base.py | 2 +- note_kfet/urls.py | 8 +++++--- requirements.txt | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index f3c23f4d..1e9e0752 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -41,7 +41,7 @@ INSTALLED_APPS = [ 'bootstrap_datepicker_plus', 'colorfield', 'crispy_forms', - 'django_htcpcp_tea', +# 'django_htcpcp_tea', 'django_tables2', 'mailer', 'phonenumber_field', diff --git a/note_kfet/urls.py b/note_kfet/urls.py index 7fc37fa7..72be36ea 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -30,9 +30,6 @@ urlpatterns = [ path('accounts/', include('django.contrib.auth.urls')), path('api/', include('api.urls')), path('permission/', include('permission.urls')), - - # Make coffee - path('coffee/', include('django_htcpcp_tea.urls')), ] # During development, serve static and media files @@ -57,6 +54,11 @@ if "debug_toolbar" in settings.INSTALLED_APPS: path('__debug__/', include(debug_toolbar.urls)), ] + urlpatterns +if "django_htcpcp_tea" in settings.INSTALLED_APPS: + # Make coffee + urlpatterns.append( + path('coffee/', include('django_htcpcp_tea.urls')) + ) handler400 = bad_request handler403 = permission_denied diff --git a/requirements.txt b/requirements.txt index 7af89d9f..1750cd66 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ django-colorfield~=0.11.0 django-crispy-forms~=2.1.0 django-extensions>=3.2.3 django-filter~=23.5 -django-htcpcp-tea~=0.8.1 +#django-htcpcp-tea~=0.8.1 django-mailer~=2.3.1 django-oauth-toolkit~=2.3.0 django-phonenumber-field~=7.3.0 From d228dbf225767303e98f08660abfd66ef332b1e1 Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 7 Feb 2024 18:02:56 +0100 Subject: [PATCH 04/14] fix some breaking changes and linters --- apps/member/views.py | 2 +- apps/note/api/views.py | 2 +- apps/note/tests/test_transactions.py | 2 +- apps/permission/scopes.py | 2 ++ apps/treasury/api/views.py | 2 +- apps/treasury/urls.py | 4 ++-- note_kfet/admin.py | 4 ++-- note_kfet/settings/base.py | 3 +++ 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/apps/member/views.py b/apps/member/views.py index 066a7ef3..e56ed7b2 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -26,7 +26,7 @@ from permission.backends import PermissionBackend from permission.models import Role from permission.views import ProtectQuerysetMixin, ProtectedCreateView -from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm,\ +from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm, \ CustomAuthenticationForm, MembershipRolesForm from .models import Club, Membership from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable diff --git a/apps/note/api/views.py b/apps/note/api/views.py index 34ffaf2d..bc4f99ef 100644 --- a/apps/note/api/views.py +++ b/apps/note/api/views.py @@ -13,7 +13,7 @@ from rest_framework import status from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet from permission.backends import PermissionBackend -from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer,\ +from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer, \ TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer, \ TrustSerializer from ..models.notes import Note, Alias, NoteUser, NoteClub, NoteSpecial, Trust diff --git a/apps/note/tests/test_transactions.py b/apps/note/tests/test_transactions.py index 4f5dd6c5..1f0920ec 100644 --- a/apps/note/tests/test_transactions.py +++ b/apps/note/tests/test_transactions.py @@ -10,7 +10,7 @@ from django.urls import reverse from django.utils import timezone from permission.models import Role -from ..api.views import AliasViewSet, ConsumerViewSet, NotePolymorphicViewSet, TemplateCategoryViewSet,\ +from ..api.views import AliasViewSet, ConsumerViewSet, NotePolymorphicViewSet, TemplateCategoryViewSet, \ TransactionTemplateViewSet, TransactionViewSet from ..models import NoteUser, Transaction, TemplateCategory, TransactionTemplate, RecurrentTransaction, \ MembershipTransaction, SpecialTransaction, NoteSpecial, Alias, Note diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index 65242804..f8fd7687 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -44,6 +44,8 @@ class PermissionOAuth2Validator(OAuth2Validator): subset of permissions. """ + oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 + valid_scopes = set() for t in Permission.PERMISSION_TYPES: diff --git a/apps/treasury/api/views.py b/apps/treasury/api/views.py index e6ba9ced..36388279 100644 --- a/apps/treasury/api/views.py +++ b/apps/treasury/api/views.py @@ -5,7 +5,7 @@ from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import SearchFilter from api.viewsets import ReadProtectedModelViewSet -from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer,\ +from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer, \ SogeCreditSerializer from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit diff --git a/apps/treasury/urls.py b/apps/treasury/urls.py index 4fe87924..144ae296 100644 --- a/apps/treasury/urls.py +++ b/apps/treasury/urls.py @@ -3,8 +3,8 @@ from django.urls import path -from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceDeleteView, InvoiceRenderView,\ - RemittanceListView, RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView,\ +from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceDeleteView, InvoiceRenderView, \ + RemittanceListView, RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView, \ UnlinkTransactionToRemittanceView, SogeCreditListView, SogeCreditManageView app_name = 'treasury' diff --git a/note_kfet/admin.py b/note_kfet/admin.py index dc209c67..1f26f559 100644 --- a/note_kfet/admin.py +++ b/note_kfet/admin.py @@ -25,8 +25,8 @@ admin_site.register(Site, SiteAdmin) # Add external apps model if "oauth2_provider" in settings.INSTALLED_APPS: - from oauth2_provider.admin import Application, ApplicationAdmin, Grant, \ - GrantAdmin, AccessToken, AccessTokenAdmin, RefreshToken, RefreshTokenAdmin + from oauth2_provider.admin import ApplicationAdmin, GrantAdmin, AccessTokenAdmin, RefreshTokenAdmin + from oauth2_provider.model import Application, Grant, AccessToken, RefreshToken admin_site.register(Application, ApplicationAdmin) admin_site.register(Grant, GrantAdmin) admin_site.register(AccessToken, AccessTokenAdmin) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 1e9e0752..fe466b1e 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -263,6 +263,9 @@ OAUTH2_PROVIDER = { 'REFRESH_TOKEN_EXPIRE_SECONDS': timedelta(days=14), } +# PKCE (fix a breaking change of django-oauth-toolkit 2.0.0) +PKCE_REQUIRED = False + # Take control on how widget templates are sourced # See https://docs.djangoproject.com/en/2.2/ref/forms/renderers/#templatessetting FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' From b6b81a8b8f1d1b9d3d388abb0f698550b19f96fb Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 7 Feb 2024 18:05:32 +0100 Subject: [PATCH 05/14] typo --- note_kfet/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/note_kfet/admin.py b/note_kfet/admin.py index 1f26f559..62d2c688 100644 --- a/note_kfet/admin.py +++ b/note_kfet/admin.py @@ -26,7 +26,7 @@ admin_site.register(Site, SiteAdmin) # Add external apps model if "oauth2_provider" in settings.INSTALLED_APPS: from oauth2_provider.admin import ApplicationAdmin, GrantAdmin, AccessTokenAdmin, RefreshTokenAdmin - from oauth2_provider.model import Application, Grant, AccessToken, RefreshToken + from oauth2_provider.models import Application, Grant, AccessToken, RefreshToken admin_site.register(Application, ApplicationAdmin) admin_site.register(Grant, GrantAdmin) admin_site.register(AccessToken, AccessTokenAdmin) From abc88d0118c7f3bbc060058cc5a50a45da3e9f6e Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 7 Feb 2024 18:21:08 +0100 Subject: [PATCH 06/14] replace url from django.conf.urls by re_path from django.urls --- apps/api/urls.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/api/urls.py b/apps/api/urls.py index 5d8b8b98..cb342b1c 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -2,7 +2,8 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.conf import settings -from django.conf.urls import url, include +from django.conf.urls import include +from django.urls import re_path from rest_framework import routers from .views import UserInformationView @@ -47,7 +48,7 @@ app_name = 'api' # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. urlpatterns = [ - url('^', include(router.urls)), - url('^me/', UserInformationView.as_view()), - url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), + re_path('^', include(router.urls)), + re_path('^me/', UserInformationView.as_view()), + re_path('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] From 82fea65b5edbf58b6bd469cdfef63dab037adef1 Mon Sep 17 00:00:00 2001 From: bleizi Date: Wed, 7 Feb 2024 20:00:58 +0100 Subject: [PATCH 07/14] django_htcpcp_tea in middleware only if in apps --- apps/api/urls.py | 2 +- note_kfet/settings/base.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/api/urls.py b/apps/api/urls.py index cb342b1c..4cb8085e 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.conf import settings -from django.conf.urls import include +from django.conf.urls import include from django.urls import re_path from rest_framework import routers diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index fe466b1e..d653dfc6 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -90,12 +90,14 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', - 'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware', 'note_kfet.middlewares.SessionMiddleware', 'note_kfet.middlewares.LoginByIPMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware', 'note_kfet.middlewares.ClacksMiddleware', ] +if "django_htcpcp_tea" in INSTALLED_APPS: + MIDDLEWARE.append('django_htcpcp_tea.middleware.HTCPCPTeaMiddleware') + ROOT_URLCONF = 'note_kfet.urls' From 399a32bece44af5b322d3089eb09a9dc31928393 Mon Sep 17 00:00:00 2001 From: bleizi Date: Sun, 11 Feb 2024 16:51:48 +0100 Subject: [PATCH 08/14] default auto field --- note_kfet/settings/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index d653dfc6..9ba5bb34 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -300,3 +300,6 @@ 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' + +# Default field for primary key +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" From fb3337966e029a1d69f5e25f1c5d5e588ec3af11 Mon Sep 17 00:00:00 2001 From: bleizi Date: Sun, 11 Feb 2024 22:24:37 +0100 Subject: [PATCH 09/14] bootstrap4 is now a standalone package from crispy-forms --- note_kfet/settings/base.py | 2 ++ requirements.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 9ba5bb34..44c34020 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -40,6 +40,7 @@ INSTALLED_APPS = [ # External apps 'bootstrap_datepicker_plus', 'colorfield', + 'crispy_bootstrap4', 'crispy_forms', # 'django_htcpcp_tea', 'django_tables2', @@ -279,6 +280,7 @@ LOGIN_REDIRECT_URL = '/' SESSION_COOKIE_AGE = 60 * 60 * 3 # Use Crispy Bootstrap4 theme +CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap4' CRISPY_TEMPLATE_PACK = 'bootstrap4' # Use Django Table2 Bootstrap4 theme diff --git a/requirements.txt b/requirements.txt index 1750cd66..f4a32c97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ beautifulsoup4~=4.12.3 +crispy-bootstrap4~=2023.1 Django~=4.2.9 django-bootstrap-datepicker-plus~=5.0.5 #django-cas-server~=2.0.0 From 2ee7f41dfebdc53de4a4b3341bc05977c2050ebb Mon Sep 17 00:00:00 2001 From: bleizi Date: Mon, 12 Feb 2024 21:25:07 +0100 Subject: [PATCH 10/14] tests with ubuntu 22.04, django-bootstrap-datepicker-plus is a standalone package and fix encoding in tests --- .gitlab-ci.yml | 38 ++-- apps/activity/forms.py | 3 +- apps/member/forms.py | 5 +- apps/note/forms.py | 3 +- apps/wei/forms/registration.py | 3 +- apps/wei/tests/test_wei_registration.py | 4 +- note_kfet/inputs.py | 261 ------------------------ tox.ini | 8 +- 8 files changed, 34 insertions(+), 291 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 98fbac88..23ba25aa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,25 +7,8 @@ stages: variables: GIT_SUBMODULE_STRATEGY: recursive -# Ubuntu 20.04 -py38-django22: - stage: test - image: ubuntu:20.04 - before_script: - # Fix tzdata prompt - - ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone - - > - apt-get update && - apt-get install --no-install-recommends -y - python3-django python3-django-crispy-forms - python3-django-extensions python3-django-filters python3-django-polymorphic - 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 py38-django22 - # Debian Bullseye -py39-django22: +py39-django42: stage: test image: debian:bullseye before_script: @@ -37,7 +20,24 @@ py39-django22: 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 py39-django22 + script: tox -e py39-django42 + +# Ubuntu 22.04 +py310-django42: + stage: test + image: ubuntu:22.04 + before_script: + # Fix tzdata prompt + - ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone + - > + apt-get update && + apt-get install --no-install-recommends -y + python3-django python3-django-crispy-forms + python3-django-extensions python3-django-filters python3-django-polymorphic + 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 py38-django42 # Debian Bookworm py311-django42: diff --git a/apps/activity/forms.py b/apps/activity/forms.py index 1ca98cef..f8744f14 100644 --- a/apps/activity/forms.py +++ b/apps/activity/forms.py @@ -4,13 +4,14 @@ from datetime import timedelta from random import shuffle +from bootstrap_datepicker_plus.widgets import DateTimePickerInput from django import forms from django.contrib.contenttypes.models import ContentType from django.utils import timezone from django.utils.translation import gettext_lazy as _ from member.models import Club from note.models import Note, NoteUser -from note_kfet.inputs import Autocomplete, DateTimePickerInput +from note_kfet.inputs import Autocomplete from note_kfet.middlewares import get_current_request from permission.backends import PermissionBackend diff --git a/apps/member/forms.py b/apps/member/forms.py index 527816cb..420b35a4 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -3,7 +3,7 @@ import io -from PIL import Image, ImageSequence +from bootstrap_datepicker_plus.widgets import DatePickerInput from django import forms from django.conf import settings from django.contrib.auth.forms import AuthenticationForm @@ -13,8 +13,9 @@ from django.forms import CheckboxSelectMultiple from django.utils import timezone from django.utils.translation import gettext_lazy as _ from note.models import NoteSpecial, Alias -from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput +from note_kfet.inputs import Autocomplete, AmountInput from permission.models import PermissionMask, Role +from PIL import Image, ImageSequence from .models import Profile, Club, Membership diff --git a/apps/note/forms.py b/apps/note/forms.py index 791abb51..f496843a 100644 --- a/apps/note/forms.py +++ b/apps/note/forms.py @@ -2,12 +2,13 @@ # SPDX-License-Identifier: GPL-3.0-or-later from datetime import datetime +from bootstrap_datepicker_plus.widgets import DateTimePickerInput from django import forms from django.contrib.contenttypes.models import ContentType from django.forms import CheckboxSelectMultiple from django.utils.timezone import make_aware from django.utils.translation import gettext_lazy as _ -from note_kfet.inputs import Autocomplete, AmountInput, DateTimePickerInput +from note_kfet.inputs import Autocomplete, AmountInput from .models import TransactionTemplate, NoteClub, Alias diff --git a/apps/wei/forms/registration.py b/apps/wei/forms/registration.py index 408071f4..65a98bfe 100644 --- a/apps/wei/forms/registration.py +++ b/apps/wei/forms/registration.py @@ -1,13 +1,14 @@ # Copyright (C) 2018-2023 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from bootstrap_datepicker_plus.widgets import DatePickerInput from django import forms from django.contrib.auth.models import User from django.db.models import Q from django.forms import CheckboxSelectMultiple from django.utils.translation import gettext_lazy as _ from note.models import NoteSpecial, NoteUser -from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget +from note_kfet.inputs import AmountInput, Autocomplete, ColorWidget from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole diff --git a/apps/wei/tests/test_wei_registration.py b/apps/wei/tests/test_wei_registration.py index 86dd4cfd..2ca28e43 100644 --- a/apps/wei/tests/test_wei_registration.py +++ b/apps/wei/tests/test_wei_registration.py @@ -439,7 +439,7 @@ class TestWEIRegistration(TestCase): emergency_contact_phone='+33123456789', )) self.assertEqual(response.status_code, 200) - self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." + self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." in str(response.context["form"].errors)) # Check that if the WEI is started, we can't register anyone @@ -635,7 +635,7 @@ class TestWEIRegistration(TestCase): )) self.assertEqual(response.status_code, 200) self.assertFalse(response.context["form"].is_valid()) - self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) + self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict( roles=[WEIRole.objects.get(name="GC WEI").id], diff --git a/note_kfet/inputs.py b/note_kfet/inputs.py index 6e729c47..e6e7f8f9 100644 --- a/note_kfet/inputs.py +++ b/note_kfet/inputs.py @@ -68,264 +68,3 @@ class ColorWidget(Widget): def value_from_datadict(self, data, files, name): val = super().value_from_datadict(data, files, name) return int(val[1:], 16) - - -""" -The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github: -https://github.com/monim67/django-bootstrap-datepicker-plus -This is distributed under Apache License 2.0. - -This adds datetime pickers with bootstrap. -""" - -"""Contains Base Date-Picker input class for widgets of this package.""" - - -class DatePickerDictionary: - """Keeps track of all date-picker input classes.""" - - _i = 0 - items = dict() - - @classmethod - def generate_id(cls): - """Return a unique ID for each date-picker input class.""" - cls._i += 1 - return 'dp_%s' % cls._i - - -class BasePickerInput(DateTimeBaseInput): - """Base Date-Picker input class for widgets of this package.""" - - template_name = 'bootstrap_datepicker_plus/date-picker.html' - picker_type = 'DATE' - format = '%Y-%m-%d' - config = {} - _default_config = { - 'id': None, - 'picker_type': None, - 'linked_to': None, - 'options': {} # final merged options - } - options = {} # options extended by user - options_param = {} # options passed as parameter - _default_options = { - 'showClose': True, - 'showClear': True, - 'showTodayButton': True, - "locale": "fr", - } - - # source: https://github.com/tutorcruncher/django-bootstrap3-datetimepicker - # file: /blob/31fbb09/bootstrap3_datetime/widgets.py#L33 - format_map = ( - ('DDD', r'%j'), - ('DD', r'%d'), - ('MMMM', r'%B'), - ('MMM', r'%b'), - ('MM', r'%m'), - ('YYYY', r'%Y'), - ('YY', r'%y'), - ('HH', r'%H'), - ('hh', r'%I'), - ('mm', r'%M'), - ('ss', r'%S'), - ('a', r'%p'), - ('ZZ', r'%z'), - ) - - class Media: - """JS/CSS resources needed to render the date-picker calendar.""" - - js = ( - 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/' - 'moment-with-locales.min.js', - 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/' - '4.17.47/js/bootstrap-datetimepicker.min.js', - 'bootstrap_datepicker_plus/js/datepicker-widget.js' - ) - css = {'all': ( - 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/' - '4.17.47/css/bootstrap-datetimepicker.css', - 'bootstrap_datepicker_plus/css/datepicker-widget.css' - ), } - - @classmethod - def format_py2js(cls, datetime_format): - """Convert python datetime format to moment datetime format.""" - for js_format, py_format in cls.format_map: - datetime_format = datetime_format.replace(py_format, js_format) - return datetime_format - - @classmethod - def format_js2py(cls, datetime_format): - """Convert moment datetime format to python datetime format.""" - for js_format, py_format in cls.format_map: - datetime_format = datetime_format.replace(js_format, py_format) - return datetime_format - - def __init__(self, attrs=None, format=None, options=None): - """Initialize the Date-picker widget.""" - self.format_param = format - self.options_param = options if options else {} - self.config = self._default_config.copy() - self.config['id'] = DatePickerDictionary.generate_id() - self.config['picker_type'] = self.picker_type - self.config['options'] = self._calculate_options() - attrs = attrs if attrs else {} - if 'class' not in attrs: - attrs['class'] = 'form-control' - super().__init__(attrs, self._calculate_format()) - - def _calculate_options(self): - """Calculate and Return the options.""" - _options = self._default_options.copy() - _options.update(self.options) - if self.options_param: - _options.update(self.options_param) - return _options - - def _calculate_format(self): - """Calculate and Return the datetime format.""" - _format = self.format_param if self.format_param else self.format - if self.config['options'].get('format'): - _format = self.format_js2py(self.config['options'].get('format')) - else: - self.config['options']['format'] = self.format_py2js(_format) - return _format - - def get_context(self, name, value, attrs): - """Return widget context dictionary.""" - context = super().get_context( - name, value, attrs) - context['widget']['attrs']['dp_config'] = json_dumps(self.config) - return context - - def start_of(self, event_id): - """ - Set Date-Picker as the start-date of a date-range. - - Args: - - event_id (string): User-defined unique id for linking two fields - """ - DatePickerDictionary.items[str(event_id)] = self - return self - - def end_of(self, event_id, import_options=True): - """ - Set Date-Picker as the end-date of a date-range. - - Args: - - event_id (string): User-defined unique id for linking two fields - - import_options (bool): inherit options from start-date input, - default: TRUE - """ - event_id = str(event_id) - if event_id in DatePickerDictionary.items: - linked_picker = DatePickerDictionary.items[event_id] - self.config['linked_to'] = linked_picker.config['id'] - if import_options: - backup_moment_format = self.config['options']['format'] - self.config['options'].update(linked_picker.config['options']) - self.config['options'].update(self.options_param) - if self.format_param or 'format' in self.options_param: - self.config['options']['format'] = backup_moment_format - else: - self.format = linked_picker.format - # Setting useCurrent is necessary, see following issue - # https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075 - self.config['options']['useCurrent'] = False - self._link_to(linked_picker) - else: - raise KeyError( - 'start-date not specified for event_id "%s"' % event_id) - return self - - def _link_to(self, linked_picker): - """ - Executed when two date-inputs are linked together. - - This method for sub-classes to override to customize the linking. - """ - pass - - -class DatePickerInput(BasePickerInput): - """ - Widget to display a Date-Picker Calendar on a DateField property. - - Args: - - attrs (dict): HTML attributes of rendered HTML input - - format (string): Python DateTime format eg. "%Y-%m-%d" - - options (dict): Options to customize the widget, see README - """ - - picker_type = 'DATE' - format = '%Y-%m-%d' - format_key = 'DATE_INPUT_FORMATS' - - -class TimePickerInput(BasePickerInput): - """ - Widget to display a Time-Picker Calendar on a TimeField property. - - Args: - - attrs (dict): HTML attributes of rendered HTML input - - format (string): Python DateTime format eg. "%Y-%m-%d" - - options (dict): Options to customize the widget, see README - """ - - picker_type = 'TIME' - format = '%H:%M' - format_key = 'TIME_INPUT_FORMATS' - template_name = 'bootstrap_datepicker_plus/time_picker.html' - - -class DateTimePickerInput(BasePickerInput): - """ - Widget to display a DateTime-Picker Calendar on a DateTimeField property. - - Args: - - attrs (dict): HTML attributes of rendered HTML input - - format (string): Python DateTime format eg. "%Y-%m-%d" - - options (dict): Options to customize the widget, see README - """ - - picker_type = 'DATETIME' - format = '%Y-%m-%d %H:%M' - format_key = 'DATETIME_INPUT_FORMATS' - - -class MonthPickerInput(BasePickerInput): - """ - Widget to display a Month-Picker Calendar on a DateField property. - - Args: - - attrs (dict): HTML attributes of rendered HTML input - - format (string): Python DateTime format eg. "%Y-%m-%d" - - options (dict): Options to customize the widget, see README - """ - - picker_type = 'MONTH' - format = '01/%m/%Y' - format_key = 'DATE_INPUT_FORMATS' - - -class YearPickerInput(BasePickerInput): - """ - Widget to display a Year-Picker Calendar on a DateField property. - - Args: - - attrs (dict): HTML attributes of rendered HTML input - - format (string): Python DateTime format eg. "%Y-%m-%d" - - options (dict): Options to customize the widget, see README - """ - - picker_type = 'YEAR' - format = '01/01/%Y' - format_key = 'DATE_INPUT_FORMATS' - - def _link_to(self, linked_picker): - """Customize the options when linked with other date-time input""" - yformat = self.config['options']['format'].replace('-01-01', '-12-31') - self.config['options']['format'] = yformat diff --git a/tox.ini b/tox.ini index 0526236f..a18af893 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] envlist = - # Ubuntu 20.04 Python - py38-django22 - # Debian Bullseye Python - py39-django22 + py39-django42 + + # Ubuntu 22.04 Python + py310-django42 # Debian Bookworm Python py311-django42 From b7a71d911d22fe2adfd322ecdeb0dfc4b2b3490f Mon Sep 17 00:00:00 2001 From: bleizi Date: Mon, 12 Feb 2024 22:56:43 +0100 Subject: [PATCH 11/14] _get_validtion_exclusions() now return a set, PIL.Image.ANTIALIAS was renamed LANCZOS and typo in .gitlab-ci.yml --- .gitlab-ci.yml | 2 +- apps/member/forms.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23ba25aa..4f041867 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ 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 py38-django42 + script: tox -e py310-django42 # Debian Bookworm py311-django42: diff --git a/apps/member/forms.py b/apps/member/forms.py index 420b35a4..0d78c726 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -33,7 +33,7 @@ class UserForm(forms.ModelForm): # Django usernames can only contain letters, numbers, @, ., +, - and _. # We want to allow users to have uncommon and unpractical usernames: # That is their problem, and we have normalized aliases for us. - return super()._get_validation_exclusions() + ["username"] + return super()._get_validation_exclusions() | {"username"} class Meta: model = User @@ -122,7 +122,7 @@ class ImageForm(forms.Form): frame = frame.crop((x, y, x + w, y + h)) frame = frame.resize( (settings.PIC_WIDTH, settings.PIC_RATIO * settings.PIC_WIDTH), - Image.ANTIALIAS, + Image.LANCZOS, ) frames.append(frame) From 96215cc1ff6ad50cdc79c1b80a1f3885b04d5b31 Mon Sep 17 00:00:00 2001 From: bleizi Date: Tue, 13 Feb 2024 13:43:14 +0100 Subject: [PATCH 12/14] oidc_claim_scope in Class instead of method --- apps/permission/scopes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index f8fd7687..6770c681 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -35,6 +35,8 @@ class PermissionScopes(BaseScopes): class PermissionOAuth2Validator(OAuth2Validator): + oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 + def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): """ User can request as many scope as he wants, including invalid scopes, @@ -44,8 +46,6 @@ class PermissionOAuth2Validator(OAuth2Validator): subset of permissions. """ - oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 - valid_scopes = set() for t in Permission.PERMISSION_TYPES: From feeb99041fe42d6cfb97794d3e989467fc85f5a8 Mon Sep 17 00:00:00 2001 From: korenstin Date: Sat, 13 Jul 2024 12:41:59 +0200 Subject: [PATCH 13/14] Fix the Alias Search API --- apps/note/api/views.py | 17 ++++------------- apps/registration/forms.py | 10 ---------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/apps/note/api/views.py b/apps/note/api/views.py index bc4f99ef..32ed1837 100644 --- a/apps/note/api/views.py +++ b/apps/note/api/views.py @@ -179,19 +179,10 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet): # We match first an alias if it is matched without normalization, # then if the normalized pattern matches a normalized alias. queryset = queryset.filter( - **{f'name{suffix}': alias_prefix + alias} - ).union( - queryset.filter( - Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) - & ~Q(**{f'name{suffix}': alias_prefix + alias}) - ), - all=True).union( - queryset.filter( - Q(**{f'normalized_name{suffix}': alias_prefix + alias.lower()}) - & ~Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) - & ~Q(**{f'name{suffix}': alias_prefix + alias}) - ), - all=True) + Q(**{f'name{suffix}': alias_prefix + alias}) + | Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) + | Q(**{f'normalized_name{suffix}': alias_prefix + alias.lower()}) + ) queryset = queryset if settings.DATABASES[queryset.db]["ENGINE"] == 'django.db.backends.postgresql' \ else queryset.order_by("name") diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 6761da43..7791a8a1 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -5,7 +5,6 @@ from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ -from member.models import Club from note.models import NoteSpecial, Alias from note_kfet.inputs import AmountInput @@ -115,12 +114,3 @@ class ValidationForm(forms.Form): required=False, initial=True, ) - - # If the bda exists - if Club.objects.filter(name__iexact="bda").exists(): - # The user can join the bda club at the inscription - join_bda = forms.BooleanField( - label=_("Join BDA Club"), - required=False, - initial=True, - ) From bbbdcc7247fe1539e1aa9eb48f447a4e6fae7472 Mon Sep 17 00:00:00 2001 From: korenstin Date: Sat, 13 Jul 2024 18:03:19 +0200 Subject: [PATCH 14/14] linters --- apps/permission/scopes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index f8fd7687..6770c681 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -35,6 +35,8 @@ class PermissionScopes(BaseScopes): class PermissionOAuth2Validator(OAuth2Validator): + oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 + def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): """ User can request as many scope as he wants, including invalid scopes, @@ -44,8 +46,6 @@ class PermissionOAuth2Validator(OAuth2Validator): subset of permissions. """ - oidc_claim_scope = None # fix breaking change of django-oauth-toolkit 2.0.0 - valid_scopes = set() for t in Permission.PERMISSION_TYPES: