Files
web-app-launcher/prisma/schema.prisma
alexei.dolgolyov 114dee57a8 feat(service-integrations): phase 1 — integration architecture foundation
- Add Integration interfaces, registry, cache, encryption, and base helpers
- Add integrationType, integrationConfig, integrationEnabled to App model
- Add integration widget type to constants and validators
- Add integration fields to AppRecord, CreateAppInput, UpdateAppInput
- Update appService with encryption/decryption for integration config
- Add API routes: list integrations, test connection, fetch endpoint data
2026-03-25 22:02:34 +03:00

352 lines
9.7 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?
onboardingComplete Boolean @default(false)
trackRecentApps Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
themeMode String?
primaryHue Int?
primarySaturation Int?
backgroundType String?
locale String?
groups UserGroup[]
createdApps App[]
boards Board[]
favorites UserFavorite[]
clicks AppClick[]
notificationChannels NotificationChannel[]
notifications Notification[]
apiTokens ApiToken[]
auditLogs AuditLog[]
boardTemplates BoardTemplate[]
@@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
integrationType String?
integrationConfig String?
integrationEnabled Boolean @default(false)
createdById String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
statuses AppStatus[]
widgets Widget[]
appTags AppTag[]
links AppLink[]
clicks AppClick[]
notifications Notification[]
favorites UserFavorite[]
@@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
themeHue Int?
themeSaturation Int?
backgroundType String?
cardSize String?
wallpaperUrl String?
wallpaperBlur Int?
wallpaperOverlay Float?
customCss String?
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)
cardSize String?
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
customCss String?
onboardingComplete Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// --- New models for Phases 4-7 ---
model Tag {
id String @id @default(cuid())
name String @unique
color String?
createdAt DateTime @default(now())
appTags AppTag[]
@@index([name])
}
model AppTag {
id String @id @default(cuid())
appId String
tagId String
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@unique([appId, tagId])
@@index([appId])
@@index([tagId])
}
model AppLink {
id String @id @default(cuid())
appId String
label String
url String
icon String?
order Int @default(0)
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
@@index([appId])
}
model UserFavorite {
id String @id @default(cuid())
userId String
appId String
order Int @default(0)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
@@unique([userId, appId])
@@index([userId])
@@index([appId])
}
model AppClick {
id String @id @default(cuid())
userId String
appId String
clickedAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
app App @relation(fields: [appId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([appId])
@@index([clickedAt])
}
model NotificationChannel {
id String @id @default(cuid())
userId String
type String // discord | slack | telegram | http
config String @default("{}") // JSON stored as string for SQLite
enabled Boolean @default(true)
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
model Notification {
id String @id @default(cuid())
userId String
appId String?
event String // app_online | app_offline | app_degraded
message String
sentAt DateTime @default(now())
readAt DateTime?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
app App? @relation(fields: [appId], references: [id], onDelete: SetNull)
@@index([userId])
@@index([appId])
@@index([sentAt])
}
model ApiToken {
id String @id @default(cuid())
userId String
name String
tokenHash String @unique
scope String // read | write | admin
lastUsedAt DateTime?
expiresAt DateTime?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([tokenHash])
}
model AuditLog {
id String @id @default(cuid())
userId String?
action String // user_created | user_deleted | etc.
entityType String
entityId String
details String @default("{}") // JSON stored as string for SQLite
createdAt DateTime @default(now())
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([userId])
@@index([action])
@@index([entityType, entityId])
@@index([createdAt])
}
model BoardTemplate {
id String @id @default(cuid())
name String
description String?
icon String?
config String @default("{}") // JSON stored as string for SQLite
isBuiltin Boolean @default(false)
createdById String?
createdAt DateTime @default(now())
createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
@@index([createdById])
}