Apply 646095da: Module settings UI fixes with moduleStore

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-23 06:49:38 +00:00
parent 162947f3cc
commit 029c30ae70
7 changed files with 223 additions and 231 deletions

View File

@@ -13,10 +13,11 @@ from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAu
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, ModuleEnableSettings, AISettings
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AISettings
from .global_settings_models import GlobalModuleSettings
from .settings_serializers import (
SystemSettingsSerializer, AccountSettingsSerializer, UserSettingsSerializer,
ModuleSettingsSerializer, ModuleEnableSettingsSerializer, AISettingsSerializer
ModuleSettingsSerializer, AISettingsSerializer
)
@@ -288,166 +289,48 @@ class ModuleSettingsViewSet(AccountModelViewSet):
@extend_schema_view(
list=extend_schema(tags=['System']),
retrieve=extend_schema(tags=['System']),
update=extend_schema(tags=['System']),
partial_update=extend_schema(tags=['System']),
)
class ModuleEnableSettingsViewSet(AccountModelViewSet):
class ModuleEnableSettingsViewSet(viewsets.ViewSet):
"""
ViewSet for managing module enable/disable settings
Unified API Standard v1.0 compliant
One record per account
Read access: All authenticated users
Write access: Admins/Owners only
ViewSet for GLOBAL module enable/disable settings (read-only, public).
Returns platform-wide module availability from GlobalModuleSettings singleton.
No authentication required - these are public platform-wide settings.
Only superadmin can modify via Django Admin at /admin/system/globalmodulesettings/.
"""
queryset = ModuleEnableSettings.objects.all()
serializer_class = ModuleEnableSettingsSerializer
authentication_classes = [JWTAuthentication]
authentication_classes = []
permission_classes = []
throttle_scope = 'system'
throttle_classes = [DebugScopedRateThrottle]
def get_permissions(self):
"""
Allow read access to all authenticated users,
but restrict write access to admins/owners
"""
if self.action in ['list', 'retrieve', 'get_current']:
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
else:
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
return [permission() for permission in permission_classes]
def get_queryset(self):
"""Get module enable settings for current account"""
# Return queryset filtered by account - but list() will handle get_or_create
queryset = super().get_queryset()
# Filter by account if available
account = getattr(self.request, 'account', None)
if not account:
user = getattr(self.request, 'user', None)
if user:
account = getattr(user, 'account', None)
if account:
queryset = queryset.filter(account=account)
return queryset
@action(detail=False, methods=['get', 'put'], url_path='current', url_name='current')
def get_current(self, request):
"""Get or update current account's module enable settings"""
if request.method == 'GET':
return self.list(request)
else:
return self.update(request, pk=None)
def list(self, request, *args, **kwargs):
"""Get or create module enable settings for current account"""
"""Return global module settings (platform-wide, read-only)"""
try:
account = getattr(request, 'account', None)
if not account:
user = getattr(request, 'user', None)
if user and hasattr(user, 'account'):
account = user.account
global_settings = GlobalModuleSettings.get_instance()
if not account:
return error_response(
error='Account not found',
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
# Check if table exists (migration might not have been run)
try:
# Get or create settings for account (one per account)
try:
settings = ModuleEnableSettings.objects.get(account=account)
except ModuleEnableSettings.DoesNotExist:
# Create default settings for account
settings = ModuleEnableSettings.objects.create(account=account)
serializer = self.get_serializer(settings)
return success_response(data=serializer.data, request=request)
except Exception as db_error:
# Check if it's a "table does not exist" error
error_str = str(db_error)
if 'does not exist' in error_str.lower() or 'relation' in error_str.lower():
import logging
logger = logging.getLogger(__name__)
logger.error(f"ModuleEnableSettings table does not exist. Migration 0007_add_module_enable_settings needs to be run: {error_str}")
return error_response(
error='Module enable settings table not found. Please run migration: python manage.py migrate igny8_core_modules_system 0007',
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
request=request
)
# Re-raise other database errors
raise
data = {
'id': 1,
'planner_enabled': global_settings.planner_enabled,
'writer_enabled': global_settings.writer_enabled,
'thinker_enabled': global_settings.thinker_enabled,
'automation_enabled': global_settings.automation_enabled,
'site_builder_enabled': global_settings.site_builder_enabled,
'linker_enabled': global_settings.linker_enabled,
'optimizer_enabled': global_settings.optimizer_enabled,
'publisher_enabled': global_settings.publisher_enabled,
'created_at': global_settings.created_at.isoformat() if global_settings.created_at else None,
'updated_at': global_settings.updated_at.isoformat() if global_settings.updated_at else None,
}
return success_response(data=data, request=request)
except Exception as e:
import traceback
error_trace = traceback.format_exc()
return error_response(
error=f'Failed to load module enable settings: {str(e)}',
error=f'Failed to load global module settings: {str(e)}',
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
request=request
)
def retrieve(self, request, pk=None, *args, **kwargs):
"""Get module enable settings for current account"""
try:
account = getattr(request, 'account', None)
if not account:
user = getattr(request, 'user', None)
if user:
account = getattr(user, 'account', None)
if not account:
return error_response(
error='Account not found',
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
# Get or create settings for account
settings, created = ModuleEnableSettings.objects.get_or_create(account=account)
serializer = self.get_serializer(settings)
return success_response(data=serializer.data, request=request)
except Exception as e:
return error_response(
error=f'Failed to load module enable settings: {str(e)}',
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
request=request
)
def update(self, request, pk=None):
"""Update module enable settings for current account"""
account = getattr(request, 'account', None)
if not account:
user = getattr(request, 'user', None)
if user:
account = getattr(user, 'account', None)
if not account:
return error_response(
error='Account not found',
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
# Get or create settings for account
settings = ModuleEnableSettings.get_or_create_for_account(account)
serializer = self.get_serializer(settings, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return success_response(data=serializer.data, request=request)
return error_response(
error='Validation failed',
errors=serializer.errors,
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
def partial_update(self, request, pk=None):
"""Partial update module enable settings"""
return self.update(request, pk)
"""Same as list - return global settings (singleton, pk ignored)"""
return self.list(request, *args, **kwargs)
@extend_schema_view(

View File

@@ -52,11 +52,9 @@ integration_image_gen_settings_viewset = IntegrationSettingsViewSet.as_view({
# Custom view for module enable settings to avoid URL routing conflict with ModuleSettingsViewSet
# This must be defined as a custom path BEFORE router.urls to ensure it matches first
# The update method handles pk=None correctly, so we can use as_view
# Read-only viewset - only GET is supported (modification via Django Admin only)
module_enable_viewset = ModuleEnableSettingsViewSet.as_view({
'get': 'list',
'put': 'update',
'patch': 'partial_update',
})
urlpatterns = [