Implement security enhancements and unified response formats across API endpoints. Update permission classes for various ViewSets to ensure proper tenant isolation and compliance with API standards. Refactor authentication endpoints to utilize success and error response helpers, improving error tracking and response consistency. Complete documentation updates reflecting these changes and achieving full compliance with API Standard v1.0.
This commit is contained in:
@@ -11,7 +11,7 @@ from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsAdminOrOwner
|
||||
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
|
||||
from django.conf import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -31,7 +31,7 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
|
||||
Following reference plugin pattern: WordPress uses update_option() for igny8_api_settings
|
||||
We store in IntegrationSettings model with account isolation
|
||||
"""
|
||||
permission_classes = [IsAuthenticatedAndActive, IsAdminOrOwner]
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
|
||||
|
||||
throttle_scope = 'system_admin'
|
||||
throttle_classes = [DebugScopedRateThrottle]
|
||||
|
||||
@@ -12,6 +12,7 @@ from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
|
||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
|
||||
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AISettings
|
||||
from .settings_serializers import (
|
||||
SystemSettingsSerializer, AccountSettingsSerializer, UserSettingsSerializer,
|
||||
@@ -34,7 +35,7 @@ class SystemSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = SystemSettings.objects.all()
|
||||
serializer_class = SystemSettingsSerializer
|
||||
permission_classes = [permissions.IsAuthenticated] # Require authentication
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
|
||||
pagination_class = CustomPageNumberPagination
|
||||
throttle_scope = 'system'
|
||||
@@ -43,8 +44,8 @@ class SystemSettingsViewSet(AccountModelViewSet):
|
||||
def get_permissions(self):
|
||||
"""Admin only for write operations, read for authenticated users"""
|
||||
if self.action in ['create', 'update', 'partial_update', 'destroy']:
|
||||
return [permissions.IsAdminUser()]
|
||||
return [permissions.IsAuthenticated()]
|
||||
return [IsAdminOrOwner()]
|
||||
return [IsAuthenticatedAndActive(), HasTenantAccess()]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Get all system settings"""
|
||||
@@ -85,7 +86,7 @@ class AccountSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = AccountSettings.objects.all()
|
||||
serializer_class = AccountSettingsSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
|
||||
pagination_class = CustomPageNumberPagination
|
||||
throttle_scope = 'system'
|
||||
@@ -145,7 +146,7 @@ class UserSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = UserSettings.objects.all()
|
||||
serializer_class = UserSettingsSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
|
||||
pagination_class = CustomPageNumberPagination
|
||||
throttle_scope = 'system'
|
||||
@@ -211,7 +212,7 @@ class ModuleSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = ModuleSettings.objects.all()
|
||||
serializer_class = ModuleSettingsSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
|
||||
pagination_class = CustomPageNumberPagination
|
||||
throttle_scope = 'system'
|
||||
@@ -290,7 +291,7 @@ class AISettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = AISettings.objects.all()
|
||||
serializer_class = AISettingsSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
|
||||
pagination_class = CustomPageNumberPagination
|
||||
throttle_scope = 'system'
|
||||
|
||||
@@ -15,7 +15,7 @@ from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.permissions import IsEditorOrAbove, IsAuthenticatedAndActive, IsViewerOrAbove
|
||||
from igny8_core.api.permissions import IsEditorOrAbove, IsAuthenticatedAndActive, IsViewerOrAbove, HasTenantAccess
|
||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||
from .models import AIPrompt, AuthorProfile, Strategy
|
||||
@@ -39,7 +39,7 @@ class AIPromptViewSet(AccountModelViewSet):
|
||||
"""
|
||||
queryset = AIPrompt.objects.all()
|
||||
serializer_class = AIPromptSerializer
|
||||
permission_classes = [] # Allow any for now (backward compatibility)
|
||||
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
|
||||
throttle_scope = 'system'
|
||||
throttle_classes = [DebugScopedRateThrottle]
|
||||
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
||||
@@ -72,6 +72,14 @@ class AIPromptViewSet(AccountModelViewSet):
|
||||
@action(detail=False, methods=['post'], url_path='save', url_name='save')
|
||||
def save_prompt(self, request):
|
||||
"""Save or update a prompt - requires editor or above"""
|
||||
# Check if user has editor or above permissions
|
||||
if not IsEditorOrAbove().has_permission(request, self):
|
||||
return error_response(
|
||||
error='Permission denied. Editor or above role required.',
|
||||
status_code=http_status.HTTP_403_FORBIDDEN,
|
||||
request=request
|
||||
)
|
||||
|
||||
prompt_type = request.data.get('prompt_type')
|
||||
prompt_value = request.data.get('prompt_value')
|
||||
|
||||
@@ -140,7 +148,15 @@ class AIPromptViewSet(AccountModelViewSet):
|
||||
|
||||
@action(detail=False, methods=['post'], url_path='reset', url_name='reset')
|
||||
def reset_prompt(self, request):
|
||||
"""Reset prompt to default"""
|
||||
"""Reset prompt to default - requires editor or above"""
|
||||
# Check if user has editor or above permissions
|
||||
if not IsEditorOrAbove().has_permission(request, self):
|
||||
return error_response(
|
||||
error='Permission denied. Editor or above role required.',
|
||||
status_code=http_status.HTTP_403_FORBIDDEN,
|
||||
request=request
|
||||
)
|
||||
|
||||
prompt_type = request.data.get('prompt_type')
|
||||
|
||||
if not prompt_type:
|
||||
|
||||
Reference in New Issue
Block a user