HH/apps/core/decorators.py
2026-04-19 10:53:12 +03:00

221 lines
6.3 KiB
Python

"""
Role-based access control decorators for PX360.
Provides decorators to restrict views based on user roles:
- PX Admin
- Hospital Admin
- Department Manager
- PX Staff
- Source User
"""
from functools import wraps
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
def px_admin_required(view_func):
"""
Decorator to restrict access to PX Admins only.
Example:
@px_admin_required
def system_settings(request):
# Only PX Admins can access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if not request.user.is_px_admin():
messages.error(request, _("Access denied. PX Admin privileges required."))
return redirect("analytics:command_center")
return view_func(request, *args, **kwargs)
return _wrapped_view
def hospital_admin_required(view_func):
"""
Decorator to restrict access to Hospital Admins and PX Admins.
Example:
@hospital_admin_required
def hospital_settings(request):
# Only Hospital Admins and PX Admins can access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
messages.error(request, _("Access denied. Hospital Admin privileges required."))
return redirect("analytics:command_center")
return view_func(request, *args, **kwargs)
return _wrapped_view
def admin_required(view_func):
"""
Decorator to restrict access to any Admin (PX, Hospital, or Dept Manager).
Example:
@admin_required
def management_view(request):
# Any admin can access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
messages.error(request, _("Access denied. Admin privileges required."))
return redirect("analytics:command_center")
return view_func(request, *args, **kwargs)
return _wrapped_view
def px_staff_required(view_func):
"""
Decorator to restrict access to PX Staff and above.
Allows: PX Admin, Hospital Admin, Department Manager, PX Staff
Example:
@px_staff_required
def complaint_management(request):
# Staff and admins can access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
user = request.user
if not (
user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager() or user.has_role("PX Staff")
):
messages.error(request, _("Access denied. PX Staff privileges required."))
return redirect("analytics:command_center")
return view_func(request, *args, **kwargs)
return _wrapped_view
def staff_required(view_func):
"""
Decorator to restrict access to Hospital Staff (not Source Users).
Allows all authenticated users except Source Users.
Example:
@staff_required
def internal_tool(request):
# Any hospital staff can access, but not source users
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if request.user.is_source_user():
messages.error(request, _("Access denied. This page is not available for source users."))
return redirect("px_sources:source_user_dashboard")
return view_func(request, *args, **kwargs)
return _wrapped_view
def source_user_required(view_func):
"""
Decorator to restrict access to Source Users only.
Example:
@source_user_required
def source_user_dashboard(request):
# Only source users can access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if not request.user.is_source_user():
raise PermissionDenied(_("Access denied. Source user privileges required."))
# Get source user profile
profile = request.user.get_source_user_profile_active()
if not profile:
messages.error(request, _("Your source user account is inactive. Please contact your administrator."))
return redirect("accounts:login")
# Store in request for easy access
request.source_user = profile
request.source = profile.source
return view_func(request, *args, **kwargs)
return _wrapped_view
def block_source_user(view_func):
"""
Decorator to BLOCK source users from accessing admin/staff pages.
Redirects source users to their dashboard instead.
Example:
@block_source_user
def staff_management(request):
# Source users CANNOT access this
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
if request.user.is_source_user():
# Silently redirect to source user dashboard
return redirect("px_sources:source_user_dashboard")
return view_func(request, *args, **kwargs)
return _wrapped_view
def source_user_or_admin(view_func):
"""
Decorator that allows both source users AND admins.
Example:
@source_user_or_admin
def complaint_detail(request, pk):
# Both source users and admins can view
"""
@wraps(view_func)
@login_required
def _wrapped_view(request, *args, **kwargs):
user = request.user
# Allow admins
if user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager():
return view_func(request, *args, **kwargs)
# Allow active source users
if user.is_source_user():
profile = user.get_source_user_profile_active()
if profile:
request.source_user = profile
request.source = profile.source
return view_func(request, *args, **kwargs)
raise PermissionDenied(_("Access denied."))
return _wrapped_view