From 71b3c2adece411c7eed2c802183f065eb3ba9071 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Wed, 15 Jul 2020 17:16:23 +0200 Subject: [PATCH] Make custom authentication backends configurable via site preferences --- aleksis/core/apps.py | 18 +++++++++++++++++- aleksis/core/preferences.py | 17 ++++++++++++++++- aleksis/core/settings.py | 7 ++++--- .../partials/alternative_login_options.html | 2 +- aleksis/core/util/core_helpers.py | 3 +++ 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py index aeda60932..54c6d4f5b 100644 --- a/aleksis/core/apps.py +++ b/aleksis/core/apps.py @@ -1,6 +1,7 @@ from typing import Any, List, Optional, Tuple import django.apps +from django.conf import settings from django.http import HttpRequest from django.utils.module_loading import autodiscover_modules @@ -12,7 +13,7 @@ from .registries import ( site_preferences_registry, ) from .util.apps import AppConfig -from .util.core_helpers import has_person +from .util.core_helpers import get_site_preferences, has_person, lazy_preference from .util.sass_helpers import clean_scss @@ -48,6 +49,18 @@ class CoreConfig(AppConfig): preference_models.register(personpreferencemodel, person_preferences_registry) preference_models.register(grouppreferencemodel, group_preferences_registry) + self._refresh_authentication_backends() + + def _refresh_authentication_backends(self): + """Refresh config list of enabled authentication backends.""" + from .preferences import AuthenticationBackends # noqa + + idx = settings.AUTHENTICATION_BACKENDS.index("django.contrib.auth.backends.ModelBackend") + + for backend in get_site_preferences()["auth__backends"]: + settings._wrapped.AUTHENTICATION_BACKENDS.insert(idx, backend) + idx += 1 + def preference_updated( self, sender: Any, @@ -57,6 +70,9 @@ class CoreConfig(AppConfig): new_value: Optional[Any] = None, **kwargs, ) -> None: + if section == "auth" and name == "backends": + self._refresh_authentication_backends() + if section == "theme": if name in ("primary", "secondary"): clean_scss() diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py index 6693aff1f..cf3d574c3 100644 --- a/aleksis/core/preferences.py +++ b/aleksis/core/preferences.py @@ -3,7 +3,12 @@ from django.forms import EmailField, ImageField, URLField from django.utils.translation import gettext_lazy as _ from dynamic_preferences.preferences import Section -from dynamic_preferences.types import ChoicePreference, FilePreference, StringPreference +from dynamic_preferences.types import ( + ChoicePreference, + FilePreference, + MultipleChoicePreference, + StringPreference, +) from .models import Person from .registries import person_preferences_registry, site_preferences_registry @@ -16,6 +21,7 @@ mail = Section("mail") notification = Section("notification") footer = Section("footer") account = Section("account") +auth = Section("auth", verbose_name=_("Authentication")) @site_preferences_registry.register @@ -178,3 +184,12 @@ class SchoolNameOfficial(StringPreference): default = "" required = False verbose_name = _("Official name of the school, e.g. as given by supervisory authority") + + +@site_preferences_registry.register +class AuthenticationBackends(MultipleChoicePreference): + section = auth + name = "backends" + default = None + choices = [(b, b) for b in settings.CUSTOM_AUTHENTICATION_BACKENDS] + verbose_name = _("Enabled custom authentication backends") diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py index 8eff3ef21..98c233088 100644 --- a/aleksis/core/settings.py +++ b/aleksis/core/settings.py @@ -282,13 +282,14 @@ if _settings.get("ldap.uri", None): "is_superuser" ] -merge_app_settings("AUTHENTICATION_BACKENDS", AUTHENTICATION_BACKENDS) +CUSTOM_AUTHENTICATION_BACKENDS = [] +merge_app_settings("AUTHENTICATION_BACKENDS", CUSTOM_AUTHENTICATION_BACKENDS) # Add ModelBckend last so all other backends get a chance # to verify passwords first AUTHENTICATION_BACKENDS.append("django.contrib.auth.backends.ModelBackend") -# Structure of items: URL name, icon name, button title +# Structure of items: backend, URL name, icon name, button title ALTERNATIVE_LOGIN_VIEWS = [] merge_app_settings("ALTERNATIVE_LOGIN_VIEWS", ALTERNATIVE_LOGIN_VIEWS, True) @@ -386,7 +387,7 @@ TEMPLATED_EMAIL_BACKEND = "templated_email.backends.vanilla_django" TEMPLATED_EMAIL_AUTO_PLAIN = True -TEMPLATE_VISIBLE_SETTINGS = ["ADMINS", "DEBUG", "ALTERNATIVE_LOGIN_VIEWS"] +TEMPLATE_VISIBLE_SETTINGS = ["ADMINS", "DEBUG"] DYNAMIC_PREFERENCES = { "REGISTRY_MODULE": "preferences", diff --git a/aleksis/core/templates/core/partials/alternative_login_options.html b/aleksis/core/templates/core/partials/alternative_login_options.html index f9198e5a8..24d36e9ef 100644 --- a/aleksis/core/templates/core/partials/alternative_login_options.html +++ b/aleksis/core/templates/core/partials/alternative_login_options.html @@ -1,6 +1,6 @@ {% if ALTERNATIVE_LOGIN_VIEWS %} <p> - {% for url, icon, text in ALTERNATIVE_LOGIN_VIEWS %} + {% for backend, url, icon, text in ALTERNATIVE_LOGIN_VIEWS %} <a class="btn-large waves-effect waves-light primary" href="{% url url %}"> <i class="material-icons left">{{ icon }}</i> {{ text }} diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index ba28f6629..8302d51db 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -323,6 +323,9 @@ def custom_information_processor(request: HttpRequest) -> dict: return { "FOOTER_MENU": CustomMenu.get_default("footer"), + "ALTERNATIVE_LOGIN_VIEWS": [ + a for a in settings.ALTERNATIVE_LOGIN_VIEWS if a[0] in settings.AUTHENTICATION_BACKENDS + ], } -- GitLab