181 lines
6.7 KiB
Python
181 lines
6.7 KiB
Python
"""
|
|
Standardized Permission Classes
|
|
Provides consistent permission checking across all endpoints
|
|
"""
|
|
from rest_framework import permissions
|
|
from rest_framework.exceptions import PermissionDenied
|
|
|
|
|
|
class IsAuthenticatedAndActive(permissions.BasePermission):
|
|
"""
|
|
Permission class that requires user to be authenticated and active
|
|
Base permission for most endpoints
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
|
|
# Check if user is active
|
|
if hasattr(request.user, 'is_active'):
|
|
return request.user.is_active
|
|
|
|
return True
|
|
|
|
|
|
class HasTenantAccess(permissions.BasePermission):
|
|
"""
|
|
Permission class that requires user to belong to the tenant/account
|
|
Ensures tenant isolation
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
|
|
# Get account from request (set by middleware)
|
|
account = getattr(request, 'account', None)
|
|
|
|
# If no account in request, try to get from user
|
|
if not account and hasattr(request.user, 'account'):
|
|
try:
|
|
account = request.user.account
|
|
except (AttributeError, Exception):
|
|
pass
|
|
|
|
# Admin/Developer/System account users bypass tenant check
|
|
if request.user and hasattr(request.user, 'is_authenticated') and request.user.is_authenticated:
|
|
try:
|
|
is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and
|
|
request.user.is_admin_or_developer()) if request.user else False
|
|
is_system_user = (hasattr(request.user, 'is_system_account_user') and
|
|
request.user.is_system_account_user()) if request.user else False
|
|
|
|
if is_admin_or_dev or is_system_user:
|
|
return True
|
|
except (AttributeError, TypeError):
|
|
pass
|
|
|
|
# Regular users must have account access
|
|
if account:
|
|
# Check if user belongs to this account
|
|
if hasattr(request.user, 'account'):
|
|
try:
|
|
user_account = request.user.account
|
|
return user_account == account or user_account.id == account.id
|
|
except (AttributeError, Exception):
|
|
pass
|
|
|
|
return False
|
|
|
|
|
|
class IsViewerOrAbove(permissions.BasePermission):
|
|
"""
|
|
Permission class that requires viewer, editor, admin, or owner role
|
|
For read-only operations
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
|
|
# Admin/Developer/System account users always have access
|
|
try:
|
|
is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and
|
|
request.user.is_admin_or_developer()) if request.user else False
|
|
is_system_user = (hasattr(request.user, 'is_system_account_user') and
|
|
request.user.is_system_account_user()) if request.user else False
|
|
|
|
if is_admin_or_dev or is_system_user:
|
|
return True
|
|
except (AttributeError, TypeError):
|
|
pass
|
|
|
|
# Check user role
|
|
if hasattr(request.user, 'role'):
|
|
role = request.user.role
|
|
# viewer, editor, admin, owner all have access
|
|
return role in ['viewer', 'editor', 'admin', 'owner']
|
|
|
|
# If no role system, allow authenticated users
|
|
return True
|
|
|
|
|
|
class IsEditorOrAbove(permissions.BasePermission):
|
|
"""
|
|
Permission class that requires editor, admin, or owner role
|
|
For content operations
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
|
|
# Admin/Developer/System account users always have access
|
|
try:
|
|
is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and
|
|
request.user.is_admin_or_developer()) if request.user else False
|
|
is_system_user = (hasattr(request.user, 'is_system_account_user') and
|
|
request.user.is_system_account_user()) if request.user else False
|
|
|
|
if is_admin_or_dev or is_system_user:
|
|
return True
|
|
except (AttributeError, TypeError):
|
|
pass
|
|
|
|
# Check user role
|
|
if hasattr(request.user, 'role'):
|
|
role = request.user.role
|
|
# editor, admin, owner have access
|
|
return role in ['editor', 'admin', 'owner']
|
|
|
|
# If no role system, allow authenticated users
|
|
return True
|
|
|
|
|
|
class IsAdminOrOwner(permissions.BasePermission):
|
|
"""
|
|
Permission class that requires admin or owner role only
|
|
For settings, keys, billing operations
|
|
"""
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
|
|
# Admin/Developer/System account users always have access
|
|
try:
|
|
is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and
|
|
request.user.is_admin_or_developer()) if request.user else False
|
|
is_system_user = (hasattr(request.user, 'is_system_account_user') and
|
|
request.user.is_system_account_user()) if request.user else False
|
|
|
|
if is_admin_or_dev or is_system_user:
|
|
return True
|
|
except (AttributeError, TypeError):
|
|
pass
|
|
|
|
# Check user role
|
|
if hasattr(request.user, 'role'):
|
|
role = request.user.role
|
|
# admin, owner have access
|
|
return role in ['admin', 'owner']
|
|
|
|
# If no role system, deny by default for security
|
|
return False
|
|
|
|
|
|
class IsSystemAccountOrDeveloper(permissions.BasePermission):
|
|
"""
|
|
Allow only system accounts (aws-admin/default-account/default) or developer role.
|
|
Use for sensitive, globally-scoped settings like integration API keys.
|
|
"""
|
|
def has_permission(self, request, view):
|
|
user = getattr(request, "user", None)
|
|
if not user or not user.is_authenticated:
|
|
return False
|
|
|
|
account_slug = getattr(getattr(user, "account", None), "slug", None)
|
|
if user.role == "developer":
|
|
return True
|
|
if account_slug in ["aws-admin", "default-account", "default"]:
|
|
return True
|
|
return False
|
|
|
|
|