From 1703320b849a490a97fe58b1b4d228f083c3d468 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:12:27 -0700 Subject: [PATCH] add run api for administrators --- src/server/routes/api/v1/definition.ts | 6 ++- src/server/routes/api/v1/server/run.ts | 68 ++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/server/routes/api/v1/server/run.ts diff --git a/src/server/routes/api/v1/definition.ts b/src/server/routes/api/v1/definition.ts index cde2eb8..62091d5 100644 --- a/src/server/routes/api/v1/definition.ts +++ b/src/server/routes/api/v1/definition.ts @@ -1,4 +1,4 @@ -import { APIDefinition } from "../../api.js"; +import type { APIDefinition } from "../../api.js"; export default { "name": "v1", @@ -28,6 +28,10 @@ export default { { "file": "file/individual", "to": "/file" + }, + { + "file": "/server/run", + "to": "/server/run" } ] } satisfies APIDefinition diff --git a/src/server/routes/api/v1/server/run.ts b/src/server/routes/api/v1/server/run.ts new file mode 100644 index 0000000..6d898c2 --- /dev/null +++ b/src/server/routes/api/v1/server/run.ts @@ -0,0 +1,68 @@ +import { Hono } from "hono" +import * as Accounts from "../../../../lib/accounts.js" +import * as auth from "../../../../lib/auth.js" +import { HttpBindings } from "@hono/node-server" +import config, { ClientConfiguration } from "../../../../lib/config.js" +import type Files from "../../../../lib/files.js" +import { getAccount, requiresAccount, requiresAdmin } from "../../../../lib/middleware.js" +import { Writable } from "node:stream" + +const router = new Hono<{ + Variables: { + account: Accounts.Account + }, + Bindings: HttpBindings +}>() + +router.use(getAccount, requiresAccount, requiresAdmin) + +class Collect extends Writable { + collected: {t: number, packet: Buffer}[] = [] + + _write(data: Buffer, _: string, cb: () => void) { + this.collected.push({t: Date.now(), packet: data}) + cb(); + } +} + +class VirtualConsole extends console.Console { + + readonly stdout: Collect + readonly stderr: Collect + + constructor() { + const stdout = new Collect(), stderr = new Collect() + super(stdout, stderr) + this.stdout = stdout, this.stderr = stderr + } + +} + +export default function(files: Files) { + + router.post("/", async (ctx) => { + let vconsole = new VirtualConsole() + let evaluated + try { + let fn = new Function( + "accounts", + "auth", + "files", + "console", + await ctx.req.text() + ) + + evaluated = await fn(Accounts, auth, files, vconsole) + } catch (err) { + vconsole.error(err) + } + + return ctx.json({ + stdout: vconsole.stdout.collected, + stderr: vconsole.stderr.collected, + evaluated + }) + }) + + return router +}