128 lines
3.7 KiB
Plaintext
128 lines
3.7 KiB
Plaintext
// Prisma Schema for EZBio - Modern URL Shortener & Link in Bio
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
name String
|
|
email String @unique
|
|
password String
|
|
role String @default("user") // "admin" | "user"
|
|
username String @unique
|
|
isActive Boolean @default(true)
|
|
emailVerified DateTime?
|
|
avatar String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
shortUrls ShortUrl[]
|
|
portal Portal?
|
|
uploadedFiles UploadedFile[]
|
|
|
|
@@map("users")
|
|
}
|
|
|
|
model ShortUrl {
|
|
id String @id @default(cuid())
|
|
originalUrl String
|
|
shortCode String @unique
|
|
title String?
|
|
password String? // bcrypt hash if password protected
|
|
expiresAt DateTime?
|
|
displayOnPortal Boolean @default(false)
|
|
clicksCount Int @default(0)
|
|
userId String?
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tags Tag[] @relation("ShortUrlTags")
|
|
clicks UrlClick[]
|
|
|
|
@@index([userId])
|
|
@@index([shortCode])
|
|
@@map("short_urls")
|
|
}
|
|
|
|
model Tag {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
shortUrls ShortUrl[] @relation("ShortUrlTags")
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("tags")
|
|
}
|
|
|
|
model UrlClick {
|
|
id String @id @default(cuid())
|
|
shortUrlId String
|
|
shortUrl ShortUrl @relation(fields: [shortUrlId], references: [id], onDelete: Cascade)
|
|
ipAddress String?
|
|
userAgent String?
|
|
deviceType String? // "desktop" | "mobile" | "tablet"
|
|
operatingSystem String?
|
|
browser String?
|
|
countryName String?
|
|
countryCode String?
|
|
city String?
|
|
referrer String?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([shortUrlId])
|
|
@@index([createdAt])
|
|
@@map("url_clicks")
|
|
}
|
|
|
|
model Portal {
|
|
id String @id @default(cuid())
|
|
userId String @unique
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
title String?
|
|
description String?
|
|
avatar String?
|
|
backgroundImage String?
|
|
headerColor String? @default("#000000")
|
|
titleColorStyle String? @default("gradient-1")
|
|
backgroundStyle String? @default("gradient-1")
|
|
vcard Json? // { fullName, phone, email, company, website }
|
|
socialLinks Json? // { facebook, twitter, instagram, threads, tiktok, youtube, telegram }
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("portals")
|
|
}
|
|
|
|
model Setting {
|
|
id String @id @default(cuid())
|
|
key String @unique
|
|
value String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("settings")
|
|
}
|
|
|
|
model UploadedFile {
|
|
id String @id @default(cuid())
|
|
key String @unique // Storage key or local filename
|
|
url String // Public URL or relative path
|
|
originalName String
|
|
mimeType String
|
|
sizeBytes BigInt // File size in bytes
|
|
category String // "avatar", "background", "logo", "favicon", "og_image"
|
|
storageType String @default("cloudflare_r2") // "cloudflare_r2" | "local"
|
|
userId String?
|
|
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([category])
|
|
@@map("uploaded_files")
|
|
}
|