From 174a6601b2f7457bde975fc3dbb7d3ba8e2520d8 Mon Sep 17 00:00:00 2001 From: Paul Bailey Date: Mon, 1 Dec 2025 23:58:20 +0000 Subject: [PATCH] feat: update database schema for multi-user support - Add User model with email, passwordHash, and name fields - Add Collaborator model for list sharing with permission levels - Add Invitation model for sharing invitations with status tracking - Add ownerId field to List model with cascade deletion - Add necessary indexes for performance optimization - Implements Requirements 1.1, 4.1, 5.1 --- prisma/schema.prisma | 70 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index cd1fb37..789e3df 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -7,13 +7,71 @@ datasource db { url = env("DATABASE_URL") } +model User { + id String @id @default(cuid()) + email String @unique + name String? + passwordHash String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + ownedLists List[] @relation("ListOwner") + collaborations Collaborator[] + sentInvitations Invitation[] @relation("InvitationInviter") + receivedInvitations Invitation[] @relation("InvitationReceiver") + + @@index([email]) +} + model List { - id String @id @default(cuid()) - title String - color String @default("#3B82F6") - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - items Item[] + id String @id @default(cuid()) + title String + color String @default("#3B82F6") + ownerId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + owner User @relation("ListOwner", fields: [ownerId], references: [id], onDelete: Cascade) + items Item[] + collaborators Collaborator[] + invitations Invitation[] + + @@index([ownerId]) + @@index([ownerId, createdAt]) +} + +model Collaborator { + id String @id @default(cuid()) + userId String + listId String + permission String // 'editor' or 'viewer' + createdAt DateTime @default(now()) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + list List @relation(fields: [listId], references: [id], onDelete: Cascade) + + @@unique([userId, listId]) + @@index([userId]) + @@index([listId]) + @@index([listId, permission]) +} + +model Invitation { + id String @id @default(cuid()) + email String + listId String + inviterId String + permission String // 'editor' or 'viewer' + status String @default("pending") // 'pending', 'accepted', 'declined' + createdAt DateTime @default(now()) + expiresAt DateTime + list List @relation(fields: [listId], references: [id], onDelete: Cascade) + inviter User @relation("InvitationInviter", fields: [inviterId], references: [id], onDelete: Cascade) + receiver User? @relation("InvitationReceiver", fields: [email], references: [email], onDelete: Cascade) + + @@index([email]) + @@index([listId]) + @@index([inviterId]) + @@index([status]) + @@index([email, status]) + @@index([listId, status]) } model Item {