Files
web-app-launcher/prisma/schema.prisma
T
alexei.dolgolyov f1b1aa5975 feat(mvp): phase 2 - database schema & services layer
Define full Prisma schema (10 models), run initial migration, build core
services (auth, user, group, app, board, permission), Zod validators,
type definitions, API response envelope, constants, and seed script.
2026-03-24 20:00:21 +03:00

173 lines
5.1 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
email String @unique
password String?
displayName String
avatarUrl String?
authProvider String @default("local") // local | oauth
role String @default("user") // admin | user
refreshToken String?
refreshTokenExpiresAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
groups UserGroup[]
createdApps App[]
boards Board[]
@@index([email])
}
model Group {
id String @id @default(cuid())
name String @unique
description String?
isDefault Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
users UserGroup[]
}
model UserGroup {
id String @id @default(cuid())
userId String
groupId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
@@unique([userId, groupId])
@@index([userId])
@@index([groupId])
}
model App {
id String @id @default(cuid())
name String
url String
icon String?
iconType String @default("lucide") // lucide | simple | url | emoji
description String?
category String?
tags String @default("") // comma-separated
healthcheckEnabled Boolean @default(false)
healthcheckInterval Int @default(300) // seconds
healthcheckMethod String @default("GET")
healthcheckExpectedStatus Int @default(200)
healthcheckTimeout Int @default(5000) // milliseconds
createdById String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
statuses AppStatus[]
widgets Widget[]
@@index([name])
@@index([category])
@@index([createdById])
}
model AppStatus {
id String @id @default(cuid())
appId String
status String @default("unknown") // online | offline | degraded | unknown
responseTime Int? // milliseconds
checkedAt DateTime @default(now())
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
@@index([appId])
@@index([checkedAt])
}
model Board {
id String @id @default(cuid())
name String
icon String?
description String?
isDefault Boolean @default(false)
isGuestAccessible Boolean @default(false)
backgroundConfig String? // JSON stored as string for SQLite
createdById String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
sections Section[]
@@index([createdById])
}
model Section {
id String @id @default(cuid())
boardId String
title String
icon String?
order Int @default(0)
isExpandedByDefault Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
board Board @relation(fields: [boardId], references: [id], onDelete: Cascade)
widgets Widget[]
@@index([boardId])
}
model Widget {
id String @id @default(cuid())
sectionId String
type String // app | bookmark | note | embed | status
order Int @default(0)
config String @default("{}") // JSON stored as string for SQLite
appId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
section Section @relation(fields: [sectionId], references: [id], onDelete: Cascade)
app App? @relation(fields: [appId], references: [id], onDelete: SetNull)
@@index([sectionId])
@@index([appId])
}
model Permission {
id String @id @default(cuid())
entityType String // board | app
entityId String
targetType String // user | group
targetId String
level String // view | edit | admin
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([entityType, entityId, targetType, targetId])
@@index([entityType, entityId])
@@index([targetType, targetId])
}
model SystemSettings {
id String @id @default("singleton")
authMode String @default("local") // local | oauth | both
registrationEnabled Boolean @default(true)
oauthClientId String?
oauthClientSecret String?
oauthDiscoveryUrl String?
defaultTheme String @default("dark")
defaultPrimaryColor String @default("#6366f1")
healthcheckDefaults String @default("{}") // JSON stored as string for SQLite
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}