27 lines
1.5 KiB
JavaScript
27 lines
1.5 KiB
JavaScript
// lib/httpUtils.js
|
|
// Admin guard -- JSON-aware (ARCHITECTURE.md 6.4, folded review fix)
|
|
//
|
|
// Uniform error envelope: { error: { code, message, ...context } }, where
|
|
// code in { forbidden, not_found, version_conflict, name_taken, active_theme,
|
|
// builtin_immutable, bad_format, too_large, uncompilable,
|
|
// bad_request, compile_failed, activation_failed, initializing }.
|
|
const db = require("@saltcorn/data/db");
|
|
const { ROLE_ADMIN, API_BASE } = require("./constants");
|
|
|
|
function isAdminReq(req) { // mirror core isAdmin (utils.js:85-100)
|
|
return !!(req.user && req.user.role_id === ROLE_ADMIN && req.user.tenant === db.getTenantSchema());
|
|
}
|
|
function wantsJson(req) {
|
|
return req.xhr
|
|
|| (req.path || "").startsWith(API_BASE) // API routes ALWAYS answer JSON (fixes multipart-import misclassify)
|
|
|| (req.get("accept") || "").includes("application/json")
|
|
|| (req.get("content-type") || "").includes("application/json");
|
|
}
|
|
function guardAdmin(req, res) {
|
|
if (isAdminReq(req)) return true;
|
|
if (wantsJson(req)) res.status(req.user ? 403 : 401).json({ error: { code: "forbidden", message: "Must be admin" } });
|
|
else res.redirect(req.user ? "/" : `/auth/login?dest=${encodeURIComponent(req.originalUrl)}`);
|
|
return false;
|
|
}
|
|
function jsonError(res, status, code, message, extra) { res.status(status).json({ error: { code, message, ...(extra || {}) } }); }
|
|
module.exports = { isAdminReq, wantsJson, guardAdmin, jsonError };
|