diff --git a/packages/console/app/src/routes/workspace/key-section.tsx b/packages/console/app/src/routes/workspace/key-section.tsx index e94d2bf8..1c2316db 100644 --- a/packages/console/app/src/routes/workspace/key-section.tsx +++ b/packages/console/app/src/routes/workspace/key-section.tsx @@ -7,6 +7,11 @@ import { createStore } from "solid-js/store" import { formatDateUTC, formatDateForTable } from "./common" import styles from "./key-section.module.css" import { Actor } from "@opencode-ai/console-core/actor.js" +import { and, Database, eq, isNull, sql } from "@opencode-ai/console-core/drizzle/index.js" +import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js" +import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" +import { AccountTable } from "@opencode-ai/console-core/schema/account.sql.js" +import { User } from "@opencode-ai/console-core/user.js" const removeKey = action(async (form: FormData) => { "use server" @@ -108,11 +113,6 @@ export function KeySection() { const params = useParams() const keys = createAsync(() => listKeys(params.id)) - function formatKey(key: string) { - if (key.length <= 11) return key - return `${key.slice(0, 7)}...${key.slice(-4)}` - } - return (
@@ -134,7 +134,8 @@ export function KeySection() { Name Key - Created + Created By + Last Used @@ -147,24 +148,27 @@ export function KeySection() { {key.name} - + {key.keyDisplay}}> + + - - {formatDateForTable(key.timeCreated)} + {key.email} + + {key.timeUsed ? formatDateForTable(key.timeUsed) : "-"}
diff --git a/packages/console/core/src/key.ts b/packages/console/core/src/key.ts index 938c1ae8..3a4426d2 100644 --- a/packages/console/core/src/key.ts +++ b/packages/console/core/src/key.ts @@ -4,19 +4,45 @@ import { Actor } from "./actor" import { and, Database, eq, isNull, sql } from "./drizzle" import { Identifier } from "./identifier" import { KeyTable } from "./schema/key.sql" +import { AccountTable } from "./schema/account.sql" +import { UserTable } from "./schema/user.sql" +import { User } from "./user" export namespace Key { - export const list = async () => { - const workspace = Actor.workspace() + export const list = fn(z.void(), async () => { + const userID = Actor.assert("user").properties.userID + const user = await User.fromID(userID) const keys = await Database.use((tx) => tx - .select() + .select({ + id: KeyTable.id, + name: KeyTable.name, + key: KeyTable.key, + timeUsed: KeyTable.timeUsed, + userID: KeyTable.userID, + email: AccountTable.email, + }) .from(KeyTable) - .where(and(eq(KeyTable.workspaceID, workspace), isNull(KeyTable.timeDeleted))) - .orderBy(sql`${KeyTable.timeCreated} DESC`), + .innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID))) + .innerJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) + .where( + and( + ...[ + eq(KeyTable.workspaceID, Actor.workspace()), + isNull(KeyTable.timeDeleted), + ...(user.role === "admin" ? [] : [eq(KeyTable.userID, userID)]), + ], + ), + ) + .orderBy(sql`${KeyTable.name} DESC`), ) - return keys - } + // only return value for user's keys + return keys.map((key) => ({ + ...key, + key: key.userID === userID ? key.key : undefined, + keyDisplay: `${key.key.slice(0, 7)}...${key.key.slice(-4)}`, + })) + }) export const create = fn( z.object({