From 045011581c8e53bb342ae9b9daeb8b9f726031b1 Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Sun, 21 Sep 2025 21:00:51 +0200 Subject: [PATCH 1/2] Handle plugin name in `plugins.getConfig` --- .../@node-red/editor-api/lib/admin/plugins.js | 1 + .../node_modules/@node-red/registry/lib/plugins.js | 14 +++++++++++--- .../@node-red/runtime/lib/api/plugins.js | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js b/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js index 304aed90e..63742c5c1 100644 --- a/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js +++ b/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js @@ -46,6 +46,7 @@ module.exports = { let opts = { user: req.user, module: req.params[0], + name: req.params[2], req: apiUtils.getRequestLogObject(req) } diff --git a/packages/node_modules/@node-red/registry/lib/plugins.js b/packages/node_modules/@node-red/registry/lib/plugins.js index 035d92004..8d165698e 100644 --- a/packages/node_modules/@node-red/registry/lib/plugins.js +++ b/packages/node_modules/@node-red/registry/lib/plugins.js @@ -74,11 +74,19 @@ function getPluginConfigs(lang) { return pluginConfigCache[lang]; } -function getPluginConfig(id, lang) { +function getPluginConfig(module, name) { let result = ''; let moduleConfigs = registry.getModuleList(); - if (moduleConfigs.hasOwnProperty(id)) { - result = generateModulePluginConfig(moduleConfigs[id]); + if (moduleConfigs.hasOwnProperty(module)) { + if (!name) { + result = generateModulePluginConfig(moduleConfigs[module]); + } else { + const config = moduleConfigs[module].plugins[name]; + if (config && config.enabled && !config.err && config.config) { + result += "\n\n"; + result += config.config; + } + } } return result; } diff --git a/packages/node_modules/@node-red/runtime/lib/api/plugins.js b/packages/node_modules/@node-red/runtime/lib/api/plugins.js index e15f33cb4..5e1fcbee3 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/plugins.js +++ b/packages/node_modules/@node-red/runtime/lib/api/plugins.js @@ -81,7 +81,7 @@ var api = module.exports = { return; } runtime.log.audit({event: "plugins.configs.get"}, opts.req); - return runtime.plugins.getPluginConfig(opts.module, opts.lang); + return runtime.plugins.getPluginConfig(opts.module, opts.name); }, /** From b93582fc38eb75eb771d08605b1b0338644fb3be Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:42:46 +0200 Subject: [PATCH 2/2] Splits the logic into two routes --- .../@node-red/editor-api/lib/admin/index.js | 1 + .../@node-red/editor-api/lib/admin/plugins.js | 17 +++++-- .../@node-red/registry/lib/index.js | 1 + .../@node-red/registry/lib/plugins.js | 45 +++++++++++++++---- .../@node-red/runtime/lib/api/plugins.js | 31 +++++++++++-- .../@node-red/runtime/lib/plugins.js | 1 + 6 files changed, 81 insertions(+), 15 deletions(-) diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/index.js b/packages/node_modules/@node-red/editor-api/lib/admin/index.js index fa910a399..6294fa8eb 100644 --- a/packages/node_modules/@node-red/editor-api/lib/admin/index.js +++ b/packages/node_modules/@node-red/editor-api/lib/admin/index.js @@ -91,6 +91,7 @@ module.exports = { // Plugins adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler); adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler); + adminApp.get(/^\/plugins\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("plugins.read"),plugins.getModule,apiUtil.errorHandler); adminApp.get(/^\/plugins\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("plugins.read"),plugins.getConfig,apiUtil.errorHandler); adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler); diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js b/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js index 63742c5c1..1a1f14ae1 100644 --- a/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js +++ b/packages/node_modules/@node-red/editor-api/lib/admin/plugins.js @@ -41,17 +41,28 @@ module.exports = { apiUtils.rejectHandler(req,res,err); }) }, + getModule: function(req, res) { + let opts = { + user: req.user, + module: req.params[0], + req: apiUtils.getRequestLogObject(req) + } + runtimeAPI.nodes.getModuleInfo(opts).then(function(result) { + res.send(result); + }).catch(function(err) { + apiUtils.rejectHandler(req,res,err); + }) + }, getConfig: function(req, res) { let opts = { user: req.user, - module: req.params[0], - name: req.params[2], + id: req.params[0] + "/" + req.params[2], req: apiUtils.getRequestLogObject(req) } if (req.get("accept") === "application/json") { - runtimeAPI.nodes.getNodeInfo(opts.module).then(function(result) { + runtimeAPI.plugins.getPluginInfo(opts).then(function(result) { res.send(result); }).catch(function(err) { apiUtils.rejectHandler(req,res,err); diff --git a/packages/node_modules/@node-red/registry/lib/index.js b/packages/node_modules/@node-red/registry/lib/index.js index 61c7a6760..856ecb970 100644 --- a/packages/node_modules/@node-red/registry/lib/index.js +++ b/packages/node_modules/@node-red/registry/lib/index.js @@ -316,6 +316,7 @@ module.exports = { registerPlugin: plugins.registerPlugin, getPlugin: plugins.getPlugin, + getPluginInfo: plugins.getPluginInfo, getPluginsByType: plugins.getPluginsByType, getPluginList: plugins.getPluginList, getPluginConfigs: plugins.getPluginConfigs, diff --git a/packages/node_modules/@node-red/registry/lib/plugins.js b/packages/node_modules/@node-red/registry/lib/plugins.js index 8d165698e..745e9b6ef 100644 --- a/packages/node_modules/@node-red/registry/lib/plugins.js +++ b/packages/node_modules/@node-red/registry/lib/plugins.js @@ -74,18 +74,16 @@ function getPluginConfigs(lang) { return pluginConfigCache[lang]; } -function getPluginConfig(module, name) { +function getPluginConfig(id, lang) { let result = ''; let moduleConfigs = registry.getModuleList(); + const module = registry.getModuleFromSetId(id); if (moduleConfigs.hasOwnProperty(module)) { - if (!name) { - result = generateModulePluginConfig(moduleConfigs[module]); - } else { - const config = moduleConfigs[module].plugins[name]; - if (config && config.enabled && !config.err && config.config) { - result += "\n\n"; - result += config.config; - } + const name = registry.getNodeFromSetId(id); + const config = moduleConfigs[module].plugins[name]; + if (config && config.enabled && !config.err && config.config) { + result += "\n\n"; + result += config.config; } } return result; @@ -106,6 +104,34 @@ function generateModulePluginConfig(module) { return result; } +function getPluginInfo(typeOrId) { + let id = typeOrId; + if (pluginToId.hasOwnProperty(typeOrId)) { + id = pluginToId[typeOrId]; + } + + if (id) { + const moduleConfigs = registry.getModuleList(); + const module = moduleConfigs[registry.getModuleFromSetId(id)]; + if (module) { + const config = module.plugins[registry.getNodeFromSetId(id)]; + if (config) { + const info = registry.filterNodeInfo(config); + if (config.hasOwnProperty("loaded")) { + info.loaded = config.loaded; + } + if (module.pending_version) { + info.pending_version = module.pending_version; + } + + info.version = module.version; + return info; + } + } + } + return null; +} + function getPluginList() { var list = []; var moduleConfigs = registry.getModuleList(); @@ -211,6 +237,7 @@ module.exports = { init, registerPlugin, getPlugin, + getPluginInfo, getPluginsByType, getPluginConfigs, getPluginConfig, diff --git a/packages/node_modules/@node-red/runtime/lib/api/plugins.js b/packages/node_modules/@node-red/runtime/lib/api/plugins.js index 5e1fcbee3..404738c07 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/plugins.js +++ b/packages/node_modules/@node-red/runtime/lib/api/plugins.js @@ -22,6 +22,31 @@ var api = module.exports = { return runtime.plugins.getPlugin(opts.id); }, + /** + * Gets the info of an individual plugin set + * @param {Object} opts + * @param {User} opts.user - the user calling the api + * @param {String} opts.id - the id of the plugin set to return + * @param {Object} opts.req - the request to log (optional) + * @return {Promise} - the plugin information + * @memberof @node-red/runtime_plugins + */ + getPluginInfo: async function(opts) { + const id = opts.id; + const result = runtime.plugins.getPluginInfo(id); + if (result) { + runtime.log.audit({ event: "plugins.info.get", id: id }, opts.req); + delete result.loaded; + return result; + } else { + runtime.log.audit({ event: "plugins.info.get", id: id, error: "not_found" }, opts.req); + var err = new Error("Plugin not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } + }, + /** * Gets all plugin definitions of a given type * @param {Object} opts @@ -67,12 +92,12 @@ var api = module.exports = { }, /** - * Gets the editor content for one registered plugin + * Gets an individual plugin's html content * @param {Object} opts * @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api * @param {Object} opts.req - the request to log (optional) - * @return {Promise} - the plugin information + * @return {Promise} - the plugin html content * @memberof @node-red/runtime_plugins */ getPluginConfig: async function(opts) { @@ -81,7 +106,7 @@ var api = module.exports = { return; } runtime.log.audit({event: "plugins.configs.get"}, opts.req); - return runtime.plugins.getPluginConfig(opts.module, opts.name); + return runtime.plugins.getPluginConfig(opts.id, opts.lang); }, /** diff --git a/packages/node_modules/@node-red/runtime/lib/plugins.js b/packages/node_modules/@node-red/runtime/lib/plugins.js index 3e85430ac..6022bf23c 100644 --- a/packages/node_modules/@node-red/runtime/lib/plugins.js +++ b/packages/node_modules/@node-red/runtime/lib/plugins.js @@ -4,6 +4,7 @@ module.exports = { init: function() {}, registerPlugin: registry.registerPlugin, getPlugin: registry.getPlugin, + getPluginInfo: registry.getPluginInfo, getPluginsByType: registry.getPluginsByType, getPluginList: registry.getPluginList, getPluginConfigs: registry.getPluginConfigs,