You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.9 KiB
95 lines
3.9 KiB
from rest_framework.permissions import BasePermission, SAFE_METHODS
|
|
|
|
|
|
def can_publish_or_moderate_post(user, institution=None) -> bool:
|
|
"""
|
|
Evaluates dynamic permission capability without hardcoding any role names or slugs:
|
|
1. User must be active and authenticated.
|
|
2. Superuser / Super Admin has global authority.
|
|
3. User must hold the capability flag: user.has_perm_flag('can_publish_posts_directly').
|
|
4. If an institution is associated with the post:
|
|
- User must be affiliated with this institution (as a member in institution.members), OR
|
|
- User's managed_regions covers the institution's geographical region.
|
|
5. Standalone post (no institution):
|
|
- User holds 'can_publish_posts_directly'.
|
|
"""
|
|
if not user or not user.is_authenticated or not user.is_active:
|
|
return False
|
|
if user.is_superuser or getattr(user, 'is_super_admin', False):
|
|
return True
|
|
|
|
# Dynamic capability check (configurable in Django Admin on Role / custom_permissions)
|
|
if not user.has_perm_flag('can_publish_posts_directly'):
|
|
return False
|
|
|
|
if institution:
|
|
# Check direct institution membership affiliation
|
|
if institution.members.filter(user=user).exists():
|
|
return True
|
|
# Check managed_regions (if user has managed regions covering this institution's region)
|
|
if hasattr(user, 'managed_regions') and getattr(institution, 'region_id', None):
|
|
if user.managed_regions.filter(id=institution.region_id).exists():
|
|
return True
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
class IsAuthorOrEditorOrReadOnly(BasePermission):
|
|
"""
|
|
Read access is public (handled at view queryset level for status).
|
|
Object write/delete access:
|
|
- Author can edit their own post (draft, pending_review, rejected).
|
|
- Editors satisfying can_publish_or_moderate_post() can edit, approve, or reject.
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if request.method in SAFE_METHODS:
|
|
return True
|
|
return bool(request.user and request.user.is_authenticated and request.user.is_active)
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
if request.method in SAFE_METHODS:
|
|
return True
|
|
|
|
if not request.user or not request.user.is_authenticated or not request.user.is_active:
|
|
return False
|
|
|
|
if request.user.is_superuser or getattr(request.user, 'is_super_admin', False):
|
|
return True
|
|
|
|
# Editor / Moderator with capability over post institution
|
|
if can_publish_or_moderate_post(request.user, getattr(obj, 'institution', None)):
|
|
return True
|
|
|
|
# Post author or owning institution member can edit or delete their own post depending on HTTP method
|
|
is_owner = False
|
|
if hasattr(obj, 'author') and obj.author == request.user:
|
|
is_owner = True
|
|
elif getattr(obj, 'institution', None) and hasattr(obj.institution, 'members'):
|
|
if obj.institution.members.filter(user=request.user, role__in=['admin', 'editor']).exists():
|
|
is_owner = True
|
|
|
|
if is_owner:
|
|
if request.method == 'DELETE':
|
|
return request.user.has_perm_flag('can_delete_own_posts')
|
|
return request.user.has_perm_flag('can_edit_own_posts')
|
|
|
|
return False
|
|
|
|
|
|
class CanPublishPost(BasePermission):
|
|
"""
|
|
Validates that authenticated user has capability to create posts (can_create_posts).
|
|
Actual status transitions (draft vs pending_review vs published) are enforced by serializer.
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if request.method in SAFE_METHODS:
|
|
return True
|
|
|
|
if not request.user or not request.user.is_authenticated or not request.user.is_active:
|
|
return False
|
|
|
|
if request.user.is_superuser or getattr(request.user, 'is_super_admin', False):
|
|
return True
|
|
|
|
return request.user.has_perm_flag('can_create_posts')
|