From bcbd456e1ee0b5ff9eacd28abcb38564a809a3ab Mon Sep 17 00:00:00 2001 From: David Wallace Date: Wed, 18 Dec 2024 18:30:49 +0100 Subject: [PATCH] refactor(accounts, middleware): change ToU middleware to callable class Signed-off-by: David Wallace --- rdmo/accounts/middleware.py | 80 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/rdmo/accounts/middleware.py b/rdmo/accounts/middleware.py index dbf654d9d..9b04342c4 100644 --- a/rdmo/accounts/middleware.py +++ b/rdmo/accounts/middleware.py @@ -1,74 +1,72 @@ """Terms and Conditions Middleware""" - # ref: https://github.com/cyface/django-termsandconditions/blob/main/termsandconditions/middleware.py import logging from django.conf import settings from django.http import HttpResponseRedirect from django.urls import reverse -from django.utils.deprecation import MiddlewareMixin from .utils import user_has_accepted_terms LOGGER = logging.getLogger(__name__) - ACCEPT_TERMS_PATH = getattr(settings, "ACCEPT_TERMS_PATH", reverse("terms_of_use_update")) TERMS_EXCLUDE_URL_PREFIX_LIST = getattr( settings, "TERMS_EXCLUDE_URL_PREFIX_LIST", - {"/admin", "/i18n", "/static", "/account"}, -) -TERMS_EXCLUDE_URL_CONTAINS_LIST = getattr( - settings, "TERMS_EXCLUDE_URL_CONTAINS_LIST", {} + ["/admin", "/i18n", "/static", "/account"], ) +TERMS_EXCLUDE_URL_CONTAINS_LIST = getattr(settings, "TERMS_EXCLUDE_URL_CONTAINS_LIST", []) TERMS_EXCLUDE_URL_LIST = getattr( settings, "TERMS_EXCLUDE_URL_LIST", - {"/", settings.LOGOUT_URL}, + ["/", settings.LOGOUT_URL], ) -class TermsAndConditionsRedirectMiddleware(MiddlewareMixin): - - def process_request(self, request): - """Process each request to app to ensure terms have been accepted""" - - if not settings.ACCOUNT_TERMS_OF_USE: - return None # If terms are not enabled, consider them accepted. - - current_path = request.META["PATH_INFO"] +class TermsAndConditionsRedirectMiddleware: + """Middleware to ensure terms and conditions have been accepted.""" - if request.user.is_authenticated and is_path_protected(current_path): - if not user_has_accepted_terms(request.user, request.session): - # Redirect to update consent page if consent is missing - return HttpResponseRedirect(reverse("terms_of_use_update")) + def __init__(self, get_response): + self.get_response = get_response - return None + def __call__(self, request): + # Skip processing if ACCOUNT_TERMS_OF_USE is disabled + if not getattr(settings, "ACCOUNT_TERMS_OF_USE", False): + return self.get_response(request) + # check if the current path is protected + if ( + request.user.is_authenticated + and self.is_path_protected(request.path) + and not user_has_accepted_terms(request.user, request.session) + ): + return HttpResponseRedirect(ACCEPT_TERMS_PATH) -def is_path_protected(path): - """ - returns True if given path is to be protected, otherwise False + # Proceed with the response for non-protected paths or accepted terms + return self.get_response(request) - The path is not to be protected when it appears on: - TERMS_EXCLUDE_URL_PREFIX_LIST, TERMS_EXCLUDE_URL_LIST, TERMS_EXCLUDE_URL_CONTAINS_LIST or as - ACCEPT_TERMS_PATH - """ - protected = True + @staticmethod + def is_path_protected(path): + """ + Determine if a given path is protected by the middleware. - for exclude_path in TERMS_EXCLUDE_URL_PREFIX_LIST: - if path.startswith(exclude_path): - protected = False + Paths are excluded if they match any of the following: + - Start with a prefix in TERMS_EXCLUDE_URL_PREFIX_LIST + - Contain a substring in TERMS_EXCLUDE_URL_CONTAINS_LIST + - Are explicitly listed in TERMS_EXCLUDE_URL_LIST + - Start with the ACCEPT_TERMS_PATH + """ + if any(path.startswith(prefix) for prefix in TERMS_EXCLUDE_URL_PREFIX_LIST): + return False - for contains_path in TERMS_EXCLUDE_URL_CONTAINS_LIST: - if contains_path in path: - protected = False + if any(substring in path for substring in TERMS_EXCLUDE_URL_CONTAINS_LIST): + return False - if path in TERMS_EXCLUDE_URL_LIST: - protected = False + if path in TERMS_EXCLUDE_URL_LIST: + return False - if path.startswith(ACCEPT_TERMS_PATH): - protected = False + if path.startswith(ACCEPT_TERMS_PATH): + return False - return protected + return True