import { createId } from '@paralleldrive/cuid2' import { boolean, pgTable, text, timestamp } from 'drizzle-orm/pg-core' /** * Better Auth core tables (`user`, `session`, `account`, `verification`) * stored in the application's own Postgres via Better Auth's Drizzle adapter. * Column names follow Better Auth's canonical Postgres schema; the admin * plugin adds `role`, `banned`, `banReason`, and `banExpires` to `user`. */ export const user = pgTable('user', { id: text('id').primaryKey(), name: text('name').notNull(), email: text('email').notNull().unique(), emailVerified: boolean('email_verified').default(false).notNull(), image: text('image'), role: text('role').default('user'), banned: boolean('banned').default(false), banReason: text('ban_reason'), banExpires: timestamp('ban_expires'), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull() }) export const session = pgTable('session', { id: text('id').primaryKey(), expiresAt: timestamp('expires_at').notNull(), token: text('token').notNull().unique(), createdAt: timestamp('created_at').notNull(), updatedAt: timestamp('updated_at').notNull(), ipAddress: text('ip_address'), userAgent: text('user_agent'), impersonatedBy: text('impersonated_by'), userId: text('user_id') .notNull() .references(() => user.id, { onDelete: 'cascade' }) }) 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').notNull(), updatedAt: timestamp('updated_at').notNull() }) export const verification = pgTable('verification', { id: text('id').primaryKey(), identifier: text('identifier').notNull(), value: text('value').notNull(), expiresAt: timestamp('expires_at').notNull(), createdAt: timestamp('created_at'), updatedAt: timestamp('updated_at') }) /** * Invitation tokens used when `AUTH_SIGNUP_MODE=invite`. An invitation is * redeemable when it is neither revoked, expired, nor already used. */ export const invitations = pgTable('invitations', { id: text('id') .primaryKey() .$defaultFn(() => createId()), email: text('email'), // SHA-256 hash of the invitation token; the plaintext only exists in the // link returned to the admin at creation time. token: text('token').notNull().unique(), invitedBy: text('invited_by').notNull(), revokedAt: timestamp('revoked_at'), usedAt: timestamp('used_at'), expiresAt: timestamp('expires_at').notNull(), createdAt: timestamp('created_at').defaultNow().notNull() })