From 1da5db549b9421055bd1c24540dcd032b7331d42 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:01:54 +0100 Subject: [PATCH 1/6] Updated to Django 4.1 * `SuccessURLAllowedHostsMixin` (used in `LoginView`) has been replaced by `RedirectURLMixin` (see https://docs.djangoproject.com/en/4.1/releases/4.1/#miscellaneous). * Logging out via GET is deprecated in favor of POST (see https://docs.djangoproject.com/en/4.1/releases/4.1/#log-out-via-get), so added a logout form to the header which is used instead of the previous button, and which appears when not using Dataporten for auth. `dataporten.views.Logout` can keep using GET, though it should ideally be replaced by POST as well. * Added the `USES_DATAPORTEN_AUTH` custom setting for use in both `web/context_processors.py` and `web/urls.py` * Made the `defer` dicts in `make_queue/forms.py` and `web/multilingual/widgets.py` use boolean values, now that it's supported by `django-js-asset` due to the changes in Django 4.1 (see https://github.com/matthiask/django-js-asset/commit/3785c6c50fd3cbfd0a666b66a4a04200630e85b1) * Explicitly set `max_length` of `ReservationRule.start_days`, due to https://github.com/goinnn/django-multiselectfield/issues/131 --- contentbox/tests/urls/hosts.py | 4 ++-- dataporten/tests/test_views.py | 2 +- internal/templates/internal/header.html | 14 +++++++++++--- make_queue/forms.py | 4 ++-- make_queue/models/reservation.py | 3 ++- requirements.txt | 2 +- web/context_processors.py | 1 + web/hosts.py | 4 ++-- web/multilingual/widgets.py | 2 +- web/settings.py | 5 +++++ web/static/web/css/header.css | 10 ++++++++++ web/templates/web/header.html | 14 +++++++++++--- web/tests/test_context_processors.py | 1 + web/urls.py | 2 +- web/widgets.py | 2 +- 15 files changed, 52 insertions(+), 18 deletions(-) diff --git a/contentbox/tests/urls/hosts.py b/contentbox/tests/urls/hosts.py index 890b0eb1b..65d8e2111 100644 --- a/contentbox/tests/urls/hosts.py +++ b/contentbox/tests/urls/hosts.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.contrib.auth.views import SuccessURLAllowedHostsMixin +from django.contrib.auth.views import RedirectURLMixin from django_hosts import host from web.hosts import host_patterns as base_host_patterns @@ -19,7 +19,7 @@ ) settings.ALLOWED_REDIRECT_HOSTS = generate_all_hosts(settings.ALL_SUBDOMAINS) # [See the comment in `web/hosts.py`] -SuccessURLAllowedHostsMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) +RedirectURLMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) # Makes sure that the subdomain of all requests is `test-internal` TEST_INTERNAL_CLIENT_DEFAULTS = {'SERVER_NAME': f'test-internal.{settings.PARENT_HOST}'} diff --git a/dataporten/tests/test_views.py b/dataporten/tests/test_views.py index 5dc0c45b8..1f42ae680 100644 --- a/dataporten/tests/test_views.py +++ b/dataporten/tests/test_views.py @@ -33,7 +33,7 @@ def test_logout(self): self.user = User.objects.create_user(username=username, password=password) self.client.login(username=username, password=password) self.assertTrue(get_user(self.client).is_authenticated) - self.client.get(reverse('logout')) + self.client.post(reverse('logout')) self.assertFalse(get_user(self.client).is_authenticated) @mock_module_attrs({ diff --git a/internal/templates/internal/header.html b/internal/templates/internal/header.html index 16f9b1098..436c9c527 100644 --- a/internal/templates/internal/header.html +++ b/internal/templates/internal/header.html @@ -43,9 +43,17 @@
{% translate "Django admin" %}
{% endif %} - -
{% translate "Log out" %}
-
+ {% host_url 'logout' host 'main' as logout_url %} + {% if USES_DATAPORTEN_AUTH %} + +
{% translate "Log out" %}
+
+ {% else %} +
+ {% csrf_token %} + +
+ {% endif %} {% endblock user_dropdown_buttons %} {% block announcements %}{% endblock announcements %} diff --git a/make_queue/forms.py b/make_queue/forms.py index 78dabaf98..a8c0f083a 100644 --- a/make_queue/forms.py +++ b/make_queue/forms.py @@ -141,7 +141,7 @@ class Meta: class Media: js = ( - JS('make_queue/js/quota_form.js', attrs={'defer': 'defer'}), + JS('make_queue/js/quota_form.js', attrs={'defer': True}), ) def clean(self): @@ -288,7 +288,7 @@ def clean(self): class CreateMachineForm(MachineFormBase): class Media: js = ( - JS('make_queue/js/machine_create.js', attrs={'defer': 'defer'}), + JS('make_queue/js/machine_create.js', attrs={'defer': True}), ) def __init__(self, *args, **kwargs): diff --git a/make_queue/models/reservation.py b/make_queue/models/reservation.py index 02a1fc3d6..f473cc447 100644 --- a/make_queue/models/reservation.py +++ b/make_queue/models/reservation.py @@ -287,7 +287,8 @@ class Day(models.IntegerChoices): start_time = models.TimeField(verbose_name=_("start time")) end_time = models.TimeField(verbose_name=_("end time")) days_changed = models.IntegerField(verbose_name=_("days"), help_text=_("Number of times midnight is passed between start and end time.")) - start_days = MultiSelectField(choices=Day.choices, min_choices=1, verbose_name=_("start days for rule periods")) + # TODO: remove the explicitly set `max_length` when https://github.com/goinnn/django-multiselectfield/issues/131 is resolved + start_days = MultiSelectField(choices=Day.choices, min_choices=1, max_length=13, verbose_name=_("start days for rule periods")) max_hours = models.FloatField(verbose_name=_("hours single period")) max_inside_border_crossed = models.FloatField(verbose_name=_("hours multi-period")) last_modified = models.DateTimeField(auto_now=True, verbose_name=_("last modified")) diff --git a/requirements.txt b/requirements.txt index 438220ea5..93ed707b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Django-related packages -Django==4.0.7 +Django==4.1.7 django-hosts==5.2 django-ckeditor==6.5.1 django-cleanup==6.0.0 diff --git a/web/context_processors.py b/web/context_processors.py index 0ca22486f..7d78caa7a 100644 --- a/web/context_processors.py +++ b/web/context_processors.py @@ -8,6 +8,7 @@ def common_context_variables(request): return { 'DEFAULT_LANGUAGE_CODE': settings.LANGUAGE_CODE, 'CURRENT_LANGUAGE_CODE': get_language(), + 'USES_DATAPORTEN_AUTH': settings.USES_DATAPORTEN_AUTH, } diff --git a/web/hosts.py b/web/hosts.py index b5f93c72e..44860f54d 100644 --- a/web/hosts.py +++ b/web/hosts.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.contrib.auth.views import SuccessURLAllowedHostsMixin +from django.contrib.auth.views import RedirectURLMixin from django_hosts import host @@ -11,4 +11,4 @@ ] # This allows the next parameter in login to redirect to pages on all the subdomains -SuccessURLAllowedHostsMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) +RedirectURLMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) diff --git a/web/multilingual/widgets.py b/web/multilingual/widgets.py index 0a1bfefa1..8465823aa 100644 --- a/web/multilingual/widgets.py +++ b/web/multilingual/widgets.py @@ -18,7 +18,7 @@ class MultiLingualTextEdit(forms.MultiWidget): class Media: js = ( - JS('web/js/forms/widgets/multi_lingual_text_field.js', attrs={'defer': 'defer'}), + JS('web/js/forms/widgets/multi_lingual_text_field.js', attrs={'defer': True}), ) def __init__(self, attrs=None, *, languages=None, subwidget_kwargs: dict[str, Any] = None): diff --git a/web/settings.py b/web/settings.py index 166a36f8a..1517b97da 100644 --- a/web/settings.py +++ b/web/settings.py @@ -196,6 +196,9 @@ def generate_all_hosts(subdomains): }, ] +# TODO: should be removed when upgrading to Django 5.0 (see https://docs.djangoproject.com/en/4.1/releases/4.1/#forms) +FORM_RENDERER = 'django.forms.renderers.DjangoDivFormRenderer' + ASGI_APPLICATION = 'web.asgi.application' CHANNEL_LAYERS = { 'default': { @@ -254,6 +257,8 @@ def generate_all_hosts(subdomains): # Dataporten +USES_DATAPORTEN_AUTH = SOCIAL_AUTH_DATAPORTEN_KEY and SOCIAL_AUTH_DATAPORTEN_SECRET # (custom setting) + SOCIAL_AUTH_DATAPORTEN_FEIDE_SSL_PROTOCOL = True SOCIAL_AUTH_LOGIN_REDIRECT_URL = reverse_lazy('front_page') SOCIAL_AUTH_NEW_USER_REDIRECT_URL = reverse_lazy('front_page') diff --git a/web/static/web/css/header.css b/web/static/web/css/header.css index 89988b446..30563f7f7 100644 --- a/web/static/web/css/header.css +++ b/web/static/web/css/header.css @@ -159,6 +159,16 @@ background-color: rgba(255, 255, 255, 0.08) !important; /* Overrides Fomantic-UI */ } +#side-nav .logout-form button[type=submit] { + width: 100%; + height: 100%; + text-align: start; + border: none; + padding: 0; + background: none; + cursor: pointer; +} + #side-nav .set-language-form { position: absolute; margin: 0; diff --git a/web/templates/web/header.html b/web/templates/web/header.html index 27be26345..564143aa9 100644 --- a/web/templates/web/header.html +++ b/web/templates/web/header.html @@ -115,9 +115,17 @@
{% translate "My tickets" %}
- -
{% translate "Log out" %}
-
+ {% host_url 'logout' host 'main' as logout_url %} + {% if USES_DATAPORTEN_AUTH %} + +
{% translate "Log out" %}
+
+ {% else %} +
+ {% csrf_token %} + +
+ {% endif %} {% endblock user_dropdown_buttons %} diff --git a/web/tests/test_context_processors.py b/web/tests/test_context_processors.py index e1744b117..78a3a931a 100644 --- a/web/tests/test_context_processors.py +++ b/web/tests/test_context_processors.py @@ -16,6 +16,7 @@ def assert_common_context_variables_have_expected_values(self, default_language_ context = self.client.get("/").context self.assertEqual(context['DEFAULT_LANGUAGE_CODE'], default_language_code) self.assertEqual(context['CURRENT_LANGUAGE_CODE'], default_language_code) + self.assertEqual(context['USES_DATAPORTEN_AUTH'], False) class TestLoginRedirect(TestCase): diff --git a/web/urls.py b/web/urls.py index a24d04145..983264134 100644 --- a/web/urls.py +++ b/web/urls.py @@ -73,7 +73,7 @@ ) # Configure login based on if we have configured Dataporten or not. -if settings.SOCIAL_AUTH_DATAPORTEN_SECRET: +if settings.USES_DATAPORTEN_AUTH: urlpatterns += i18n_patterns( path("login/", RedirectView.as_view(url="/login/dataporten/", query_string=True), name='login'), path("logout/", Logout.as_view(), name='logout'), diff --git a/web/widgets.py b/web/widgets.py index 605f3a3a6..677dac0fc 100644 --- a/web/widgets.py +++ b/web/widgets.py @@ -234,7 +234,7 @@ def __init__(self, *args, **kwargs): @property def media(self): config_data_attrs = { - # Boolean values should be converted to strings (for use by JavaScript), as the `JS` class does not properly support boolean attributes + # Boolean values should be converted to strings, to make it easier for JavaScript code to parse the data attributes 'should-allow-all-tags': json.dumps(self.config_name == settings.CKEDITOR_EDIT_SOURCE_CONFIG_NAME), } return forms.Media( From 30ebca333f27302a6307074c9c3691f585749729 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:10:33 +0100 Subject: [PATCH 2/6] Improved code for allowed login redirect hosts This makes our code not reliant on monkey-patching an undocumented mixin class (`RedirectURLMixin`), and instead uses `LoginView` more in the intended, documented way by setting `success_url_allowed_hosts` through its `as_view()` method. --- contentbox/tests/urls/hosts.py | 22 +++++++++++----------- web/hosts.py | 4 ---- web/urls.py | 7 ++++++- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/contentbox/tests/urls/hosts.py b/contentbox/tests/urls/hosts.py index 65d8e2111..3bebe75e2 100644 --- a/contentbox/tests/urls/hosts.py +++ b/contentbox/tests/urls/hosts.py @@ -1,9 +1,18 @@ from django.conf import settings -from django.contrib.auth.views import RedirectURLMixin from django_hosts import host -from web.hosts import host_patterns as base_host_patterns from web.settings import generate_all_hosts + +# (Changing settings should be done before importing other parts of our code, as it might use these settings +# - like the login path in `web.urls`) +# Set the subdomain and host settings again, as more subdomains are added to `host_patterns` below. +settings.ALL_SUBDOMAINS = ( + *settings.ALL_SUBDOMAINS, + 'test-internal', 'test-main', +) +settings.ALLOWED_REDIRECT_HOSTS = generate_all_hosts(settings.ALL_SUBDOMAINS) + +from web.hosts import host_patterns as base_host_patterns from . import urls_internal, urls_main @@ -12,14 +21,5 @@ host(r"test-main", urls_main.__name__, name='test_main'), ] -# Set the subdomain and host settings again, as we have added more subdomains to `host_patterns` -settings.ALL_SUBDOMAINS = ( - *settings.ALL_SUBDOMAINS, - 'test-internal', 'test-main', -) -settings.ALLOWED_REDIRECT_HOSTS = generate_all_hosts(settings.ALL_SUBDOMAINS) -# [See the comment in `web/hosts.py`] -RedirectURLMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) - # Makes sure that the subdomain of all requests is `test-internal` TEST_INTERNAL_CLIENT_DEFAULTS = {'SERVER_NAME': f'test-internal.{settings.PARENT_HOST}'} diff --git a/web/hosts.py b/web/hosts.py index 44860f54d..4a2f660b0 100644 --- a/web/hosts.py +++ b/web/hosts.py @@ -1,5 +1,4 @@ from django.conf import settings -from django.contrib.auth.views import RedirectURLMixin from django_hosts import host @@ -9,6 +8,3 @@ host(r"docs", 'docs.urls', name='docs'), host(r"", settings.ROOT_URLCONF, name='main'), ] - -# This allows the next parameter in login to redirect to pages on all the subdomains -RedirectURLMixin.success_url_allowed_hosts = set(settings.ALLOWED_REDIRECT_HOSTS) diff --git a/web/urls.py b/web/urls.py index 983264134..8d92fa34d 100644 --- a/web/urls.py +++ b/web/urls.py @@ -88,7 +88,12 @@ # If it is not configured, we would like to have a simple login page. So that # we can test with non-superusers without giving them access to the admin page. urlpatterns += i18n_patterns( - path("login/", auth_views.LoginView.as_view(template_name='web/login.html', redirect_authenticated_user=True), name='login'), + path("login/", auth_views.LoginView.as_view( + template_name='web/login.html', + redirect_authenticated_user=True, + # This allows the `next` query parameter (used when logging in) to redirect to pages on all the subdomains + success_url_allowed_hosts=set(settings.ALLOWED_REDIRECT_HOSTS), + ), name='login'), path("logout/", auth_views.LogoutView.as_view(next_page="/"), name='logout'), prefix_default_language=False, From eb4c90175baa3c96aecc91af8f516111562e2677 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:01:51 +0100 Subject: [PATCH 3/6] Use specific AppConfig for web in INSTALLED_APPS The main entrypoint app (`web` in this project) is normally not listed in the `INSTALLED_APPS` setting (see https://github.com/django/django/blob/7dfd29b84e5a27d61ae62cb5ed9122d5a99ee1be/docs/intro/tutorial02.txt#L222-L230 and https://github.com/mdn/django-locallibrary-tutorial/blob/e55f668e6cf1d5dd322eb900f89d2313a0d93cba/locallibrary/settings.py#L40-L49), but was possibly added by mistake in 82afc323bf1cbaf83eb2110b1a1d480aae76b9ca. However, we still want to use the `AppConfig` in `web/apps.py`, so this change should make that clearer. --- web/management/commands/runserver.py | 2 +- web/settings.py | 7 ++++--- web/static/ckeditor/ckeditor/config.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/web/management/commands/runserver.py b/web/management/commands/runserver.py index a41c7f276..a786df3ac 100644 --- a/web/management/commands/runserver.py +++ b/web/management/commands/runserver.py @@ -10,7 +10,7 @@ class Command(runserver.Command): Overrides the ``runserver`` management command. It's currently extending ``daphne``'s command, as it's the one we would normally be using. - This requires that the ``web`` app is listed before other apps that override ``runserver``, in the ``INSTALLED_APPS`` setting. + This requires that ``web.apps.WebConfig`` is listed before other apps that override ``runserver``, in the ``INSTALLED_APPS`` setting. """ def inner_run(self, *args, **options): diff --git a/web/settings.py b/web/settings.py index 1517b97da..6a7918660 100644 --- a/web/settings.py +++ b/web/settings.py @@ -71,8 +71,9 @@ INSTALLED_APPS = [ - # The main entrypoint app; should be listed first, to be able to override things like management commands - 'web', + # App used for things regarding the whole project or across other apps + # (Should be listed first, to be able to override things like management commands) + 'web.apps.WebConfig', # Should be listed before `django.contrib.staticfiles` # (see https://channels.readthedocs.io/en/stable/releases/4.0.0.html#decoupling-of-the-daphne-application-server) @@ -92,7 +93,7 @@ # Other third-party packages 'social_django', - 'ckeditor', # must be listed after `web` to make the custom `ckeditor/config.js` apply + 'ckeditor', # must be listed after `web.apps.WebConfig` to make the custom `ckeditor/config.js` apply 'ckeditor_uploader', 'phonenumber_field', 'simple_history', diff --git a/web/static/ckeditor/ckeditor/config.js b/web/static/ckeditor/ckeditor/config.js index 764ea188f..8bcffe97a 100644 --- a/web/static/ckeditor/ckeditor/config.js +++ b/web/static/ckeditor/ckeditor/config.js @@ -1,5 +1,5 @@ /* - Note: To make this configuration file apply, the `ckeditor` app must be listed after `web` in `INSTALLED_APPS`. + Note: To make this configuration file apply, the `ckeditor` app must be listed after `web.apps.WebConfig` in `INSTALLED_APPS`. */ // `CKEDITOR_CONFIG_FROM_DJANGO` is defined in `config_from_django.js` // noinspection ES6ConvertVarToLetConst From 8e9d66c15ced597951c4167d28424c0d781727a6 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:04:00 +0100 Subject: [PATCH 4/6] Changed app order on the Django admin index page This was made possible by Django 4.1 (see https://docs.djangoproject.com/en/4.1/releases/4.1/#django-contrib-admin). --- web/admin.py | 34 ++++++++++++++++++++++++++++++++++ web/apps.py | 5 +++++ web/settings.py | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 web/admin.py diff --git a/web/admin.py b/web/admin.py new file mode 100644 index 000000000..d6ced3a30 --- /dev/null +++ b/web/admin.py @@ -0,0 +1,34 @@ +from django.contrib import admin + + +class WebAdminSite(admin.AdminSite): + apps_listed_first = ( + 'users', + 'groups', + 'contentbox', + 'announcements', + 'news', + 'make_queue', + 'makerspace', + 'faq', + # Apps belonging on other subdomains + 'internal', + 'docs', + # Non-used (or rarely used) apps + 'checkin', + 'auth', + ) + _apps__to__index = {app: i for i, app in enumerate(apps_listed_first)} + + def get_app_list(self, request, app_label=None): + app_list = super().get_app_list(request, app_label=app_label) + + sort_last_key = len(self.apps_listed_first) + + def app_sorting_key(app_dict: dict): + # Sorts the apps so that those whose labels are in `apps_listed_first` are listed first, + # and the rest are sorted last (keeping their original order) + return self._apps__to__index.get(app_dict['app_label'], sort_last_key) + + app_list.sort(key=app_sorting_key) + return app_list diff --git a/web/apps.py b/web/apps.py index a67c6fe70..581c666b2 100644 --- a/web/apps.py +++ b/web/apps.py @@ -1,4 +1,5 @@ from django.apps import AppConfig +from django.contrib.admin.apps import AdminConfig class WebConfig(AppConfig): @@ -12,3 +13,7 @@ def ready(self): # Register / connect to the signals here when the app starts signals.connect() + + +class WebAdminConfig(AdminConfig): + default_site = 'web.admin.WebAdminSite' diff --git a/web/settings.py b/web/settings.py index 6a7918660..3f7504426 100644 --- a/web/settings.py +++ b/web/settings.py @@ -80,12 +80,12 @@ 'daphne', # Built-in Django apps - 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'web.apps.WebAdminConfig', # replaces 'django.contrib.admin' # Third-party packages with significant effect on Django's functionality 'django_hosts', From c12a27f9a4b76850b6060b60044055d9b7d36c9a Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Thu, 17 Nov 2022 20:24:14 +0100 Subject: [PATCH 5/6] Made Dataporten logout view use POST ...instead of GET. This makes the logout button code in `header.html` easier, and removes the possibility of an adversary making users modify their state by e.g. sending a link to https://makentnu.no/logout/, which would make the user log out when clicked; this would not be possible now that the view uses POST with a CSRF token. Also removed the `USES_DATAPORTEN_AUTH` context variable, as it's no longer used in any templates. --- dataporten/views.py | 2 +- internal/templates/internal/header.html | 15 ++++----------- web/context_processors.py | 1 - web/templates/web/header.html | 15 ++++----------- web/tests/test_context_processors.py | 1 - 5 files changed, 9 insertions(+), 25 deletions(-) diff --git a/dataporten/views.py b/dataporten/views.py index c912cd7c4..2cca89ebe 100644 --- a/dataporten/views.py +++ b/dataporten/views.py @@ -15,7 +15,7 @@ class Logout(View): - def get(self, request): + def post(self, request): logout(request) return HttpResponseRedirect(settings.LOGOUT_URL) diff --git a/internal/templates/internal/header.html b/internal/templates/internal/header.html index 436c9c527..818fb4096 100644 --- a/internal/templates/internal/header.html +++ b/internal/templates/internal/header.html @@ -43,17 +43,10 @@
{% translate "Django admin" %}
{% endif %} - {% host_url 'logout' host 'main' as logout_url %} - {% if USES_DATAPORTEN_AUTH %} - -
{% translate "Log out" %}
-
- {% else %} -
- {% csrf_token %} - -
- {% endif %} +
+ {% csrf_token %} + +
{% endblock user_dropdown_buttons %} {% block announcements %}{% endblock announcements %} diff --git a/web/context_processors.py b/web/context_processors.py index 7d78caa7a..0ca22486f 100644 --- a/web/context_processors.py +++ b/web/context_processors.py @@ -8,7 +8,6 @@ def common_context_variables(request): return { 'DEFAULT_LANGUAGE_CODE': settings.LANGUAGE_CODE, 'CURRENT_LANGUAGE_CODE': get_language(), - 'USES_DATAPORTEN_AUTH': settings.USES_DATAPORTEN_AUTH, } diff --git a/web/templates/web/header.html b/web/templates/web/header.html index 564143aa9..81342401e 100644 --- a/web/templates/web/header.html +++ b/web/templates/web/header.html @@ -115,17 +115,10 @@
{% translate "My tickets" %}
- {% host_url 'logout' host 'main' as logout_url %} - {% if USES_DATAPORTEN_AUTH %} - -
{% translate "Log out" %}
-
- {% else %} -
- {% csrf_token %} - -
- {% endif %} +
+ {% csrf_token %} + +
{% endblock user_dropdown_buttons %} diff --git a/web/tests/test_context_processors.py b/web/tests/test_context_processors.py index 78a3a931a..e1744b117 100644 --- a/web/tests/test_context_processors.py +++ b/web/tests/test_context_processors.py @@ -16,7 +16,6 @@ def assert_common_context_variables_have_expected_values(self, default_language_ context = self.client.get("/").context self.assertEqual(context['DEFAULT_LANGUAGE_CODE'], default_language_code) self.assertEqual(context['CURRENT_LANGUAGE_CODE'], default_language_code) - self.assertEqual(context['USES_DATAPORTEN_AUTH'], False) class TestLoginRedirect(TestCase): From c1355df3bf4e4755f6a9aa1a643a598b34a39625 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Mon, 27 Feb 2023 02:37:59 +0100 Subject: [PATCH 6/6] Updated CHANGELOG for #596 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72644dc6e..52181066c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ A summary of changes made to the codebase, grouped per deployment. ### Improvements +- Updated Django to version 4.1 - Place files uploaded through CKEditor in a separate folder for each model - Made all pages have a consistent (browser tab) title format - Most pages will have " | MAKE NTNU" as suffix to the title; @@ -19,10 +20,13 @@ A summary of changes made to the codebase, grouped per deployment. ### Fixes - Made the CKEditor file uploader work on all subdomains +- Prevented [CSRF attacks](https://owasp.org/www-community/attacks/csrf) against the logout URL, + by requiring logout requests being sent using `POST` instead of `GET` ### Other changes - Set minimum required Python version to 3.10 +- Changed order of the apps listed on [the Django admin index page](https://admin.makentnu.no/) - Never-ending masses of code cleanup