diff --git a/.github/workflows/build_docker_image.yml b/.github/workflows/build_docker_image.yml index 053f800..b93e49b 100644 --- a/.github/workflows/build_docker_image.yml +++ b/.github/workflows/build_docker_image.yml @@ -15,7 +15,7 @@ jobs: services: mariadb: - image: mariadb:10.2 + image: mariadb:10.4 env: MARIADB_USER: amelie_test MARIADB_PASSWORD: amelie_test diff --git a/amelie/activities/migrations/0011_alter_activity_components.py b/amelie/activities/migrations/0011_alter_activity_components.py new file mode 100644 index 0000000..e4d8114 --- /dev/null +++ b/amelie/activities/migrations/0011_alter_activity_components.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.11 on 2024-04-14 16:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('activities', '0010_auto_20221031_2218'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='components', + field=models.ManyToManyField(blank=True, to='activities.activity'), + ), + ] diff --git a/amelie/api/common.py b/amelie/api/common.py index b8f3f08..4448da1 100644 --- a/amelie/api/common.py +++ b/amelie/api/common.py @@ -32,4 +32,4 @@ def strip_markdown(markdowntext): :return: Text without markdown formatting. :rtype: unicode """ - return ''.join(BeautifulSoup(markdown(markdowntext), "html.parser").findAll(text=True)) + return ''.join(BeautifulSoup(markdown(markdowntext), "html.parser").findAll(string=True)) diff --git a/amelie/calendar/participation_urls.py b/amelie/calendar/participation_urls.py index 870bb6e..b9d372b 100644 --- a/amelie/calendar/participation_urls.py +++ b/amelie/calendar/participation_urls.py @@ -1,9 +1,9 @@ -from django.conf.urls import url +from django.urls import re_path from amelie.calendar import views app_name = 'calendar' urlpatterns = [ - url(r'^(?P\d+)/pay/', views.PayParticipationView.as_view(), name='pay_participation'), + re_path(r'^(?P\d+)/pay/', views.PayParticipationView.as_view(), name='pay_participation'), ] diff --git a/amelie/calendar/views.py b/amelie/calendar/views.py index 6b08de2..c48139b 100644 --- a/amelie/calendar/views.py +++ b/amelie/calendar/views.py @@ -1,7 +1,7 @@ from django.contrib import messages from django.shortcuts import get_object_or_404, redirect from django.utils import timezone -from django.utils.translation import ugettext_lazy as _l +from django.utils.translation import gettext_lazy as _l from django.views.generic import TemplateView from amelie.calendar.models import Participation diff --git a/amelie/claudia/claudia_views.py b/amelie/claudia/claudia_views.py index 65f476c..5798633 100644 --- a/amelie/claudia/claudia_views.py +++ b/amelie/claudia/claudia_views.py @@ -6,7 +6,7 @@ from django.views.generic import ListView, DetailView, View, TemplateView from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView from django.views.generic.detail import SingleObjectMixin -from django.utils.translation import ugettext_lazy as _l +from django.utils.translation import gettext_lazy as _l from amelie.settings import SYSADMINS_ABBR from amelie.tools.mixins import RequireCommitteeMixin, RequireStrictCommitteeMixin diff --git a/amelie/education/views.py b/amelie/education/views.py index c40c446..72c5689 100644 --- a/amelie/education/views.py +++ b/amelie/education/views.py @@ -5,7 +5,7 @@ from django.shortcuts import render, get_object_or_404, redirect from django.utils import timezone from django.utils.encoding import force_str -from django.utils.http import is_safe_url +from django.utils.http import url_has_allowed_host_and_scheme from django.views.decorators.http import require_http_methods from django.views.generic import TemplateView @@ -384,7 +384,7 @@ def course_new(request): if form.is_valid(): course_obj = form.save() course_obj.save() - if next and is_safe_url(next, [request.get_host()]): + if next and url_has_allowed_host_and_scheme(next, [request.get_host()]): return redirect(next) return redirect("education:complaint_new") @@ -401,7 +401,7 @@ def module_new(request): if form.is_valid(): module_obj = form.save() module_obj.save() - if next and is_safe_url(next, [request.get_host()]): + if next and url_has_allowed_host_and_scheme(next, [request.get_host()]): return redirect(next) return redirect("education:complaint_new") diff --git a/amelie/members/forms.py b/amelie/members/forms.py index 6293120..5356ccc 100644 --- a/amelie/members/forms.py +++ b/amelie/members/forms.py @@ -46,7 +46,7 @@ def save(self, *args, **kwargs): if field == "preferences": old = [preference.name for preference in getattr(old_person, field).all()] new = [preference.name for preference in self.cleaned_data[field].all()] + [preference.name for preference in self.instance.preferences.filter(adjustable=False)] - + added = list(set(new)-set(old)) removed = list(set(old)-set(new)) diff --git a/amelie/members/urls.py b/amelie/members/urls.py index 40a57fe..4231afd 100644 --- a/amelie/members/urls.py +++ b/amelie/members/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls import include -from django.urls import path +from django.urls import path, include app_name = 'members' diff --git a/amelie/oauth/forms.py b/amelie/oauth/forms.py index 0375ca8..f750efa 100644 --- a/amelie/oauth/forms.py +++ b/amelie/oauth/forms.py @@ -1,6 +1,6 @@ from django import forms from django.forms import widgets -from django.utils.translation import ugettext_lazy as _l +from django.utils.translation import gettext_lazy as _l class OAuth2RequestForm(forms.Form): diff --git a/amelie/settings/environ.py b/amelie/settings/environ.py index d44753b..6c99512 100644 --- a/amelie/settings/environ.py +++ b/amelie/settings/environ.py @@ -49,6 +49,19 @@ def get_random_secret_key_no_dollar(): PYDEV_DEBUGGER = False PYDEV_DEBUGGER_IP = None +# Load the debug toolbar -- does not need to be changed in principle +if DEBUG_TOOLBAR: + def custom_show_toolbar(request): + return True + + # Order is important + INSTALLED_APPS = INSTALLED_APPS + ('debug_toolbar',) + MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware'] + MIDDLEWARE + + DEBUG_TOOLBAR_CONFIG = { + 'SHOW_TOOLBAR_CALLBACK': '%s.%s' % (__name__, custom_show_toolbar.__name__), + } + # Do not redirect to HTTPS, because the nginx proxy container only listens on HTTP SECURE_SSL_REDIRECT = False diff --git a/amelie/settings/generic.py b/amelie/settings/generic.py index 0bc9944..eb365e6 100644 --- a/amelie/settings/generic.py +++ b/amelie/settings/generic.py @@ -208,6 +208,8 @@ 'mozilla_django_oidc.middleware.SessionRefresh', # Verify OIDC session tokens ] +INTERNAL_IPS = ['127.0.0.1', 'localhost', '172.17.0.1'] + # Authentication backends used by the application AUTHENTICATION_BACKENDS = [ 'amelie.tools.auth.IAOIDCAuthenticationBackend', # Logins via OIDC / auth.ia @@ -302,7 +304,7 @@ 'ckeditor_uploader', # SSL Runserver - 'sslserver', + # 'sslserver', # Django-celery helper for celery results 'django_celery_results', diff --git a/amelie/tools/cache.py b/amelie/tools/cache.py index f2dcef9..6237fd4 100644 --- a/amelie/tools/cache.py +++ b/amelie/tools/cache.py @@ -1,4 +1,4 @@ -from threading import currentThread +from threading import current_thread from django.core.cache.backends.locmem import LocMemCache from django.utils.deprecation import MiddlewareMixin @@ -12,13 +12,13 @@ def get_request_cache(): temp = RequestCacheMiddleware() temp.process_request(None) - return _request_cache[currentThread()] + return _request_cache[current_thread()] # LocMemCache is a threadsafe local memory cache class RequestCache(LocMemCache): def __init__(self): - name = 'locmemcache@%i' % hash(currentThread()) + name = 'locmemcache@%i' % hash(current_thread()) params = dict() super(RequestCache, self).__init__(name, params) @@ -31,7 +31,7 @@ def __init__(self, *args, **kwargs): # noinspection PyMethodMayBeStatic,PyUnusedLocal def process_request(self, request): - cache = _request_cache.get(currentThread()) or RequestCache() - _request_cache[currentThread()] = cache + cache = _request_cache.get(current_thread()) or RequestCache() + _request_cache[current_thread()] = cache cache.clear() diff --git a/amelie/tools/middleware.py b/amelie/tools/middleware.py index 3da3690..80085e4 100644 --- a/amelie/tools/middleware.py +++ b/amelie/tools/middleware.py @@ -36,6 +36,5 @@ def process_request(self, request): request.is_board = request.user.is_superuser or request.person.is_board() request.is_education_committee = request.is_board or request.person.is_education_committee() - if not request.session.get(translation.LANGUAGE_SESSION_KEY, False): - preferred_language = request.person.preferred_language - translation.activate(preferred_language) + preferred_language = request.person.preferred_language + translation.activate(preferred_language) diff --git a/amelie/urls.py b/amelie/urls.py index 708110a..eb3ba96 100644 --- a/amelie/urls.py +++ b/amelie/urls.py @@ -1,9 +1,8 @@ import oauth2_provider.views from django.conf import settings -from django.conf.urls import include from django.contrib import admin -from django.urls import reverse_lazy, path, re_path +from django.urls import reverse_lazy, path, re_path, include from django.contrib.auth.views import LogoutView from django.views.generic.base import RedirectView from django.views.static import serve @@ -20,7 +19,6 @@ path('admin/', admin.site.urls), path('legacy_login/', views.login, name='legacy_login'), path('legacy_logout/', LogoutView.as_view(), name='legacy_logout'), - path('i18n/', include('django.conf.urls.i18n')), path('profile/', views.profile_overview, name='profile_overview'), path('profile/edit/', views.profile_edit, name='profile_edit'), path('profile////', views.profile_actions, name='profile_actions'), @@ -137,11 +135,9 @@ if settings.DEBUG_TOOLBAR: - import debug_toolbar + from debug_toolbar.toolbar import debug_toolbar_urls # Django debug toolbar - urlpatterns += [ - path('__debugtoolbar__/', include(debug_toolbar.urls), name='django_debug_toolbar') - ] + urlpatterns += debug_toolbar_urls() # Redirect for 500 errors handler500 = views.server_error diff --git a/locale/nl/LC_MESSAGES/django.mo b/locale/nl/LC_MESSAGES/django.mo index 6045ae5..d374192 100644 Binary files a/locale/nl/LC_MESSAGES/django.mo and b/locale/nl/LC_MESSAGES/django.mo differ diff --git a/requirements.txt b/requirements.txt index 712b2cc..3d31e9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ -Django>=3.2.16,<3.3 - +Django>=4.2.11,<4.3 importlib-metadata>=1.4.0,<5.0 # importlib-metadata 5+ causes Celery bug: https://github.com/celery/celery/issues/7783 -celery>=5.2.7,<5.3 +celery>=5.3.5,<5.4 flower==1.2.0 django-celery-results>=2.4,<2.5 @@ -9,7 +8,6 @@ django-allow-cidr>=0.5.0,<0.6 django-compressor>=4.1,<4.2 django-localflavor>=3.1,<3.2 django-extensions>=3.2.1,<3.3 -django-iban>=0.3.1,<0.4 django-formtools>=2.4,<2.5 django-auditlog>=2.2.0,<2.3 django-oauth-toolkit>=1.7.1,<1.8 # 2.x has breaking changes. @@ -21,22 +19,23 @@ django-environ django-modern-rpc>=1.0.1,<1.1 # WYSIWYG Editor for Django -django-ckeditor>=6.3.2,<6.4 # 6.4+ requires Python3.8+ and Django 3.2+ +django-ckeditor>=6.3.2 # FCM (Firebase Cloud Messaging) -fcm-django>=0.3.11,<0.4 # 1.x has breaking changes (old firebase api removed) - -# Custom forks or specific commits of django packages -git+https://github.com/Inter-Actief/django-sslserver@204586ce686212a4c2848c12f88f7279802b5dcc +fcm-django>=0.3.11,<1 # 1.x has breaking changes (old firebase api removed) # TODO: Breaking -# Other random dependencies, to be documented, see issue #556 ... +# Used for stripping Markdown notations and indexing the IA Summary website. beautifulsoup4>=4.11.1,<4.12 + +# Sanitizing Markdown strings in amelie template tags bleach>=5.0.1,<5.1 + +# Other random dependencies, to be documented, see issue #556 ... httplib2>=0.20.4,<0.21 icalendar>=4.1.0,<4.2 Markdown>=3.3.7,<3.4 # 3.4+ has breaking changes in changelog that have not been checked. markdown2>=2.4.5,<2.5 -mysqlclient>=2.1.1,<2.2 +mysqlclient # Pillow requires libjpeg-dev zlib1g-dev (on Debian) Pillow>=9.2.0,<9.3 python-gitlab>=3.10,<3.11.0 @@ -44,13 +43,13 @@ python-dateutil>=2.8.2,<2.9 # python-ldap requires libldap-dev libsasl2-dev (on Debian) to build python-ldap>=3.4.3,<3.5 raven>=6.10.0,<6.11 -reportlab>=3.6.11,<3.7 -requests>=2.28.1,<2.29 +reportlab>=3.6.11 +requests>=2.28.1,<2.32 twython>=3.9.1,<3.10 -html2text>=2020.1.16,<2021.2 +html2text>=2020.1.16,<2024.2.26 # Daphne - to run the website in ASGI mode on a proper webserver -daphne>=3.0,<3.1 +daphne>=3.0,<4.2 # UWSGI - to run the website in WSGI mode on a proper webserver uwsgi>=2.0,<2.1 @@ -62,20 +61,17 @@ google-api-python-client>=2.63.0,<3 oauth2client>=4.1.3,<4.2 pyOpenSSL>=22.1.0,<23.3.0 # PKCS12 deprecation in 23.3.0, need to migrate gsuite plugin to google-auth-oauthlib. See https://googleapis.github.io/google-api-python-client/docs/oauth.html -# Mastodon API wrapper -Mastodon.py>=1.5.1,<1.6 - # Development -django-debug-toolbar>=3.7,<3.8 +django-debug-toolbar>=3.7,<4.5 django-rosetta>=0.9.8,<0.10 docutils>=0.19,<0.20 -pyinotify>=0.9.6,<0.10 -model_bakery>=1.7.0,<1.8 -django-silk>=5.0.1,<5.1 +pyinotify +model_bakery>=1.7.0,<1.19 +django-silk>=5.0.1,<5.2 # SAML IdP (requires xmlsec1 (on Debian)) -pysaml2>=7.2.1,<7.3 -djangosaml2idp>=0.7.2,<0.8 +pysaml2>=7.2.1,<7.5 +djangosaml2idp>=0.7.2,<0.8 #TODO: Officially only supports Django up-and-till 3.0 (not updated for the last 3 years) # Single Sign On - OIDC Client mozilla-django-oidc