89 lines
3.0 KiB
Python
89 lines
3.0 KiB
Python
"""
|
|
Tenant-aware middleware for multi-tenancy
|
|
"""
|
|
|
|
from django.http import HttpResponseRedirect
|
|
from django.urls import reverse
|
|
from django.utils.deprecation import MiddlewareMixin
|
|
|
|
|
|
class TenantMiddleware(MiddlewareMixin):
|
|
"""
|
|
Middleware that sets the current hospital context from the authenticated user.
|
|
|
|
This middleware ensures that:
|
|
- authenticated users have their tenant_hospital set from their profile
|
|
- PX admins can switch between hospitals via session
|
|
- PX admins without a selected hospital are redirected to select-hospital
|
|
- Source Users have their source context available
|
|
- All requests have tenant context available
|
|
"""
|
|
|
|
EXEMPT_PATHS = [
|
|
"/core/select-hospital/",
|
|
"/accounts/logout/",
|
|
"/accounts/password_reset/",
|
|
"/accounts/password_reset/done/",
|
|
"/accounts/reset/",
|
|
"/api/",
|
|
"/health/",
|
|
"/admin/",
|
|
"/__debug__/",
|
|
]
|
|
|
|
def process_request(self, request):
|
|
"""Set tenant hospital context on each request."""
|
|
if request.user and request.user.is_authenticated:
|
|
request.user_roles = request.user.get_role_names()
|
|
|
|
request.source_user = None
|
|
request.source_user_profile = None
|
|
if request.user.is_source_user():
|
|
profile = request.user.get_source_user_profile_active()
|
|
if profile:
|
|
request.source_user = profile
|
|
request.source_user_profile = profile
|
|
|
|
if request.user.is_px_admin():
|
|
hospital_id = request.session.get("selected_hospital_id")
|
|
if hospital_id:
|
|
from apps.organizations.models import Hospital
|
|
|
|
try:
|
|
request.tenant_hospital = Hospital.objects.get(id=hospital_id)
|
|
except Hospital.DoesNotExist:
|
|
request.tenant_hospital = None
|
|
request.session.pop("selected_hospital_id", None)
|
|
else:
|
|
request.tenant_hospital = None
|
|
else:
|
|
request.tenant_hospital = request.user.hospital
|
|
else:
|
|
request.tenant_hospital = None
|
|
request.user_roles = []
|
|
request.source_user = None
|
|
request.source_user_profile = None
|
|
|
|
return None
|
|
|
|
def process_view(self, request, view_func, view_args, view_kwargs):
|
|
"""Redirect PX admins without hospital to select-hospital page."""
|
|
if not request.user or not request.user.is_authenticated:
|
|
return None
|
|
|
|
if not request.user.is_px_admin():
|
|
return None
|
|
|
|
if request.tenant_hospital:
|
|
return None
|
|
|
|
path = request.path
|
|
for exempt_path in self.EXEMPT_PATHS:
|
|
if path.startswith(exempt_path):
|
|
return None
|
|
|
|
if request.headers.get("x-requested-with") == "XMLHttpRequest":
|
|
return None
|
|
|
|
return HttpResponseRedirect(reverse("core:select_hospital"))
|