import { NextApiRequest, NextApiResponse } from 'next' import { prisma } from './prisma' import { Role } from '@prisma/client' import bcrypt from 'bcryptjs' import { v4 as uuid } from 'uuid' export const SESSION_COOKIE = 'qms_session' export const SESSION_EXPIRY_DAYS = 7 export async function hashPassword(password: string) { return bcrypt.hash(password, 12) } export async function verifyPassword(password: string, hash: string) { return bcrypt.compare(password, hash) } export async function createSession(userId: string) { const token = uuid() const expiresAt = new Date() expiresAt.setDate(expiresAt.getDate() + SESSION_EXPIRY_DAYS) await prisma.session.create({ data: { userId, token, expiresAt }, }) return token } export async function getSessionUser(req: NextApiRequest) { const token = req.cookies[SESSION_COOKIE] if (!token) return null const session = await prisma.session.findUnique({ where: { token }, include: { user: true }, }) if (!session || session.expiresAt < new Date()) { if (session) await prisma.session.delete({ where: { token } }) return null } return session.user } export async function requireAuth( req: NextApiRequest, res: NextApiResponse, allowedRoles?: Role[] ) { const user = await getSessionUser(req) if (!user || !user.active) { res.status(401).json({ error: 'Unauthorised' }) return null } if (allowedRoles && !allowedRoles.includes(user.role)) { res.status(403).json({ error: 'Forbidden' }) return null } return user } export async function logAction( userId: string, action: string, entity: string, entityId: string, before?: unknown, after?: unknown ) { await prisma.auditLog.create({ data: { userId, action, entity, entityId, before: before as any, after: after as any, }, }) } export function generateRef(prefix: string, count: number) { return `${prefix}-${String(count + 1).padStart(3, '0')}` } // Role permission helpers export const ROLE_PERMISSIONS: Record = { ADMIN: ['*'], QC: ['capa', 'audits', 'ncr', 'resolutions', 'documents', 'risk', 'suppliers', 'standards', 'shipping-standard', 'dashboard', 'reports', 'export'], PRODUCTION: ['fill', 'my-submissions', 'report-issue'], PRODUCTION_LEAD: ['fill', 'my-submissions', 'report-issue', 'shipments', 'escapes', 'shipping-standard', 'ncr', 'dashboard'], LOGISTICS_LEAD: ['shipments', 'escapes', 'shipping-standard', 'ncr', 'dashboard'], MANAGEMENT: ['dashboard', 'reports', 'export'], } as const // Only these roles may batch-email a client release package export const SHIPMENT_SEND_ROLES: Role[] = ['ADMIN', 'PRODUCTION_LEAD', 'LOGISTICS_LEAD'] export function canAccess(role: Role, module: string): boolean { const perms = ROLE_PERMISSIONS[role] return perms.includes('*') || perms.includes(module as any) }