# retoor <retoor@molodetz.nl>
import logging
from typing import Annotated
from fastapi import Depends, APIRouter, Request
from fastapi.responses import HTMLResponse
from devplacepy.models import AdminSettingsForm
from devplacepy.database import get_table, clear_settings_cache
from devplacepy.utils import require_admin, generate_uid
from devplacepy.seo import base_seo_context, site_url, website_schema
from devplacepy.responses import respond, action_result
from devplacepy.schemas import AdminSettingsOut
from devplacepy.services.audit import record as audit
from devplacepy.dependencies import json_or_form
logger = logging.getLogger(__name__)
router = APIRouter()
CLEARABLE_SETTINGS = {"extra_head"}
@router.get("/settings", response_class=HTMLResponse)
async def admin_settings(request: Request):
admin = require_admin(request)
settings = get_table("site_settings")
all_settings = {s["key"]: s["value"] for s in settings.all()}
base = site_url(request)
seo_ctx = base_seo_context(
request,
title="Settings - Admin",
description="Manage DevPlace site settings.",
robots="noindex,nofollow",
breadcrumbs=[
{"name": "Home", "url": "/feed"},
{"name": "Admin", "url": "/admin"},
{"name": "Settings", "url": "/admin/settings"},
],
schemas=[website_schema(base)],
)
return respond(
request,
"admin_settings.html",
{
**seo_ctx,
"request": request,
"user": admin,
"settings": all_settings,
"admin_section": "settings",
},
model=AdminSettingsOut,
)
@router.post("/settings")
async def admin_settings_save(
request: Request, data: Annotated[AdminSettingsForm, Depends(json_or_form(AdminSettingsForm))]
):
admin = require_admin(request)
settings = get_table("site_settings")
changes = []
for key, value in data.model_dump().items():
existing = settings.find_one(key=key)
if existing:
if value == "" and key not in CLEARABLE_SETTINGS:
continue
old_value = existing.get("value")
if str(old_value) == str(value):
continue
settings.update({"id": existing["id"], "key": key, "value": value}, ["id"])
changes.append((key, old_value, value))
else:
settings.insert({"uid": generate_uid(), "key": key, "value": value})
changes.append((key, None, value))
clear_settings_cache()
logger.info(f"Admin {admin['username']} updated settings")
for key, old_value, new_value in changes:
audit.record(
request,
"admin.setting.update",
user=admin,
target_type="setting",
target_uid=key,
target_label=key,
old_value=old_value,
new_value=new_value,
summary=f"admin {admin['username']} updated setting {key}",
links=[audit.setting(key)],
)
return action_result(request, "/admin/settings")