import { boolean, foreignKey, index, jsonb, pgTable, text, timestamp, } from "drizzle-orm/pg-core"; import { type Organization, organizations, } from "../models/orgModels/orgTable.js"; export const user = pgTable( "user", { id: text("id").primaryKey(), name: text("name").notNull(), email: text("email").notNull().unique(), emailVerified: boolean("email_verified") .$defaultFn(() => false) .notNull(), image: text("image"), createdAt: timestamp("created_at", { withTimezone: true }) .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), updatedAt: timestamp("updated_at", { withTimezone: true }) .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), role: text("role"), banned: boolean("banned"), banReason: text("ban_reason"), banExpires: timestamp("ban_expires", { withTimezone: true }), createdBy: text("created_by"), lastActiveAt: timestamp("last_active_at", { withTimezone: true }), }, (table) => [ foreignKey({ columns: [table.createdBy], foreignColumns: [organizations.id], name: "user_created_by_fkey", }), ], ); export const session = pgTable( "session", { id: text("id").primaryKey(), expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), token: text("token").notNull().unique(), createdAt: timestamp("created_at", { withTimezone: true }).notNull(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(), ipAddress: text("ip_address"), userAgent: text("user_agent"), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), impersonatedBy: text("impersonated_by"), activeOrganizationId: text("active_organization_id"), city: text("city"), country: text("country"), }, (table) => [index("session_userId_idx").on(table.userId)], ).enableRLS(); export const account = pgTable( "account", { id: text("id").primaryKey(), accountId: text("account_id").notNull(), providerId: text("provider_id").notNull(), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), accessToken: text("access_token"), refreshToken: text("refresh_token"), idToken: text("id_token"), accessTokenExpiresAt: timestamp("access_token_expires_at"), refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), scope: text("scope"), password: text("password"), createdAt: timestamp("created_at", { withTimezone: true }).notNull(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(), }, (table) => [index("account_userId_idx").on(table.userId)], ).enableRLS(); export const verification = pgTable( "verification", { id: text("id").primaryKey(), identifier: text("identifier").notNull(), value: text("value").notNull(), expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), createdAt: timestamp("created_at", { withTimezone: true }).$defaultFn( () => /* @__PURE__ */ new Date(), ), updatedAt: timestamp("updated_at", { withTimezone: true }).$defaultFn( () => /* @__PURE__ */ new Date(), ), }, (table) => [index("verification_identifier_idx").on(table.identifier)], ).enableRLS(); export const member = pgTable( "member", { id: text("id").primaryKey(), organizationId: text("organization_id") .notNull() .references(() => organizations.id, { onDelete: "cascade" }), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), role: text("role").default("member").notNull(), createdAt: timestamp("created_at", { withTimezone: true }).notNull(), }, (table) => [ index("member_organizationId_idx").on(table.organizationId), index("member_userId_idx").on(table.userId), ], ).enableRLS(); export const invitation = pgTable( "invitation", { id: text("id").primaryKey(), organizationId: text("organization_id") .notNull() .references(() => organizations.id, { onDelete: "cascade" }), email: text("email").notNull(), role: text("role"), status: text("status").default("pending").notNull(), createdAt: timestamp("created_at", { withTimezone: true }) .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), inviterId: text("inviter_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), }, (table) => [ index("invitation_organizationId_idx").on(table.organizationId), index("invitation_email_idx").on(table.email), ], ).enableRLS(); // OAuth Provider tables export const jwks = pgTable("jwks", { id: text("id").primaryKey(), publicKey: text("public_key").notNull(), privateKey: text("private_key").notNull(), createdAt: timestamp("created_at", { withTimezone: true }).notNull(), expiresAt: timestamp("expires_at", { withTimezone: true }), }).enableRLS(); export const oauthClient = pgTable("oauth_client", { id: text("id").primaryKey(), clientId: text("client_id").notNull().unique(), clientSecret: text("client_secret"), disabled: boolean("disabled").default(false), skipConsent: boolean("skip_consent"), enableEndSession: boolean("enable_end_session"), scopes: text("scopes").array(), userId: text("user_id").references(() => user.id, { onDelete: "cascade" }), createdAt: timestamp("created_at", { withTimezone: true }), updatedAt: timestamp("updated_at", { withTimezone: true }), name: text("name"), uri: text("uri"), icon: text("icon"), contacts: text("contacts").array(), tos: text("tos"), policy: text("policy"), softwareId: text("software_id"), softwareVersion: text("software_version"), softwareStatement: text("software_statement"), redirectUris: text("redirect_uris").array().notNull(), postLogoutRedirectUris: text("post_logout_redirect_uris").array(), tokenEndpointAuthMethod: text("token_endpoint_auth_method"), grantTypes: text("grant_types").array(), responseTypes: text("response_types").array(), public: boolean("public"), type: text("type"), referenceId: text("reference_id"), metadata: jsonb("metadata"), }).enableRLS(); export const oauthRefreshToken = pgTable("oauth_refresh_token", { id: text("id").primaryKey(), token: text("token").notNull(), clientId: text("client_id") .notNull() .references(() => oauthClient.clientId, { onDelete: "cascade" }), sessionId: text("session_id").references(() => session.id, { onDelete: "set null", }), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), referenceId: text("reference_id"), expiresAt: timestamp("expires_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }), revoked: timestamp("revoked", { withTimezone: true }), scopes: text("scopes").array().notNull(), }).enableRLS(); export const oauthAccessToken = pgTable("oauth_access_token", { id: text("id").primaryKey(), token: text("token").unique(), clientId: text("client_id") .notNull() .references(() => oauthClient.clientId, { onDelete: "cascade" }), sessionId: text("session_id").references(() => session.id, { onDelete: "set null", }), userId: text("user_id").references(() => user.id, { onDelete: "cascade" }), referenceId: text("reference_id"), refreshId: text("refresh_id").references(() => oauthRefreshToken.id, { onDelete: "cascade", }), expiresAt: timestamp("expires_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }), scopes: text("scopes").array().notNull(), }).enableRLS(); export const oauthConsent = pgTable("oauth_consent", { id: text("id").primaryKey(), clientId: text("client_id") .notNull() .references(() => oauthClient.clientId, { onDelete: "cascade" }), userId: text("user_id").references(() => user.id, { onDelete: "cascade" }), referenceId: text("reference_id"), scopes: text("scopes").array().notNull(), createdAt: timestamp("created_at", { withTimezone: true }), updatedAt: timestamp("updated_at", { withTimezone: true }), }).enableRLS(); export const bannedUser = pgTable("banned_user", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), banReason: text("ban_reason"), banExpires: timestamp("ban_expires", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .$defaultFn(() => new Date()), revokedAt: timestamp("revoked_at", { withTimezone: true }), }).enableRLS(); export const authSchema = { user, session, account, verification, member, invitation, bannedUser, organizations, jwks, oauthClient, oauthRefreshToken, oauthAccessToken, oauthConsent, }; export type User = typeof user.$inferSelect; export type Member = typeof member.$inferSelect; export type Invite = typeof invitation.$inferSelect; export type BannedUser = typeof bannedUser.$inferSelect; export type FullInvite = Invite & { inviter: User; organization: Organization; };