import re from django.conf import settings from django.shortcuts import redirect class RBACMiddleware: ROLE_ROUTES = { "admin": [r"^/admin/", r"^/ops/", r"^/portal/"], "ops": [r"^/ops/"], "buyer": [r"^/portal/"], } def __init__(self, get_response): self.get_response = get_response def __call__(self, request): user = request.user if user.is_authenticated and not user.is_staff and not user.is_superuser: path = request.path_info user_role = getattr(request.user, "role", None) allowed = self.ROLE_ROUTES.get(user_role, []) if any(re.match(pattern, path) for pattern in allowed): return self.get_response(request) # The path belongs to a portal this role may not enter. Send them to # the role-aware landing view rather than straight into a portal they # cannot use. It used to redirect if *any* role's pattern matched the # path without belonging to this role, which bounced a buyer off # /portal/ itself (the admin patterns include /portal/), and looped # with the landing redirect. if any( re.match(pattern, path) for patterns in self.ROLE_ROUTES.values() for pattern in patterns ): return redirect(settings.LOGIN_REDIRECT_URL) return self.get_response(request)