// 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" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } // ============================================ // Core Models // ============================================ model User { id String @id @default(uuid()) email String @unique password String firstName String? lastName String? isActive Boolean @default(true) // Relations roles UserRole[] refreshTokens RefreshToken[] // Multi-tenancy (optional) tenantId String? tenant Tenant? @relation(fields: [tenantId], references: [id]) // Timestamps & Soft Delete createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? @@index([email]) @@index([tenantId]) } model Role { id String @id @default(uuid()) name String @unique description String? isSystem Boolean @default(false) // Relations users UserRole[] permissions RolePermission[] // Timestamps & Soft Delete createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? @@index([name]) } model Permission { id String @id @default(uuid()) name String @unique description String? resource String // e.g., "users", "posts" action String // e.g., "create", "read", "update", "delete" // Relations roles RolePermission[] // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([resource, action]) @@index([resource]) } // Many-to-many: User <-> Role model UserRole { id String @id @default(uuid()) userId String roleId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @@unique([userId, roleId]) @@index([userId]) @@index([roleId]) } // Many-to-many: Role <-> Permission model RolePermission { id String @id @default(uuid()) roleId String permissionId String role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @@unique([roleId, permissionId]) @@index([roleId]) @@index([permissionId]) } // ============================================ // Authentication // ============================================ model RefreshToken { id String @id @default(uuid()) token String @unique userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) expiresAt DateTime createdAt DateTime @default(now()) @@index([token]) @@index([userId]) } // ============================================ // Multi-tenancy (Optional) // ============================================ model Tenant { id String @id @default(uuid()) name String slug String @unique isActive Boolean @default(true) // Relations users User[] // Timestamps & Soft Delete createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? @@index([slug]) } // ============================================ // i18n / Translations (Optional - DB driven) // ============================================ model Translation { id String @id @default(uuid()) key String locale String // e.g., "en", "tr", "de" value String namespace String @default("common") // e.g., "common", "errors", "validation" // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([key, locale, namespace]) @@index([key]) @@index([locale]) @@index([namespace]) } // ============================================ // CMS - Site Content Management // ============================================ model Project { id String @id @default(uuid()) title String image String roles String @default("[]") // JSON array stored as string for SQLite color String @default("#FF5733") sortOrder Int @default(0) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? // Soft delete support @@index([sortOrder]) } // ============================================ // Audit Log — CMS İşlem Kayıtları // ============================================ model AuditLog { id String @id @default(uuid()) entity String // "project", "client", "content", "media" entityId String // İlgili kaydın ID'si action String // "CREATE", "UPDATE", "DELETE", "RESTORE" before String? // JSON — önceki durum after String? // JSON — sonraki durum userId String? // İşlemi yapan kullanıcı ip String? // İstek IP'si createdAt DateTime @default(now()) @@index([entity, entityId]) @@index([action]) @@index([createdAt]) } model SiteContent { id String @id @default(uuid()) section String // "hero", "services", "process", "about", "contact", "footer", "navbar" locale String @default("tr") content String @default("{}") // JSON stored as string for SQLite createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([section, locale]) @@index([section]) @@index([locale]) } model MediaFile { id String @id @default(uuid()) filename String originalName String mimetype String path String url String size Int createdAt DateTime @default(now()) } model Client { id String @id @default(uuid()) name String logo String // URL to logo image website String? // Optional website URL sortOrder Int @default(0) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([sortOrder]) }