import crypto from 'node:crypto';
export function createResetToken() {
const token = crypto.randomBytes(32).toString('hex');
const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
const expiresAt = new Date(Date.now() + 30 * 60 * 1000);
import { withClient } from '../db/pool';
export async function findUserByEmail(email: string) {
return withClient(async (client) => {
const res = await client.query('SELECT id, email, name FROM users WHERE email = $1', [email]);
return res.rows[0] ?? null;
import type { RequestHandler } from 'express';
export const csp: RequestHandler = (_req, res, next) => {
const policy = [
"default-src 'self'",
"base-uri 'self'",
import { z } from 'zod';
const toInt = (v: unknown) => (typeof v === 'string' ? Number(v) : v);
export const ListQuery = z.object({
limit: z.preprocess(toInt, z.number().int().min(1).max(100)).default(20),