import { integer, json, pgTable, text, timestamp, varchar, } from "drizzle-orm/pg-core"; import { user } from "./better.auth.schema"; import { relations } from "drizzle-orm"; export const twoFactor = pgTable("two_factor", { id: text("id").primaryKey(), secret: text("secret").notNull(), backupCodes: json("backup_codes").$type(), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), createdAt: timestamp("created_at").notNull(), updatedAt: timestamp("updated_at").notNull(), }); export const twofaSessions = pgTable("twofa_sessions", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), sessionId: text("session_id").notNull(), // Better Auth session ID // Verification Tracking verificationToken: text("verification_token").notNull().unique(), // Unique nonce for this attempt codeUsed: text("code_used"), // The TOTP code submitted (prevent replay) status: varchar("status", { length: 16 }).notNull(), // "pending" | "verified" | "failed" | "expired" attempts: integer("attempts").default(0).notNull(), maxAttempts: integer("max_attempts").default(5).notNull(), verifiedAt: timestamp("verified_at"), expiresAt: timestamp("expires_at").notNull(), createdAt: timestamp("created_at").notNull(), // Security Audit ipAddress: text("ip_address").default(""), userAgent: text("user_agent").default(""), }); export const twofaSessionsRelations = relations(twofaSessions, ({ one }) => ({ userAccount: one(user, { fields: [twofaSessions.userId], references: [user.id], }), }));