mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-20 09:14:22 +01:00
97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
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())]),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
})
|
|
}
|