mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 20:35:24 +00:00
* add deps * hook up dau from audit table to analytics page * add audit event for code nav * analytics dashboard * add changelog entry * add news entry * smaller video and news data nit * feedback
308 lines
7.5 KiB
Text
308 lines
7.5 KiB
Text
// 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 = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
enum RepoIndexingStatus {
|
||
NEW
|
||
IN_INDEX_QUEUE
|
||
INDEXING
|
||
INDEXED
|
||
FAILED
|
||
IN_GC_QUEUE
|
||
GARBAGE_COLLECTING
|
||
GARBAGE_COLLECTION_FAILED
|
||
}
|
||
|
||
enum ConnectionSyncStatus {
|
||
SYNC_NEEDED
|
||
IN_SYNC_QUEUE
|
||
SYNCING
|
||
SYNCED
|
||
SYNCED_WITH_WARNINGS
|
||
FAILED
|
||
}
|
||
|
||
enum StripeSubscriptionStatus {
|
||
ACTIVE
|
||
INACTIVE
|
||
}
|
||
|
||
model Repo {
|
||
id Int @id @default(autoincrement())
|
||
name String
|
||
displayName String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
/// When the repo was last indexed successfully.
|
||
indexedAt DateTime?
|
||
isFork Boolean
|
||
isArchived Boolean
|
||
metadata Json // For schema see repoMetadataSchema in packages/backend/src/types.ts
|
||
cloneUrl String
|
||
webUrl String?
|
||
connections RepoToConnection[]
|
||
imageUrl String?
|
||
repoIndexingStatus RepoIndexingStatus @default(NEW)
|
||
|
||
// The id of the repo in the external service
|
||
external_id String
|
||
// The type of the external service (e.g., github, gitlab, etc.)
|
||
external_codeHostType String
|
||
// The base url of the external service (e.g., https://github.com)
|
||
external_codeHostUrl String
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
searchContexts SearchContext[]
|
||
|
||
@@unique([external_id, external_codeHostUrl, orgId])
|
||
}
|
||
|
||
model SearchContext {
|
||
id Int @id @default(autoincrement())
|
||
|
||
name String
|
||
description String?
|
||
repos Repo[]
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
@@unique([name, orgId])
|
||
}
|
||
|
||
model Connection {
|
||
id Int @id @default(autoincrement())
|
||
name String
|
||
config Json
|
||
isDeclarative Boolean @default(false)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
/// When the connection was last synced successfully.
|
||
syncedAt DateTime?
|
||
repos RepoToConnection[]
|
||
syncStatus ConnectionSyncStatus @default(SYNC_NEEDED)
|
||
syncStatusMetadata Json?
|
||
|
||
// The type of connection (e.g., github, gitlab, etc.)
|
||
connectionType String
|
||
|
||
// The organization that owns this connection
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
@@unique([name, orgId])
|
||
}
|
||
|
||
model RepoToConnection {
|
||
addedAt DateTime @default(now())
|
||
|
||
connection Connection @relation(fields: [connectionId], references: [id], onDelete: Cascade)
|
||
connectionId Int
|
||
|
||
repo Repo @relation(fields: [repoId], references: [id], onDelete: Cascade)
|
||
repoId Int
|
||
|
||
@@id([connectionId, repoId])
|
||
}
|
||
|
||
model Invite {
|
||
/// The globally unique invite id
|
||
id String @id @default(cuid())
|
||
|
||
/// Time of invite creation
|
||
createdAt DateTime @default(now())
|
||
|
||
/// The email of the recipient of the invite
|
||
recipientEmail String
|
||
|
||
/// The user that created the invite
|
||
host User @relation(fields: [hostUserId], references: [id], onDelete: Cascade)
|
||
hostUserId String
|
||
|
||
/// The organization the invite is for
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
@@unique([recipientEmail, orgId])
|
||
}
|
||
|
||
model AccountRequest {
|
||
id String @id @default(cuid())
|
||
|
||
createdAt DateTime @default(now())
|
||
|
||
requestedBy User @relation(fields: [requestedById], references: [id], onDelete: Cascade)
|
||
requestedById String @unique
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
@@unique([requestedById, orgId])
|
||
}
|
||
|
||
model Org {
|
||
id Int @id @default(autoincrement())
|
||
name String
|
||
domain String @unique
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
members UserToOrg[]
|
||
connections Connection[]
|
||
repos Repo[]
|
||
secrets Secret[]
|
||
apiKeys ApiKey[]
|
||
isOnboarded Boolean @default(false)
|
||
imageUrl String?
|
||
metadata Json? // For schema see orgMetadataSchema in packages/web/src/types.ts
|
||
|
||
stripeCustomerId String?
|
||
stripeSubscriptionStatus StripeSubscriptionStatus?
|
||
stripeLastUpdatedAt DateTime?
|
||
|
||
/// List of pending invites to this organization
|
||
invites Invite[]
|
||
|
||
audits Audit[]
|
||
|
||
accountRequests AccountRequest[]
|
||
|
||
searchContexts SearchContext[]
|
||
}
|
||
|
||
enum OrgRole {
|
||
OWNER
|
||
MEMBER
|
||
GUEST
|
||
}
|
||
|
||
model UserToOrg {
|
||
joinedAt DateTime @default(now())
|
||
|
||
/// The linked organization
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
/// The linked user
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
userId String
|
||
|
||
role OrgRole @default(MEMBER)
|
||
|
||
@@id([orgId, userId])
|
||
}
|
||
|
||
model Secret {
|
||
orgId Int
|
||
key String
|
||
encryptedValue String
|
||
iv String
|
||
|
||
createdAt DateTime @default(now())
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
|
||
@@id([orgId, key])
|
||
}
|
||
|
||
model ApiKey {
|
||
name String
|
||
hash String @id @unique
|
||
|
||
createdAt DateTime @default(now())
|
||
lastUsedAt DateTime?
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
createdBy User @relation(fields: [createdById], references: [id], onDelete: Cascade)
|
||
createdById String
|
||
|
||
}
|
||
|
||
model Audit {
|
||
id String @id @default(cuid())
|
||
timestamp DateTime @default(now())
|
||
|
||
action String
|
||
actorId String
|
||
actorType String
|
||
targetId String
|
||
targetType String
|
||
sourcebotVersion String
|
||
metadata Json?
|
||
|
||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
orgId Int
|
||
|
||
@@index([actorId, actorType, targetId, targetType, orgId])
|
||
|
||
// Fast path for analytics queries – orgId is first because we assume most deployments are single tenant
|
||
@@index([orgId, timestamp, action, actorId], map: "idx_audit_core_actions_full")
|
||
|
||
// Fast path for analytics queries for a specific user
|
||
@@index([actorId, timestamp], map: "idx_audit_actor_time_full")
|
||
}
|
||
|
||
// @see : https://authjs.dev/concepts/database-models#user
|
||
model User {
|
||
id String @id @default(cuid())
|
||
name String?
|
||
email String? @unique
|
||
hashedPassword String?
|
||
emailVerified DateTime?
|
||
image String?
|
||
accounts Account[]
|
||
orgs UserToOrg[]
|
||
pendingApproval Boolean @default(true)
|
||
accountRequest AccountRequest?
|
||
|
||
/// List of pending invites that the user has created
|
||
invites Invite[]
|
||
|
||
apiKeys ApiKey[]
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
}
|
||
|
||
// @see : https://authjs.dev/concepts/database-models#account
|
||
model Account {
|
||
id String @id @default(cuid())
|
||
userId String
|
||
type String
|
||
provider String
|
||
providerAccountId String
|
||
refresh_token String?
|
||
access_token String?
|
||
expires_at Int?
|
||
token_type String?
|
||
scope String?
|
||
id_token String?
|
||
session_state String?
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([provider, providerAccountId])
|
||
}
|
||
|
||
// @see : https://authjs.dev/concepts/database-models#verificationtoken
|
||
model VerificationToken {
|
||
identifier String
|
||
token String
|
||
expires DateTime
|
||
|
||
@@unique([identifier, token])
|
||
}
|