sourcebot/packages/db/prisma/schema.prisma
Michael Sukkarieh 60a3528394
V4 (#311)
Sourcebot V4 introduces authentication, performance improvements and code navigation. Checkout the [migration guide](https://docs.sourcebot.dev/self-hosting/upgrade/v3-to-v4-guide) for information on upgrading your instance to v4.

### Changed
- [**Breaking Change**] Authentication is now required by default. Notes:
  - When setting up your instance, email / password login will be the default authentication provider.
  - The first user that logs into the instance is given the `owner` role. ([docs](https://docs.sourcebot.dev/docs/more/roles-and-permissions)).
  - Subsequent users can request to join the instance. The `owner` can approve / deny requests to join the instance via `Settings` > `Members` > `Pending Requests`.
  - If a user is approved to join the instance, they are given the `member` role.
  - Additional login providers, including email links and SSO, can be configured with additional environment variables. ([docs](https://docs.sourcebot.dev/self-hosting/configuration/authentication)).
- Clicking on a search result now takes you to the `/browse` view. Files can still be previewed by clicking the "Preview" button or holding `Cmd` / `Ctrl` when clicking on a search result. [#315](https://github.com/sourcebot-dev/sourcebot/pull/315)

### Added
- [Sourcebot EE] Added search-based code navigation, allowing you to jump between symbol definition and references when viewing source files. [Read the documentation](https://docs.sourcebot.dev/docs/search/code-navigation). [#315](https://github.com/sourcebot-dev/sourcebot/pull/315)
- Added collapsible filter panel. [#315](https://github.com/sourcebot-dev/sourcebot/pull/315)

### Fixed
- Improved scroll performance for large numbers of search results. [#315](https://github.com/sourcebot-dev/sourcebot/pull/315)
2025-05-28 16:08:42 -07:00

282 lines
6.8 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[]
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
}
// @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])
}