summaryrefslogtreecommitdiffhomepage
path: root/cloud/core/src/key.ts
blob: b62a8961b5524b253817f981d95ca003f03d91a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { z } from "zod"
import { fn } from "./util/fn"
import { Actor } from "./actor"
import { and, Database, eq, sql } from "./drizzle"
import { Identifier } from "./identifier"
import { KeyTable } from "./schema/key.sql"

export namespace Key {
  export const list = async () => {
    const workspace = Actor.workspace()
    const keys = await Database.use((tx) =>
      tx
        .select()
        .from(KeyTable)
        .where(eq(KeyTable.workspaceID, workspace))
        .orderBy(sql`${KeyTable.timeCreated} DESC`),
    )
    return keys
  }

  export const create = fn(z.object({ name: z.string().min(1).max(255) }), async (input) => {
    const workspaceID = Actor.workspace()
    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: Actor.use(),
        name,
        key: secretKey,
        timeUsed: null,
      }),
    )

    return keyID
  })

  export const remove = fn(z.object({ id: z.string() }), async (input) => {
    const workspace = Actor.workspace()
    await Database.use((tx) =>
      tx.delete(KeyTable).where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace))),
    )
  })
}