125 lines
4.2 KiB
Python
Raw Normal View History

2026-05-11 07:02:06 +02:00
import logging
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse, JSONResponse
from devplacepy.templating import templates
2026-06-08 17:38:33 +02:00
from devplacepy.utils import require_admin, not_found
2026-05-11 07:02:06 +02:00
from devplacepy.services.manager import service_manager
2026-05-12 15:07:34 +02:00
from devplacepy.seo import base_seo_context, site_url, website_schema
2026-05-11 07:02:06 +02:00
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("", response_class=HTMLResponse)
async def services_page(request: Request):
admin = require_admin(request)
2026-06-08 17:38:33 +02:00
services = service_manager.describe_all()
2026-05-12 15:07:34 +02:00
base = site_url(request)
seo_ctx = base_seo_context(
request,
2026-05-23 01:50:31 +02:00
title="Services - Admin",
2026-06-08 17:38:33 +02:00
description="Monitor and configure background services on DevPlace.",
2026-05-12 15:07:34 +02:00
breadcrumbs=[
{"name": "Home", "url": "/feed"},
{"name": "Admin", "url": "/admin"},
{"name": "Services", "url": "/admin/services"},
],
schemas=[website_schema(base)],
)
2026-05-13 23:03:06 +02:00
return templates.TemplateResponse(request, "services.html", {
2026-05-12 15:07:34 +02:00
**seo_ctx,
2026-05-11 07:02:06 +02:00
"request": request,
"user": admin,
"services": services,
"admin_section": "services",
})
@router.get("/data")
async def services_data(request: Request):
require_admin(request)
2026-06-08 17:38:33 +02:00
return JSONResponse({"services": service_manager.describe_all()})
@router.get("/{name}", response_class=HTMLResponse)
async def service_detail(request: Request, name: str):
admin = require_admin(request)
svc = service_manager.get_service(name)
if svc is None:
raise not_found("Service not found")
info = svc.describe()
base = site_url(request)
seo_ctx = base_seo_context(
request,
title=f"{info['title']} - Services",
description=info["description"] or f"Configure the {info['title']} service.",
robots="noindex",
breadcrumbs=[
{"name": "Home", "url": "/feed"},
{"name": "Admin", "url": "/admin"},
{"name": "Services", "url": "/admin/services"},
{"name": info["title"], "url": f"/admin/services/{name}"},
],
schemas=[website_schema(base)],
)
return templates.TemplateResponse(request, "service_detail.html", {
**seo_ctx,
"request": request,
"user": admin,
"service": info,
"admin_section": "services",
})
@router.get("/{name}/data")
async def service_detail_data(request: Request, name: str):
require_admin(request)
svc = service_manager.get_service(name)
if svc is None:
return JSONResponse({"error": "unknown service"}, status_code=404)
return JSONResponse({"service": svc.describe()})
@router.post("/{name}/start")
async def service_start(request: Request, name: str):
require_admin(request)
if not service_manager.set_enabled(name, True):
return JSONResponse({"ok": False, "error": "unknown service"}, status_code=404)
return JSONResponse({"ok": True})
@router.post("/{name}/stop")
async def service_stop(request: Request, name: str):
require_admin(request)
if not service_manager.set_enabled(name, False):
return JSONResponse({"ok": False, "error": "unknown service"}, status_code=404)
return JSONResponse({"ok": True})
@router.post("/{name}/run")
async def service_run(request: Request, name: str):
require_admin(request)
if not service_manager.send_command(name, "run"):
return JSONResponse({"ok": False, "error": "unknown service"}, status_code=404)
return JSONResponse({"ok": True})
@router.post("/{name}/clear-logs")
async def service_clear_logs(request: Request, name: str):
require_admin(request)
if not service_manager.send_command(name, "clear"):
return JSONResponse({"ok": False, "error": "unknown service"}, status_code=404)
return JSONResponse({"ok": True})
@router.post("/{name}/config")
async def service_config(request: Request, name: str):
require_admin(request)
form = await request.form()
result = service_manager.save_config(name, dict(form))
if result is None:
return JSONResponse({"ok": False, "error": "unknown service"}, status_code=404)
if not result["ok"]:
return JSONResponse(result, status_code=400)
return JSONResponse(result)