feat: initial scaffold - backend, frontend, Prisma schema, Docker
- Prisma schema: User, Session, RepoConfig, Preview, Job, WebhookToken, NoConfigComment, AdminSettings - Backend: auth (login/logout/me/first-user setup), webhook handler with HMAC verification, EC2 service, SSH service, deploy pipeline, job queue worker, cron workers - Frontend: Login with first-user detection, Dashboard, PreviewDetail with live log streaming, Settings, Repos config, Admin panel, SetupWizard, Privacy page - Docker Compose and Dockerfile for self-hosted deployment - Uses bcryptjs for Node 24 compatibility Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum PreviewStatus {
|
||||
PROVISIONING
|
||||
BUILDING
|
||||
RUNNING
|
||||
FAILED
|
||||
STOPPED
|
||||
IGNORED
|
||||
}
|
||||
|
||||
enum JobType {
|
||||
DEPLOY
|
||||
STOP
|
||||
INACTIVITY_STOP
|
||||
}
|
||||
|
||||
enum JobStatus {
|
||||
PENDING
|
||||
RUNNING
|
||||
DONE
|
||||
FAILED
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(128)
|
||||
passwordHash String @db.VarChar(256)
|
||||
isAdmin Boolean @default(false)
|
||||
isFounder Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
giteaUsername String? @db.VarChar(128)
|
||||
giteaPAT String? @db.Text
|
||||
giteaInstanceUrl String? @db.VarChar(512)
|
||||
|
||||
awsAccessKeyId String? @db.VarChar(256)
|
||||
awsSecretAccessKey String? @db.Text
|
||||
awsRegion String? @db.VarChar(64)
|
||||
|
||||
sessions Session[]
|
||||
repoConfigs RepoConfig[]
|
||||
webhookToken WebhookToken?
|
||||
noConfigComments NoConfigComment[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id Int @id @default(autoincrement())
|
||||
hash String @db.VarChar(512)
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model RepoConfig {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
repoOwner String @db.VarChar(128)
|
||||
repoName String @db.VarChar(128)
|
||||
isEnabled Boolean @default(false)
|
||||
|
||||
giteaWebhookId String? @db.VarChar(128)
|
||||
|
||||
denyList String[]
|
||||
instanceType String @default("t2.medium") @db.VarChar(64)
|
||||
inactivityHours Float @default(12)
|
||||
port Int @default(3000)
|
||||
envVars Json @default("{}")
|
||||
useDockerCompose Boolean @default(false)
|
||||
composeFilePath String? @db.VarChar(512)
|
||||
aptPackages String[]
|
||||
setupCommands String[]
|
||||
buildCommands String[]
|
||||
postBuildCommands String[]
|
||||
runCommand String? @db.Text
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
previews Preview[]
|
||||
|
||||
@@unique([repoOwner, repoName])
|
||||
}
|
||||
|
||||
model Preview {
|
||||
id Int @id @default(autoincrement())
|
||||
repoConfigId Int
|
||||
repoConfig RepoConfig @relation(fields: [repoConfigId], references: [id], onDelete: Cascade)
|
||||
prNumber Int
|
||||
prTitle String @db.VarChar(512)
|
||||
commitSha String @db.VarChar(64)
|
||||
instanceId String? @db.VarChar(64)
|
||||
instanceIp String? @db.VarChar(64)
|
||||
port Int @default(3000)
|
||||
status PreviewStatus @default(PROVISIONING)
|
||||
logs String @default("") @db.Text
|
||||
pid Int?
|
||||
sshPrivateKey String? @db.Text
|
||||
sshKeyName String? @db.VarChar(128)
|
||||
giteaCommentId Int?
|
||||
lastActivityAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
stoppedAt DateTime?
|
||||
|
||||
jobs Job[]
|
||||
}
|
||||
|
||||
model Job {
|
||||
id Int @id @default(autoincrement())
|
||||
previewId Int?
|
||||
preview Preview? @relation(fields: [previewId], references: [id], onDelete: Cascade)
|
||||
type JobType
|
||||
status JobStatus @default(PENDING)
|
||||
payload Json @default("{}")
|
||||
error String? @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
startedAt DateTime?
|
||||
finishedAt DateTime?
|
||||
}
|
||||
|
||||
model WebhookToken {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @unique
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
token String @db.VarChar(256)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model NoConfigComment {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
repoOwner String @db.VarChar(128)
|
||||
repoName String @db.VarChar(128)
|
||||
prNumber Int
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([userId, repoOwner, repoName, prNumber])
|
||||
}
|
||||
|
||||
model AdminSettings {
|
||||
id Int @id @default(1)
|
||||
defaultInstanceType String @default("t2.medium") @db.VarChar(64)
|
||||
maxConcurrentInstancesPerUser Int @default(5)
|
||||
logSizeLimitBytes Int @default(1048576)
|
||||
previewRetentionDays Int @default(30)
|
||||
webhookRateLimitPerMinute Int @default(10)
|
||||
contactEmail String @default("") @db.VarChar(256)
|
||||
}
|
||||
Reference in New Issue
Block a user