This commit is contained in:
Frank
2025-10-04 01:12:22 -04:00
parent e7b6ffb314
commit 82509e8604
8 changed files with 778 additions and 43 deletions

View File

@@ -18,34 +18,38 @@ export namespace Key {
return keys
}
export const create = fn(z.object({ name: z.string().min(1).max(255) }), async (input) => {
const { name } = input
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")
const user = Actor.assert("user")
// 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(),
actor: user,
userID: user.properties.userID,
name,
key: secretKey,
timeUsed: null,
}),
)
await Database.use((tx) =>
tx.insert(KeyTable).values({
id: keyID,
workspaceID: Actor.workspace(),
userID: input.userID,
name,
key: secretKey,
timeUsed: null,
}),
)
return keyID
})
return keyID
},
)
export const remove = fn(z.object({ id: z.string() }), async (input) => {
const workspace = Actor.workspace()

View File

@@ -1,18 +1,15 @@
import { mysqlTable, varchar, uniqueIndex, json } from "drizzle-orm/mysql-core"
import { mysqlTable, varchar, uniqueIndex } from "drizzle-orm/mysql-core"
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
import { workspaceIndexes } from "./workspace.sql"
import { Actor } from "../actor"
export const KeyTable = mysqlTable(
"key",
{
...workspaceColumns,
...timestamps,
actor: json("actor").$type<Actor.Info>(),
name: varchar("name", { length: 255 }).notNull(),
oldName: varchar("old_name", { length: 255 }),
key: varchar("key", { length: 255 }).notNull(),
userID: ulid("user_id"),
userID: ulid("user_id").notNull(),
timeUsed: utc("time_used"),
},
(table) => [...workspaceIndexes(table), uniqueIndex("global_key").on(table.key)],

View File

@@ -100,12 +100,25 @@ export namespace User {
)
// create api key
//if (account) {
// const existing = await Database.use(tx => {
// const key = tx.select().from(KeyTable).where(and(eq(KeyTable.workspaceID, workspaceID), eq(KeyTable, account.id))).then((rows) => rows[0])
// return key
// })
//}
if (account) {
await Database.use(async (tx) => {
const user = await tx
.select()
.from(UserTable)
.where(and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.accountID, account.id)))
.then((rows) => rows[0])
const key = await tx
.select()
.from(KeyTable)
.where(and(eq(KeyTable.workspaceID, workspaceID), eq(KeyTable.userID, user.id)))
.then((rows) => rows[0])
if (key) return
await Key.create({ userID: user.id, name: "Default API Key" })
})
}
// send email, ignore errors
try {
@@ -151,12 +164,11 @@ export namespace User {
await Promise.all(
invitations.map((invite) =>
Actor.provide(
"user",
"system",
{
workspaceID: invite.workspaceID,
userID: invite.id,
},
() => Key.create({ name: "Default API Key" }),
() => Key.create({ userID: invite.id, name: "Default API Key" }),
),
),
)

View File

@@ -31,12 +31,11 @@ export namespace Workspace {
})
})
await Actor.provide(
"user",
"system",
{
workspaceID,
userID,
},
() => Key.create({ name: "Default API Key" }),
() => Key.create({ userID, name: "Default API Key" }),
)
return workspaceID
})