ixg_platform/apps/core/middleware.py
ixgadmin 19d67555da Add public buyer self-registration
A UK buyer can now create their own account at /portal/signup/. The screen
creates a Keycloak user through a least-privilege service account
(ixg-provisioning: manage-users, view-users) and the matching Django row as
a buyer, then sends them through the normal sign-in flow to the portal.

Staff status is derived from the role in the OIDC backend rather than
asserted, so a self-registered buyer is not staff and does not become staff
on a later sign-in. The platform root and the RBAC middleware now route
each role to its own portal, which also fixes a redirect loop that the
staff fix exposed for non-staff buyers.
2026-09-21 11:30:29 +00:00

37 lines
1.4 KiB
Python

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)