From 960c200558161024ecf23ced181291c3f4187ee8 Mon Sep 17 00:00:00 2001 From: Mat Manna Date: Tue, 4 Aug 2026 10:37:22 -0400 Subject: [PATCH] feat: show revoker slack id --- src/api/routers/apiKeys.ts | 7 ++++++- src/web/keys.tsx | 37 ++++++++++++++++++++----------------- src/web/style.css | 6 +++++- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/api/routers/apiKeys.ts b/src/api/routers/apiKeys.ts index dd31609..3b3ac24 100644 --- a/src/api/routers/apiKeys.ts +++ b/src/api/routers/apiKeys.ts @@ -3,8 +3,10 @@ import { z } from "zod"; import { authRequiredProcedure, isChannelManager } from "../context"; import { generateApiKey } from "../../lib/api-keys"; import { getDb } from "../../db"; -import { apiKeys, apiKeyChannels } from "../../db/schema"; +import { apiKeys, apiKeyChannels, authUser } from "../../db/schema"; import { eq } from "drizzle-orm"; +import { aliasedTable } from "drizzle-orm/alias"; + export const listApiKeys = authRequiredProcedure .route({ method: "GET", path: "/api-keys" }) @@ -13,6 +15,7 @@ export const listApiKeys = authRequiredProcedure const userId = context.session?.user?.id; if (!userId) return []; + const revokedByUser = aliasedTable(authUser, "revokedByUser"); const keys = await db .select({ id: apiKeys.id, @@ -20,8 +23,10 @@ export const listApiKeys = authRequiredProcedure keyPrefix: apiKeys.keyPrefix, createdAt: apiKeys.createdAt, lastUsedAt: apiKeys.lastUsedAt, + revokedBy: revokedByUser.slackId, }) .from(apiKeys) + .leftJoin(revokedByUser, eq(apiKeys.revokedBy, revokedByUser.id)) .where(eq(apiKeys.owner, userId)); const keysWithChannels = await Promise.all( diff --git a/src/web/keys.tsx b/src/web/keys.tsx index e7ac758..86baf5e 100644 --- a/src/web/keys.tsx +++ b/src/web/keys.tsx @@ -120,23 +120,26 @@ function KeysList() { {keys.map((k) => (
{k.name} ind_{k.keyPrefix}...{" "} - {k.revokedBy && `Revoked by ${k.revokedBy}`}{" "} - + .then((r) => r.json()) + .then((data) => { + setKeys(Array.isArray(data) ? data : []); + setKeysPending(false); + }) + .catch((e) => setError(String(e))); + }} + class="button bg-red" + > + revoke! + + } {k.channels != null && k.channels.length > 0 ? ( <> scoped channels: ({k.channels.length}) @@ -157,7 +160,7 @@ function KeysList() { createRoot(document.getElementById("app")!).render(

integrate with indigest

-

for now, all keys are read-only

+ {/**

for now, all keys are read-only

**/}
, ); diff --git a/src/web/style.css b/src/web/style.css index 7cdf0ac..881faf5 100644 --- a/src/web/style.css +++ b/src/web/style.css @@ -346,11 +346,15 @@ body { transition: all 0.2s ease; } -.red { +.bg-red { background-color: #983b3d; color: white; } +.red { + color: #983b3d; +} + .card, .input { border: 1px solid; -- 2.51.2