calcom/prisma/schema.prisma
Deepak Prabhakara 1a20b0a0c6
Add log in with Google and SAML (#1192)
* Add log in with Google

* Fix merge conflicts

* Merge branch 'main' into feature/copy-add-identity-provider

# Conflicts:
#	pages/api/auth/[...nextauth].tsx
#	pages/api/auth/forgot-password.ts
#	pages/settings/security.tsx
#	prisma/schema.prisma
#	public/static/locales/en/common.json

* WIP: SAML login

* fixed login

* fixed verified_email check for Google

* tweaks to padding

* added BoxyHQ SAML service to local docker-compose

* identityProvider is missing from the select clause

* user may be undefined

* fix for yarn build

* Added SAML configuration to Settings -> Security page

* UI tweaks

* get saml login flag from the server

* UI tweaks

* moved SAMLConfiguration to a component in ee

* updated saml migration date

* fixed merge conflict

* fixed merge conflict

* lint fixes

* check-types fixes

* check-types fixes

* fixed type errors

* updated docker image for SAML Jackson

* added api keys config

* added default values for SAML_TENANT_ID and SAML_PRODUCT_ID

* - move all env vars related to saml into a separate file for easy access
- added SAML_ADMINS comma separated list of emails that will be able to configure the SAML metadata

* cleanup after merging main

* revert mistake during merge

* revert mistake during merge

* set info text to indicate SAML has been configured.

* tweaks to text

* tweaks to text

* i18n text

* i18n text

* tweak

* use a separate db for saml to avoid Prisma schema being out of sync

* use separate docker-compose file for saml

* padding tweak

* Prepare for implementing SAML login for the hosted solution

* WIP: Support for SAML in the hosted solution

* teams view has changed, adjusting saml changes accordingly

* enabled SAML only for PRO plan

* if user was invited and signs in via saml/google then update the user record

* WIP: embed saml lib

* 302 instead of 307

* no separate docker-compose file for saml

* - ogs cleanup
- type fixes

* fixed types for jackson

* cleaned up cors, not needed by the oauth flow

* updated jackson to support encryption at rest

* updated saml-jackson lib

* allow only the required http methods

* fixed issue with latest merge with main

* - Added instructions for deploying SAML support
- Tweaked SAML audience identifier

* fixed check for hosted Cal instance

* Added a new route to initiate Google and SAML login flows

* updated saml-jackson lib (node engine version is now 14.x or above)

* moved SAML instructions from Google Docs to a docs file

* moved randomString to lib

* comment SAML_DATABASE_URL and SAML_ADMINS in .env.example so that default is SAML off.

* fixed path to randomString

* updated @boxyhq/saml-jackson to v0.3.0

* fixed TS errors

* tweaked SAML config UI

* fixed types

* added e2e test for Google login

* setup secrets for Google login test

* test for OAuth login buttons (Google and SAML)

* enabled saml for the test

* added test for SAML config UI

* fixed nextauth import

* use pkce flow

* tweaked NextAuth config for saml

* updated saml-jackson

* added ability to delete SAML configuration

* SAML variables explainers and refactoring

* Prevents constant collision

* Var name changes

* Env explainers

* better validation for email

Co-authored-by: Omar López <zomars@me.com>

* enabled GOOGLE_API_CREDENTIALS in e2e tests (Github Actions secret)

* cleanup (will create an issue to handle forgot password for Google and SAML identities)

Co-authored-by: Chris <76668588+bytesbuffer@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
2022-01-13 20:05:23 +00:00

338 lines
9.8 KiB
Text

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
enum SchedulingType {
ROUND_ROBIN @map("roundRobin")
COLLECTIVE @map("collective")
}
enum PeriodType {
UNLIMITED @map("unlimited")
ROLLING @map("rolling")
RANGE @map("range")
}
model EventType {
id Int @id @default(autoincrement())
title String
slug String
description String?
position Int @default(0)
locations Json?
length Int
hidden Boolean @default(false)
users User[] @relation("user_eventtype")
userId Int?
team Team? @relation(fields: [teamId], references: [id])
teamId Int?
bookings Booking[]
availability Availability[]
destinationCalendar DestinationCalendar[]
eventName String?
customInputs EventTypeCustomInput[]
timeZone String?
periodType PeriodType @default(UNLIMITED)
periodStartDate DateTime?
periodEndDate DateTime?
periodDays Int?
periodCountCalendarDays Boolean?
requiresConfirmation Boolean @default(false)
disableGuests Boolean @default(false)
minimumBookingNotice Int @default(120)
schedulingType SchedulingType?
Schedule Schedule[]
price Int @default(0)
currency String @default("usd")
slotInterval Int?
@@unique([userId, slug])
}
model Credential {
id Int @id @default(autoincrement())
type String
key Json
user User? @relation(fields: [userId], references: [id])
userId Int?
}
enum UserPlan {
FREE
TRIAL
PRO
}
enum IdentityProvider {
CAL
GOOGLE
SAML
}
model DestinationCalendar {
id Int @id @default(autoincrement())
integration String
externalId String
user User? @relation(fields: [userId], references: [id])
userId Int? @unique
booking Booking? @relation(fields: [bookingId], references: [id])
bookingId Int? @unique
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int? @unique
}
model User {
id Int @id @default(autoincrement())
username String? @unique
name String?
email String @unique
emailVerified DateTime?
password String?
bio String?
avatar String?
timeZone String @default("Europe/London")
weekStart String @default("Sunday")
// DEPRECATED - TO BE REMOVED
startTime Int @default(0)
endTime Int @default(1440)
// </DEPRECATED>
bufferTime Int @default(0)
hideBranding Boolean @default(false)
theme String?
createdDate DateTime @default(now()) @map(name: "created")
eventTypes EventType[] @relation("user_eventtype")
credentials Credential[]
teams Membership[]
bookings Booking[]
availability Availability[]
selectedCalendars SelectedCalendar[]
completedOnboarding Boolean @default(false)
locale String?
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
identityProvider IdentityProvider @default(CAL)
identityProviderId String?
invitedTo Int?
plan UserPlan @default(PRO)
Schedule Schedule[]
webhooks Webhook[]
brandColor String @default("#292929")
// the location where the events will end up
destinationCalendar DestinationCalendar?
away Boolean @default(false)
metadata Json?
@@map(name: "users")
}
model Team {
id Int @id @default(autoincrement())
name String?
slug String? @unique
logo String?
bio String?
hideBranding Boolean @default(false)
members Membership[]
eventTypes EventType[]
}
enum MembershipRole {
MEMBER
ADMIN
OWNER
}
model Membership {
teamId Int
userId Int
accepted Boolean @default(false)
role MembershipRole
team Team @relation(fields: [teamId], references: [id])
user User @relation(fields: [userId], references: [id])
@@id([userId, teamId])
}
model VerificationRequest {
id Int @id @default(autoincrement())
identifier String
token String @unique
expires DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([identifier, token])
}
model BookingReference {
id Int @id @default(autoincrement())
type String
uid String
meetingId String?
meetingPassword String?
meetingUrl String?
booking Booking? @relation(fields: [bookingId], references: [id])
bookingId Int?
}
model Attendee {
id Int @id @default(autoincrement())
email String
name String
timeZone String
booking Booking? @relation(fields: [bookingId], references: [id])
bookingId Int?
}
enum BookingStatus {
CANCELLED @map("cancelled")
ACCEPTED @map("accepted")
REJECTED @map("rejected")
PENDING @map("pending")
}
model DailyEventReference {
id Int @id @default(autoincrement())
dailyurl String @default("dailycallurl")
dailytoken String @default("dailytoken")
booking Booking? @relation(fields: [bookingId], references: [id])
bookingId Int?
}
model Booking {
id Int @id @default(autoincrement())
uid String @unique
user User? @relation(fields: [userId], references: [id])
userId Int?
references BookingReference[]
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
title String
description String?
startTime DateTime
endTime DateTime
attendees Attendee[]
location String?
dailyRef DailyEventReference?
createdAt DateTime @default(now())
updatedAt DateTime?
confirmed Boolean @default(true)
rejected Boolean @default(false)
status BookingStatus @default(ACCEPTED)
paid Boolean @default(false)
payment Payment[]
destinationCalendar DestinationCalendar?
}
model Schedule {
id Int @id @default(autoincrement())
user User? @relation(fields: [userId], references: [id])
userId Int?
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
title String?
freeBusyTimes Json?
}
model Availability {
id Int @id @default(autoincrement())
label String?
user User? @relation(fields: [userId], references: [id])
userId Int?
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
days Int[]
startTime DateTime @db.Time
endTime DateTime @db.Time
date DateTime? @db.Date
}
model SelectedCalendar {
user User @relation(fields: [userId], references: [id])
userId Int
integration String
externalId String
@@id([userId, integration, externalId])
}
enum EventTypeCustomInputType {
TEXT @map("text")
TEXTLONG @map("textLong")
NUMBER @map("number")
BOOL @map("bool")
}
model EventTypeCustomInput {
id Int @id @default(autoincrement())
eventTypeId Int
eventType EventType @relation(fields: [eventTypeId], references: [id])
label String
type EventTypeCustomInputType
required Boolean
placeholder String @default("")
}
model ResetPasswordRequest {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String
expires DateTime
}
enum ReminderType {
PENDING_BOOKING_CONFIRMATION
}
model ReminderMail {
id Int @id @default(autoincrement())
referenceId Int
reminderType ReminderType
elapsedMinutes Int
createdAt DateTime @default(now())
}
enum PaymentType {
STRIPE
}
model Payment {
id Int @id @default(autoincrement())
uid String @unique
type PaymentType
bookingId Int
booking Booking? @relation(fields: [bookingId], references: [id])
amount Int
fee Int
currency String
success Boolean
refunded Boolean
data Json
externalId String @unique
}
enum WebhookTriggerEvents {
BOOKING_CREATED
BOOKING_RESCHEDULED
BOOKING_CANCELLED
}
model Webhook {
id String @id @unique
userId Int
subscriberUrl String
payloadTemplate String?
createdAt DateTime @default(now())
active Boolean @default(true)
eventTriggers WebhookTriggerEvents[]
user User @relation(fields: [userId], references: [id])
}