- Remove |safe from |tojson in HTML attributes (x-data) - quotes must become " for browsers to parse correctly - Update LANG-002 and LANG-003 architecture rules to document correct |tojson usage patterns: - HTML attributes: |tojson (no |safe) - Script blocks: |tojson|safe - Fix validator to warn when |tojson|safe is used in x-data (breaks HTML attribute parsing) - Improve code quality across services, APIs, and tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
211 lines
5.7 KiB
Python
211 lines
5.7 KiB
Python
# app/api/v1/admin/settings.py
|
|
"""
|
|
Platform settings management endpoints.
|
|
|
|
Provides endpoints for:
|
|
- Viewing all platform settings
|
|
- Creating/updating settings
|
|
- Managing configuration by category
|
|
"""
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.api.deps import get_current_admin_api
|
|
from app.core.database import get_db
|
|
from app.exceptions import ConfirmationRequiredException, ResourceNotFoundException
|
|
from app.services.admin_audit_service import admin_audit_service
|
|
from app.services.admin_settings_service import admin_settings_service
|
|
from models.database.user import User
|
|
from models.schema.admin import (
|
|
AdminSettingCreate,
|
|
AdminSettingListResponse,
|
|
AdminSettingResponse,
|
|
AdminSettingUpdate,
|
|
)
|
|
|
|
router = APIRouter(prefix="/settings")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@router.get("", response_model=AdminSettingListResponse)
|
|
def get_all_settings(
|
|
category: str | None = Query(None, description="Filter by category"),
|
|
is_public: bool | None = Query(None, description="Filter by public flag"),
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""
|
|
Get all platform settings.
|
|
|
|
Can be filtered by category (system, security, marketplace, notifications)
|
|
and by public flag (settings that can be exposed to frontend).
|
|
"""
|
|
settings = admin_settings_service.get_all_settings(db, category, is_public)
|
|
|
|
return AdminSettingListResponse(
|
|
settings=settings, total=len(settings), category=category
|
|
)
|
|
|
|
|
|
@router.get("/categories")
|
|
def get_setting_categories(
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""Get list of all setting categories."""
|
|
# This could be enhanced to return counts per category
|
|
return {
|
|
"categories": [
|
|
"system",
|
|
"security",
|
|
"marketplace",
|
|
"notifications",
|
|
"integrations",
|
|
"payments",
|
|
]
|
|
}
|
|
|
|
|
|
@router.get("/{key}", response_model=AdminSettingResponse)
|
|
def get_setting(
|
|
key: str,
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""Get specific setting by key."""
|
|
setting = admin_settings_service.get_setting_by_key(db, key)
|
|
|
|
if not setting:
|
|
raise ResourceNotFoundException(resource_type="Setting", identifier=key)
|
|
|
|
return AdminSettingResponse.model_validate(setting)
|
|
|
|
|
|
@router.post("", response_model=AdminSettingResponse)
|
|
def create_setting(
|
|
setting_data: AdminSettingCreate,
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""
|
|
Create new platform setting.
|
|
|
|
Setting keys should be lowercase with underscores (e.g., max_vendors_allowed).
|
|
"""
|
|
result = admin_settings_service.create_setting(
|
|
db=db, setting_data=setting_data, admin_user_id=current_admin.id
|
|
)
|
|
|
|
# Log action
|
|
admin_audit_service.log_action(
|
|
db=db,
|
|
admin_user_id=current_admin.id,
|
|
action="create_setting",
|
|
target_type="setting",
|
|
target_id=setting_data.key,
|
|
details={
|
|
"category": setting_data.category,
|
|
"value_type": setting_data.value_type,
|
|
},
|
|
)
|
|
db.commit()
|
|
|
|
return result
|
|
|
|
|
|
@router.put("/{key}", response_model=AdminSettingResponse)
|
|
def update_setting(
|
|
key: str,
|
|
update_data: AdminSettingUpdate,
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""Update existing setting value."""
|
|
old_value = admin_settings_service.get_setting_value(db, key)
|
|
|
|
result = admin_settings_service.update_setting(
|
|
db=db, key=key, update_data=update_data, admin_user_id=current_admin.id
|
|
)
|
|
|
|
# Log action
|
|
admin_audit_service.log_action(
|
|
db=db,
|
|
admin_user_id=current_admin.id,
|
|
action="update_setting",
|
|
target_type="setting",
|
|
target_id=key,
|
|
details={"old_value": str(old_value), "new_value": update_data.value},
|
|
)
|
|
db.commit()
|
|
|
|
return result
|
|
|
|
|
|
@router.post("/upsert", response_model=AdminSettingResponse)
|
|
def upsert_setting(
|
|
setting_data: AdminSettingCreate,
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""
|
|
Create or update setting (upsert).
|
|
|
|
If setting exists, updates its value. If not, creates new setting.
|
|
"""
|
|
result = admin_settings_service.upsert_setting(
|
|
db=db, setting_data=setting_data, admin_user_id=current_admin.id
|
|
)
|
|
|
|
# Log action
|
|
admin_audit_service.log_action(
|
|
db=db,
|
|
admin_user_id=current_admin.id,
|
|
action="upsert_setting",
|
|
target_type="setting",
|
|
target_id=setting_data.key,
|
|
details={"category": setting_data.category},
|
|
)
|
|
db.commit()
|
|
|
|
return result
|
|
|
|
|
|
@router.delete("/{key}")
|
|
def delete_setting(
|
|
key: str,
|
|
confirm: bool = Query(False, description="Must be true to confirm deletion"),
|
|
db: Session = Depends(get_db),
|
|
current_admin: User = Depends(get_current_admin_api),
|
|
):
|
|
"""
|
|
Delete platform setting.
|
|
|
|
Requires confirmation parameter.
|
|
WARNING: Deleting settings may affect platform functionality.
|
|
"""
|
|
if not confirm:
|
|
raise ConfirmationRequiredException(
|
|
operation="delete_setting",
|
|
message="Deletion requires confirmation parameter: confirm=true",
|
|
)
|
|
|
|
message = admin_settings_service.delete_setting(
|
|
db=db, key=key, admin_user_id=current_admin.id
|
|
)
|
|
|
|
# Log action
|
|
admin_audit_service.log_action(
|
|
db=db,
|
|
admin_user_id=current_admin.id,
|
|
action="delete_setting",
|
|
target_type="setting",
|
|
target_id=key,
|
|
details={},
|
|
)
|
|
db.commit()
|
|
|
|
return {"message": message}
|