mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
WIP: create new runtime-api
This commit is contained in:
parent
e8a637498d
commit
e8e8f70c27
17
jsdoc.json
Normal file
17
jsdoc.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"tags": {
|
||||||
|
"allowUnknownTags": false,
|
||||||
|
"dictionaries": ["jsdoc"]
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"include": [
|
||||||
|
"./red/runtime-api"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"templates": {
|
||||||
|
"systemName": "Node-RED Runtime API",
|
||||||
|
"theme":"yeti",
|
||||||
|
"footer": "",
|
||||||
|
"copyright": "Released under the Apache License v2.0"
|
||||||
|
}
|
||||||
|
}
|
226
package.json
226
package.json
@ -1,115 +1,119 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "0.18.4",
|
"version": "0.18.4",
|
||||||
"description": "A visual tool for wiring the Internet of Things",
|
"description": "A visual tool for wiring the Internet of Things",
|
||||||
"homepage": "http://nodered.org",
|
"homepage": "http://nodered.org",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/node-red/node-red.git"
|
"url": "https://github.com/node-red/node-red.git"
|
||||||
},
|
|
||||||
"main": "red/red.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "node red.js",
|
|
||||||
"test": "grunt",
|
|
||||||
"build": "grunt build"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"node-red": "./red.js",
|
|
||||||
"node-red-pi": "bin/node-red-pi"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Nick O'Leary"
|
|
||||||
},
|
},
|
||||||
{
|
"main": "red/red.js",
|
||||||
"name": "Dave Conway-Jones"
|
"scripts": {
|
||||||
|
"start": "node red.js",
|
||||||
|
"test": "grunt",
|
||||||
|
"build": "grunt build",
|
||||||
|
"doc": "jsdoc --pedantic --recurse -c jsdoc.json -t ./node_modules/ink-docstrap/template"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"node-red": "./red.js",
|
||||||
|
"node-red-pi": "bin/node-red-pi"
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Nick O'Leary"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dave Conway-Jones"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"messaging",
|
||||||
|
"iot",
|
||||||
|
"flow"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"basic-auth": "2.0.0",
|
||||||
|
"bcryptjs": "2.4.3",
|
||||||
|
"body-parser": "1.18.2",
|
||||||
|
"cheerio": "0.22.0",
|
||||||
|
"clone": "2.1.1",
|
||||||
|
"cookie": "0.3.1",
|
||||||
|
"cookie-parser": "1.4.3",
|
||||||
|
"cors": "2.8.4",
|
||||||
|
"cron": "1.3.0",
|
||||||
|
"express": "4.16.2",
|
||||||
|
"express-session": "1.15.6",
|
||||||
|
"follow-redirects": "1.3.0",
|
||||||
|
"fs-extra": "5.0.0",
|
||||||
|
"fs.notify": "0.0.4",
|
||||||
|
"hash-sum": "1.0.2",
|
||||||
|
"i18next": "1.10.6",
|
||||||
|
"ink-docstrap": "^1.3.2",
|
||||||
|
"is-utf8": "0.2.1",
|
||||||
|
"js-yaml": "3.10.0",
|
||||||
|
"json-stringify-safe": "5.0.1",
|
||||||
|
"jsonata": "1.5.0",
|
||||||
|
"media-typer": "0.3.0",
|
||||||
|
"memorystore": "1.6.0",
|
||||||
|
"mime": "1.4.1",
|
||||||
|
"mqtt": "2.15.1",
|
||||||
|
"multer": "1.3.0",
|
||||||
|
"mustache": "2.3.0",
|
||||||
|
"node-red-node-email": "0.1.*",
|
||||||
|
"node-red-node-feedparser": "0.1.*",
|
||||||
|
"node-red-node-rbe": "0.2.*",
|
||||||
|
"node-red-node-twitter": "0.1.*",
|
||||||
|
"nopt": "4.0.1",
|
||||||
|
"oauth2orize": "1.11.0",
|
||||||
|
"on-headers": "1.0.1",
|
||||||
|
"passport": "0.4.0",
|
||||||
|
"passport-http-bearer": "1.0.1",
|
||||||
|
"passport-oauth2-client-password": "0.1.2",
|
||||||
|
"raw-body": "2.3.2",
|
||||||
|
"semver": "5.4.1",
|
||||||
|
"sentiment": "2.1.0",
|
||||||
|
"uglify-js": "3.3.6",
|
||||||
|
"when": "3.7.8",
|
||||||
|
"ws": "1.1.5",
|
||||||
|
"xml2js": "0.4.19"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"bcrypt": "~1.0.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chromedriver": "^2.33.2",
|
||||||
|
"grunt": "~1.0.1",
|
||||||
|
"grunt-chmod": "~1.1.1",
|
||||||
|
"grunt-cli": "~1.2.0",
|
||||||
|
"grunt-concurrent": "~2.3.1",
|
||||||
|
"grunt-contrib-clean": "~1.1.0",
|
||||||
|
"grunt-contrib-compress": "~1.4.0",
|
||||||
|
"grunt-contrib-concat": "~1.0.1",
|
||||||
|
"grunt-contrib-copy": "~1.0.0",
|
||||||
|
"grunt-contrib-jshint": "~1.1.0",
|
||||||
|
"grunt-contrib-uglify": "~3.3.0",
|
||||||
|
"grunt-contrib-watch": "~1.0.0",
|
||||||
|
"grunt-jsonlint": "~1.1.0",
|
||||||
|
"grunt-mocha-istanbul": "5.0.2",
|
||||||
|
"grunt-nodemon": "~0.4.2",
|
||||||
|
"grunt-sass": "~2.0.0",
|
||||||
|
"grunt-simple-mocha": "~0.4.1",
|
||||||
|
"grunt-webdriver": "^2.0.3",
|
||||||
|
"istanbul": "0.4.5",
|
||||||
|
"jsdoc": "3.5.5",
|
||||||
|
"mocha": "^5.1.1",
|
||||||
|
"should": "^8.4.0",
|
||||||
|
"sinon": "1.17.7",
|
||||||
|
"stoppable": "^1.0.6",
|
||||||
|
"supertest": "3.0.0",
|
||||||
|
"wdio-chromedriver-service": "^0.1.1",
|
||||||
|
"wdio-mocha-framework": "^0.5.11",
|
||||||
|
"wdio-spec-reporter": "^0.1.3",
|
||||||
|
"webdriverio": "^4.9.11"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"editor",
|
|
||||||
"messaging",
|
|
||||||
"iot",
|
|
||||||
"flow"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"basic-auth": "2.0.0",
|
|
||||||
"bcryptjs": "2.4.3",
|
|
||||||
"body-parser": "1.18.2",
|
|
||||||
"cheerio": "0.22.0",
|
|
||||||
"clone": "2.1.1",
|
|
||||||
"cookie": "0.3.1",
|
|
||||||
"cookie-parser": "1.4.3",
|
|
||||||
"cors": "2.8.4",
|
|
||||||
"cron": "1.3.0",
|
|
||||||
"express": "4.16.2",
|
|
||||||
"express-session": "1.15.6",
|
|
||||||
"follow-redirects": "1.3.0",
|
|
||||||
"fs-extra": "5.0.0",
|
|
||||||
"fs.notify": "0.0.4",
|
|
||||||
"hash-sum": "1.0.2",
|
|
||||||
"i18next": "1.10.6",
|
|
||||||
"is-utf8": "0.2.1",
|
|
||||||
"js-yaml": "3.10.0",
|
|
||||||
"json-stringify-safe": "5.0.1",
|
|
||||||
"jsonata": "1.5.0",
|
|
||||||
"media-typer": "0.3.0",
|
|
||||||
"memorystore": "1.6.0",
|
|
||||||
"mqtt": "2.15.1",
|
|
||||||
"multer": "1.3.0",
|
|
||||||
"mustache": "2.3.0",
|
|
||||||
"node-red-node-email": "0.1.*",
|
|
||||||
"node-red-node-feedparser": "0.1.*",
|
|
||||||
"node-red-node-rbe": "0.2.*",
|
|
||||||
"node-red-node-twitter": "0.1.*",
|
|
||||||
"nopt": "4.0.1",
|
|
||||||
"oauth2orize": "1.11.0",
|
|
||||||
"on-headers": "1.0.1",
|
|
||||||
"passport": "0.4.0",
|
|
||||||
"passport-http-bearer": "1.0.1",
|
|
||||||
"passport-oauth2-client-password": "0.1.2",
|
|
||||||
"raw-body": "2.3.2",
|
|
||||||
"semver": "5.4.1",
|
|
||||||
"sentiment": "2.1.0",
|
|
||||||
"uglify-js": "3.3.6",
|
|
||||||
"when": "3.7.8",
|
|
||||||
"ws": "1.1.5",
|
|
||||||
"xml2js": "0.4.19"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"bcrypt": "~1.0.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"chromedriver": "^2.33.2",
|
|
||||||
"grunt": "~1.0.1",
|
|
||||||
"grunt-chmod": "~1.1.1",
|
|
||||||
"grunt-cli": "~1.2.0",
|
|
||||||
"grunt-concurrent": "~2.3.1",
|
|
||||||
"grunt-contrib-clean": "~1.1.0",
|
|
||||||
"grunt-contrib-compress": "~1.4.0",
|
|
||||||
"grunt-contrib-concat": "~1.0.1",
|
|
||||||
"grunt-contrib-copy": "~1.0.0",
|
|
||||||
"grunt-contrib-jshint": "~1.1.0",
|
|
||||||
"grunt-contrib-uglify": "~3.3.0",
|
|
||||||
"grunt-contrib-watch": "~1.0.0",
|
|
||||||
"grunt-jsonlint": "~1.1.0",
|
|
||||||
"grunt-mocha-istanbul": "5.0.2",
|
|
||||||
"grunt-nodemon": "~0.4.2",
|
|
||||||
"grunt-sass": "~2.0.0",
|
|
||||||
"grunt-simple-mocha": "~0.4.1",
|
|
||||||
"grunt-webdriver": "^2.0.3",
|
|
||||||
"istanbul": "0.4.5",
|
|
||||||
"mocha": "^5.1.1",
|
|
||||||
"should": "^8.4.0",
|
|
||||||
"sinon": "1.17.7",
|
|
||||||
"stoppable": "^1.0.6",
|
|
||||||
"supertest": "3.0.0",
|
|
||||||
"wdio-chromedriver-service": "^0.1.1",
|
|
||||||
"wdio-mocha-framework": "^0.5.11",
|
|
||||||
"wdio-spec-reporter": "^0.1.3",
|
|
||||||
"webdriverio": "^4.9.11"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,72 +14,56 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var log;
|
var runtimeAPI;
|
||||||
var redNodes;
|
var apiUtils = require("../util");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(_runtimeAPI) {
|
||||||
redNodes = runtime.nodes;
|
runtimeAPI = _runtimeAPI;
|
||||||
log = runtime.log;
|
|
||||||
},
|
},
|
||||||
get: function(req,res) {
|
get: function(req,res) {
|
||||||
var id = req.params.id;
|
var opts = {
|
||||||
var flow = redNodes.getFlow(id);
|
user: req.user,
|
||||||
if (flow) {
|
id: req.params.id
|
||||||
log.audit({event: "flow.get",id:id},req);
|
|
||||||
res.json(flow);
|
|
||||||
} else {
|
|
||||||
log.audit({event: "flow.get",id:id,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.flows.getFlow(opts).then(function(result) {
|
||||||
|
return res.json(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
var flow = req.body;
|
var opts = {
|
||||||
redNodes.addFlow(flow).then(function(id) {
|
user: req.user,
|
||||||
log.audit({event: "flow.add",id:id},req);
|
flow: req.body
|
||||||
res.json({id:id});
|
}
|
||||||
|
runtimeAPI.flows.addFlow(opts).then(function(id) {
|
||||||
|
return res.json({id:id});
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()},req);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
put: function(req,res) {
|
put: function(req,res) {
|
||||||
var id = req.params.id;
|
var opts = {
|
||||||
var flow = req.body;
|
user: req.user,
|
||||||
try {
|
id: req.params.id,
|
||||||
redNodes.updateFlow(id,flow).then(function() {
|
flow: req.body
|
||||||
log.audit({event: "flow.update",id:id},req);
|
|
||||||
res.json({id:id});
|
|
||||||
}).catch(function(err) {
|
|
||||||
log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
})
|
|
||||||
} catch(err) {
|
|
||||||
if (err.code === 404) {
|
|
||||||
log.audit({event: "flow.update",id:id,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
} else {
|
|
||||||
log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.flows.updateFlow(opts).then(function(id) {
|
||||||
|
return res.json({id:id});
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
delete: function(req,res) {
|
delete: function(req,res) {
|
||||||
var id = req.params.id;
|
var opts = {
|
||||||
try {
|
user: req.user,
|
||||||
redNodes.removeFlow(id).then(function() {
|
id: req.params.id
|
||||||
log.audit({event: "flow.remove",id:id},req);
|
|
||||||
res.status(204).end();
|
|
||||||
})
|
|
||||||
} catch(err) {
|
|
||||||
if (err.code === 404) {
|
|
||||||
log.audit({event: "flow.remove",id:id,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
} else {
|
|
||||||
log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.flows.deleteFlow(opts).then(function() {
|
||||||
|
res.status(204).end();
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,72 +14,56 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var log;
|
var runtimeAPI;
|
||||||
var redNodes;
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(_runtimeAPI) {
|
||||||
redNodes = runtime.nodes;
|
runtimeAPI = _runtimeAPI;
|
||||||
log = runtime.log;
|
|
||||||
},
|
},
|
||||||
get: function(req,res) {
|
get: function(req,res) {
|
||||||
var version = req.get("Node-RED-API-Version")||"v1";
|
var version = req.get("Node-RED-API-Version")||"v1";
|
||||||
if (version === "v1") {
|
if (!/^v[12]$/.test(version)) {
|
||||||
log.audit({event: "flows.get",version:"v1"},req);
|
return res.status(500).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||||
res.json(redNodes.getFlows().flows);
|
|
||||||
} else if (version === "v2") {
|
|
||||||
log.audit({event: "flows.get",version:"v2"},req);
|
|
||||||
res.json(redNodes.getFlows());
|
|
||||||
} else {
|
|
||||||
log.audit({event: "flows.get",version:version,error:"invalid_api_version"},req);
|
|
||||||
res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
|
||||||
}
|
}
|
||||||
|
var opts = {
|
||||||
|
user: req.user
|
||||||
|
}
|
||||||
|
runtimeAPI.flows.getFlows(opts).then(function(result) {
|
||||||
|
if (version === "v1") {
|
||||||
|
res.json(result.flows);
|
||||||
|
} else if (version === "v2") {
|
||||||
|
res.json(result);
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
var version = req.get("Node-RED-API-Version")||"v1";
|
var version = req.get("Node-RED-API-Version")||"v1";
|
||||||
if (!/^v[12]$/.test(version)) {
|
if (!/^v[12]$/.test(version)) {
|
||||||
log.audit({event: "flows.set",version:version,error:"invalid_api_version"},req);
|
return res.status(500).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||||
res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var flows = req.body;
|
var opts = {
|
||||||
var deploymentType = req.get("Node-RED-Deployment-Type")||"full";
|
user: req.user,
|
||||||
log.audit({event: "flows.set",type:deploymentType,version:version},req);
|
deploymentType: req.get("Node-RED-Deployment-Type")||"full"
|
||||||
if (deploymentType === 'reload') {
|
}
|
||||||
redNodes.loadFlows().then(function(flowId) {
|
|
||||||
if (version === "v1") {
|
if (opts.deploymentType !== 'reload') {
|
||||||
res.status(204).end();
|
if (version === "v1") {
|
||||||
} else {
|
opts.flows = {flows: req.body}
|
||||||
res.json({rev:flowId});
|
} else {
|
||||||
}
|
opts.flows = req.body;
|
||||||
}).catch(function(err) {
|
|
||||||
log.warn(log._("api.flows.error-reload",{message:err.message}));
|
|
||||||
log.warn(err.stack);
|
|
||||||
res.status(500).json({error:"unexpected_error", message:err.message});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var flowConfig = flows;
|
|
||||||
if (version === "v2") {
|
|
||||||
flowConfig = flows.flows;
|
|
||||||
if (flows.hasOwnProperty('rev')) {
|
|
||||||
var currentVersion = redNodes.getFlows().rev;
|
|
||||||
if (currentVersion !== flows.rev) {
|
|
||||||
//TODO: log warning
|
|
||||||
return res.status(409).json({code:"version_mismatch"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
redNodes.setFlows(flowConfig,deploymentType).then(function(flowId) {
|
|
||||||
if (version === "v1") {
|
|
||||||
res.status(204).end();
|
|
||||||
} else if (version === "v2") {
|
|
||||||
res.json({rev:flowId});
|
|
||||||
}
|
|
||||||
}).catch(function(err) {
|
|
||||||
log.warn(log._("api.flows.error-save",{message:err.message}));
|
|
||||||
log.warn(err.stack);
|
|
||||||
res.status(500).json({error:err.code || "unexpected_error", message:err.message});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtimeAPI.flows.setFlows(opts).then(function(result) {
|
||||||
|
if (version === "v1") {
|
||||||
|
res.status(204).end();
|
||||||
|
} else {
|
||||||
|
res.json(result);
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ var auth = require("../auth");
|
|||||||
var apiUtil = require("../util");
|
var apiUtil = require("../util");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(runtimeAPI) {
|
||||||
flows.init(runtime);
|
flows.init(runtimeAPI);
|
||||||
flow.init(runtime);
|
flow.init(runtimeAPI);
|
||||||
nodes.init(runtime);
|
nodes.init(runtimeAPI);
|
||||||
|
|
||||||
var needsPermission = auth.needsPermission;
|
var needsPermission = auth.needsPermission;
|
||||||
|
|
||||||
|
@ -14,230 +14,133 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var when = require("when");
|
|
||||||
var apiUtils = require("../util");
|
var apiUtils = require("../util");
|
||||||
var redNodes;
|
|
||||||
var log;
|
var runtimeAPI;
|
||||||
var settings;
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(_runtimeAPI) {
|
||||||
redNodes = runtime.nodes;
|
runtimeAPI = _runtimeAPI;
|
||||||
log = runtime.log;
|
|
||||||
settings = runtime.settings;
|
|
||||||
},
|
},
|
||||||
getAll: function(req,res) {
|
getAll: function(req,res) {
|
||||||
|
var opts = {
|
||||||
|
user: req.user
|
||||||
|
}
|
||||||
if (req.get("accept") == "application/json") {
|
if (req.get("accept") == "application/json") {
|
||||||
log.audit({event: "nodes.list.get"},req);
|
runtimeAPI.nodes.getNodeList(opts).then(function(list) {
|
||||||
res.json(redNodes.getNodeList());
|
res.json(list);
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
log.audit({event: "nodes.configs.get"},req);
|
runtimeAPI.nodes.getNodeConfigs(opts).then(function(configs) {
|
||||||
res.send(redNodes.getNodeConfigs(lang));
|
res.send(configs);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
if (!settings.available()) {
|
var opts = {
|
||||||
log.audit({event: "nodes.install",error:"settings_unavailable"},req);
|
user: req.user,
|
||||||
res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
|
module: req.body.module,
|
||||||
return;
|
version: req.body.version
|
||||||
}
|
}
|
||||||
var node = req.body;
|
runtimeAPI.nodes.addModule(opts).then(function(info) {
|
||||||
var promise;
|
res.json(info);
|
||||||
var isUpgrade = false;
|
|
||||||
if (node.module) {
|
|
||||||
var module = redNodes.getModuleInfo(node.module);
|
|
||||||
if (module) {
|
|
||||||
if (!node.version || module.version === node.version) {
|
|
||||||
log.audit({event: "nodes.install",module:node.module, version:node.version, error:"module_already_loaded"},req);
|
|
||||||
res.status(400).json({error:"module_already_loaded", message:"Module already loaded"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!module.local) {
|
|
||||||
log.audit({event: "nodes.install",module:node.module, version:node.version, error:"module_not_local"},req);
|
|
||||||
res.status(400).json({error:"module_not_local", message:"Module not locally installed"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isUpgrade = true;
|
|
||||||
}
|
|
||||||
promise = redNodes.installModule(node.module,node.version);
|
|
||||||
} else {
|
|
||||||
log.audit({event: "nodes.install",module:node.module,error:"invalid_request"},req);
|
|
||||||
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
promise.then(function(info) {
|
|
||||||
if (node.module) {
|
|
||||||
log.audit({event: "nodes.install",module:node.module,version:node.version},req);
|
|
||||||
res.json(info);
|
|
||||||
}
|
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
if (err.code === 404) {
|
apiUtils.rejectHandler(req,res,err);
|
||||||
log.audit({event: "nodes.install",module:node.module,version:node.version,error:"not_found"},req);
|
})
|
||||||
res.status(404).end();
|
|
||||||
} else if (err.code) {
|
|
||||||
log.audit({event: "nodes.install",module:node.module,version:node.version,error:err.code},req);
|
|
||||||
res.status(400).json({error:err.code, message:err.message});
|
|
||||||
} else {
|
|
||||||
log.audit({event: "nodes.install",module:node.module,version:node.version,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: function(req,res) {
|
delete: function(req,res) {
|
||||||
if (!settings.available()) {
|
var opts = {
|
||||||
log.audit({event: "nodes.remove",error:"settings_unavailable"},req);
|
user: req.user,
|
||||||
res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
|
module: req.params[0]
|
||||||
return;
|
|
||||||
}
|
|
||||||
var mod = req.params[0];
|
|
||||||
try {
|
|
||||||
var promise = null;
|
|
||||||
var module = redNodes.getModuleInfo(mod);
|
|
||||||
if (!module) {
|
|
||||||
log.audit({event: "nodes.remove",module:mod,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
promise = redNodes.uninstallModule(mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
promise.then(function(list) {
|
|
||||||
log.audit({event: "nodes.remove",module:mod},req);
|
|
||||||
res.status(204).end();
|
|
||||||
}).catch(function(err) {
|
|
||||||
log.audit({event: "nodes.remove",module:mod,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
log.audit({event: "nodes.remove",module:mod,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.nodes.removeModule(opts).then(function(info) {
|
||||||
|
res.status(204).end();
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getSet: function(req,res) {
|
getSet: function(req,res) {
|
||||||
var id = req.params[0] + "/" + req.params[2];
|
var opts = {
|
||||||
var result = null;
|
user: req.user,
|
||||||
|
id: req.params[0] + "/" + req.params[2]
|
||||||
|
}
|
||||||
if (req.get("accept") === "application/json") {
|
if (req.get("accept") === "application/json") {
|
||||||
result = redNodes.getNodeInfo(id);
|
runtimeAPI.nodes.getNodeInfo(opts).then(function(result) {
|
||||||
if (result) {
|
|
||||||
log.audit({event: "nodes.info.get",id:id},req);
|
|
||||||
delete result.loaded;
|
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} else {
|
}).catch(function(err) {
|
||||||
log.audit({event: "nodes.info.get",id:id,error:"not_found"},req);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
res.status(404).end();
|
})
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
result = redNodes.getNodeConfig(id,lang);
|
runtimeAPI.nodes.getNodeConfig(opts).then(function(result) {
|
||||||
if (result) {
|
return res.json(result);
|
||||||
log.audit({event: "nodes.config.get",id:id},req);
|
}).catch(function(err) {
|
||||||
res.send(result);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
} else {
|
})
|
||||||
log.audit({event: "nodes.config.get",id:id,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getModule: function(req,res) {
|
getModule: function(req,res) {
|
||||||
var module = req.params[0];
|
var opts = {
|
||||||
var result = redNodes.getModuleInfo(module);
|
user: req.user,
|
||||||
if (result) {
|
module: req.params[0]
|
||||||
log.audit({event: "nodes.module.get",module:module},req);
|
|
||||||
res.json(result);
|
|
||||||
} else {
|
|
||||||
log.audit({event: "nodes.module.get",module:module,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.nodes.getModuleInfo(opts).then(function(result) {
|
||||||
|
res.send(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
putSet: function(req,res) {
|
putSet: function(req,res) {
|
||||||
if (!settings.available()) {
|
|
||||||
log.audit({event: "nodes.info.set",error:"settings_unavailable"},req);
|
|
||||||
res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var body = req.body;
|
var body = req.body;
|
||||||
if (!body.hasOwnProperty("enabled")) {
|
if (!body.hasOwnProperty("enabled")) {
|
||||||
log.audit({event: "nodes.info.set",error:"invalid_request"},req);
|
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||||
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var id = req.params[0] + "/" + req.params[2];
|
var opts = {
|
||||||
try {
|
user: req.user,
|
||||||
var node = redNodes.getNodeInfo(id);
|
id: req.params[0] + "/" + req.params[2],
|
||||||
var info;
|
enabled: body.enabled
|
||||||
if (!node) {
|
|
||||||
log.audit({event: "nodes.info.set",id:id,error:"not_found"},req);
|
|
||||||
res.status(404).end();
|
|
||||||
} else {
|
|
||||||
delete node.loaded;
|
|
||||||
putNode(node, body.enabled).then(function(result) {
|
|
||||||
log.audit({event: "nodes.info.set",id:id,enabled:body.enabled},req);
|
|
||||||
res.json(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
log.audit({event: "nodes.info.set",id:id,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.nodes.setNodeSetState(opts).then(function(result) {
|
||||||
|
res.send(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
putModule: function(req,res) {
|
putModule: function(req,res) {
|
||||||
if (!settings.available()) {
|
|
||||||
log.audit({event: "nodes.module.set",error:"settings_unavailable"},req);
|
|
||||||
res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var body = req.body;
|
var body = req.body;
|
||||||
if (!body.hasOwnProperty("enabled")) {
|
if (!body.hasOwnProperty("enabled")) {
|
||||||
log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||||
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var mod = req.params[0];
|
var opts = {
|
||||||
try {
|
user: req.user,
|
||||||
var module = redNodes.getModuleInfo(mod);
|
module: req.params[0],
|
||||||
if (!module) {
|
enabled: body.enabled
|
||||||
log.audit({event: "nodes.module.set",module:mod,error:"not_found"},req);
|
|
||||||
return res.status(404).end();
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodes = module.nodes;
|
|
||||||
var promises = [];
|
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
|
||||||
promises.push(putNode(nodes[i],body.enabled));
|
|
||||||
}
|
|
||||||
when.settle(promises).then(function() {
|
|
||||||
res.json(redNodes.getModuleInfo(mod));
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
log.audit({event: "nodes.module.set",module:mod,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.nodes.setModuleState(opts).then(function(result) {
|
||||||
|
res.send(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getIcons: function(req,res) {
|
getIcons: function(req,res) {
|
||||||
log.audit({event: "nodes.icons.get"},req);
|
var opts = {
|
||||||
res.json(redNodes.getNodeIcons());
|
user: req.user
|
||||||
|
}
|
||||||
|
runtimeAPI.nodes.getIconList(opts).then(function(list) {
|
||||||
|
res.json(list);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function putNode(node, enabled) {
|
|
||||||
var info;
|
|
||||||
var promise;
|
|
||||||
if (!node.err && node.enabled === enabled) {
|
|
||||||
promise = when.resolve(node);
|
|
||||||
} else {
|
|
||||||
if (enabled) {
|
|
||||||
promise = redNodes.enableNode(node.id);
|
|
||||||
} else {
|
|
||||||
promise = redNodes.disableNode(node.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
@ -14,39 +14,23 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var log;
|
var runtimeAPI;
|
||||||
var api;
|
var apiUtils = require("../util");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(_runtimeAPI) {
|
||||||
log = runtime.log;
|
runtimeAPI = _runtimeAPI
|
||||||
api = runtime.nodes;
|
|
||||||
},
|
},
|
||||||
get: function (req, res) {
|
get: function (req, res) {
|
||||||
// TODO: It should verify the given node id is of the type specified -
|
var opts = {
|
||||||
// but that would add a dependency from this module to the
|
user: req.user,
|
||||||
// registry module that knows about node types.
|
type: req.params.type,
|
||||||
var nodeType = req.params.type;
|
id: req.params.id
|
||||||
var nodeID = req.params.id;
|
|
||||||
log.audit({event: "credentials.get",type:nodeType,id:nodeID},req);
|
|
||||||
var credentials = api.getCredentials(nodeID);
|
|
||||||
if (!credentials) {
|
|
||||||
res.json({});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var definition = api.getCredentialDefinition(nodeType);
|
runtimeAPI.flows.getNodeCredentials(opts).then(function(result) {
|
||||||
|
res.json(result);
|
||||||
var sendCredentials = {};
|
}).catch(function(err) {
|
||||||
for (var cred in definition) {
|
apiUtils.rejectHandler(req,res,err);
|
||||||
if (definition.hasOwnProperty(cred)) {
|
})
|
||||||
if (definition[cred].type == "password") {
|
|
||||||
var key = 'has_' + cred;
|
|
||||||
sendCredentials[key] = credentials[cred] != null && credentials[cred] !== '';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sendCredentials[cred] = credentials[cred] || '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.json(sendCredentials);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ var auth = require("../auth");
|
|||||||
var nodes = require("../admin/nodes"); // TODO: move /icons into here
|
var nodes = require("../admin/nodes"); // TODO: move /icons into here
|
||||||
var needsPermission;
|
var needsPermission;
|
||||||
var runtime;
|
var runtime;
|
||||||
|
var runtimeAPI;
|
||||||
var log;
|
var log;
|
||||||
var apiUtil = require("../util");
|
var apiUtil = require("../util");
|
||||||
|
|
||||||
@ -38,16 +39,17 @@ var ensureRuntimeStarted = function(req,res,next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(server, _runtime) {
|
init: function(server, settings, _runtime, _runtimeAPI) {
|
||||||
runtime = _runtime;
|
runtime = _runtime;
|
||||||
|
runtimeAPI = _runtimeAPI;
|
||||||
log = runtime.log;
|
log = runtime.log;
|
||||||
needsPermission = auth.needsPermission;
|
needsPermission = auth.needsPermission;
|
||||||
var settings = runtime.settings;
|
|
||||||
if (!settings.disableEditor) {
|
if (!settings.disableEditor) {
|
||||||
info.init(runtime);
|
info.init(runtimeAPI);
|
||||||
comms.init(server,runtime);
|
comms.init(server,runtime);
|
||||||
|
|
||||||
var ui = require("./ui");
|
var ui = require("./ui");
|
||||||
|
// ui is passed runtime so it get access runtime.nodes.getNodeIconPath
|
||||||
ui.init(runtime);
|
ui.init(runtime);
|
||||||
var editorApp = express();
|
var editorApp = express();
|
||||||
if (settings.requireHttps === true) {
|
if (settings.requireHttps === true) {
|
||||||
@ -67,7 +69,7 @@ module.exports = {
|
|||||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||||
|
|
||||||
var theme = require("./theme");
|
var theme = require("./theme");
|
||||||
theme.init(runtime);
|
theme.init(settings, runtime.version());
|
||||||
editorApp.use("/theme",theme.app());
|
editorApp.use("/theme",theme.app());
|
||||||
editorApp.use("/",ui.editorResources);
|
editorApp.use("/",ui.editorResources);
|
||||||
|
|
||||||
@ -91,7 +93,7 @@ module.exports = {
|
|||||||
|
|
||||||
// Credentials
|
// Credentials
|
||||||
var credentials = require("./credentials");
|
var credentials = require("./credentials");
|
||||||
credentials.init(runtime);
|
credentials.init(runtimeAPI);
|
||||||
editorApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,apiUtil.errorHandler);
|
editorApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,apiUtil.errorHandler);
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
@ -100,11 +102,8 @@ module.exports = {
|
|||||||
editorApp.get("/settings/user",needsPermission("settings.read"),info.userSettings,apiUtil.errorHandler);
|
editorApp.get("/settings/user",needsPermission("settings.read"),info.userSettings,apiUtil.errorHandler);
|
||||||
// User Settings
|
// User Settings
|
||||||
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
||||||
|
|
||||||
// SSH keys
|
// SSH keys
|
||||||
var sshkeys = require("./sshkeys");
|
editorApp.use("/settings/user/keys",info.sshkeys());
|
||||||
sshkeys.init(runtime);
|
|
||||||
editorApp.use("/settings/user/keys",sshkeys.app());
|
|
||||||
|
|
||||||
return editorApp;
|
return editorApp;
|
||||||
}
|
}
|
||||||
|
@ -13,117 +13,48 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
var theme = require("../editor/theme");
|
var apiUtils = require("../util");
|
||||||
var util = require('util');
|
var runtimeAPI;
|
||||||
var runtime;
|
var sshkeys = require("./sshkeys");
|
||||||
var settings;
|
var theme = require("./theme");
|
||||||
var log;
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(_runtime) {
|
init: function(_runtimeAPI) {
|
||||||
runtime = _runtime;
|
runtimeAPI = _runtimeAPI;
|
||||||
settings = runtime.settings;
|
sshkeys.init(runtimeAPI);
|
||||||
log = runtime.log;
|
|
||||||
},
|
},
|
||||||
runtimeSettings: function(req,res) {
|
runtimeSettings: function(req,res) {
|
||||||
var safeSettings = {
|
var opts = {
|
||||||
httpNodeRoot: settings.httpNodeRoot||"/",
|
|
||||||
version: settings.version,
|
|
||||||
user: req.user
|
user: req.user
|
||||||
}
|
}
|
||||||
|
runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) {
|
||||||
var themeSettings = theme.settings();
|
var themeSettings = theme.settings();
|
||||||
if (themeSettings) {
|
if (themeSettings) {
|
||||||
safeSettings.editorTheme = themeSettings;
|
result.editorTheme = themeSettings;
|
||||||
}
|
|
||||||
|
|
||||||
if (util.isArray(settings.paletteCategories)) {
|
|
||||||
safeSettings.paletteCategories = settings.paletteCategories;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.flowFilePretty) {
|
|
||||||
safeSettings.flowFilePretty = settings.flowFilePretty;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!runtime.nodes.paletteEditorEnabled()) {
|
|
||||||
safeSettings.editorTheme = safeSettings.editorTheme || {};
|
|
||||||
safeSettings.editorTheme.palette = safeSettings.editorTheme.palette || {};
|
|
||||||
safeSettings.editorTheme.palette.editable = false;
|
|
||||||
}
|
|
||||||
if (runtime.storage.projects) {
|
|
||||||
var activeProject = runtime.storage.projects.getActiveProject();
|
|
||||||
if (activeProject) {
|
|
||||||
safeSettings.project = activeProject;
|
|
||||||
} else if (runtime.storage.projects.flowFileExists()) {
|
|
||||||
safeSettings.files = {
|
|
||||||
flow: runtime.storage.projects.getFlowFilename(),
|
|
||||||
credentials: runtime.storage.projects.getCredentialsFilename()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
safeSettings.git = {
|
res.json(result);
|
||||||
globalUser: runtime.storage.projects.getGlobalGitUser()
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType();
|
|
||||||
|
|
||||||
settings.exportNodeSettings(safeSettings);
|
|
||||||
res.json(safeSettings);
|
|
||||||
},
|
},
|
||||||
userSettings: function(req, res) {
|
userSettings: function(req, res) {
|
||||||
var username;
|
var opts = {
|
||||||
if (!req.user || req.user.anonymous) {
|
user: req.user
|
||||||
username = '_';
|
|
||||||
} else {
|
|
||||||
username = req.user.username;
|
|
||||||
}
|
}
|
||||||
res.json(settings.getUserSettings(username)||{});
|
runtimeAPI.settings.getUserSettings(opts).then(function(result) {
|
||||||
|
res.json(result);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
updateUserSettings: function(req,res) {
|
updateUserSettings: function(req,res) {
|
||||||
var username;
|
var opts = {
|
||||||
if (!req.user || req.user.anonymous) {
|
user: req.user,
|
||||||
username = '_';
|
settings: req.body
|
||||||
} else {
|
|
||||||
username = req.user.username;
|
|
||||||
}
|
|
||||||
var currentSettings = settings.getUserSettings(username)||{};
|
|
||||||
currentSettings = extend(currentSettings, req.body);
|
|
||||||
try {
|
|
||||||
settings.setUserSettings(username, currentSettings).then(function() {
|
|
||||||
log.audit({event: "settings.update",username:username},req);
|
|
||||||
res.status(204).end();
|
|
||||||
}).catch(function(err) {
|
|
||||||
log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
log.warn(log._("settings.user-not-available",{message:log._("settings.not-available")}));
|
|
||||||
log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
|
||||||
}
|
}
|
||||||
|
runtimeAPI.settings.updateUserSettings(opts).then(function(result) {
|
||||||
|
res.status(204).end();
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
sshkeys: function() {
|
||||||
|
return sshkeys.app()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extend(target, source) {
|
|
||||||
var keys = Object.keys(source);
|
|
||||||
var i = keys.length;
|
|
||||||
while(i--) {
|
|
||||||
var value = source[keys[i]]
|
|
||||||
var type = typeof value;
|
|
||||||
if (type === 'string' || type === 'number' || type === 'boolean' || Array.isArray(value)) {
|
|
||||||
target[keys[i]] = value;
|
|
||||||
} else if (value === null) {
|
|
||||||
if (target.hasOwnProperty(keys[i])) {
|
|
||||||
delete target[keys[i]];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Object
|
|
||||||
if (target.hasOwnProperty(keys[i])) {
|
|
||||||
target[keys[i]] = extend(target[keys[i]],value);
|
|
||||||
} else {
|
|
||||||
target[keys[i]] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var express = require("express");
|
var express = require("express");
|
||||||
var os = require("os");
|
var runtimeAPI;
|
||||||
var runtime;
|
|
||||||
var needsPermission = require("../auth").needsPermission;
|
var needsPermission = require("../auth").needsPermission;
|
||||||
|
|
||||||
function getUsername(userObj) {
|
function getUsername(userObj) {
|
||||||
@ -28,94 +27,66 @@ function getUsername(userObj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(_runtime) {
|
init: function(_runtimeAPI) {
|
||||||
runtime = _runtime;
|
runtimeAPI = _runtimeAPI;
|
||||||
},
|
},
|
||||||
app: function() {
|
app: function() {
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
// SSH keys
|
|
||||||
|
|
||||||
// List all SSH keys
|
// List all SSH keys
|
||||||
app.get("/", needsPermission("settings.read"), function(req,res) {
|
app.get("/", needsPermission("settings.read"), function(req,res) {
|
||||||
var username = getUsername(req.user);
|
var opts = {
|
||||||
runtime.storage.projects.ssh.listSSHKeys(username)
|
user: req.user
|
||||||
.then(function(list) {
|
}
|
||||||
|
runtimeAPI.settings.getUserKeys(opts).then(function(list) {
|
||||||
res.json({
|
res.json({
|
||||||
keys: list
|
keys: list
|
||||||
});
|
});
|
||||||
})
|
}).catch(function(err) {
|
||||||
.catch(function(err) {
|
apiUtils.rejectHandler(req,res,err);
|
||||||
// console.log(err.stack);
|
|
||||||
if (err.code) {
|
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
|
||||||
} else {
|
|
||||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get SSH key detail
|
// Get SSH key detail
|
||||||
app.get("/:id", needsPermission("settings.read"), function(req,res) {
|
app.get("/:id", needsPermission("settings.read"), function(req,res) {
|
||||||
var username = getUsername(req.user);
|
var opts = {
|
||||||
// console.log('username:', username);
|
user: req.user,
|
||||||
runtime.storage.projects.ssh.getSSHKey(username, req.params.id)
|
id: req.params.id
|
||||||
.then(function(data) {
|
}
|
||||||
if (data) {
|
runtimeAPI.settings.getUserKey(opts).then(function(data) {
|
||||||
res.json({
|
res.json({
|
||||||
publickey: data
|
publickey: data
|
||||||
});
|
});
|
||||||
} else {
|
}).catch(function(err) {
|
||||||
res.status(404).end();
|
apiUtils.rejectHandler(req,res,err);
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
if (err.code) {
|
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
|
||||||
} else {
|
|
||||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate a SSH key
|
// Generate a SSH key
|
||||||
app.post("/", needsPermission("settings.write"), function(req,res) {
|
app.post("/", needsPermission("settings.write"), function(req,res) {
|
||||||
var username = getUsername(req.user);
|
var opts = {
|
||||||
// console.log('req.body:', req.body);
|
user: req.user,
|
||||||
if ( req.body && req.body.name && /^[a-zA-Z0-9\-_]+$/.test(req.body.name)) {
|
id: req.params.id
|
||||||
runtime.storage.projects.ssh.generateSSHKey(username, req.body)
|
}
|
||||||
.then(function(name) {
|
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
||||||
// console.log('generate key --- success name:', name);
|
res.json({
|
||||||
res.json({
|
name: name
|
||||||
name: name
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
if (err.code) {
|
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
|
||||||
} else {
|
|
||||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}).catch(function(err) {
|
||||||
else {
|
apiUtils.rejectHandler(req,res,err);
|
||||||
res.status(400).json({error:"unexpected_error", message:"You need to have body or body.name"});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Delete a SSH key
|
// Delete a SSH key
|
||||||
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
||||||
var username = getUsername(req.user);
|
var opts = {
|
||||||
runtime.storage.projects.ssh.deleteSSHKey(username, req.params.id)
|
user: req.user,
|
||||||
.then(function() {
|
id: req.params.id
|
||||||
|
}
|
||||||
|
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
})
|
}).catch(function(err) {
|
||||||
.catch(function(err) {
|
apiUtils.rejectHandler(req,res,err);
|
||||||
if (err.code) {
|
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
|
||||||
} else {
|
|
||||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ var defaultContext = {
|
|||||||
var theme = null;
|
var theme = null;
|
||||||
var themeContext = clone(defaultContext);
|
var themeContext = clone(defaultContext);
|
||||||
var themeSettings = null;
|
var themeSettings = null;
|
||||||
var runtime = null;
|
|
||||||
|
|
||||||
var themeApp;
|
var themeApp;
|
||||||
|
|
||||||
@ -78,11 +77,10 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(settings,version) {
|
||||||
var settings = runtime.settings;
|
|
||||||
themeContext = clone(defaultContext);
|
themeContext = clone(defaultContext);
|
||||||
if (runtime.version) {
|
if (version) {
|
||||||
themeContext.version = runtime.version();
|
themeContext.version = version;
|
||||||
}
|
}
|
||||||
themeSettings = null;
|
themeSettings = null;
|
||||||
theme = settings.editorTheme || {};
|
theme = settings.editorTheme || {};
|
||||||
|
@ -26,13 +26,10 @@ var apiUtil = require("./util");
|
|||||||
|
|
||||||
var adminApp;
|
var adminApp;
|
||||||
var server;
|
var server;
|
||||||
var runtime;
|
|
||||||
var editor;
|
var editor;
|
||||||
|
|
||||||
function init(_server,_runtime) {
|
function init(_server,settings,runtime,runtimeAPI) {
|
||||||
server = _server;
|
server = _server;
|
||||||
runtime = _runtime;
|
|
||||||
var settings = runtime.settings;
|
|
||||||
if (settings.httpAdminRoot !== false) {
|
if (settings.httpAdminRoot !== false) {
|
||||||
apiUtil.init(runtime);
|
apiUtil.init(runtime);
|
||||||
adminApp = express();
|
adminApp = express();
|
||||||
@ -61,7 +58,7 @@ function init(_server,_runtime) {
|
|||||||
// Editor
|
// Editor
|
||||||
if (!settings.disableEditor) {
|
if (!settings.disableEditor) {
|
||||||
editor = require("./editor");
|
editor = require("./editor");
|
||||||
var editorApp = editor.init(server, runtime);
|
var editorApp = editor.init(server, settings, runtime, runtimeAPI);
|
||||||
adminApp.use(editorApp);
|
adminApp.use(editorApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +67,7 @@ function init(_server,_runtime) {
|
|||||||
adminApp.use(corsHandler);
|
adminApp.use(corsHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminApiApp = require("./admin").init(runtime);
|
var adminApiApp = require("./admin").init(runtimeAPI);
|
||||||
adminApp.use(adminApiApp);
|
adminApp.use(adminApiApp);
|
||||||
} else {
|
} else {
|
||||||
adminApp = null;
|
adminApp = null;
|
||||||
|
@ -41,5 +41,15 @@ module.exports = {
|
|||||||
lang = acceptedLanguages[0];
|
lang = acceptedLanguages[0];
|
||||||
}
|
}
|
||||||
return lang;
|
return lang;
|
||||||
|
},
|
||||||
|
rejectHandler: function(req,res,err) {
|
||||||
|
res.status(err.status||500);
|
||||||
|
if (err.code || err.message) {
|
||||||
|
res.json({
|
||||||
|
code: err.code||"unexpected_error",
|
||||||
|
message: err.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ var fs = require("fs");
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
var runtime = require("./runtime");
|
var runtime = require("./runtime");
|
||||||
|
var runtimeAPI = require("./runtime-api");
|
||||||
|
|
||||||
var api = require("./api");
|
var api = require("./api");
|
||||||
|
|
||||||
process.env.NODE_RED_HOME = process.env.NODE_RED_HOME || path.resolve(__dirname+"/..");
|
process.env.NODE_RED_HOME = process.env.NODE_RED_HOME || path.resolve(__dirname+"/..");
|
||||||
@ -67,7 +69,10 @@ module.exports = {
|
|||||||
|
|
||||||
if (userSettings.httpAdminRoot !== false) {
|
if (userSettings.httpAdminRoot !== false) {
|
||||||
runtime.init(userSettings,api);
|
runtime.init(userSettings,api);
|
||||||
api.init(httpServer,runtime);
|
|
||||||
|
runtimeAPI.init(runtime);
|
||||||
|
api.init(httpServer,userSettings,runtime,runtimeAPI);
|
||||||
|
|
||||||
apiEnabled = true;
|
apiEnabled = true;
|
||||||
server = runtime.adminApi.server;
|
server = runtime.adminApi.server;
|
||||||
runtime.server = runtime.adminApi.server;
|
runtime.server = runtime.adminApi.server;
|
||||||
|
19
red/runtime-api/auth.js
Normal file
19
red/runtime-api/auth.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module red/auth
|
||||||
|
*/
|
19
red/runtime-api/comms.js
Normal file
19
red/runtime-api/comms.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module red/comms
|
||||||
|
*/
|
248
red/runtime-api/flows.js
Normal file
248
red/runtime-api/flows.js
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace RED.flows
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Flows
|
||||||
|
* @alias Dave
|
||||||
|
* @type {object}
|
||||||
|
* @property {string} rev - the flow revision identifier
|
||||||
|
* @property {Array} flows - the flow configuration, an array of node configuration objects
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Flow
|
||||||
|
* @type {object}
|
||||||
|
* @property {string} id - the flow identifier
|
||||||
|
* @property {string} label - a label for the flow
|
||||||
|
* @property {Array} nodes - an array of node configuration objects
|
||||||
|
*/
|
||||||
|
|
||||||
|
var runtime;
|
||||||
|
|
||||||
|
var api = module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
runtime = _runtime;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Gets the current flow configuration
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<Flows>} - the active flow configuration
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
getFlows: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
runtime.log.audit({event: "flows.get"}/*,req*/);
|
||||||
|
var version = opts.version||"v1";
|
||||||
|
return resolve(runtime.nodes.getFlows());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Sets the current flow configuration
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<Flows>} - the active flow configuration
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
setFlows: function(opts) {
|
||||||
|
var err;
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
|
||||||
|
var flows = opts.flows;
|
||||||
|
var deploymentType = opts.deploymentType||"full";
|
||||||
|
runtime.log.audit({event: "flows.set",type:deploymentType}/*,req*/);
|
||||||
|
|
||||||
|
var apiPromise;
|
||||||
|
if (deploymentType === 'reload') {
|
||||||
|
apiPromise = runtime.nodes.loadFlows();
|
||||||
|
} else {
|
||||||
|
if (flows.hasOwnProperty('rev')) {
|
||||||
|
var currentVersion = runtime.nodes.getFlows().rev;
|
||||||
|
if (currentVersion !== flows.rev) {
|
||||||
|
err = new Error();
|
||||||
|
err.code = "version_mismatch";
|
||||||
|
err.status = 409;
|
||||||
|
//TODO: log warning
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apiPromise = runtime.nodes.setFlows(flows.flows,deploymentType);
|
||||||
|
}
|
||||||
|
apiPromise.then(function(flowId) {
|
||||||
|
return resolve({rev:flowId});
|
||||||
|
}).catch(function(err) {
|
||||||
|
log.warn(log._("api.flows.error-"+(deploymentType === 'reload'?'reload':'save'),{message:err.message}));
|
||||||
|
log.warn(err.stack);
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a flow configuration
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.flow - the flow to add
|
||||||
|
* @return {Promise<String>} - the id of the added flow
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
addFlow: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var flow = opts.flow;
|
||||||
|
runtime.nodes.addFlow(flow).then(function(id) {
|
||||||
|
runtime.log.audit({event: "flow.add",id:id});
|
||||||
|
return resolve(id);
|
||||||
|
}).catch(function(err) {
|
||||||
|
runtime.log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an individual flow configuration
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.id - the id of the flow to retrieve
|
||||||
|
* @return {Promise<Flow>} - the active flow configuration
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
getFlow: function(opts) {
|
||||||
|
return new Promise(function (resolve,reject) {
|
||||||
|
var flow = runtime.nodes.getFlow(opts.id);
|
||||||
|
if (flow) {
|
||||||
|
runtime.log.audit({event: "flow.get",id:opts.id});
|
||||||
|
return resolve(flow);
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Updates an existing flow configuration
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.id - the id of the flow to update
|
||||||
|
* @param {Object} opts.flow - the flow configuration
|
||||||
|
* @return {Promise<String>} - the id of the updated flow
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
updateFlow: function(opts) {
|
||||||
|
return new Promise(function (resolve,reject) {
|
||||||
|
var flow = opts.flow;
|
||||||
|
var id = opts.id;
|
||||||
|
try {
|
||||||
|
runtime.nodes.updateFlow(id,flow).then(function() {
|
||||||
|
runtime.log.audit({event: "flow.update",id:id});
|
||||||
|
return resolve(id);
|
||||||
|
}).catch(function(err) {
|
||||||
|
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
})
|
||||||
|
} catch(err) {
|
||||||
|
if (err.code === 404) {
|
||||||
|
runtime.log.audit({event: "flow.update",id:id,error:"not_found"});
|
||||||
|
// TODO: this swap around of .code and .status isn't ideal
|
||||||
|
err.status = 404;
|
||||||
|
err.code = "not_found";
|
||||||
|
return reject(err);
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Deletes a flow
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.id - the id of the flow to delete
|
||||||
|
* @return {Promise} - resolves if successful
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
deleteFlow: function(opts) {
|
||||||
|
return new Promise(function (resolve,reject) {
|
||||||
|
var id = opts.id;
|
||||||
|
try {
|
||||||
|
runtime.nodes.removeFlow(id).then(function() {
|
||||||
|
log.audit({event: "flow.remove",id:id});
|
||||||
|
return resolve();
|
||||||
|
})
|
||||||
|
} catch(err) {
|
||||||
|
if (err.code === 404) {
|
||||||
|
log.audit({event: "flow.remove",id:id,error:"not_found"});
|
||||||
|
// TODO: this swap around of .code and .status isn't ideal
|
||||||
|
err.status = 404;
|
||||||
|
err.code = "not_found";
|
||||||
|
return reject(err);
|
||||||
|
} else {
|
||||||
|
log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the safe credentials for a node
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.type - the node type to return the credential information for
|
||||||
|
* @param {String} opts.id - the node id
|
||||||
|
* @return {Promise<Object>} - the safe credentials
|
||||||
|
* @memberof RED.flows
|
||||||
|
*/
|
||||||
|
getNodeCredentials: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
log.audit({event: "credentials.get",type:opts.type,id:opts.id});
|
||||||
|
var credentials = runtime.nodes.getCredentials(opts.id);
|
||||||
|
if (!credentials) {
|
||||||
|
return resolve({});
|
||||||
|
}
|
||||||
|
var definition = runtime.nodes.getCredentialDefinition(opts.type);
|
||||||
|
|
||||||
|
var sendCredentials = {};
|
||||||
|
for (var cred in definition) {
|
||||||
|
if (definition.hasOwnProperty(cred)) {
|
||||||
|
if (definition[cred].type == "password") {
|
||||||
|
var key = 'has_' + cred;
|
||||||
|
sendCredentials[key] = credentials[cred] != null && credentials[cred] !== '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sendCredentials[cred] = credentials[cred] || '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(sendCredentials);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
red/runtime-api/index.js
Normal file
64
red/runtime-api/index.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user accessing the API
|
||||||
|
* @typedef User
|
||||||
|
* @type {object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace RED
|
||||||
|
*/
|
||||||
|
var api = module.exports = {
|
||||||
|
init: function(runtime) {
|
||||||
|
api.flows.init(runtime);
|
||||||
|
api.nodes.init(runtime);
|
||||||
|
api.settings.init(runtime);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auth module
|
||||||
|
*/
|
||||||
|
auth: require("./auth"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comms module
|
||||||
|
*/
|
||||||
|
comms: require("./comms"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flows module
|
||||||
|
*/
|
||||||
|
flows: require("./flows"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Library module
|
||||||
|
*/
|
||||||
|
library: require("./library"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nodes module
|
||||||
|
*/
|
||||||
|
nodes: require("./nodes"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings module
|
||||||
|
*/
|
||||||
|
settings: require("./settings")
|
||||||
|
}
|
35
red/runtime-api/library.js
Normal file
35
red/runtime-api/library.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module red/library
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does something
|
||||||
|
*/
|
||||||
|
setEnty: function() {},
|
||||||
|
/**
|
||||||
|
* Does something
|
||||||
|
*/
|
||||||
|
getEntry: function() {},
|
||||||
|
/**
|
||||||
|
* Does something
|
||||||
|
*/
|
||||||
|
getEntries: function() {}
|
||||||
|
}
|
377
red/runtime-api/nodes.js
Normal file
377
red/runtime-api/nodes.js
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
"use strict"
|
||||||
|
/**
|
||||||
|
* @namespace RED.nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
var runtime;
|
||||||
|
|
||||||
|
function putNode(node, enabled) {
|
||||||
|
var promise;
|
||||||
|
if (!node.err && node.enabled === enabled) {
|
||||||
|
promise = Promise.resolve(node);
|
||||||
|
} else {
|
||||||
|
if (enabled) {
|
||||||
|
promise = runtime.nodes.enableNode(node.id);
|
||||||
|
} else {
|
||||||
|
promise = runtime.nodes.disableNode(node.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var api = module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
runtime = _runtime;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the info of an individual node set
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.id - the id of the node set to return
|
||||||
|
* @return {Promise<NodeInfo>} - the node information
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getNodeInfo: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var id = opts.id;
|
||||||
|
var result = redNodes.getNodeInfo(id);
|
||||||
|
if (result) {
|
||||||
|
runtime.log.audit({event: "nodes.info.get",id:id});
|
||||||
|
delete result.loaded;
|
||||||
|
return resolve(result);
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of node modules installed in the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<NodeList>} - the list of node modules
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getNodeList: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
runtime.log.audit({event: "nodes.list.get"});
|
||||||
|
return resolve(runtime.nodes.getNodeList());
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an individual node's html content
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.id - the id of the node set to return
|
||||||
|
* @param {String} opts.lang - the locale language to return
|
||||||
|
* @return {Promise<String>} - the node html content
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getNodeConfig: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var id = opts.id;
|
||||||
|
var lang = opts.lang;
|
||||||
|
var result = runtime.nodes.getNodeConfig(id,lang);
|
||||||
|
if (result) {
|
||||||
|
runtime.log.audit({event: "nodes.config.get",id:id});
|
||||||
|
return resolve(result);
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Gets all node html content
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.lang - the locale language to return
|
||||||
|
* @return {Promise<String>} - the node html content
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getNodeConfigs: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
runtime.log.audit({event: "nodes.configs.get"});
|
||||||
|
return resolve(runtime.nodes.getNodeConfigs(opts.lang));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the info of a node module
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.module - the id of the module to return
|
||||||
|
* @return {Promise<ModuleInfo>} - the node module info
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getModuleInfo: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var module = opts.module;
|
||||||
|
var result = redNodes.getModuleInfo(module);
|
||||||
|
if (result) {
|
||||||
|
runtime.log.audit({event: "nodes.module.get",id:id});
|
||||||
|
return resolve(result);
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "nodes.module.get",id:id,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install a new module into the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.module - the id of the module to install
|
||||||
|
* @param {String} opts.version - (optional) the version of the module to install
|
||||||
|
* @return {Promise<ModuleInfo>} - the node module info
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
addModule: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
if (!runtime.settings.available()) {
|
||||||
|
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"});
|
||||||
|
let err = new Error("Settings unavailable");
|
||||||
|
err.code = "settings_unavailable";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
if (opts.module) {
|
||||||
|
var existingModule = runtime.nodes.getModuleInfo(opts.module);
|
||||||
|
if (existingModule) {
|
||||||
|
if (!opts.version || existingModule.version === opts.version) {
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_already_loaded"});
|
||||||
|
let err = new Error("Module already loaded");
|
||||||
|
err.code = "module_already_loaded";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
if (!module.local) {
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_not_local"});
|
||||||
|
let err = new Error("Module not locally installed");
|
||||||
|
err.code = "module_not_local";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runtime.nodes.installModule(opts.module,opts.version).then(function(info) {
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version});
|
||||||
|
return resolve(info);
|
||||||
|
}).catch(function(err) {
|
||||||
|
if (err.code === 404) {
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:"not_found"});
|
||||||
|
// TODO: code/status
|
||||||
|
err.status = 404;
|
||||||
|
} else if (err.code) {
|
||||||
|
err.status = 400;
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code});
|
||||||
|
} else {
|
||||||
|
err.status = 400;
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
}
|
||||||
|
return reject(err);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"});
|
||||||
|
let err = new Error("Invalid request");
|
||||||
|
err.code = "invalid_request";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Removes a module from the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.module - the id of the module to remove
|
||||||
|
* @return {Promise} - resolves when complete
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
removeModule: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
if (!runtime.settings.available()) {
|
||||||
|
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"});
|
||||||
|
let err = new Error("Settings unavailable");
|
||||||
|
err.code = "settings_unavailable";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
var module = runtime.nodes.getModuleInfo(opts.module);
|
||||||
|
if (!module) {
|
||||||
|
runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
runtime.nodes.uninstallModule(opts.module).then(function() {
|
||||||
|
runtime.log.audit({event: "nodes.remove",module:opts.module});
|
||||||
|
resolve();
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
return reject(err);
|
||||||
|
})
|
||||||
|
} catch(err) {
|
||||||
|
runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables a module in the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.module - the id of the module to enable or disable
|
||||||
|
* @param {String} opts.enabled - whether the module should be enabled or disabled
|
||||||
|
* @return {Promise<ModuleInfo>} - the module info object
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
setModuleState: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
if (!runtime.settings.available()) {
|
||||||
|
runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"});
|
||||||
|
let err = new Error("Settings unavailable");
|
||||||
|
err.code = "settings_unavailable";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var mod = opts.module;
|
||||||
|
var module = runtime.nodes.getModuleInfo(mod);
|
||||||
|
if (!module) {
|
||||||
|
runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodes = module.nodes;
|
||||||
|
var promises = [];
|
||||||
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
|
promises.push(putNode(nodes[i],opts.enabled));
|
||||||
|
}
|
||||||
|
Promise.all(promises).then(function() {
|
||||||
|
return resolve(runtime.nodes.getModuleInfo(mod));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
runtime.log.audit({event: "nodes.module.set",module:mod,enabled:opts.enabled,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables a n individual node-set in the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {String} opts.id - the id of the node-set to enable or disable
|
||||||
|
* @param {String} opts.enabled - whether the module should be enabled or disabled
|
||||||
|
* @return {Promise<ModuleInfo>} - the module info object
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
setNodeSetState: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
if (!runtime.settings.available()) {
|
||||||
|
runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"});
|
||||||
|
let err = new Error("Settings unavailable");
|
||||||
|
err.code = "settings_unavailable";
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = opts.id;
|
||||||
|
var enabled = opts.enabled;
|
||||||
|
try {
|
||||||
|
var node = runtime.nodes.getNodeInfo(id);
|
||||||
|
if (!node) {
|
||||||
|
runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"});
|
||||||
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
} else {
|
||||||
|
delete node.loaded;
|
||||||
|
putNode(node,enabled).then(function(result) {
|
||||||
|
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled});
|
||||||
|
return resolve(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: getModuleCatalogs
|
||||||
|
*/
|
||||||
|
getModuleCatalogs: function() {},
|
||||||
|
/**
|
||||||
|
* TODO: getModuleCatalog
|
||||||
|
*/
|
||||||
|
getModuleCatalog: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of all icons available in the modules installed within the runtime
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<IconList>} - the list of all icons
|
||||||
|
* @memberof RED.nodes
|
||||||
|
*/
|
||||||
|
getIconList: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
runtime.log.audit({event: "nodes.icons.get"});
|
||||||
|
return resolve(runtime.nodes.getNodeIcons());
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* TODO: getIcon
|
||||||
|
*/
|
||||||
|
getIcon: function() {}
|
||||||
|
}
|
257
red/runtime-api/settings.js
Normal file
257
red/runtime-api/settings.js
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace RED.settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
var util = require("util");
|
||||||
|
var runtime;
|
||||||
|
|
||||||
|
function extend(target, source) {
|
||||||
|
var keys = Object.keys(source);
|
||||||
|
var i = keys.length;
|
||||||
|
while(i--) {
|
||||||
|
var value = source[keys[i]]
|
||||||
|
var type = typeof value;
|
||||||
|
if (type === 'string' || type === 'number' || type === 'boolean' || Array.isArray(value)) {
|
||||||
|
target[keys[i]] = value;
|
||||||
|
} else if (value === null) {
|
||||||
|
if (target.hasOwnProperty(keys[i])) {
|
||||||
|
delete target[keys[i]];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Object
|
||||||
|
if (target.hasOwnProperty(keys[i])) {
|
||||||
|
target[keys[i]] = extend(target[keys[i]],value);
|
||||||
|
} else {
|
||||||
|
target[keys[i]] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUsername(userObj) {
|
||||||
|
var username = '__default';
|
||||||
|
if ( userObj && userObj.name ) {
|
||||||
|
username = userObj.name;
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
var api = module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
runtime = _runtime;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Gets the runtime settings object
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<Object>} - the runtime settings
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
getRuntimeSettings: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
try {
|
||||||
|
var safeSettings = {
|
||||||
|
httpNodeRoot: runtime.settings.httpNodeRoot||"/",
|
||||||
|
version: runtime.settings.version,
|
||||||
|
user: opts.user
|
||||||
|
}
|
||||||
|
|
||||||
|
if (util.isArray(runtime.settings.paletteCategories)) {
|
||||||
|
safeSettings.paletteCategories = runtime.settings.paletteCategories;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime.settings.flowFilePretty) {
|
||||||
|
safeSettings.flowFilePretty = runtime.settings.flowFilePretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!runtime.nodes.paletteEditorEnabled()) {
|
||||||
|
safeSettings.editorTheme = safeSettings.editorTheme || {};
|
||||||
|
safeSettings.editorTheme.palette = safeSettings.editorTheme.palette || {};
|
||||||
|
safeSettings.editorTheme.palette.editable = false;
|
||||||
|
}
|
||||||
|
if (runtime.storage.projects) {
|
||||||
|
var activeProject = runtime.storage.projects.getActiveProject();
|
||||||
|
if (activeProject) {
|
||||||
|
safeSettings.project = activeProject;
|
||||||
|
} else if (runtime.storage.projects.flowFileExists()) {
|
||||||
|
safeSettings.files = {
|
||||||
|
flow: runtime.storage.projects.getFlowFilename(),
|
||||||
|
credentials: runtime.storage.projects.getCredentialsFilename()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
safeSettings.git = {
|
||||||
|
globalUser: runtime.storage.projects.getGlobalGitUser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType();
|
||||||
|
|
||||||
|
runtime.settings.exportNodeSettings(safeSettings);
|
||||||
|
|
||||||
|
resolve(safeSettings);
|
||||||
|
}catch(err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an individual user's settings object
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<Object>} - the user settings
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
getUserSettings: function(opts) {
|
||||||
|
var username;
|
||||||
|
if (!opts.user || opts.user.anonymous) {
|
||||||
|
username = '_';
|
||||||
|
} else {
|
||||||
|
username = opts.user.username;
|
||||||
|
}
|
||||||
|
return Promise.resolve(runtime.settings.getUserSettings(username)||{});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an individual user's settings object.
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.settings - the updates to the user settings
|
||||||
|
* @return {Promise<Object>} - the user settings
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
updateUserSettings: function(opts) {
|
||||||
|
var username;
|
||||||
|
if (!opts.user || opts.user.anonymous) {
|
||||||
|
username = '_';
|
||||||
|
} else {
|
||||||
|
username = opts.user.username;
|
||||||
|
}
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var currentSettings = runtime.settings.getUserSettings(username)||{};
|
||||||
|
currentSettings = extend(currentSettings, opts.settings);
|
||||||
|
try {
|
||||||
|
runtime.settings.setUserSettings(username, currentSettings).then(function() {
|
||||||
|
runtime.log.audit({event: "settings.update",username:username});
|
||||||
|
return resolve();
|
||||||
|
}).catch(function(err) {
|
||||||
|
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
log.warn(log._("settings.user-not-available",{message:log._("settings.not-available")}));
|
||||||
|
log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of a user's ssh keys
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @return {Promise<Object>} - the user's ssh keys
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
getUserKeys: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var username = getUsername(opts.user);
|
||||||
|
runtime.storage.projects.ssh.listSSHKeys(username).then(function(list) {
|
||||||
|
return resolve(list);
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a user's ssh public key
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {User} opts.id - the id of the key to return
|
||||||
|
* @return {Promise<String>} - the user's ssh public key
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
getUserKey: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var username = getUsername(opts.user);
|
||||||
|
// console.log('username:', username);
|
||||||
|
runtime.storage.projects.ssh.getSSHKey(username, opts.id).then(function(data) {
|
||||||
|
if (data) {
|
||||||
|
return resolve(data);
|
||||||
|
} else {
|
||||||
|
var err = new Error("Key not found");
|
||||||
|
err.code = "not_found";
|
||||||
|
err.status = 404;
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new ssh key pair
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {User} opts.name - the id of the key to return
|
||||||
|
* @param {User} opts.password - (optional) the password for the key pair
|
||||||
|
* @param {User} opts.comment - (option) a comment to associate with the key pair
|
||||||
|
* @param {User} opts.size - (optional) the size of the key. Default: 2048
|
||||||
|
* @return {Promise<String>} - the id of the generated key
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
generateUserKey: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var username = getUsername(opts.user);
|
||||||
|
runtime.storage.projects.ssh.generateSSHKey(username, opts).then(function(name) {
|
||||||
|
return resolve(name);
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a user's ssh key pair
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {User} opts.id - the id of the key to delete
|
||||||
|
* @return {Promise} - resolves when deleted
|
||||||
|
* @memberof RED.settings
|
||||||
|
*/
|
||||||
|
removeUserKey: function(opts) {
|
||||||
|
return new Promise(function(resolve,reject) {
|
||||||
|
var username = getUsername(req.user);
|
||||||
|
runtime.storage.projects.ssh.deleteSSHKey(username, opts.id).then(function() {
|
||||||
|
return resolve();
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -107,6 +107,11 @@ function getSSHKey(username, name) {
|
|||||||
function generateSSHKey(username, options) {
|
function generateSSHKey(username, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var name = options.name || "";
|
var name = options.name || "";
|
||||||
|
if (!/^[a-zA-Z0-9\-_]+$/.test(options.name)) {
|
||||||
|
var err = new Error("Invalid SSH Key name");
|
||||||
|
e.code = "invalid_key_name";
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
return checkExistSSHKeyFiles(username, name)
|
return checkExistSSHKeyFiles(username, name)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
if ( result ) {
|
if ( result ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user