HH/apps/core/decorators.py
2026-03-09 16:10:24 +03:00

237 lines
6.8 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 Coordinator
- 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_coordinator_required(view_func):
"""
Decorator to restrict access to PX Coordinators and above.
Allows: PX Admin, Hospital Admin, Department Manager, PX Coordinator
Example:
@px_coordinator_required
def complaint_management(request):
# Coordinators 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 Coordinator')):
messages.error(
request,
_("Access denied. PX Coordinator 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