Files
neo/backend/prisma/schema.prisma
2025-12-22 23:48:09 +01:00

191 lines
5.0 KiB
Plaintext

// Tenant-specific database schema
// This schema is applied to each tenant's database
// NOTE: Each tenant has its own database, so there is NO tenantId column in these tables
generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma/tenant"
binaryTargets = ["native", "debian-openssl-3.0.x"]
}
datasource db {
provider = "mysql"
url = env("TENANT_DATABASE_URL")
}
// User & Auth
model User {
id String @id @default(uuid())
email String @unique
password String
firstName String?
lastName String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userRoles UserRole[]
accounts Account[]
@@map("users")
}
// RBAC - Spatie-like
model Role {
id String @id @default(uuid())
name String
guardName String @default("api")
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userRoles UserRole[]
rolePermissions RolePermission[]
@@unique([name, guardName])
@@map("roles")
}
model Permission {
id String @id @default(uuid())
name String
guardName String @default("api")
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
rolePermissions RolePermission[]
@@unique([name, guardName])
@@map("permissions")
}
model UserRole {
id String @id @default(uuid())
userId String
roleId String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId])
@@index([userId])
@@index([roleId])
@@map("user_roles")
}
model RolePermission {
id String @id @default(uuid())
roleId String
permissionId String
createdAt DateTime @default(now())
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
@@unique([roleId, permissionId])
@@index([roleId])
@@index([permissionId])
@@map("role_permissions")
}
// Object Definition (Metadata)
model ObjectDefinition {
id String @id @default(uuid())
apiName String @unique
label String
pluralLabel String?
description String? @db.Text
isSystem Boolean @default(false)
isCustom Boolean @default(true)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
fields FieldDefinition[]
pages AppPage[]
@@map("object_definitions")
}
model FieldDefinition {
id String @id @default(uuid())
objectDefinitionId String
apiName String
label String
type String // String, Number, Date, Boolean, Reference, etc.
length Int?
precision Int?
scale Int?
referenceObject String?
defaultValue String? @db.Text
description String? @db.Text
isRequired Boolean @default(false)
isUnique Boolean @default(false)
isSystem Boolean @default(false)
isCustom Boolean @default(true)
displayOrder Int @default(0)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
object ObjectDefinition @relation(fields: [objectDefinitionId], references: [id], onDelete: Cascade)
@@unique([objectDefinitionId, apiName])
@@index([objectDefinitionId])
@@map("field_definitions")
}
// Example static object: Account
model Account {
id String @id @default(uuid())
name String
status String @default("active")
ownerId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
owner User @relation(fields: [ownerId], references: [id])
@@index([ownerId])
@@map("accounts")
}
// Application Builder
model App {
id String @id @default(uuid())
slug String @unique
label String
description String? @db.Text
icon String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
pages AppPage[]
@@map("apps")
}
model AppPage {
id String @id @default(uuid())
appId String
slug String
label String
type String // list, board, dashboard, form, detail
objectApiName String?
objectId String?
config Json? // page-specific configuration
sortOrder Int @default(0)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
object ObjectDefinition? @relation(fields: [objectId], references: [id])
@@unique([appId, slug])
@@index([appId])
@@index([objectId])
@@map("app_pages")
}