Newer
Older
express-blog / src / middleware / setPolicy.js
const { evaluateRules } = require("../utils/evaluateRules.js");
const { handleRedirect } = require("./redirect.js");

/**
 * Route-level policy enforcement middleware.
 * @param {Object} config - { policy: "allow"|"deny"|"deny-children", rules: Array }
 */
function setPolicy(config) {
  return (req, res, next) => {
    const session = res.locals.session || {
      isAuthenticated: false,
      groups: [],
      user: null,
    };
    // return res.json(session);
    const policy = config.policy || "allow";
    const rules = config.rules || [];
    const redirectTarget = config.redirectOnFail || "/";

    // 1. "allow" and "deny-children" permit access to the route itself
    if (policy === "allow" || policy === "deny-children") {
      return next();
    }

    // 2. "deny" requires authentication AND passing the rule set
    if (policy === "deny") {
      if (session.isAuthenticated && evaluateRules(rules, session)) {
        return next();
      }

      // Log the rejection for audit trails
      if (req.log) {
        req.log.warn(
          { user: session.user, policy, rules },
          "Access Denied by Policy",
        );
      }

      // CASE: User is not logged in - Redirect to OIDC Login
      if (!session.isAuthenticated) {
        req.log.warn("REDIRECT " + JSON.stringify(session));
        return handleRedirect(req, res, "/guest-access", 302);
      }

      // CASE: User is logged in but lacks permissions - Redirect to target (or 403 page)
      return handleRedirect(req, res, redirectTarget, 302);
    }

    // Default safety: Fail closed
    res.status(403).send("Security Policy Violation");
  };
}

module.exports = setPolicy;