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