// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } generator dbml { provider = "prisma-dbml-generator" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Setting { key String @id value String // this value will be parsed with JSON.parse } model User { sub String @id display_name String? picture_url String? profile_url String? lastTimeGainStarted DateTime @default(now()) // the time base used to determine the amount of stack the user should gain pixelStack Int @default(0) // amount of pixels stacked for this user undoExpires DateTime? // when the undo for the most recent pixel expires at isAdmin Boolean @default(false) isModerator Boolean @default(false) pixels Pixel[] FactionMember FactionMember[] Ban Ban? AuditLog AuditLog[] IPAddress IPAddress[] } model Instance { id Int @id @default(autoincrement()) hostname String @unique name String? logo_url String? banner_url String? Ban Ban? } model IPAddress { ip String userSub String lastUsedAt DateTime createdAt DateTime @default(now()) user User @relation(fields: [userSub], references: [sub]) @@id([ip, userSub]) } model PaletteColor { id Int @id @default(autoincrement()) name String hex String @unique } model Pixel { id Int @id @default(autoincrement()) userId String x Int y Int color String isTop Boolean @default(false) isModAction Boolean @default(false) createdAt DateTime @default(now()) deletedAt DateTime? user User @relation(fields: [userId], references: [sub]) // do not add a relation to PaletteColor, in the case the palette gets changed // https://github.com/prisma/prisma/issues/18058 } model Faction { id String @id @default(uuid()) name String image String? FactionMember FactionMember[] FactionRole FactionRole[] FactionSocial FactionSocial[] FactionSetting FactionSetting[] } // people can be apart of multiple factions at once model FactionMember { id Int @id @default(autoincrement()) sub String factionId String user User @relation(fields: [sub], references: [sub]) faction Faction @relation(fields: [factionId], references: [id]) } // future proofing maybe: different roles for the same faction // factions by default should have LEADER, MODERATOR, MEMBER model FactionRole { id String @id @default(uuid()) name String level Int // permission level (similar to matrix [0 = member, 100 = leader]) factionId String faction Faction @relation(fields: [factionId], references: [id]) } model FactionSocial { id String @id @default(uuid()) factionId String title String? // display name for the link url String // [!] rel=nofollow [!] position Int faction Faction @relation(fields: [factionId], references: [id]) } model FactionSetting { id String @id @default(uuid()) factionId String key String value String definition FactionSettingDefinition @relation(fields: [key], references: [id]) faction Faction @relation(fields: [factionId], references: [id]) } // global definition for the faction setting model FactionSettingDefinition { id String @id name String type String // enum of type of setting (eg. text, checkbox) minimumLevel Int // what level is needed to modify this setting (>=) FactionSetting FactionSetting[] } model Ban { id Int @id @default(autoincrement()) userId String? @unique instanceId Int? @unique privateNote String? publicNote String? expiresAt DateTime createdAt DateTime @default(now()) updatedAt DateTime? user User? @relation(fields: [userId], references: [sub]) instance Instance? @relation(fields: [instanceId], references: [id]) AuditLog AuditLog[] } enum AuditLogAction { BAN_CREATE BAN_UPDATE BAN_DELETE CANVAS_SIZE CANVAS_FILL CANVAS_FREEZE CANVAS_UNFREEZE CANVAS_AREA_UNDO USER_MOD USER_UNMOD USER_ADMIN USER_UNADMIN } model AuditLog { id Int @id @default(autoincrement()) userId String? action AuditLogAction reason String? comment String? // service comment banId Int? createdAt DateTime @default(now()) updatedAt DateTime? user User? @relation(fields: [userId], references: [sub]) ban Ban? @relation(fields: [banId], references: [id]) }