feat(db): add users, sessions_auth, auth_tokens tables

This commit is contained in:
2026-05-20 22:42:07 +02:00
parent ee7ca9187a
commit 7c5600cdef
4 changed files with 862 additions and 0 deletions

View File

@@ -78,8 +78,63 @@ export const attempts = sqliteTable(
})
);
export const users = sqliteTable(
'users',
{
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
displayName: text('display_name').notNull(),
passwordHash: text('password_hash'),
role: text('role', { enum: ['user', 'sysadmin'] }).notNull().default('user'),
isActive: integer('is_active', { mode: 'boolean' }).notNull().default(true),
emailVerifiedAt: integer('email_verified_at'),
pendingEmail: text('pending_email'),
createdAt: integer('created_at').notNull().default(sql`(unixepoch())`),
updatedAt: integer('updated_at').notNull().default(sql`(unixepoch())`),
},
(t) => ({ emailIdx: index('users_email_idx').on(t.email) })
);
export const sessionsAuth = sqliteTable(
'sessions_auth',
{
id: text('id').primaryKey(),
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
createdAt: integer('created_at').notNull().default(sql`(unixepoch())`),
expiresAt: integer('expires_at').notNull(),
lastUsedAt: integer('last_used_at').notNull().default(sql`(unixepoch())`),
userAgent: text('user_agent'),
ip: text('ip'),
},
(t) => ({
userIdx: index('sessions_auth_user_idx').on(t.userId),
expIdx: index('sessions_auth_expires_idx').on(t.expiresAt),
})
);
export const authTokens = sqliteTable(
'auth_tokens',
{
id: integer('id').primaryKey({ autoIncrement: true }),
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
tokenHash: text('token_hash').notNull(),
purpose: text('purpose', { enum: ['verify_email', 'password_reset', 'invite', 'change_email'] }).notNull(),
payload: text('payload'),
expiresAt: integer('expires_at').notNull(),
usedAt: integer('used_at'),
createdAt: integer('created_at').notNull().default(sql`(unixepoch())`),
},
(t) => ({
hashIdx: index('auth_tokens_hash_idx').on(t.tokenHash),
userPurposeIdx: index('auth_tokens_user_purpose_idx').on(t.userId, t.purpose),
})
);
export type LessonRow = typeof lessons.$inferSelect;
export type CardRow = typeof cards.$inferSelect;
export type CardProgressRow = typeof cardProgress.$inferSelect;
export type SessionRow = typeof sessions.$inferSelect;
export type AttemptRow = typeof attempts.$inferSelect;
export type UserRow = typeof users.$inferSelect;
export type SessionAuthRow = typeof sessionsAuth.$inferSelect;
export type AuthTokenRow = typeof authTokens.$inferSelect;