diff --git a/apps/dashboard/lib/db.ts b/apps/dashboard/lib/db.ts index 9e0c0dd631..d66407c8f8 100644 --- a/apps/dashboard/lib/db.ts +++ b/apps/dashboard/lib/db.ts @@ -1,6 +1,7 @@ import { dbEnv } from "@/lib/env"; import { Client } from "@planetscale/database"; -import { drizzle, schema } from "@unkey/db"; +import { type PlanetScaleDatabase, drizzle, schema } from "@unkey/db"; +export type Database = PlanetScaleDatabase; export const db = drizzle( new Client({ diff --git a/apps/dashboard/lib/trpc/routers/key/create.ts b/apps/dashboard/lib/trpc/routers/key/create.ts index 864fffb8e0..1ee7b7b26f 100644 --- a/apps/dashboard/lib/trpc/routers/key/create.ts +++ b/apps/dashboard/lib/trpc/routers/key/create.ts @@ -1,4 +1,4 @@ -import { db, schema } from "@/lib/db"; +import { type Database, type Identity, db, schema } from "@/lib/db"; import { ingestAuditLogs } from "@/lib/tinybird"; import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; @@ -77,6 +77,10 @@ export const createKey = rateLimitedProcedure(ratelimit.create) }); } + const identity = input.ownerId + ? await upsertIdentity(db, keyAuth.workspaceId, input.ownerId) + : null; + const keyId = newId("key"); const { key, hash, start } = await newKey({ prefix: input.prefix, @@ -107,6 +111,7 @@ export const createKey = rateLimitedProcedure(ratelimit.create) deletedAt: null, enabled: input.enabled, environment: input.environment, + identityId: identity?.id, }) .catch((_err) => { throw new TRPCError({ @@ -135,3 +140,53 @@ export const createKey = rateLimitedProcedure(ratelimit.create) return { keyId, key }; }); + +async function upsertIdentity( + db: Database, + workspaceId: string, + externalId: string, +): Promise { + let identity = await db.query.identities.findFirst({ + where: (table, { and, eq }) => + and(eq(table.workspaceId, workspaceId), eq(table.externalId, externalId)), + }); + + if (!identity) { + await db + .insert(schema.identities) + .values({ + id: newId("identity"), + createdAt: Date.now(), + environment: "default", + meta: {}, + externalId, + updatedAt: null, + workspaceId, + }) + .onDuplicateKeyUpdate({ + set: { + updatedAt: Date.now(), + }, + }) + .catch((_err) => { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Failed to insert identity", + }); + }); + + identity = await db.query.identities + .findFirst({ + where: (table, { and, eq }) => + and(eq(table.workspaceId, workspaceId), eq(table.externalId, externalId)), + }) + .catch((_err) => { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Failed to read identity after upsert", + }); + }); + } + + return identity as Identity; +}