You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
35 lines
1.5 KiB
35 lines
1.5 KiB
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
|
|
export const users = sqliteTable("users", {
|
|
id: integer().primaryKey().autoincrement(),
|
|
username: text().notNull().unique(),
|
|
email: text(), // unique index added via migration
|
|
nickname: text(),
|
|
password: text().notNull(),
|
|
avatar: text(),
|
|
role: text().notNull().default("user"),
|
|
status: text().notNull().default("active"),
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
|
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
|
|
.defaultNow()
|
|
.$onUpdate(() => new Date())
|
|
.notNull(),
|
|
// --- auth fields ---
|
|
emailVerified: integer("email_verified", { mode: "boolean" }).default(false).notNull(),
|
|
passwordHistory: text("password_history").default("[]").notNull(),
|
|
failedLoginAttempts: integer("failed_login_attempts").default(0).notNull(),
|
|
lockoutUntil: integer("lockout_until", { mode: "timestamp_ms" }),
|
|
lastLoginAt: integer("last_login_at", { mode: "timestamp_ms" }),
|
|
lastLoginIp: text("last_login_ip"),
|
|
});
|
|
|
|
export const userSessions = sqliteTable("user_sessions", {
|
|
id: text().primaryKey(),
|
|
userId: integer("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
refreshTokenHash: text("refresh_token_hash").notNull(),
|
|
userAgent: text("user_agent"),
|
|
ip: text(),
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
|
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
|
revokedAt: integer("revoked_at", { mode: "timestamp_ms" }),
|
|
});
|