refactor(scripts): switch webhooks:all to api fetch

Hits GET /admin/webhooks instead of opening the local SQLite directly,
so the task can be run from a developer laptop without ssh or file
access to the server. Drops the FFI/read/write task permissions in
favour of net/env.
This commit is contained in:
Julien Calixte
2026-05-05 14:07:31 +02:00
parent 1c160b6c53
commit 355fc45316
2 changed files with 43 additions and 20 deletions

View File

@@ -6,7 +6,7 @@
"server:prod": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi server.ts", "server:prod": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi server.ts",
"migrate": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi src/migrations/init.ts", "migrate": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi src/migrations/init.ts",
"webhooks": "deno run --allow-net --allow-env scripts/manage-webhooks.ts", "webhooks": "deno run --allow-net --allow-env scripts/manage-webhooks.ts",
"webhooks:all": "deno run --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi scripts/list-all-webhooks.ts" "webhooks:all": "deno run --allow-net --allow-env scripts/list-all-webhooks.ts"
}, },
"imports": { "imports": {
"@db/sqlite": "jsr:@db/sqlite@^0.13.0", "@db/sqlite": "jsr:@db/sqlite@^0.13.0",

View File

@@ -1,29 +1,52 @@
// Admin: list every webhook subscription from the local SQLite, across all // Admin: list every webhook subscription via the Remanso API. Requires the
// DIDs. Talks to the database directly — does NOT go through the API. // authenticated DID to be in the server-side ADMIN_DIDS allowlist.
// //
// deno task webhooks:all // deno task webhooks:all
// //
// Reads SQLITE_PATH (defaults to "notes.db"). The `token` column is // Inputs (env or flag, env preferred):
// intentionally excluded from the output — it is a write-only secret. // ATPROTO_HANDLE / --handle e.g. alice.eurosky.social
// ATPROTO_APP_PASSWORD / --app-password app password (NOT your account password)
// REMANSO_API / --api default: https://api.remanso.space
import { Database } from "@db/sqlite"; const HELP = `
Usage:
deno task webhooks:all
type WebhookRow = { Inputs (env or flag, env preferred):
id: number; ATPROTO_HANDLE / --handle your AT Protocol handle
did: string; ATPROTO_APP_PASSWORD / --app-password app password (NOT your account password)
method: string; REMANSO_API / --api default: https://api.remanso.space
url: string; `;
verb: string;
import { parseArgs, sessionFromFlagsOrEnv } from "./_atproto-session.ts";
const die = (msg: string): never => {
console.error(`error: ${msg}`);
console.error(HELP);
Deno.exit(1);
}; };
const path = Deno.env.get("SQLITE_PATH") ?? "notes.db"; const main = async () => {
const db = new Database(path); const flags = parseArgs(Deno.args);
if (flags.help === "true" || flags.h === "true") {
console.log(HELP);
Deno.exit(0);
}
const rows = db.prepare( const { session, api } = await sessionFromFlagsOrEnv(flags).catch(
"SELECT id, did, method, url, verb FROM webhook_subscription ORDER BY did, id", (e: Error) => die(e.message),
).all<WebhookRow>(); );
const res = await fetch(`${api}/admin/webhooks`, {
headers: { "Authorization": `Bearer ${session.accessJwt}` },
});
if (!res.ok) {
console.error(`list-all failed (${res.status}): ${await res.text()}`);
Deno.exit(1);
}
const rows = await res.json();
console.log(JSON.stringify(rows, null, 2)); console.log(JSON.stringify(rows, null, 2));
console.error(`[done] ${rows.length} subscription(s) at ${path}`); console.error(`[done] ${rows.length} subscription(s) at ${api}`);
};
db.close(); await main();