Files
ad/molodetz/routers/admin/services.py
T

70 lines
2.6 KiB
Python

# retoor <retoor@molodetz.nl>
from fastapi import APIRouter, HTTPException, Request
from molodetz.responses import action_result, respond
from molodetz.routers.admin._shared import admin_seo
from molodetz.schemas.admin import ServiceDetailOut, ServicesOut
from molodetz.services.base import manager
from molodetz.utils.audit import record
from molodetz.utils.auth import not_found, require_admin
router = APIRouter()
VERBS = ("start", "stop", "run", "clear")
def _service(name):
service = manager.get(name)
if service is None:
not_found("Onbekende service")
return service
@router.get("/services")
async def services_index(request: Request):
require_admin(request)
return respond(request, "admin/services.html", {"services": manager.describe_all(), "seo": admin_seo(request, "Services")}, model=ServicesOut)
@router.get("/services/{name}")
async def services_detail(request: Request, name: str):
require_admin(request)
service = _service(name)
ctx = {"service": manager.describe(service), "seo": admin_seo(request, service.title)}
return respond(request, "admin/service.html", ctx, model=ServiceDetailOut)
async def _payload(request):
if request.headers.get("content-type", "").startswith("application/json"):
data = await request.json()
return data if isinstance(data, dict) else {}
form = await request.form()
return {key: value for key, value in form.items()}
@router.post("/services/{name}/command")
async def services_command(request: Request, name: str):
user = require_admin(request)
service = _service(name)
verb = (await _payload(request)).get("verb", "")
if verb not in VERBS:
raise HTTPException(400, "Onbekend commando")
if verb in ("start", "stop"):
manager.set_enabled(service.name, verb == "start")
else:
manager.send_command(service.name, verb)
record(request, f"service.command.{verb}", targets=[("service", service.name)], user=user)
return action_result(request, f"/admin/services/{service.name}", data={"verb": verb})
@router.post("/services/{name}/config")
async def services_config(request: Request, name: str):
user = require_admin(request)
service = _service(name)
values = await _payload(request)
try:
updates = manager.save_config(service.name, values)
except ValueError as exc:
raise HTTPException(400, str(exc)) from exc
record(request, "service.config.save", payload={"keys": sorted(updates)}, targets=[("service", service.name)], user=user)
return action_result(request, f"/admin/services/{service.name}", data={"saved": sorted(updates)})