Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const Form = require("@saltcorn/data/models/form");
const File = require("@saltcorn/data/models/file");
const Plugin = require("@saltcorn/data/models/plugin");
const db = require("@saltcorn/data/db");
const { getState } = require("@saltcorn/data/db/state");
const { getState, features } = require("@saltcorn/data/db/state");
const { spawn } = require("child_process");
const fs = require("fs").promises;
const path = require("path");
Expand Down Expand Up @@ -250,12 +250,30 @@ const configuration_workflow = () =>
],
});

// Only admins may trigger a rebuild of the main bundle. Uses the centralized
// authorize_api hook when the running core supports it (features.authorize_access_hooks),
// falling back to a plain role check on older cores.
const isRunBuildAuthorized = async (req) => {
if (features?.authorize_access_hooks) {
return await getState().authorizeApi(req.user, {
route: "react/run_build",
action: "post",
req,
});
}
return !!(req.user && req.user.role_id <= 1);
};

const routes = ({ app_code_source, app_code_path, sc_folder, build_mode }) => {
return [
{
url: "/react/run_build",
method: "post",
callback: async (req, res) => {
if (!(await isRunBuildAuthorized(req))) {
res.status(401).json({ error: "Not authorized" });
return;
}
getState().log(5, "Building your React code");
getState().log(
6,
Expand Down Expand Up @@ -297,6 +315,32 @@ module.exports = {
plugin_name: "react",
configuration_workflow,
routes,
authorize_api: (cfg) => async (request, user) => {
if (request.route !== "react/run_build") return null;
return user && user.role_id <= 1
? { decision: "allow" }
: {
decision: "deny",
reason: "Only admins may rebuild the React bundle",
};
},
// Gates the "React" viewtemplate's build_user_code route (react_view.js) -
// only admins may rebuild a view's per-view bundle. Scoped to that one
// route so it never weighs in on the view's regular get/post rendering.
authorize_view: (cfg) => async (request, user) => {
if (
request.action !== "post" ||
request.route !== "build_user_code" ||
request.view?.viewtemplate !== "React"
)
return null;
return user && user.role_id <= 1
? { decision: "allow" }
: {
decision: "deny",
reason: "Only admins may rebuild the React view bundle",
};
},
viewtemplates: (cfg) => [require("./react_view")],
headers: (cfg) => {
const tenant = db.getTenantSchema() || "public";
Expand Down
24 changes: 24 additions & 0 deletions react_view.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const Workflow = require("@saltcorn/data/models/workflow");
const Form = require("@saltcorn/data/models/form");
const Table = require("@saltcorn/data/models/table");
const View = require("@saltcorn/data/models/view");
const { features } = require("@saltcorn/data/db/state");
const { div } = require("@saltcorn/markup/tags");
const {
stateFieldsToWhere,
Expand Down Expand Up @@ -134,13 +136,35 @@ const configuration_workflow = () =>
],
});

// Only admins may rebuild a view's user-code bundle. Uses the centralized
// authorize_view hook when the running core supports it (features.authorize_access_hooks),
// falling back to a plain role check on older cores.
const isBuildUserCodeAuthorized = async (viewname, req) => {
if (features?.authorize_access_hooks) {
const view = await View.findOne({ name: viewname });
return !!(
view &&
(await view.authorize(req.user, {
action: "post",
route: "build_user_code",
req,
body: {},
}))
);
}
return !!(req.user && req.user.role_id <= 1);
};

const build_user_code = async (
table_id,
viewname,
{ user_code, build_mode, timestamp },
{},
{ req }
) => {
if (!(await isBuildUserCodeAuthorized(viewname, req))) {
return { json: { error: "Not authorized" } };
}
try {
await buildAndUpdateView(
user_code || defaultUserCode(table_id),
Expand Down
Loading