175 lines
5.3 KiB
Python
175 lines
5.3 KiB
Python
"""
|
|
Custom decorators for PX Source User access control.
|
|
|
|
Provides decorators to:
|
|
- Restrict views to source users only
|
|
- Block source users from admin pages
|
|
"""
|
|
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 source_user_required(view_func):
|
|
"""
|
|
Decorator to restrict access to source users only.
|
|
|
|
Use this on views that should ONLY be accessible to source users.
|
|
Blocks all admin/management/staff pages.
|
|
|
|
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):
|
|
# Check if user has source user profile
|
|
if not hasattr(request.user, 'source_user_profile'):
|
|
raise PermissionDenied(
|
|
_("Access denied. Source user privileges required.")
|
|
)
|
|
|
|
source_user = request.user.source_user_profile
|
|
|
|
# Check if source user is active
|
|
if not source_user.is_active:
|
|
# Log out the user
|
|
from django.contrib.auth import logout
|
|
logout(request)
|
|
messages.error(
|
|
request,
|
|
_("Your source user account is inactive. Please contact your administrator.")
|
|
)
|
|
return redirect('accounts:login')
|
|
|
|
# Store source_user and source in request for easy access
|
|
request.source_user = source_user
|
|
request.source = source_user.source
|
|
|
|
return view_func(request, *args, **kwargs)
|
|
|
|
return _wrapped_view
|
|
|
|
|
|
def block_source_user(view_func):
|
|
"""
|
|
Decorator to BLOCK source users from accessing admin pages.
|
|
|
|
Use this on admin/management views that source users should NOT access.
|
|
Allows all other users (PX Admin, Hospital Admin, Department Manager, etc.)
|
|
|
|
Example:
|
|
@block_source_user
|
|
def source_list(request):
|
|
# Source users CANNOT access this
|
|
"""
|
|
@wraps(view_func)
|
|
@login_required
|
|
def _wrapped_view(request, *args, **kwargs):
|
|
# Check if user is ONLY a source user (no other admin roles)
|
|
if _is_pure_source_user(request.user):
|
|
messages.error(
|
|
request,
|
|
_("Access denied. Source users cannot access admin pages.")
|
|
)
|
|
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.
|
|
|
|
Use this on views that should be accessible to:
|
|
- Source users (for their own data)
|
|
- PX Admins, Hospital Admins, Department Managers
|
|
|
|
Example:
|
|
@source_user_or_admin
|
|
def complaint_detail(request, pk):
|
|
# Both source users and admins can view complaints
|
|
"""
|
|
@wraps(view_func)
|
|
@login_required
|
|
def _wrapped_view(request, *args, **kwargs):
|
|
# Allow if user has admin roles
|
|
if _has_admin_role(request.user):
|
|
return view_func(request, *args, **kwargs)
|
|
|
|
# Allow if user is an active source user
|
|
if hasattr(request.user, 'source_user_profile'):
|
|
source_user = request.user.source_user_profile
|
|
if source_user.is_active:
|
|
request.source_user = source_user
|
|
request.source = source_user.source
|
|
return view_func(request, *args, **kwargs)
|
|
|
|
# Deny access
|
|
raise PermissionDenied(_("Access denied."))
|
|
|
|
return _wrapped_view
|
|
|
|
|
|
def _is_pure_source_user(user):
|
|
"""
|
|
Check if user is ONLY a source user with no admin roles.
|
|
|
|
Returns True if:
|
|
- User is in 'PX Source User' group
|
|
- User is NOT in any admin groups
|
|
"""
|
|
admin_groups = ['PX Admin', 'Hospital Admin', 'Department Manager']
|
|
|
|
# Check if user has any admin roles
|
|
has_admin_role = user.groups.filter(name__in=admin_groups).exists()
|
|
|
|
if has_admin_role:
|
|
return False
|
|
|
|
# Check if user is a source user
|
|
has_source_user_profile = hasattr(user, 'source_user_profile')
|
|
|
|
if has_source_user_profile:
|
|
source_user = user.source_user_profile
|
|
if source_user.is_active:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def _has_admin_role(user):
|
|
"""
|
|
Check if user has any admin role.
|
|
"""
|
|
admin_groups = ['PX Admin', 'Hospital Admin', 'Department Manager']
|
|
return user.groups.filter(name__in=admin_groups).exists()
|
|
|
|
|
|
def px_admin_required(view_func):
|
|
"""
|
|
Decorator to restrict access to PX Admins only.
|
|
|
|
Use this on views that should ONLY be accessible to PX Admins.
|
|
"""
|
|
@wraps(view_func)
|
|
@login_required
|
|
def _wrapped_view(request, *args, **kwargs):
|
|
if not user.is_px_admin():
|
|
messages.error(
|
|
request,
|
|
_("Access denied. PX Admin privileges required.")
|
|
)
|
|
return redirect('dashboard:dashboard')
|
|
|
|
return view_func(request, *args, **kwargs)
|
|
|
|
return _wrapped_view
|