feat(webhooks): add admin endpoint to list every subscription

Adds GET /admin/webhooks gated by an ADMIN_DIDS env-var allowlist of
verified AT Proto DIDs. Fail-closed: if ADMIN_DIDS is unset, the route
always returns 403 — no accidental exposure on deploys that forget it.
This commit is contained in:
Julien Calixte
2026-05-05 14:07:22 +02:00
parent c00f3d631c
commit 34faa10be2
2 changed files with 38 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import {
getNotes,
getNotesByDid,
getNotesByDids,
listAllWebhooks,
listWebhooksByDid,
type WebhookVerb,
} from "./src/data/db.ts";
@@ -39,6 +40,32 @@ const requireDidOwnership = async (
return true;
};
const ADMIN_DIDS = new Set(
(Deno.env.get("ADMIN_DIDS") ?? "")
.split(",")
.map((d) => d.trim())
.filter(Boolean),
);
const requireAdmin = async (ctx: AuthCtx): Promise<boolean> => {
let verifiedDid: string;
try {
verifiedDid = await authenticateRequest(
ctx.request.headers.get("Authorization"),
);
} catch {
ctx.response.status = 401;
ctx.response.body = { error: "Unauthorized" };
return false;
}
if (!ADMIN_DIDS.has(verifiedDid)) {
ctx.response.status = 403;
ctx.response.body = { error: "Admin only" };
return false;
}
return true;
};
const router = new Router();
const PAGINATION = 20;
@@ -117,6 +144,11 @@ router.post("/notes/feed", async (ctx) => {
const ALLOWED_VERBS = ["create", "delete", "bulk-create"] as const;
router.get("/admin/webhooks", async (ctx) => {
if (!(await requireAdmin(ctx))) return;
ctx.response.body = listAllWebhooks();
});
router.get("/:did/webhooks", async (ctx) => {
const { did } = ctx.params;
if (!(await requireDidOwnership(ctx, did))) return;

View File

@@ -136,6 +136,12 @@ export const listWebhooksByDid = (
).all<Omit<WebhookSubscriptionRow, "token">>(did);
};
export const listAllWebhooks = (): Omit<WebhookSubscriptionRow, "token">[] => {
return db.prepare(
"SELECT id, did, method, url, verb FROM webhook_subscription ORDER BY did, id",
).all<Omit<WebhookSubscriptionRow, "token">>();
};
export const getWebhooksByDidAndVerb = (
did: string,
verb: WebhookVerb,