HH/apps/px_sources/permissions.py
2026-03-09 16:10:24 +03:00

160 lines
4.6 KiB
Python

"""
DRF Permissions for PX Source User access control.
Provides permission classes to restrict API access based on user role:
- Source users can only access their own data
- Admins have full access
"""
from rest_framework import permissions
from apps.px_sources.models import SourceUser
class IsSourceUser(permissions.BasePermission):
"""
Allow access only to active source users.
Use this on views that should ONLY be accessible to source users.
Example:
permission_classes = [IsSourceUser]
"""
def has_permission(self, request, view):
if not request.user or not request.user.is_authenticated:
return False
# Check if user has source user profile
if not hasattr(request.user, 'source_user_profile'):
return False
# Check if source user is active
source_user = request.user.source_user_profile
return source_user.is_active
class IsSourceUserOrAdmin(permissions.BasePermission):
"""
Allow access to source users AND admins.
Use this on views that should be accessible to:
- Active source users
- PX Admins, Hospital Admins, Department Managers
Example:
permission_classes = [IsSourceUserOrAdmin]
"""
def has_permission(self, request, view):
if not request.user or not request.user.is_authenticated:
return False
# Allow admins
if request.user.is_superuser or request.user.is_px_admin():
return True
# Allow hospital admins
if request.user.is_hospital_admin():
return True
# Allow active source users
if hasattr(request.user, 'source_user_profile'):
source_user = request.user.source_user_profile
return source_user.is_active
return False
class IsSourceUserOwnData(permissions.BasePermission):
"""
Object-level permission to ensure source users can only access their own data.
Use this on detail views to ensure source users can only view/edit
complaints and inquiries from their assigned source.
Example:
permission_classes = [IsSourceUserOrAdmin, IsSourceUserOwnData]
"""
def has_object_permission(self, request, view, obj):
if not request.user or not request.user.is_authenticated:
return False
# Admins can access everything
if request.user.is_superuser or request.user.is_px_admin():
return True
# Check if user is a source user
if not hasattr(request.user, 'source_user_profile'):
return False
source_user = request.user.source_user_profile
if not source_user.is_active:
return False
# Check if object belongs to user's source
if hasattr(obj, 'source'):
return obj.source == source_user.source
# If object doesn't have a source field, deny access
return False
class IsAdminUser(permissions.BasePermission):
"""
Allow access only to admin users (not source users).
Use this on admin-only API endpoints.
Example:
permission_classes = [IsAdminUser]
"""
def has_permission(self, request, view):
if not request.user or not request.user.is_authenticated:
return False
# Block pure source users
if _is_pure_source_user(request.user):
return False
# Allow admins
return request.user.is_superuser or request.user.is_px_admin() or request.user.is_hospital_admin()
class IsPXAdmin(permissions.BasePermission):
"""
Allow access only to PX Admins.
Use this on PX Admin-only API endpoints.
"""
def has_permission(self, request, view):
if not request.user or not request.user.is_authenticated:
return False
return request.user.is_px_admin()
def _is_pure_source_user(user):
"""
Check if user is ONLY a source user with no admin roles.
"""
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