Skip to content

Commit

Permalink
refactor(accounts, middleware): change ToU middleware to callable class
Browse files Browse the repository at this point in the history
Signed-off-by: David Wallace <[email protected]>
  • Loading branch information
MyPyDavid committed Dec 18, 2024
1 parent 72988b6 commit bcbd456
Showing 1 changed file with 39 additions and 41 deletions.
80 changes: 39 additions & 41 deletions rdmo/accounts/middleware.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit bcbd456

Please sign in to comment.