- POST /auth/forgot-password with welcome/reset email templates - POST /auth/reset-password with Zod validation, 4-hour tokens - Per-email rate limiting (3/hr) via Valkey, no user enumeration - Login page "Forgot password?" toggle with inline form - /reset-password page for setting new password from email link - Initial user seed sends welcome email instead of requiring password - CLI script for force-resetting passwords via kubectl exec - APP_URL env var in chart, removed INITIAL_USER_PASSWORD Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
export const UserRole = z.enum(['admin', 'manager', 'staff', 'technician', 'instructor'])
|
|
export type UserRole = z.infer<typeof UserRole>
|
|
|
|
export const RegisterSchema = z.object({
|
|
email: z.string().email(),
|
|
password: z.string().min(12).max(128),
|
|
firstName: z.string().min(1).max(100),
|
|
lastName: z.string().min(1).max(100),
|
|
role: UserRole.default('staff'),
|
|
})
|
|
export type RegisterInput = z.infer<typeof RegisterSchema>
|
|
|
|
export const LoginSchema = z.object({
|
|
email: z.string().email(),
|
|
password: z.string().min(1),
|
|
})
|
|
export type LoginInput = z.infer<typeof LoginSchema>
|
|
|
|
export const PinLoginSchema = z.object({
|
|
code: z.string().min(8).max(10).regex(/^\d+$/, 'Code must be digits only'),
|
|
})
|
|
export type PinLoginInput = z.infer<typeof PinLoginSchema>
|
|
|
|
export const SetPinSchema = z.object({
|
|
pin: z.string().min(4).max(6).regex(/^\d+$/, 'PIN must be digits only'),
|
|
})
|
|
export type SetPinInput = z.infer<typeof SetPinSchema>
|
|
|
|
export const ForgotPasswordSchema = z.object({
|
|
email: z.string().email(),
|
|
})
|
|
export type ForgotPasswordInput = z.infer<typeof ForgotPasswordSchema>
|
|
|
|
export const ResetPasswordSchema = z.object({
|
|
token: z.string().min(1),
|
|
newPassword: z.string().min(12, 'Password must be at least 12 characters').max(128),
|
|
})
|
|
export type ResetPasswordInput = z.infer<typeof ResetPasswordSchema>
|