From 81b4027737de728379366d58c9198ae71f2205a0 Mon Sep 17 00:00:00 2001 From: piopi Date: Mon, 13 Jan 2025 09:13:31 -0500 Subject: [PATCH 1/6] feat: add tenant table/logic --- eslint.config.js | 9 +++++++++ prisma/schema.prisma | 21 +++++++++++++++++++-- src/lib/server/auth/index.ts | 26 +++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 4c9cdec..5b2744d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -41,6 +41,15 @@ export default ts.config( caughtErrorsIgnorePattern: '^_', }, ], + 'no-restricted-syntax': [ + 'error', + { + selector: + 'CallExpression:matches([callee.object.object.name="prisma"], [callee.object.object.name="prismaTransactionClient"], [callee.object.object.name="transactionClient"]):matches([callee.property.name="findFirst"], [callee.property.name="findMany"], [callee.property.name="updateMany"], [callee.property.name="deleteMany"], [callee.property.name="count"], [callee.property.name="aggregate"], [callee.property.name="groupBy"]):not(:has(ObjectExpression > Property[key.name="where"] > ObjectExpression > Property[key.name="tenantId"]))', + message: + 'Please filter on the current tenant when using findFirst, findMany, updateMany, deleteMany, count, aggregate or groupBy.', + }, + ], }, } ); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3033568..af4a1f4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,12 +15,29 @@ datasource db { } model User { - id String @id @default(uuid()) - clerkId String @unique + id String @default(uuid()) + clerkId String + tenant Tenant @relation(fields: [tenantId], references: [id]) + tenantId String email String? name String createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt + + @@id([id, tenantId]) + @@unique([clerkId, tenantId]) +} + +model Tenant { + id String @id @default(uuid()) + name String + slug String @unique + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + clerkId String @unique + User User[] + + @@map("tenant") } diff --git a/src/lib/server/auth/index.ts b/src/lib/server/auth/index.ts index 8bc10b9..e5b5d9d 100644 --- a/src/lib/server/auth/index.ts +++ b/src/lib/server/auth/index.ts @@ -14,7 +14,7 @@ export async function validateSession({ locals }: ServerLoadEvent) { return redirect(307, '/login'); } - if (!locals.auth.orgId && locals.auth.sessionId) { + if ((!locals.auth.orgId && locals.auth.sessionId) || !locals.auth.orgId) { // Sign out the user if they are not associated with an organization await clerkSessionClient.sessions.revokeSession(locals.auth.sessionId); return redirect(307, '/login'); @@ -22,9 +22,32 @@ export async function validateSession({ locals }: ServerLoadEvent) { const clerkUser = await clerkClient.users.getUser(locals.auth.userId); + const tenantClerkId = locals.auth.orgId; + + let tenant = await prisma.tenant.findUnique({ + where: { + clerkId: tenantClerkId, + }, + }); + + if (!tenant) { + const organization = await clerkClient.organizations.getOrganization({ + organizationId: tenantClerkId, + }); + + tenant = await prisma.tenant.create({ + data: { + clerkId: tenantClerkId, + name: organization.name, + slug: organization.slug ?? `tenant-${tenantClerkId}`, + }, + }); + } + let user = await prisma.user.findFirst({ where: { clerkId: clerkUser.id, + tenantId: tenant.id, }, }); @@ -41,6 +64,7 @@ export async function validateSession({ locals }: ServerLoadEvent) { clerkId: clerkUser.id, email: clerkUser.emailAddresses[0].emailAddress, name: clerkUser.fullName ?? '', + tenantId: tenant.id, }, }); -- 2.45.3 From a3b02d20ebf5eebfaf07b2d03d318fb8f0723eb2 Mon Sep 17 00:00:00 2001 From: piopi Date: Mon, 13 Jan 2025 09:13:46 -0500 Subject: [PATCH 2/6] feat: add tenant table/logic --- .../migration.sql | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 prisma/migrations/20250113141320_add_tenant_table/migration.sql diff --git a/prisma/migrations/20250113141320_add_tenant_table/migration.sql b/prisma/migrations/20250113141320_add_tenant_table/migration.sql new file mode 100644 index 0000000..3634aa2 --- /dev/null +++ b/prisma/migrations/20250113141320_add_tenant_table/migration.sql @@ -0,0 +1,39 @@ +/* + Warnings: + + - The primary key for the `User` table will be changed. If it partially fails, the table could be left without primary key constraint. + - A unique constraint covering the columns `[clerkId,tenantId]` on the table `User` will be added. If there are existing duplicate values, this will fail. + - Added the required column `tenantId` to the `User` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropIndex +DROP INDEX "User_clerkId_key"; + +-- AlterTable +ALTER TABLE "User" DROP CONSTRAINT "User_pkey", +ADD COLUMN "tenantId" TEXT NOT NULL, +ADD CONSTRAINT "User_pkey" PRIMARY KEY ("id", "tenantId"); + +-- CreateTable +CREATE TABLE "tenant" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "slug" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + "clerkId" TEXT NOT NULL, + + CONSTRAINT "tenant_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "tenant_slug_key" ON "tenant"("slug"); + +-- CreateIndex +CREATE UNIQUE INDEX "tenant_clerkId_key" ON "tenant"("clerkId"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_clerkId_tenantId_key" ON "User"("clerkId", "tenantId"); + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- 2.45.3 From 46c2af74358cda25b3b53fdf17297993eef05ea0 Mon Sep 17 00:00:00 2001 From: piopi Date: Mon, 13 Jan 2025 09:15:06 -0500 Subject: [PATCH 3/6] feat: add tenant table/logic --- src/lib/server/pothos/schema/users.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/server/pothos/schema/users.ts b/src/lib/server/pothos/schema/users.ts index 24db8da..055bb40 100644 --- a/src/lib/server/pothos/schema/users.ts +++ b/src/lib/server/pothos/schema/users.ts @@ -19,6 +19,8 @@ builder.queryFields((t) => ({ users: t.prismaField({ type: [User], resolve: async () => { + // TODO: Fix this when we add a tenant context + // eslint-disable-next-line no-restricted-syntax return await prisma.user.findMany(); }, }), -- 2.45.3 From 1339bcfa73c670be8eb0bdaf6d4bd612400957fe Mon Sep 17 00:00:00 2001 From: piopi Date: Tue, 14 Jan 2025 21:56:39 -0500 Subject: [PATCH 4/6] yolo bitch --- .../migration.sql | 12 ++++++------ prisma/schema.prisma | 16 +++++++--------- 2 files changed, 13 insertions(+), 15 deletions(-) rename prisma/migrations/{20250113141320_add_tenant_table => 20250115025622_add_tenant_table}/migration.sql (76%) diff --git a/prisma/migrations/20250113141320_add_tenant_table/migration.sql b/prisma/migrations/20250115025622_add_tenant_table/migration.sql similarity index 76% rename from prisma/migrations/20250113141320_add_tenant_table/migration.sql rename to prisma/migrations/20250115025622_add_tenant_table/migration.sql index 3634aa2..8969743 100644 --- a/prisma/migrations/20250113141320_add_tenant_table/migration.sql +++ b/prisma/migrations/20250115025622_add_tenant_table/migration.sql @@ -15,25 +15,25 @@ ADD COLUMN "tenantId" TEXT NOT NULL, ADD CONSTRAINT "User_pkey" PRIMARY KEY ("id", "tenantId"); -- CreateTable -CREATE TABLE "tenant" ( +CREATE TABLE "Tenant" ( "id" TEXT NOT NULL, "name" TEXT NOT NULL, "slug" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, - "clerkId" TEXT NOT NULL, + "clerkOrganizationId" TEXT NOT NULL, - CONSTRAINT "tenant_pkey" PRIMARY KEY ("id") + CONSTRAINT "Tenant_pkey" PRIMARY KEY ("id") ); -- CreateIndex -CREATE UNIQUE INDEX "tenant_slug_key" ON "tenant"("slug"); +CREATE UNIQUE INDEX "Tenant_slug_key" ON "Tenant"("slug"); -- CreateIndex -CREATE UNIQUE INDEX "tenant_clerkId_key" ON "tenant"("clerkId"); +CREATE UNIQUE INDEX "Tenant_clerkOrganizationId_key" ON "Tenant"("clerkOrganizationId"); -- CreateIndex CREATE UNIQUE INDEX "User_clerkId_tenantId_key" ON "User"("clerkId", "tenantId"); -- AddForeignKey -ALTER TABLE "User" ADD CONSTRAINT "User_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE "User" ADD CONSTRAINT "User_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index af4a1f4..f458363 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -31,13 +31,11 @@ model User { } model Tenant { - id String @id @default(uuid()) - name String - slug String @unique - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - clerkId String @unique - User User[] - - @@map("tenant") + id String @id @default(uuid()) + name String + slug String @unique + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + clerkOrganizationId String @unique + User User[] } -- 2.45.3 From f5795ec13f17dec373e8db99c4632f0714474b22 Mon Sep 17 00:00:00 2001 From: piopi Date: Tue, 14 Jan 2025 21:57:37 -0500 Subject: [PATCH 5/6] yolo bitch --- src/lib/server/auth/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/server/auth/index.ts b/src/lib/server/auth/index.ts index e5b5d9d..e628e58 100644 --- a/src/lib/server/auth/index.ts +++ b/src/lib/server/auth/index.ts @@ -26,7 +26,7 @@ export async function validateSession({ locals }: ServerLoadEvent) { let tenant = await prisma.tenant.findUnique({ where: { - clerkId: tenantClerkId, + clerkOrganizationId: tenantClerkId, }, }); @@ -37,7 +37,7 @@ export async function validateSession({ locals }: ServerLoadEvent) { tenant = await prisma.tenant.create({ data: { - clerkId: tenantClerkId, + clerkOrganizationId: tenantClerkId, name: organization.name, slug: organization.slug ?? `tenant-${tenantClerkId}`, }, -- 2.45.3 From 8780db4a5308d2cb3d4df9510fdfd82159e7db70 Mon Sep 17 00:00:00 2001 From: piopi Date: Tue, 14 Jan 2025 22:21:44 -0500 Subject: [PATCH 6/6] yolo bitch --- .../20250115025622_add_tenant_table/migration.sql | 4 ++-- prisma/schema.prisma | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/prisma/migrations/20250115025622_add_tenant_table/migration.sql b/prisma/migrations/20250115025622_add_tenant_table/migration.sql index 8969743..6dd7285 100644 --- a/prisma/migrations/20250115025622_add_tenant_table/migration.sql +++ b/prisma/migrations/20250115025622_add_tenant_table/migration.sql @@ -19,8 +19,8 @@ CREATE TABLE "Tenant" ( "id" TEXT NOT NULL, "name" TEXT NOT NULL, "slug" TEXT NOT NULL, - "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMP(3) NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, "clerkOrganizationId" TEXT NOT NULL, CONSTRAINT "Tenant_pkey" PRIMARY KEY ("id") diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f458363..fb780a0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -34,8 +34,8 @@ model Tenant { id String @id @default(uuid()) name String slug String @unique - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt clerkOrganizationId String @unique - User User[] + users User[] } -- 2.45.3