70 lines
2.6 KiB
Python
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("Unknown 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, "Unknown command")
|
|
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)})
|