Add config API endpoints and tests; update docs
This commit is contained in:
68
src/server/api/config.py
Normal file
68
src/server/api/config.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from src.config.settings import settings
|
||||
from src.server.models.config import AppConfig, ConfigUpdate, ValidationResult
|
||||
from src.server.utils.dependencies import require_auth
|
||||
|
||||
router = APIRouter(prefix="/api/config", tags=["config"])
|
||||
|
||||
|
||||
@router.get("", response_model=AppConfig)
|
||||
def get_config(auth: Optional[dict] = Depends(require_auth)) -> AppConfig:
|
||||
"""Return current application configuration (read-only)."""
|
||||
# Construct AppConfig from pydantic-settings where possible
|
||||
cfg_data = {
|
||||
"name": getattr(settings, "app_name", "Aniworld"),
|
||||
"data_dir": getattr(settings, "data_dir", "data"),
|
||||
"scheduler": getattr(settings, "scheduler", {}),
|
||||
"logging": getattr(settings, "logging", {}),
|
||||
"backup": getattr(settings, "backup", {}),
|
||||
"other": getattr(settings, "other", {}),
|
||||
}
|
||||
try:
|
||||
return AppConfig(**cfg_data)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to read config: {e}")
|
||||
|
||||
|
||||
@router.put("", response_model=AppConfig)
|
||||
def update_config(update: ConfigUpdate, auth: dict = Depends(require_auth)) -> AppConfig:
|
||||
"""Apply an update to the configuration and return the new config.
|
||||
|
||||
Note: persistence strategy for settings is out-of-scope for this task.
|
||||
This endpoint updates the in-memory Settings where possible and returns
|
||||
the merged result as an AppConfig.
|
||||
"""
|
||||
# Build current AppConfig from settings then apply update
|
||||
current = get_config(auth)
|
||||
new_cfg = update.apply_to(current)
|
||||
|
||||
# Mirror some fields back into pydantic-settings 'settings' where safe.
|
||||
# Avoid writing secrets or unsupported fields.
|
||||
try:
|
||||
if new_cfg.data_dir:
|
||||
setattr(settings, "data_dir", new_cfg.data_dir)
|
||||
# scheduler/logging/backup/other kept in memory only for now
|
||||
setattr(settings, "scheduler", new_cfg.scheduler.model_dump())
|
||||
setattr(settings, "logging", new_cfg.logging.model_dump())
|
||||
setattr(settings, "backup", new_cfg.backup.model_dump())
|
||||
setattr(settings, "other", new_cfg.other)
|
||||
except Exception:
|
||||
# Best-effort; do not fail the request if persistence is not available
|
||||
pass
|
||||
|
||||
return new_cfg
|
||||
|
||||
|
||||
@router.post("/validate", response_model=ValidationResult)
|
||||
def validate_config(cfg: AppConfig, auth: dict = Depends(require_auth)) -> ValidationResult:
|
||||
"""Validate a provided AppConfig without applying it.
|
||||
|
||||
Returns ValidationResult with any validation errors.
|
||||
"""
|
||||
try:
|
||||
return cfg.validate()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
Reference in New Issue
Block a user