Buckets:
| 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())]), | |
| ), | |
| ), | |
| ) | |
| }) | |
| } | |
Xet Storage Details
- Size:
- 2.85 kB
- Xet hash:
- de891fcf9cf464cceed2f132ff8372cf90f4d81998ce582fc0327cefce7cbc31
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.