| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import { z } from "zod"
- import { fn } from "./util/fn"
- import { Actor } from "./actor"
- import { and, Database, eq, isNull, sql } from "./drizzle"
- import { Identifier } from "./identifier"
- import { KeyTable } from "./schema/key.sql"
- import { UserTable } from "./schema/user.sql"
- import { AuthTable } from "./schema/auth.sql"
- export namespace Key {
- export const list = fn(z.void(), async () => {
- const keys = await Database.use((tx) =>
- tx
- .select({
- id: KeyTable.id,
- name: KeyTable.name,
- key: KeyTable.key,
- timeUsed: KeyTable.timeUsed,
- userID: KeyTable.userID,
- email: AuthTable.subject,
- })
- .from(KeyTable)
- .innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID)))
- .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")))
- .where(
- and(
- ...[
- eq(KeyTable.workspaceID, Actor.workspace()),
- isNull(KeyTable.timeDeleted),
- ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
- ],
- ),
- )
- .orderBy(sql`${KeyTable.name} DESC`),
- )
- // only return value for user's keys
- return keys.map((key) => ({
- ...key,
- key: key.userID === Actor.userID() ? key.key : undefined,
- keyDisplay: `${key.key.slice(0, 7)}...${key.key.slice(-4)}`,
- }))
- })
- export const create = fn(
- z.object({
- userID: z.string(),
- name: z.string().min(1).max(255),
- }),
- async (input) => {
- const { name } = input
- // Generate secret key: sk- + 64 random characters (upper, lower, numbers)
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- let secretKey = "sk-"
- const array = new Uint32Array(64)
- crypto.getRandomValues(array)
- for (let i = 0, l = array.length; i < l; i++) {
- secretKey += chars[array[i] % chars.length]
- }
- const keyID = Identifier.create("key")
- await Database.use((tx) =>
- tx.insert(KeyTable).values({
- id: keyID,
- workspaceID: Actor.workspace(),
- userID: input.userID,
- name,
- key: secretKey,
- timeUsed: null,
- }),
- )
- return keyID
- },
- )
- export const remove = fn(z.object({ id: z.string() }), async (input) => {
- // only admin can remove other user's keys
- await Database.use((tx) =>
- tx
- .update(KeyTable)
- .set({
- timeDeleted: sql`now()`,
- })
- .where(
- and(
- ...[
- eq(KeyTable.id, input.id),
- eq(KeyTable.workspaceID, Actor.workspace()),
- ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
- ],
- ),
- ),
- )
- })
- }
|