import { randomBytes, timingSafeEqual } from 'node:crypto';
import { ForbiddenError } from '../domain/errors.js';
import { getAuthorization } from '../services/rbac.js';
export function ensureCsrf(req, res, next) {
    req.session.csrfToken ??= randomBytes(32).toString('base64url');
    res.locals.csrfToken = req.session.csrfToken;
    next();
}
export function csrfProtection(req, _res, next) {
    if (['GET', 'HEAD', 'OPTIONS'].includes(req.method))
        return next();
    const supplied = String(req.get('X-CSRF-Token') ?? req.body?._csrf ?? '');
    const expected = req.session.csrfToken ?? '';
    const a = Buffer.from(supplied);
    const b = Buffer.from(expected);
    if (!a.length || a.length !== b.length || !timingSafeEqual(a, b))
        return next(new ForbiddenError('نشانه امنیتی فرم منقضی یا نامعتبر است. صفحه را تازه کنید.'));
    next();
}
export function loadCurrentUser(db) {
    return async (req, res, next) => {
        try {
            res.locals.currentPath = req.path;
            res.locals.flash = req.session.flash;
            delete req.session.flash;
            if (!req.session.userId)
                return next();
            const result = await db.query(`SELECT id, name, username, warehouse_id, force_password_change, session_version, active, archived_at
         FROM users WHERE id = $1`, [req.session.userId]);
            const row = result.rows[0];
            if (!row || !row.active || row.archived_at || row.session_version !== req.session.sessionVersion) {
                req.session.destroy(() => undefined);
                return next();
            }
            const auth = await getAuthorization(db, row.id);
            req.currentUser = {
                id: row.id, name: row.name, username: row.username, warehouseId: row.warehouse_id,
                forcePasswordChange: row.force_password_change, sessionVersion: row.session_version,
                roles: auth.roles, permissions: auth.permissions
            };
            res.locals.user = req.currentUser;
            res.locals.permissions = auth.permissions;
            next();
        }
        catch (error) {
            next(error);
        }
    };
}
export function requireAuth(req, res, next) {
    if (!req.currentUser)
        return res.redirect('/login');
    if (req.currentUser.forcePasswordChange && !['/password/force', '/logout'].includes(req.path))
        return res.redirect('/password/force');
    next();
}
export function requirePermission(permission) {
    return (req, _res, next) => {
        if (!req.currentUser)
            return next(new ForbiddenError());
        if (!req.currentUser.permissions.has(permission))
            return next(new ForbiddenError());
        next();
    };
}
export function setFlash(req, kind, message) {
    req.session.flash = { kind, message };
}
export function auditContext(req) {
    return {
        actorId: req.currentUser?.id ?? null,
        actorRole: req.currentUser?.roles.join(',') ?? null,
        ip: req.ip ?? null,
        userAgent: req.get('user-agent') ?? null
    };
}
//# sourceMappingURL=middleware.js.map