""" 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