- Add employeeNumber and pinHash fields to users table - POST /auth/pin-login: takes combined code (4-digit employee# + 4-digit PIN) - POST /auth/set-pin: employee sets their own PIN (requires full auth) - DELETE /auth/pin: remove PIN - Lock screen with numpad, auto-submits on 8 digits, visual dot separator - POS uses its own auth token separate from admin session - Admin "POS" link clears admin session before navigating - /pos route has no auth guard — lock screen is the auth - API client uses POS token when available, admin token otherwise - Auto-lock timer reads pos_lock_timeout from app_config (default 15 min) - Lock button in POS top bar, shows current cashier name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
27 lines
1.0 KiB
TypeScript
27 lines
1.0 KiB
TypeScript
import { pgTable, uuid, varchar, timestamp, pgEnum, boolean } from 'drizzle-orm/pg-core'
|
|
|
|
export const userRoleEnum = pgEnum('user_role', [
|
|
'admin',
|
|
'manager',
|
|
'staff',
|
|
'technician',
|
|
'instructor',
|
|
])
|
|
|
|
export const users = pgTable('user', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
email: varchar('email', { length: 255 }).notNull().unique(),
|
|
passwordHash: varchar('password_hash', { length: 255 }).notNull(),
|
|
firstName: varchar('first_name', { length: 100 }).notNull(),
|
|
lastName: varchar('last_name', { length: 100 }).notNull(),
|
|
role: userRoleEnum('role').notNull().default('staff'),
|
|
employeeNumber: varchar('employee_number', { length: 20 }).unique(),
|
|
pinHash: varchar('pin_hash', { length: 255 }),
|
|
isActive: boolean('is_active').notNull().default(true),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export type User = typeof users.$inferSelect
|
|
export type UserInsert = typeof users.$inferInsert
|