Merge branch 'dev' into pr_2221

This commit is contained in:
Nick O'Leary 2019-08-12 14:44:30 +01:00
commit 7d4c2442da
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
42 changed files with 434 additions and 214 deletions

View File

@ -28,7 +28,7 @@ To help us understand the issue, please fill-in as much of the following informa
### Please tell us about your environment: ### Please tell us about your environment:
- [ ] Node-RED version: - [ ] Node-RED version:
- [ ] node.js version: - [ ] Node.js version:
- [ ] npm version: - [ ] npm version:
- [ ] Platform/OS: - [ ] Platform/OS:
- [ ] Browser: - [ ] Browser:

View File

@ -33,7 +33,7 @@ To help us understand the issue, please fill-in as much of the following informa
### Please tell us about your environment: ### Please tell us about your environment:
- [ ] Node-RED version: - [ ] Node-RED version:
- [ ] node.js version: - [ ] Node.js version:
- [ ] npm version: - [ ] npm version:
- [ ] Platform/OS: - [ ] Platform/OS:
- [ ] Browser: - [ ] Browser:

View File

@ -9,5 +9,3 @@ matrix:
before_script: before_script:
- npm install -g istanbul coveralls - npm install -g istanbul coveralls
- node_js: "8" - node_js: "8"
allow_failures:
- node_js: "12"

View File

@ -725,7 +725,7 @@ Nodes
- Initial support of sequence rules for SWITCH node (#1545) - Initial support of sequence rules for SWITCH node (#1545)
- initial support of SORT node (#1500) - initial support of SORT node (#1500)
- Inject node - let once delay be editable (#1541) - Inject node - let once delay be editable (#1541)
- Introduce `nodeMaxMessageBufferLength` setting for msg sequence nodes - Introduce `nodeMessageBufferMaxLength` setting for msg sequence nodes
- Let CSV correct parts if we remove header row. - Let CSV correct parts if we remove header row.
- let default apply if msg.delay not set in override mode. (#1397) - let default apply if msg.delay not set in override mode. (#1397)
- let trigger node be reset by boolean message (#1554) - let trigger node be reset by boolean message (#1554)

View File

@ -26,7 +26,7 @@ relevant nodes, press Ctrl-E and copy the flow data from the Export dialog.
At a minimum, please include: At a minimum, please include:
- Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly. - Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly.
- Version of node.js - what does `node -v` say? - Version of Node.js - what does `node -v` say?
## Feature requests ## Feature requests

View File

@ -496,7 +496,9 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-chmod'); grunt.loadNpmTasks('grunt-chmod');
grunt.loadNpmTasks('grunt-jsonlint'); grunt.loadNpmTasks('grunt-jsonlint');
grunt.loadNpmTasks('grunt-mocha-istanbul'); grunt.loadNpmTasks('grunt-mocha-istanbul');
grunt.loadNpmTasks('grunt-webdriver'); if (fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
grunt.loadNpmTasks('grunt-webdriver');
}
grunt.loadNpmTasks('grunt-jsdoc'); grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-jsdoc-to-markdown'); grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
grunt.loadNpmTasks('grunt-npm-command'); grunt.loadNpmTasks('grunt-npm-command');
@ -555,8 +557,8 @@ module.exports = function(grunt) {
}); });
grunt.registerTask('verifyUiTestDependencies', function() { grunt.registerTask('verifyUiTestDependencies', function() {
if (!fs.existsSync(path.join("node_modules", "chromedriver"))) { if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
grunt.fail.fatal('You need to run "npm install chromedriver@2" before running UI test.'); grunt.fail.fatal('You need to install the UI test dependencies first.\nUse the script in "scripts/install-ui-test-dependencies.sh"');
return false; return false;
} }
}); });
@ -579,9 +581,15 @@ module.exports = function(grunt) {
'Runs code style check on editor code', 'Runs code style check on editor code',
['jshint:editor']); ['jshint:editor']);
grunt.registerTask('test-ui', if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
'Builds editor content then runs unit tests on editor ui', grunt.registerTask('test-ui',
['verifyUiTestDependencies','build','jshint:editor','webdriver:all']); 'Builds editor content then runs unit tests on editor ui',
['verifyUiTestDependencies']);
} else {
grunt.registerTask('test-ui',
'Builds editor content then runs unit tests on editor ui',
['verifyUiTestDependencies','build','jshint:editor','webdriver:all']);
}
grunt.registerTask('test-nodes', grunt.registerTask('test-nodes',
'Runs unit tests on core nodes', 'Runs unit tests on core nodes',

View File

@ -95,7 +95,6 @@
"grunt-npm-command": "~0.1.2", "grunt-npm-command": "~0.1.2",
"grunt-sass": "~2.0.0", "grunt-sass": "~2.0.0",
"grunt-simple-mocha": "~0.4.1", "grunt-simple-mocha": "~0.4.1",
"grunt-webdriver": "^2.0.3",
"http-proxy": "^1.16.2", "http-proxy": "^1.16.2",
"istanbul": "0.4.5", "istanbul": "0.4.5",
"minami": "1.2.3", "minami": "1.2.3",
@ -105,10 +104,6 @@
"sinon": "1.17.7", "sinon": "1.17.7",
"stoppable": "^1.1.0", "stoppable": "^1.1.0",
"supertest": "3.4.2", "supertest": "3.4.2",
"wdio-chromedriver-service": "^0.1.5",
"wdio-mocha-framework": "^0.6.4",
"wdio-spec-reporter": "^0.1.5",
"webdriverio": "^4.14.1",
"node-red-node-test-helper": "^0.2.3", "node-red-node-test-helper": "^0.2.3",
"jsdoc-nr-template": "node-red/jsdoc-nr-template" "jsdoc-nr-template": "node-red/jsdoc-nr-template"
}, },

View File

@ -30,7 +30,8 @@ module.exports = {
scope: req.params.scope, scope: req.params.scope,
id: req.params.id, id: req.params.id,
key: req.params[0], key: req.params[0],
store: req.query['store'] store: req.query['store'],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.context.getValue(opts).then(function(result) { runtimeAPI.context.getValue(opts).then(function(result) {
res.json(result); res.json(result);
@ -45,7 +46,8 @@ module.exports = {
scope: req.params.scope, scope: req.params.scope,
id: req.params.id, id: req.params.id,
key: req.params[0], key: req.params[0],
store: req.query['store'] store: req.query['store'],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.context.delete(opts).then(function(result) { runtimeAPI.context.delete(opts).then(function(result) {
res.status(204).end(); res.status(204).end();

View File

@ -24,7 +24,8 @@ module.exports = {
get: function(req,res) { get: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.flows.getFlow(opts).then(function(result) { runtimeAPI.flows.getFlow(opts).then(function(result) {
return res.json(result); return res.json(result);
@ -35,7 +36,8 @@ module.exports = {
post: function(req,res) { post: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
flow: req.body flow: req.body,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.flows.addFlow(opts).then(function(id) { runtimeAPI.flows.addFlow(opts).then(function(id) {
return res.json({id:id}); return res.json({id:id});
@ -47,7 +49,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
flow: req.body flow: req.body,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.flows.updateFlow(opts).then(function(id) { runtimeAPI.flows.updateFlow(opts).then(function(id) {
return res.json({id:id}); return res.json({id:id});
@ -58,7 +61,8 @@ module.exports = {
delete: function(req,res) { delete: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.flows.deleteFlow(opts).then(function() { runtimeAPI.flows.deleteFlow(opts).then(function() {
res.status(204).end(); res.status(204).end();

View File

@ -27,7 +27,8 @@ module.exports = {
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"}); return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
} }
var opts = { var opts = {
user: req.user user: req.user,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.flows.getFlows(opts).then(function(result) { runtimeAPI.flows.getFlows(opts).then(function(result) {
if (version === "v1") { if (version === "v1") {
@ -46,7 +47,8 @@ module.exports = {
} }
var opts = { var opts = {
user: req.user, user: req.user,
deploymentType: req.get("Node-RED-Deployment-Type")||"full" deploymentType: req.get("Node-RED-Deployment-Type")||"full",
req: apiUtils.getRequestLogObject(req)
} }
if (opts.deploymentType !== 'reload') { if (opts.deploymentType !== 'reload') {

View File

@ -48,13 +48,13 @@ module.exports = {
// Nodes // Nodes
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler); adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler); adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
adminApp.get(/\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler); adminApp.get(/^\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler); adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler); adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler); adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler);
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler); adminApp.delete(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler); adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler); adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
// Context // Context
adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler); adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler);

View File

@ -24,7 +24,8 @@ module.exports = {
}, },
getAll: function(req,res) { getAll: function(req,res) {
var opts = { var opts = {
user: req.user user: req.user,
req: apiUtils.getRequestLogObject(req)
} }
if (req.get("accept") == "application/json") { if (req.get("accept") == "application/json") {
runtimeAPI.nodes.getNodeList(opts).then(function(list) { runtimeAPI.nodes.getNodeList(opts).then(function(list) {
@ -42,7 +43,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
module: req.body.module, module: req.body.module,
version: req.body.version version: req.body.version,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.addModule(opts).then(function(info) { runtimeAPI.nodes.addModule(opts).then(function(info) {
res.json(info); res.json(info);
@ -54,7 +56,8 @@ module.exports = {
delete: function(req,res) { delete: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
module: req.params[0] module: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.removeModule(opts).then(function() { runtimeAPI.nodes.removeModule(opts).then(function() {
res.status(204).end(); res.status(204).end();
@ -66,7 +69,8 @@ module.exports = {
getSet: function(req,res) { getSet: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params[0] + "/" + req.params[2] id: req.params[0] + "/" + req.params[2],
req: apiUtils.getRequestLogObject(req)
} }
if (req.get("accept") === "application/json") { if (req.get("accept") === "application/json") {
runtimeAPI.nodes.getNodeInfo(opts).then(function(result) { runtimeAPI.nodes.getNodeInfo(opts).then(function(result) {
@ -87,7 +91,8 @@ module.exports = {
getModule: function(req,res) { getModule: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
module: req.params[0] module: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.getModuleInfo(opts).then(function(result) { runtimeAPI.nodes.getModuleInfo(opts).then(function(result) {
res.send(result); res.send(result);
@ -106,7 +111,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params[0] + "/" + req.params[2], id: req.params[0] + "/" + req.params[2],
enabled: body.enabled enabled: body.enabled,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.setNodeSetState(opts).then(function(result) { runtimeAPI.nodes.setNodeSetState(opts).then(function(result) {
res.send(result); res.send(result);
@ -125,7 +131,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
module: req.params[0], module: req.params[0],
enabled: body.enabled enabled: body.enabled,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.setModuleState(opts).then(function(result) { runtimeAPI.nodes.setModuleState(opts).then(function(result) {
res.send(result); res.send(result);
@ -139,7 +146,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
module: req.params[0], module: req.params[0],
lang: req.query.lng lang: req.query.lng,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) { runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) {
res.json(result); res.json(result);
@ -152,7 +160,8 @@ module.exports = {
getModuleCatalogs: function(req,res) { getModuleCatalogs: function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
lang: req.query.lng lang: req.query.lng,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) { runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) {
res.json(result); res.json(result);
@ -164,7 +173,8 @@ module.exports = {
getIcons: function(req,res) { getIcons: function(req,res) {
var opts = { var opts = {
user: req.user user: req.user,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.nodes.getIconList(opts).then(function(list) { runtimeAPI.nodes.getIconList(opts).then(function(list) {
res.json(list); res.json(list);

View File

@ -22,7 +22,8 @@ var needsPermission = require("../auth").needsPermission;
function listProjects(req,res) { function listProjects(req,res) {
var opts = { var opts = {
user: req.user user: req.user,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.listProjects(opts).then(function(result) { runtimeAPI.projects.listProjects(opts).then(function(result) {
res.json(result); res.json(result);
@ -33,7 +34,8 @@ function listProjects(req,res) {
function getProject(req,res) { function getProject(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getProject(opts).then(function(data) { runtimeAPI.projects.getProject(opts).then(function(data) {
if (data) { if (data) {
@ -49,7 +51,8 @@ function getProjectStatus(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: req.query.remote remote: req.query.remote,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getStatus(opts).then(function(data){ runtimeAPI.projects.getStatus(opts).then(function(data){
if (data) { if (data) {
@ -64,7 +67,8 @@ function getProjectStatus(req,res) {
function getProjectRemotes(req,res) { function getProjectRemotes(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getRemotes(opts).then(function(data) { runtimeAPI.projects.getRemotes(opts).then(function(data) {
res.json(data); res.json(data);
@ -98,7 +102,8 @@ module.exports = {
app.post("/", needsPermission("projects.write"), function(req,res) { app.post("/", needsPermission("projects.write"), function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
project: req.body project: req.body,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.createProject(opts).then(function(result) { runtimeAPI.projects.createProject(opts).then(function(result) {
res.json(result); res.json(result);
@ -112,7 +117,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
project: req.body project: req.body,
req: apiUtils.getRequestLogObject(req)
} }
if (req.body.active) { if (req.body.active) {
@ -150,7 +156,8 @@ module.exports = {
app.delete("/:id", needsPermission("projects.write"), function(req,res) { app.delete("/:id", needsPermission("projects.write"), function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.deleteProject(opts).then(function() { runtimeAPI.projects.deleteProject(opts).then(function() {
res.status(204).end(); res.status(204).end();
@ -168,7 +175,8 @@ module.exports = {
app.get("/:id/files", needsPermission("projects.read"), function(req,res) { app.get("/:id/files", needsPermission("projects.read"), function(req,res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getFiles(opts).then(function(data) { runtimeAPI.projects.getFiles(opts).then(function(data) {
res.json(data); res.json(data);
@ -185,7 +193,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0], path: req.params[0],
tree: req.params.treeish tree: req.params.treeish,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getFile(opts).then(function(data) { runtimeAPI.projects.getFile(opts).then(function(data) {
res.json({content:data}); res.json({content:data});
@ -199,7 +208,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0] path: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.revertFile(opts).then(function() { runtimeAPI.projects.revertFile(opts).then(function() {
@ -214,7 +224,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0] path: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.stageFile(opts).then(function() { runtimeAPI.projects.stageFile(opts).then(function() {
getProjectStatus(req,res); getProjectStatus(req,res);
@ -228,7 +239,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.body.files path: req.body.files,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.stageFile(opts).then(function() { runtimeAPI.projects.stageFile(opts).then(function() {
getProjectStatus(req,res); getProjectStatus(req,res);
@ -242,7 +254,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
message: req.body.message message: req.body.message,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.commit(opts).then(function() { runtimeAPI.projects.commit(opts).then(function() {
getProjectStatus(req,res); getProjectStatus(req,res);
@ -256,7 +269,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0] path: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.unstageFile(opts).then(function() { runtimeAPI.projects.unstageFile(opts).then(function() {
getProjectStatus(req,res); getProjectStatus(req,res);
@ -269,7 +283,8 @@ module.exports = {
app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) { app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.unstageFile(opts).then(function() { runtimeAPI.projects.unstageFile(opts).then(function() {
getProjectStatus(req,res); getProjectStatus(req,res);
@ -284,7 +299,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0], path: req.params[0],
type: req.params.type type: req.params.type,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getFileDiff(opts).then(function(data) { runtimeAPI.projects.getFileDiff(opts).then(function(data) {
res.json({ res.json({
@ -301,7 +317,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
limit: req.query.limit || 20, limit: req.query.limit || 20,
before: req.query.before before: req.query.before,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getCommits(opts).then(function(data) { runtimeAPI.projects.getCommits(opts).then(function(data) {
res.json(data); res.json(data);
@ -315,7 +332,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
sha: req.params.sha sha: req.params.sha,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getCommit(opts).then(function(data) { runtimeAPI.projects.getCommit(opts).then(function(data) {
res.json({commit:data}); res.json({commit:data});
@ -330,7 +348,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: req.params[0], remote: req.params[0],
track: req.query.u track: req.query.u,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.push(opts).then(function(data) { runtimeAPI.projects.push(opts).then(function(data) {
res.status(204).end(); res.status(204).end();
@ -346,7 +365,8 @@ module.exports = {
id: req.params.id, id: req.params.id,
remote: req.params[0], remote: req.params[0],
track: req.query.setUpstream, track: req.query.setUpstream,
allowUnrelatedHistories: req.query.allowUnrelatedHistories allowUnrelatedHistories: req.query.allowUnrelatedHistories,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.pull(opts).then(function(data) { runtimeAPI.projects.pull(opts).then(function(data) {
res.status(204).end(); res.status(204).end();
@ -359,7 +379,8 @@ module.exports = {
app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) { app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id id: req.params.id,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.abortMerge(opts).then(function() { runtimeAPI.projects.abortMerge(opts).then(function() {
res.status(204).end(); res.status(204).end();
@ -374,7 +395,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
path: req.params[0], path: req.params[0],
resolution: req.body.resolutions resolution: req.body.resolutions,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.resolveMerge(opts).then(function() { runtimeAPI.projects.resolveMerge(opts).then(function() {
res.status(204).end(); res.status(204).end();
@ -388,7 +410,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: false remote: false,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getBranches(opts).then(function(data) { runtimeAPI.projects.getBranches(opts).then(function(data) {
res.json(data); res.json(data);
@ -403,7 +426,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
branch: req.params.branchName, branch: req.params.branchName,
force: !!req.query.force force: !!req.query.force,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.deleteBranch(opts).then(function(data) { runtimeAPI.projects.deleteBranch(opts).then(function(data) {
res.status(204).end(); res.status(204).end();
@ -417,7 +441,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: true remote: true,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getBranches(opts).then(function(data) { runtimeAPI.projects.getBranches(opts).then(function(data) {
res.json(data); res.json(data);
@ -431,7 +456,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
branch: req.params[0] branch: req.params[0],
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.getBranchStatus(opts).then(function(data) { runtimeAPI.projects.getBranchStatus(opts).then(function(data) {
res.json(data); res.json(data);
@ -446,7 +472,8 @@ module.exports = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
branch: req.body.name, branch: req.body.name,
create: req.body.create create: req.body.create,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.setBranch(opts).then(function(data) { runtimeAPI.projects.setBranch(opts).then(function(data) {
res.json(data); res.json(data);
@ -463,7 +490,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: req.body remote: req.body,
req: apiUtils.getRequestLogObject(req)
} }
if (/^https?:\/\/[^/]+@/i.test(req.body.url)) { if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"}); res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
@ -481,7 +509,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: req.params.remoteName remote: req.params.remoteName,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.removeRemote(opts).then(function(data) { runtimeAPI.projects.removeRemote(opts).then(function(data) {
getProjectRemotes(req,res); getProjectRemotes(req,res);
@ -497,7 +526,8 @@ module.exports = {
var opts = { var opts = {
user: req.user, user: req.user,
id: req.params.id, id: req.params.id,
remote: remote remote: remote,
req: apiUtils.getRequestLogObject(req)
} }
runtimeAPI.projects.updateRemote(opts).then(function() { runtimeAPI.projects.updateRemote(opts).then(function() {
res.status(204).end(); res.status(204).end();

View File

@ -47,5 +47,12 @@ module.exports = {
code: err.code||"unexpected_error", code: err.code||"unexpected_error",
message: err.message||err.toString() message: err.message||err.toString()
}); });
},
getRequestLogObject: function(req) {
return {
user: req.user,
path: req.path,
ip: (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined
}
} }
} }

View File

@ -80,7 +80,7 @@
"projects-new": "新規", "projects-new": "新規",
"projects-open": "開く", "projects-open": "開く",
"projects-settings": "設定", "projects-settings": "設定",
"showNodeLabelDefault": "追加したノードのラベルを表示する" "showNodeLabelDefault": "追加したノードのラベルを表示"
} }
}, },
"actions": { "actions": {
@ -351,7 +351,8 @@
"pasteNode": "ノードを貼り付け", "pasteNode": "ノードを貼り付け",
"undoChange": "変更操作を戻す", "undoChange": "変更操作を戻す",
"searchBox": "ノードを検索", "searchBox": "ノードを検索",
"managePalette": "パレットの管理" "managePalette": "パレットの管理",
"actionList": "動作一覧"
}, },
"library": { "library": {
"library": "ライブラリ", "library": "ライブラリ",
@ -527,11 +528,13 @@
"none": "選択されていません", "none": "選択されていません",
"refresh": "読み込みのため更新してください", "refresh": "読み込みのため更新してください",
"empty": "データが存在しません", "empty": "データが存在しません",
"node": "Node", "node": "ノード",
"flow": "Flow", "flow": "フロー",
"global": "Global", "global": "グローバル",
"deleteConfirm": "データを削除しても良いですか?", "deleteConfirm": "データを削除しても良いですか?",
"autoRefresh": "自動更新" "autoRefresh": "自動更新",
"refrsh": "更新",
"delete": "削除"
}, },
"palette": { "palette": {
"name": "パレットの管理", "name": "パレットの管理",
@ -736,7 +739,16 @@
}, },
"jsonEditor": { "jsonEditor": {
"title": "JSONエディタ", "title": "JSONエディタ",
"format": "JSONフォーマット" "format": "JSONフォーマット",
"rawMode": "JSONを編集",
"uiMode": "ビジュアルエディタ",
"insertAbove": "上に挿入",
"insertBelow": "下に挿入",
"addItem": "要素を追加",
"copyPath": "要素のパスをコピー",
"expandItems": "要素を展開",
"collapseItems": "要素を折り畳む",
"duplicate": "複製"
}, },
"markdownEditor": { "markdownEditor": {
"title": "マークダウンエディタ", "title": "マークダウンエディタ",
@ -930,7 +942,7 @@
"appearance": "外観", "appearance": "外観",
"env": "環境変数" "env": "環境変数"
}, },
"languages" : { "languages": {
"de": "ドイツ語", "de": "ドイツ語",
"en-US": "英語", "en-US": "英語",
"ja": "日本語", "ja": "日本語",

View File

@ -526,7 +526,7 @@ RED.editor = (function() {
} else if (node.type.indexOf("subflow:")===0) { } else if (node.type.indexOf("subflow:")===0) {
var subflow = RED.nodes.subflow(node.type.substring(8)); var subflow = RED.nodes.subflow(node.type.substring(8));
label = RED._("subflow.editSubflowInstance",{name:RED.utils.sanitize(subflow.name)}) label = RED._("subflow.editSubflowInstance",{name:RED.utils.sanitize(subflow.name)})
} else { } else if (node._def !== undefined) {
if (typeof node._def.paletteLabel !== "undefined") { if (typeof node._def.paletteLabel !== "undefined") {
try { try {
label = RED.utils.sanitize((typeof node._def.paletteLabel === "function" ? node._def.paletteLabel.call(node._def) : node._def.paletteLabel)||""); label = RED.utils.sanitize((typeof node._def.paletteLabel === "function" ? node._def.paletteLabel.call(node._def) : node._def.paletteLabel)||"");

View File

@ -152,7 +152,7 @@ RED.palette = (function() {
function getPaletteNode(type) { function getPaletteNode(type) {
return $(".red-ui-palette-node[data-palette-type='"+type+"']"); return $(".red-ui-palette-node[data-palette-type='"+type+"']");
} }
function addNodeType(nt,def) { function addNodeType(nt,def) {
if (getPaletteNode(nt).length) { if (getPaletteNode(nt).length) {
return; return;
@ -241,7 +241,6 @@ RED.palette = (function() {
RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp")); RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp"));
}); });
var chart = $("#red-ui-workspace-chart"); var chart = $("#red-ui-workspace-chart");
var chartOffset = chart.offset();
var chartSVG = $("#red-ui-workspace-chart>svg").get(0); var chartSVG = $("#red-ui-workspace-chart>svg").get(0);
var activeSpliceLink; var activeSpliceLink;
var mouseX; var mouseX;
@ -265,8 +264,8 @@ RED.palette = (function() {
ui.originalPosition.left = $('#' + e.target.id).offset().left; ui.originalPosition.left = $('#' + e.target.id).offset().left;
if (def.inputs > 0 && def.outputs > 0) { if (def.inputs > 0 && def.outputs > 0) {
mouseX = ui.position.left-paletteWidth+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft(); mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
mouseY = ui.position.top-paletteTop+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop(); mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop();
if (!spliceTimer) { if (!spliceTimer) {
spliceTimer = setTimeout(function() { spliceTimer = setTimeout(function() {
var nodes = []; var nodes = [];
@ -416,7 +415,7 @@ RED.palette = (function() {
createCategory(newCategory,category,category,"node-red"); createCategory(newCategory,category,category,"node-red");
var currentCategoryNode = paletteNode.closest(".red-ui-palette-category"); var currentCategoryNode = paletteNode.closest(".red-ui-palette-category");
var newCategoryNode = $("#palette-"+category); var newCategoryNode = $("#red-ui-palette-"+category);
newCategoryNode.append(paletteNode); newCategoryNode.append(paletteNode);
if (newCategoryNode.find(".red-ui-palette-node").length === 1) { if (newCategoryNode.find(".red-ui-palette-node").length === 1) {
categoryContainers[category].open(); categoryContainers[category].open();
@ -429,9 +428,6 @@ RED.palette = (function() {
currentCategoryNode.find("i").toggleClass("expanded"); currentCategoryNode.find("i").toggleClass("expanded");
} }
} }
} }
}); });
} }

View File

@ -3167,7 +3167,7 @@ RED.view = (function() {
var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill; var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill;
thisNode.selectAll(".red-ui-flow-node-status").style("display","inline").attr("class","red-ui-flow-node-status "+statusClass); thisNode.selectAll(".red-ui-flow-node-status").style("display","inline").attr("class","red-ui-flow-node-status "+statusClass);
} }
if (d.status.text) { if (d.status.hasOwnProperty('text')) {
thisNode.selectAll(".red-ui-flow-node-status-label").text(d.status.text); thisNode.selectAll(".red-ui-flow-node-status-label").text(d.status.text);
} else { } else {
thisNode.selectAll(".red-ui-flow-node-status-label").text(""); thisNode.selectAll(".red-ui-flow-node-status-label").text("");

View File

@ -42,14 +42,14 @@ RED.debug = (function() {
var content = $("<div>").css({"position":"relative","height":"100%"}); var content = $("<div>").css({"position":"relative","height":"100%"});
var toolbar = $('<div class="red-ui-sidebar-header">'+ var toolbar = $('<div class="red-ui-sidebar-header">'+
'<span class="button-group"><a id="red-ui-sidebar-debug-filter" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span></a></span>'+ '<span class="button-group"><a id="red-ui-sidebar-debug-filter" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span></a></span>'+
'<span class="button-group"><a id="red-ui-sidebar-debug-clear" class="red-ui-sidebar-header-button" href="#" data-i18n="[title]node-red:debug.sidebar.clearLog"><i class="fa fa-trash"></i></a></span></div>').appendTo(content); '<span class="button-group"><a id="red-ui-sidebar-debug-clear" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-trash"></i></a></span></div>').appendTo(content);
var footerToolbar = $('<div>'+ var footerToolbar = $('<div>'+
// '<span class="button-group">'+ // '<span class="button-group">'+
// '<a class="red-ui-footer-button-toggle text-button selected" id="red-ui-sidebar-debug-view-list" href="#"><span data-i18n="">list</span></a>'+ // '<a class="red-ui-footer-button-toggle text-button selected" id="red-ui-sidebar-debug-view-list" href="#"><span data-i18n="">list</span></a>'+
// '<a class="red-ui-footer-button-toggle text-button" id="red-ui-sidebar-debug-view-table" href="#"><span data-i18n="">table</span></a> '+ // '<a class="red-ui-footer-button-toggle text-button" id="red-ui-sidebar-debug-view-table" href="#"><span data-i18n="">table</span></a> '+
// '</span>'+ // '</span>'+
'<span class="button-group"><a id="red-ui-sidebar-debug-open" class="red-ui-footer-button" href="#" data-i18n="[title]node-red:debug.sidebar.openWindow"><i class="fa fa-desktop"></i></a></span> ' + '<span class="button-group"><a id="red-ui-sidebar-debug-open" class="red-ui-footer-button" href="#"><i class="fa fa-desktop"></i></a></span> ' +
'</div>'); '</div>');
messageList = $('<div class="red-ui-debug-content red-ui-debug-content-list"/>').appendTo(content); messageList = $('<div class="red-ui-debug-content red-ui-debug-content-list"/>').appendTo(content);

View File

@ -372,7 +372,6 @@
}, },
oneditsave: function() { oneditsave: function() {
var rules = $("#node-input-rule-container").editableList('items'); var rules = $("#node-input-rule-container").editableList('items');
var ruleset;
var node = this; var node = this;
node.rules = []; node.rules = [];
rules.each(function(i) { rules.each(function(i) {

View File

@ -226,7 +226,6 @@
}, },
oneditsave: function() { oneditsave: function() {
var rules = $("#node-input-rule-container").editableList('items'); var rules = $("#node-input-rule-container").editableList('items');
var ruleset;
var node = this; var node = this;
node.rules= []; node.rules= [];
rules.each(function(i) { rules.each(function(i) {

View File

@ -42,7 +42,7 @@ module.exports = function(RED) {
node.addname = n.addname || ""; node.addname = n.addname || "";
try { try {
if (node.spltType === "str") { if (node.spltType === "str") {
this.splt = (n.splt || "\\n").replace(/\\n/,"\n").replace(/\\r/,"\r").replace(/\\t/,"\t").replace(/\\e/,"\e").replace(/\\f/,"\f").replace(/\\0/,"\0"); this.splt = (n.splt || "\\n").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t").replace(/\\e/g,"\e").replace(/\\f/g,"\f").replace(/\\0/g,"\0");
} else if (node.spltType === "bin") { } else if (node.spltType === "bin") {
var spltArray = JSON.parse(n.splt); var spltArray = JSON.parse(n.splt);
if (Array.isArray(spltArray)) { if (Array.isArray(spltArray)) {

View File

@ -22,12 +22,12 @@
<dd>Sets the delay, in milliseconds, to be applied to the message. This <dd>Sets the delay, in milliseconds, to be applied to the message. This
option only applies if the node is configured to allow the message to option only applies if the node is configured to allow the message to
override the configured default delay interval.</dd> override the configured default delay interval.</dd>
<dt class="optional">reset</dt> <dt class="optional">reset</dt>
<dd>If the received message has this property set to any value, all <dd>If the received message has this property set to any value, all
outstanding messages held by the node are cleared without being sent.</dd> outstanding messages held by the node are cleared without being sent.</dd>
<dt class="optional">flush</dt> <dt class="optional">flush</dt>
<dd>If the received message has this property set to any value, all <dd>If the received message has this property set to any value, all
outstanding messages held by the node are sent immediately.</dd> outstanding messages held by the node are sent immediately.</dd>
</dl> </dl>
<h3>Details</h3> <h3>Details</h3>
<p>When configured to delay messages, the delay interval can be a fixed value, <p>When configured to delay messages, the delay interval can be a fixed value,

View File

@ -22,6 +22,8 @@
<dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd> <dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd>
<dt class="optional">reset</dt> <dt class="optional">reset</dt>
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd> <dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
<dt class="optional">flush</dt>
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージを直ちに送信します。</dd>
</dl> </dl>
<h3>詳細</h3> <h3>詳細</h3>
<p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。</p> <p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。</p>

View File

@ -7,7 +7,8 @@
"username": "ユーザ名", "username": "ユーザ名",
"password": "パスワード", "password": "パスワード",
"property": "プロパティ", "property": "プロパティ",
"selectNodes": "ノードを選択..." "selectNodes": "ノードを選択...",
"expand": "展開"
}, },
"status": { "status": {
"connected": "接続済", "connected": "接続済",
@ -137,7 +138,10 @@
"debugNodes": "debugード", "debugNodes": "debugード",
"clearLog": "ログを削除", "clearLog": "ログを削除",
"filterLog": "ログのフィルタリング", "filterLog": "ログのフィルタリング",
"openWindow": "新しいウィンドウで開く" "openWindow": "新しいウィンドウで開く",
"copyPath": "パスをコピー",
"copyPayload": "値をコピー",
"pinPath": "展開を固定"
}, },
"messageMenu": { "messageMenu": {
"collapseAll": "全パスを折りたたむ", "collapseAll": "全パスを折りたたむ",
@ -615,7 +619,8 @@
"tail": "tail", "tail": "tail",
"index": "index between", "index": "index between",
"exp": "JSONata式", "exp": "JSONata式",
"else": "その他" "else": "その他",
"hask": "has key"
}, },
"errors": { "errors": {
"invalid-expr": "不正な表現: __error__", "invalid-expr": "不正な表現: __error__",

View File

@ -67,7 +67,7 @@ var api = module.exports = {
* @param {String} opts.id - the id of the context * @param {String} opts.id - the id of the context
* @param {String} opts.store - the context store * @param {String} opts.store - the context store
* @param {String} opts.key - the context key * @param {String} opts.key - the context key
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - the node information * @return {Promise} - the node information
* @memberof @node-red/runtime_context * @memberof @node-red/runtime_context
*/ */
@ -81,7 +81,7 @@ var api = module.exports = {
var availableStores = runtime.nodes.listContextStores(); var availableStores = runtime.nodes.listContextStores();
//{ default: 'default', stores: [ 'default', 'file' ] } //{ default: 'default', stores: [ 'default', 'file' ] }
if (store && availableStores.stores.indexOf(store) === -1) { if (store && availableStores.stores.indexOf(store) === -1) {
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -106,7 +106,7 @@ var api = module.exports = {
if (store !== availableStores.default) { if (store !== availableStores.default) {
encoded.store = store; encoded.store = store;
} }
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}, opts.req);
resolve(encoded); resolve(encoded);
}); });
return; return;
@ -127,7 +127,7 @@ var api = module.exports = {
// TODO: proper error reporting // TODO: proper error reporting
if (!errorReported) { if (!errorReported) {
errorReported = true; errorReported = true;
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"unexpected_error"}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"unexpected_error"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "unexpected_error"; err.code = "unexpected_error";
err.status = 400; err.status = 400;
@ -139,7 +139,7 @@ var api = module.exports = {
c--; c--;
if (c === 0) { if (c === 0) {
if (!errorReported) { if (!errorReported) {
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key},opts.req);
resolve(result); resolve(result);
} }
} }
@ -147,7 +147,7 @@ var api = module.exports = {
}) })
} }
} else { } else {
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key},opts.req);
resolve({}); resolve({});
} }
}) })
@ -161,7 +161,7 @@ var api = module.exports = {
* @param {String} opts.id - the id of the context * @param {String} opts.id - the id of the context
* @param {String} opts.store - the context store * @param {String} opts.store - the context store
* @param {String} opts.key - the context key * @param {String} opts.key - the context key
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - the node information * @return {Promise} - the node information
* @memberof @node-red/runtime_context * @memberof @node-red/runtime_context
*/ */
@ -175,7 +175,7 @@ var api = module.exports = {
var availableStores = runtime.nodes.listContextStores(); var availableStores = runtime.nodes.listContextStores();
//{ default: 'default', stores: [ 'default', 'file' ] } //{ default: 'default', stores: [ 'default', 'file' ] }
if (store && availableStores.stores.indexOf(store) === -1) { if (store && availableStores.stores.indexOf(store) === -1) {
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"},opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -196,13 +196,13 @@ var api = module.exports = {
if (key) { if (key) {
store = store || availableStores.default; store = store || availableStores.default;
ctx.set(key,undefined,store,function(err) { ctx.set(key,undefined,store,function(err) {
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key}); runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key},opts.req);
resolve(); resolve();
}); });
return; return;
} else { } else {
// TODO: support deleting whole context // TODO: support deleting whole context
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"},opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -243,7 +243,7 @@ var api = module.exports = {
// }) // })
} }
} else { } else {
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key}); runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key},opts.req);
resolve(); resolve();
} }

View File

@ -43,12 +43,13 @@ var api = module.exports = {
* Gets the current flow configuration * Gets the current flow configuration
* @param {Object} opts * @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<Flows>} - the active flow configuration * @return {Promise<Flows>} - the active flow configuration
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
getFlows: function(opts) { getFlows: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.log.audit({event: "flows.get"}/*,req*/); runtime.log.audit({event: "flows.get"}, opts.req);
return resolve(runtime.nodes.getFlows()); return resolve(runtime.nodes.getFlows());
}); });
}, },
@ -56,6 +57,7 @@ var api = module.exports = {
* Sets the current flow configuration * Sets the current flow configuration
* @param {Object} opts * @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<Flows>} - the active flow configuration * @return {Promise<Flows>} - the active flow configuration
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
@ -64,7 +66,7 @@ var api = module.exports = {
var flows = opts.flows; var flows = opts.flows;
var deploymentType = opts.deploymentType||"full"; var deploymentType = opts.deploymentType||"full";
runtime.log.audit({event: "flows.set",type:deploymentType}/*,req*/); runtime.log.audit({event: "flows.set",type:deploymentType}, opts.req);
var apiPromise; var apiPromise;
if (deploymentType === 'reload') { if (deploymentType === 'reload') {
@ -98,6 +100,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.flow - the flow to add * @param {Object} opts.flow - the flow to add
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the id of the added flow * @return {Promise<String>} - the id of the added flow
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
@ -105,10 +108,10 @@ var api = module.exports = {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
var flow = opts.flow; var flow = opts.flow;
runtime.nodes.addFlow(flow).then(function(id) { runtime.nodes.addFlow(flow).then(function(id) {
runtime.log.audit({event: "flow.add",id:id}); runtime.log.audit({event: "flow.add",id:id}, opts.req);
return resolve(id); return resolve(id);
}).catch(function(err) { }).catch(function(err) {
runtime.log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
}) })
@ -122,6 +125,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.id - the id of the flow to retrieve * @param {Object} opts.id - the id of the flow to retrieve
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Flow>} - the active flow configuration * @return {Promise<Flow>} - the active flow configuration
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
@ -129,10 +133,10 @@ var api = module.exports = {
return new Promise(function (resolve,reject) { return new Promise(function (resolve,reject) {
var flow = runtime.nodes.getFlow(opts.id); var flow = runtime.nodes.getFlow(opts.id);
if (flow) { if (flow) {
runtime.log.audit({event: "flow.get",id:opts.id}); runtime.log.audit({event: "flow.get",id:opts.id}, opts.req);
return resolve(flow); return resolve(flow);
} else { } else {
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"}); runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -147,6 +151,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.id - the id of the flow to update * @param {Object} opts.id - the id of the flow to update
* @param {Object} opts.flow - the flow configuration * @param {Object} opts.flow - the flow configuration
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the id of the updated flow * @return {Promise<String>} - the id of the updated flow
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
@ -156,22 +161,22 @@ var api = module.exports = {
var id = opts.id; var id = opts.id;
try { try {
runtime.nodes.updateFlow(id,flow).then(function() { runtime.nodes.updateFlow(id,flow).then(function() {
runtime.log.audit({event: "flow.update",id:id}); runtime.log.audit({event: "flow.update",id:id}, opts.req);
return resolve(id); return resolve(id);
}).catch(function(err) { }).catch(function(err) {
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
}) })
} catch(err) { } catch(err) {
if (err.code === 404) { if (err.code === 404) {
runtime.log.audit({event: "flow.update",id:id,error:"not_found"}); runtime.log.audit({event: "flow.update",id:id,error:"not_found"}, opts.req);
// TODO: this swap around of .code and .status isn't ideal // TODO: this swap around of .code and .status isn't ideal
err.status = 404; err.status = 404;
err.code = "not_found"; err.code = "not_found";
return reject(err); return reject(err);
} else { } else {
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
} }
@ -184,6 +189,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.id - the id of the flow to delete * @param {Object} opts.id - the id of the flow to delete
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - resolves if successful * @return {Promise} - resolves if successful
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
@ -192,22 +198,22 @@ var api = module.exports = {
var id = opts.id; var id = opts.id;
try { try {
runtime.nodes.removeFlow(id).then(function() { runtime.nodes.removeFlow(id).then(function() {
runtime.log.audit({event: "flow.remove",id:id}); runtime.log.audit({event: "flow.remove",id:id}, opts.req);
return resolve(); return resolve();
}).catch(function(err) { }).catch(function(err) {
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
}); });
} catch(err) { } catch(err) {
if (err.code === 404) { if (err.code === 404) {
runtime.log.audit({event: "flow.remove",id:id,error:"not_found"}); runtime.log.audit({event: "flow.remove",id:id,error:"not_found"}, opts.req);
// TODO: this swap around of .code and .status isn't ideal // TODO: this swap around of .code and .status isn't ideal
err.status = 404; err.status = 404;
err.code = "not_found"; err.code = "not_found";
return reject(err); return reject(err);
} else { } else {
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
} }
@ -221,12 +227,13 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @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.type - the node type to return the credential information for
* @param {String} opts.id - the node id * @param {String} opts.id - the node id
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the safe credentials * @return {Promise<Object>} - the safe credentials
* @memberof @node-red/runtime_flows * @memberof @node-red/runtime_flows
*/ */
getNodeCredentials: function(opts) { getNodeCredentials: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.log.audit({event: "credentials.get",type:opts.type,id:opts.id}); runtime.log.audit({event: "credentials.get",type:opts.type,id:opts.id}, opts.req);
var credentials = runtime.nodes.getCredentials(opts.id); var credentials = runtime.nodes.getCredentials(opts.id);
if (!credentials) { if (!credentials) {
return resolve({}); return resolve({});

View File

@ -32,13 +32,14 @@ var api = module.exports = {
* @param {String} opts.library - the library * @param {String} opts.library - the library
* @param {String} opts.type - the type of entry * @param {String} opts.type - the type of entry
* @param {String} opts.path - the path of the entry * @param {String} opts.path - the path of the entry
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String|Object>} - resolves when complete * @return {Promise<String|Object>} - resolves when complete
* @memberof @node-red/runtime_library * @memberof @node-red/runtime_library
*/ */
getEntry: function(opts) { getEntry: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.library.getEntry(opts.library,opts.type,opts.path).then(function(result) { runtime.library.getEntry(opts.library,opts.type,opts.path).then(function(result) {
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path}); runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path}, opts.req);
return resolve(result); return resolve(result);
}).catch(function(err) { }).catch(function(err) {
if (err) { if (err) {
@ -51,10 +52,10 @@ var api = module.exports = {
} else { } else {
err.status = 400; err.status = 400;
} }
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}); runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}, opts.req);
return reject(err); return reject(err);
} }
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}); runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}, opts.req);
var error = new Error(); var error = new Error();
error.code = "not_found"; error.code = "not_found";
error.status = 404; error.status = 404;
@ -72,22 +73,23 @@ var api = module.exports = {
* @param {String} opts.path - the path of the entry * @param {String} opts.path - the path of the entry
* @param {Object} opts.meta - any meta data associated with the entry * @param {Object} opts.meta - any meta data associated with the entry
* @param {String} opts.body - the body of the entry * @param {String} opts.body - the body of the entry
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - resolves when complete * @return {Promise} - resolves when complete
* @memberof @node-red/runtime_library * @memberof @node-red/runtime_library
*/ */
saveEntry: function(opts) { saveEntry: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.library.saveEntry(opts.library,opts.type,opts.path,opts.meta,opts.body).then(function() { runtime.library.saveEntry(opts.library,opts.type,opts.path,opts.meta,opts.body).then(function() {
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path}); runtime.log.audit({event: "library.set",type:opts.type,path:opts.path}, opts.req);
return resolve(); return resolve();
}).catch(function(err) { }).catch(function(err) {
runtime.log.warn(runtime.log._("api.library.error-save-entry",{path:opts.path,message:err.toString()})); runtime.log.warn(runtime.log._("api.library.error-save-entry",{path:opts.path,message:err.toString()}));
if (err.code === 'forbidden') { if (err.code === 'forbidden') {
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"forbidden"}); runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"forbidden"}, opts.req);
err.status = 403; err.status = 403;
return reject(err); return reject(err);
} }
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"unexpected_error",message:err.toString()}); runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"unexpected_error",message:err.toString()}, opts.req);
var error = new Error(); var error = new Error();
error.status = 400; error.status = 400;
return reject(error); return reject(error);

View File

@ -48,6 +48,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the node set to return * @param {String} opts.id - the id of the node set to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<NodeInfo>} - the node information * @return {Promise<NodeInfo>} - the node information
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -56,11 +57,11 @@ var api = module.exports = {
var id = opts.id; var id = opts.id;
var result = runtime.nodes.getNodeInfo(id); var result = runtime.nodes.getNodeInfo(id);
if (result) { if (result) {
runtime.log.audit({event: "nodes.info.get",id:id}); runtime.log.audit({event: "nodes.info.get",id:id}, opts.req);
delete result.loaded; delete result.loaded;
return resolve(result); return resolve(result);
} else { } else {
runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"}); runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -73,12 +74,13 @@ var api = module.exports = {
* Gets the list of node modules installed in the runtime * Gets the list of node modules installed in the runtime
* @param {Object} opts * @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<NodeList>} - the list of node modules * @return {Promise<NodeList>} - the list of node modules
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
getNodeList: function(opts) { getNodeList: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.log.audit({event: "nodes.list.get"}); runtime.log.audit({event: "nodes.list.get"}, opts.req);
return resolve(runtime.nodes.getNodeList()); return resolve(runtime.nodes.getNodeList());
}) })
}, },
@ -89,6 +91,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the node set to return * @param {String} opts.id - the id of the node set to return
* @param {String} opts.lang - the locale language to return * @param {String} opts.lang - the locale language to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the node html content * @return {Promise<String>} - the node html content
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -98,10 +101,10 @@ var api = module.exports = {
var lang = opts.lang; var lang = opts.lang;
var result = runtime.nodes.getNodeConfig(id,lang); var result = runtime.nodes.getNodeConfig(id,lang);
if (result) { if (result) {
runtime.log.audit({event: "nodes.config.get",id:id}); runtime.log.audit({event: "nodes.config.get",id:id}, opts.req);
return resolve(result); return resolve(result);
} else { } else {
runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"}); runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -114,12 +117,13 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.lang - the locale language to return * @param {String} opts.lang - the locale language to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the node html content * @return {Promise<String>} - the node html content
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
getNodeConfigs: function(opts) { getNodeConfigs: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.log.audit({event: "nodes.configs.get"}); runtime.log.audit({event: "nodes.configs.get"}, opts.req);
return resolve(runtime.nodes.getNodeConfigs(opts.lang)); return resolve(runtime.nodes.getNodeConfigs(opts.lang));
}); });
}, },
@ -129,6 +133,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.module - the id of the module to return * @param {String} opts.module - the id of the module to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<ModuleInfo>} - the node module info * @return {Promise<ModuleInfo>} - the node module info
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -136,10 +141,10 @@ var api = module.exports = {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
var result = runtime.nodes.getModuleInfo(opts.module); var result = runtime.nodes.getModuleInfo(opts.module);
if (result) { if (result) {
runtime.log.audit({event: "nodes.module.get",id:opts.module}); runtime.log.audit({event: "nodes.module.get",id:opts.module}, opts.req);
return resolve(result); return resolve(result);
} else { } else {
runtime.log.audit({event: "nodes.module.get",id:opts.module,error:"not_found"}); runtime.log.audit({event: "nodes.module.get",id:opts.module,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -154,13 +159,14 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.module - the id of the module to install * @param {String} opts.module - the id of the module to install
* @param {String} opts.version - (optional) the version of the module to install * @param {String} opts.version - (optional) the version of the module to install
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<ModuleInfo>} - the node module info * @return {Promise<ModuleInfo>} - the node module info
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
addModule: function(opts) { addModule: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
if (!runtime.settings.available()) { if (!runtime.settings.available()) {
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}); runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req);
var err = new Error("Settings unavailable"); var err = new Error("Settings unavailable");
err.code = "settings_unavailable"; err.code = "settings_unavailable";
err.status = 400; err.status = 400;
@ -170,7 +176,7 @@ var api = module.exports = {
var existingModule = runtime.nodes.getModuleInfo(opts.module); var existingModule = runtime.nodes.getModuleInfo(opts.module);
if (existingModule) { if (existingModule) {
if (!opts.version || existingModule.version === opts.version) { if (!opts.version || existingModule.version === opts.version) {
runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_already_loaded"}); runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_already_loaded"}, opts.req);
var err = new Error("Module already loaded"); var err = new Error("Module already loaded");
err.code = "module_already_loaded"; err.code = "module_already_loaded";
err.status = 400; err.status = 400;
@ -178,24 +184,24 @@ var api = module.exports = {
} }
} }
runtime.nodes.installModule(opts.module,opts.version).then(function(info) { runtime.nodes.installModule(opts.module,opts.version).then(function(info) {
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version}); runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version}, opts.req);
return resolve(info); return resolve(info);
}).catch(function(err) { }).catch(function(err) {
if (err.code === 404) { if (err.code === 404) {
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:"not_found"}); runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:"not_found"}, opts.req);
// TODO: code/status // TODO: code/status
err.status = 404; err.status = 404;
} else if (err.code) { } else if (err.code) {
err.status = 400; err.status = 400;
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code}); runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code}, opts.req);
} else { } else {
err.status = 400; err.status = 400;
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
} }
return reject(err); return reject(err);
}) })
} else { } else {
runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}); runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}, opts.req);
var err = new Error("Invalid request"); var err = new Error("Invalid request");
err.code = "invalid_request"; err.code = "invalid_request";
err.status = 400; err.status = 400;
@ -209,13 +215,14 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.module - the id of the module to remove * @param {String} opts.module - the id of the module to remove
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - resolves when complete * @return {Promise} - resolves when complete
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
removeModule: function(opts) { removeModule: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
if (!runtime.settings.available()) { if (!runtime.settings.available()) {
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}); runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req);
var err = new Error("Settings unavailable"); var err = new Error("Settings unavailable");
err.code = "settings_unavailable"; err.code = "settings_unavailable";
err.status = 400; err.status = 400;
@ -223,7 +230,7 @@ var api = module.exports = {
} }
var module = runtime.nodes.getModuleInfo(opts.module); var module = runtime.nodes.getModuleInfo(opts.module);
if (!module) { if (!module) {
runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}); runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -231,15 +238,15 @@ var api = module.exports = {
} }
try { try {
runtime.nodes.uninstallModule(opts.module).then(function() { runtime.nodes.uninstallModule(opts.module).then(function() {
runtime.log.audit({event: "nodes.remove",module:opts.module}); runtime.log.audit({event: "nodes.remove",module:opts.module}, opts.req);
resolve(); resolve();
}).catch(function(err) { }).catch(function(err) {
err.status = 400; err.status = 400;
runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
return reject(err); return reject(err);
}) })
} catch(error) { } catch(error) {
runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}); runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}, opts.req);
error.status = 400; error.status = 400;
return reject(error); return reject(error);
} }
@ -252,6 +259,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @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.module - the id of the module to enable or disable
* @param {String} opts.enabled - whether the module should be enabled or disabled * @param {String} opts.enabled - whether the module should be enabled or disabled
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<ModuleInfo>} - the module info object * @return {Promise<ModuleInfo>} - the module info object
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -259,7 +267,7 @@ var api = module.exports = {
var mod = opts.module; var mod = opts.module;
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
if (!runtime.settings.available()) { if (!runtime.settings.available()) {
runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}); runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}, opts.req);
var err = new Error("Settings unavailable"); var err = new Error("Settings unavailable");
err.code = "settings_unavailable"; err.code = "settings_unavailable";
err.status = 400; err.status = 400;
@ -268,7 +276,7 @@ var api = module.exports = {
try { try {
var module = runtime.nodes.getModuleInfo(mod); var module = runtime.nodes.getModuleInfo(mod);
if (!module) { if (!module) {
runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}); runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -287,7 +295,7 @@ var api = module.exports = {
return reject(err); return reject(err);
}); });
} catch(error) { } catch(error) {
runtime.log.audit({event: "nodes.module.set",module:mod,enabled:opts.enabled,error:error.code||"unexpected_error",message:error.toString()}); runtime.log.audit({event: "nodes.module.set",module:mod,enabled:opts.enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req);
error.status = 400; error.status = 400;
return reject(error); return reject(error);
} }
@ -300,13 +308,14 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @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.id - the id of the node-set to enable or disable
* @param {String} opts.enabled - whether the module should be enabled or disabled * @param {String} opts.enabled - whether the module should be enabled or disabled
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<ModuleInfo>} - the module info object * @return {Promise<ModuleInfo>} - the module info object
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
setNodeSetState: function(opts) { setNodeSetState: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
if (!runtime.settings.available()) { if (!runtime.settings.available()) {
runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}); runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}, opts.req);
var err = new Error("Settings unavailable"); var err = new Error("Settings unavailable");
err.code = "settings_unavailable"; err.code = "settings_unavailable";
err.status = 400; err.status = 400;
@ -318,7 +327,7 @@ var api = module.exports = {
try { try {
var node = runtime.nodes.getNodeInfo(id); var node = runtime.nodes.getNodeInfo(id);
if (!node) { if (!node) {
runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}); runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}, opts.req);
var err = new Error(); var err = new Error();
err.code = "not_found"; err.code = "not_found";
err.status = 404; err.status = 404;
@ -326,16 +335,16 @@ var api = module.exports = {
} else { } else {
delete node.loaded; delete node.loaded;
putNode(node,enabled).then(function(result) { putNode(node,enabled).then(function(result) {
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled}); runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled}, opts.req);
return resolve(result); return resolve(result);
}).catch(function(err) { }).catch(function(err) {
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
}); });
} }
} catch(error) { } catch(error) {
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}); runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req);
error.status = 400; error.status = 400;
return reject(error); return reject(error);
} }
@ -347,6 +356,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US) * @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US)
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the message catalogs * @return {Promise<Object>} - the message catalogs
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -376,6 +386,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {User} opts.module - the module * @param {User} opts.module - the module
* @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US) * @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US)
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the message catalog * @return {Promise<Object>} - the message catalog
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
@ -397,12 +408,13 @@ var api = module.exports = {
* Gets the list of all icons available in the modules installed within the runtime * Gets the list of all icons available in the modules installed within the runtime
* @param {Object} opts * @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<IconList>} - the list of all icons * @return {Promise<IconList>} - the list of all icons
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */
getIconList: function(opts) { getIconList: function(opts) {
return new Promise(function(resolve,reject) { return new Promise(function(resolve,reject) {
runtime.log.audit({event: "nodes.icons.get"}); runtime.log.audit({event: "nodes.icons.get"}, opts.req);
return resolve(runtime.nodes.getNodeIcons()); return resolve(runtime.nodes.getNodeIcons());
}); });
@ -413,6 +425,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.module - the id of the module requesting the icon * @param {String} opts.module - the id of the module requesting the icon
* @param {String} opts.icon - the name of the icon * @param {String} opts.icon - the name of the icon
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Buffer>} - the icon file as a Buffer or null if no icon available * @return {Promise<Buffer>} - the icon file as a Buffer or null if no icon available
* @memberof @node-red/runtime_nodes * @memberof @node-red/runtime_nodes
*/ */

View File

@ -27,11 +27,12 @@ var api = module.exports = {
available: function(opts) { available: function(opts) {
return Promise.resolve(!!runtime.storage.projects); return Promise.resolve(!!runtime.storage.projects);
}, },
/** /**
* List projects known to the runtime * List projects known to the runtime
* @param {Object} opts * @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)
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -56,10 +57,12 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.project - the project information * @param {Object} opts.project - the project information
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
createProject: function(opts) { createProject: function(opts) {
runtime.log.audit({event: "projects.create",name:opts.project?opts.project.name:"missing-name"}, opts.req);
return runtime.storage.projects.createProject(opts.user, opts.project) return runtime.storage.projects.createProject(opts.user, opts.project)
}, },
@ -69,11 +72,13 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project to initialise * @param {String} opts.id - the id of the project to initialise
* @param {Object} opts.project - the project information * @param {Object} opts.project - the project information
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
initialiseProject: function(opts) { initialiseProject: function(opts) {
// Initialised set when creating default files for an empty repo // Initialised set when creating default files for an empty repo
runtime.log.audit({event: "projects.initialise",id:opts.id}, opts.req);
return runtime.storage.projects.initialiseProject(opts.user, opts.id, opts.project) return runtime.storage.projects.initialiseProject(opts.user, opts.id, opts.project)
}, },
@ -81,6 +86,7 @@ var api = module.exports = {
* Gets the active project * Gets the active project
* @param {Object} opts * @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<Object>} - the active project * @return {Promise<Object>} - the active project
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -93,11 +99,13 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project to activate * @param {String} opts.id - the id of the project to activate
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
setActiveProject: function(opts) { setActiveProject: function(opts) {
var currentProject = runtime.storage.projects.getActiveProject(opts.user); var currentProject = runtime.storage.projects.getActiveProject(opts.user);
runtime.log.audit({event: "projects.set",id:opts.id}, opts.req);
if (!currentProject || opts.id !== currentProject.name) { if (!currentProject || opts.id !== currentProject.name) {
return runtime.storage.projects.setActiveProject(opts.user, opts.id); return runtime.storage.projects.setActiveProject(opts.user, opts.id);
} else { } else {
@ -110,6 +118,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project to get * @param {String} opts.id - the id of the project to get
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the project metadata * @return {Promise<Object>} - the project metadata
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -123,10 +132,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project to update * @param {String} opts.id - the id of the project to update
* @param {Object} opts.project - the project information * @param {Object} opts.project - the project information
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
updateProject: function(opts) { updateProject: function(opts) {
runtime.log.audit({event: "projects.update",id:opts.id}, opts.req);
return runtime.storage.projects.updateProject(opts.user, opts.id, opts.project); return runtime.storage.projects.updateProject(opts.user, opts.id, opts.project);
}, },
@ -135,10 +146,12 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project to update * @param {String} opts.id - the id of the project to update
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
deleteProject: function(opts) { deleteProject: function(opts) {
runtime.log.audit({event: "projects.delete",id:opts.id}, opts.req);
return runtime.storage.projects.deleteProject(opts.user, opts.id); return runtime.storage.projects.deleteProject(opts.user, opts.id);
}, },
@ -148,6 +161,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Boolean} opts.remote - whether to include status of remote repos * @param {Boolean} opts.remote - whether to include status of remote repos
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the project status * @return {Promise<Object>} - the project status
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -161,6 +175,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Boolean} opts.remote - whether to return remote branches (true) or local (false) * @param {Boolean} opts.remote - whether to return remote branches (true) or local (false)
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - a list of the local branches * @return {Promise<Object>} - a list of the local branches
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -174,6 +189,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.branch - the name of the branch * @param {String} opts.branch - the name of the branch
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the status of the branch * @return {Promise<Object>} - the status of the branch
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -188,10 +204,12 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.branch - the name of the branch * @param {String} opts.branch - the name of the branch
* @param {Boolean} opts.create - whether to create the branch if it doesn't exist * @param {Boolean} opts.create - whether to create the branch if it doesn't exist
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
setBranch: function(opts) { setBranch: function(opts) {
runtime.log.audit({event: "projects.branch.set",id:opts.id, branch: opts.branch, create:opts.create}, opts.req);
return runtime.storage.projects.setBranch(opts.user, opts.id, opts.branch, opts.create) return runtime.storage.projects.setBranch(opts.user, opts.id, opts.branch, opts.create)
}, },
@ -202,10 +220,12 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.branch - the name of the branch * @param {String} opts.branch - the name of the branch
* @param {Boolean} opts.force - whether to force delete * @param {Boolean} opts.force - whether to force delete
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
deleteBranch: function(opts) { deleteBranch: function(opts) {
runtime.log.audit({event: "projects.branch.delete",id:opts.id, branch: opts.branch, force:opts.force}, opts.req);
return runtime.storage.projects.deleteBranch(opts.user, opts.id, opts.branch, false, opts.force); return runtime.storage.projects.deleteBranch(opts.user, opts.id, opts.branch, false, opts.force);
}, },
@ -215,10 +235,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.message - the message to associate with the commit * @param {String} opts.message - the message to associate with the commit
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
commit: function(opts) { commit: function(opts) {
runtime.log.audit({event: "projects.commit",id:opts.id}, opts.req);
return runtime.storage.projects.commit(opts.user, opts.id,{message: opts.message}); return runtime.storage.projects.commit(opts.user, opts.id,{message: opts.message});
}, },
@ -228,6 +250,7 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.sha - the sha of the commit to return * @param {String} opts.sha - the sha of the commit to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the commit details * @return {Promise<Object>} - the commit details
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -242,6 +265,7 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.limit - limit how many to return * @param {String} opts.limit - limit how many to return
* @param {String} opts.before - id of the commit to work back from * @param {String} opts.before - id of the commit to work back from
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Array>} - an array of commits * @return {Promise<Array>} - an array of commits
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -257,10 +281,12 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
abortMerge: function(opts) { abortMerge: function(opts) {
runtime.log.audit({event: "projects.merge.abort",id:opts.id}, opts.req);
return runtime.storage.projects.abortMerge(opts.user, opts.id); return runtime.storage.projects.abortMerge(opts.user, opts.id);
}, },
@ -271,10 +297,12 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.path - the path of the file being merged * @param {String} opts.path - the path of the file being merged
* @param {String} opts.resolutions - how to resolve the merge conflict * @param {String} opts.resolutions - how to resolve the merge conflict
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
resolveMerge: function(opts) { resolveMerge: function(opts) {
runtime.log.audit({event: "projects.merge.resolve",id:opts.id, file:opts.path}, opts.req);
return runtime.storage.projects.resolveMerge(opts.user, opts.id, opts.path, opts.resolution); return runtime.storage.projects.resolveMerge(opts.user, opts.id, opts.path, opts.resolution);
}, },
@ -283,6 +311,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the file listing * @return {Promise<Object>} - the file listing
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -297,6 +326,7 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.path - the path of the file * @param {String} opts.path - the path of the file
* @param {String} opts.tree - the version control tree to use * @param {String} opts.tree - the version control tree to use
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the content of the file * @return {Promise<String>} - the content of the file
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -310,10 +340,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String|Array} opts.path - the path of the file, or an array of paths * @param {String|Array} opts.path - the path of the file, or an array of paths
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
stageFile: function(opts) { stageFile: function(opts) {
runtime.log.audit({event: "projects.file.stage",id:opts.id, file:opts.path}, opts.req);
return runtime.storage.projects.stageFile(opts.user, opts.id, opts.path); return runtime.storage.projects.stageFile(opts.user, opts.id, opts.path);
}, },
@ -323,10 +355,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.path - the path of the file. If not set, all staged files are unstaged * @param {String} opts.path - the path of the file. If not set, all staged files are unstaged
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
unstageFile: function(opts) { unstageFile: function(opts) {
runtime.log.audit({event: "projects.file.unstage",id:opts.id, file:opts.path}, opts.req);
return runtime.storage.projects.unstageFile(opts.user, opts.id, opts.path); return runtime.storage.projects.unstageFile(opts.user, opts.id, opts.path);
}, },
@ -336,10 +370,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.path - the path of the file * @param {String} opts.path - the path of the file
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
revertFile: function(opts) { revertFile: function(opts) {
runtime.log.audit({event: "projects.file.revert",id:opts.id, file:opts.path}, opts.req);
return runtime.storage.projects.revertFile(opts.user, opts.id,opts.path) return runtime.storage.projects.revertFile(opts.user, opts.id,opts.path)
}, },
@ -350,6 +386,7 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.path - the path of the file * @param {String} opts.path - the path of the file
* @param {String} opts.type - the type of diff * @param {String} opts.type - the type of diff
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the requested diff * @return {Promise<Object>} - the requested diff
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -362,6 +399,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - a list of project remotes * @return {Promise<Object>} - a list of project remotes
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
@ -378,10 +416,12 @@ var api = module.exports = {
* @param {Object} opts.remote - the remote metadata * @param {Object} opts.remote - the remote metadata
* @param {String} opts.remote.name - the name of the remote * @param {String} opts.remote.name - the name of the remote
* @param {String} opts.remote.url - the url of the remote * @param {String} opts.remote.url - the url of the remote
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
addRemote: function(opts) { addRemote: function(opts) {
runtime.log.audit({event: "projects.remote.add",id:opts.id, remote:opts.remote.name}, opts.req);
return runtime.storage.projects.addRemote(opts.user, opts.id, opts.remote) return runtime.storage.projects.addRemote(opts.user, opts.id, opts.remote)
}, },
@ -391,10 +431,12 @@ var api = module.exports = {
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.remote - the name of the remote * @param {String} opts.remote - the name of the remote
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
removeRemote: function(opts) { removeRemote: function(opts) {
runtime.log.audit({event: "projects.remote.delete",id:opts.id, remote:opts.remote}, opts.req);
return runtime.storage.projects.removeRemote(opts.user, opts.id, opts.remote); return runtime.storage.projects.removeRemote(opts.user, opts.id, opts.remote);
}, },
@ -405,10 +447,12 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {Object} opts.remote - the remote metadata * @param {Object} opts.remote - the remote metadata
* @param {String} opts.remote.name - the name of the remote * @param {String} opts.remote.name - the name of the remote
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
updateRemote: function(opts) { updateRemote: function(opts) {
runtime.log.audit({event: "projects.remote.update",id:opts.id, remote:opts.remote.name}, opts.req);
return runtime.storage.projects.updateRemote(opts.user, opts.id, opts.remote.name, opts.remote) return runtime.storage.projects.updateRemote(opts.user, opts.id, opts.remote.name, opts.remote)
}, },
@ -416,10 +460,15 @@ var api = module.exports = {
* Pull changes from the remote * Pull changes from the remote
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {String} opts.remote - the remote to pull
* @param {Boolean} opts.track - whether to track this remote
* @param {Boolean} opts.allowUnrelatedHistories -
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
pull: function(opts) { pull: function(opts) {
runtime.log.audit({event: "projects.pull",id:opts.id, remote: opts.remote, track:opts.track}, opts.req);
return runtime.storage.projects.pull(opts.user, opts.id, opts.remote, opts.track, opts.allowUnrelatedHistories); return runtime.storage.projects.pull(opts.user, opts.id, opts.remote, opts.track, opts.allowUnrelatedHistories);
}, },
@ -430,10 +479,12 @@ var api = module.exports = {
* @param {String} opts.id - the id of the project * @param {String} opts.id - the id of the project
* @param {String} opts.remote - the name of the remote * @param {String} opts.remote - the name of the remote
* @param {String} opts.track - whether to set the remote as the upstream * @param {String} opts.track - whether to set the remote as the upstream
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - resolves when complete * @return {Promise<Object>} - resolves when complete
* @memberof @node-red/runtime_projects * @memberof @node-red/runtime_projects
*/ */
push: function(opts) { push: function(opts) {
runtime.log.audit({event: "projects.push",id:opts.id, remote: opts.remote, track:opts.track}, opts.req);
return runtime.storage.projects.push(opts.user, opts.id, opts.remote, opts.track); return runtime.storage.projects.push(opts.user, opts.id, opts.remote, opts.track);
} }

View File

@ -60,6 +60,7 @@ var api = module.exports = {
* Gets the runtime settings object * Gets the runtime settings object
* @param {Object} opts * @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<Object>} - the runtime settings * @return {Promise<Object>} - the runtime settings
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -125,6 +126,7 @@ var api = module.exports = {
* Gets an individual user's settings object * Gets an individual user's settings object
* @param {Object} opts * @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<Object>} - the user settings * @return {Promise<Object>} - the user settings
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -143,6 +145,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {Object} opts.settings - the updates to the user settings * @param {Object} opts.settings - the updates to the user settings
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<Object>} - the user settings * @return {Promise<Object>} - the user settings
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -158,16 +161,16 @@ var api = module.exports = {
currentSettings = extend(currentSettings, opts.settings); currentSettings = extend(currentSettings, opts.settings);
try { try {
runtime.settings.setUserSettings(username, currentSettings).then(function() { runtime.settings.setUserSettings(username, currentSettings).then(function() {
runtime.log.audit({event: "settings.update",username:username}); runtime.log.audit({event: "settings.update",username:username}, opts.req);
return resolve(); return resolve();
}).catch(function(err) { }).catch(function(err) {
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
}); });
} catch(err) { } catch(err) {
runtime.log.warn(runtime.log._("settings.user-not-available",{message:runtime.log._("settings.not-available")})); runtime.log.warn(runtime.log._("settings.user-not-available",{message:runtime.log._("settings.not-available")}));
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}); runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}, opts.req);
err.status = 400; err.status = 400;
return reject(err); return reject(err);
} }
@ -178,6 +181,7 @@ var api = module.exports = {
* Gets a list of a user's ssh keys * Gets a list of a user's ssh keys
* @param {Object} opts * @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<Object>} - the user's ssh keys * @return {Promise<Object>} - the user's ssh keys
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -198,6 +202,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {User} opts.id - the id of the key to return * @param {User} opts.id - the id of the key to return
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the user's ssh public key * @return {Promise<String>} - the user's ssh public key
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -229,6 +234,7 @@ var api = module.exports = {
* @param {User} opts.password - (optional) the password for the key pair * @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.comment - (option) a comment to associate with the key pair
* @param {User} opts.size - (optional) the size of the key. Default: 2048 * @param {User} opts.size - (optional) the size of the key. Default: 2048
* @param {Object} opts.req - the request to log (optional)
* @return {Promise<String>} - the id of the generated key * @return {Promise<String>} - the id of the generated key
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */
@ -249,6 +255,7 @@ var api = module.exports = {
* @param {Object} opts * @param {Object} opts
* @param {User} opts.user - the user calling the api * @param {User} opts.user - the user calling the api
* @param {User} opts.id - the id of the key to delete * @param {User} opts.id - the id of the key to delete
* @param {Object} opts.req - the request to log (optional)
* @return {Promise} - resolves when deleted * @return {Promise} - resolves when deleted
* @memberof @node-red/runtime_settings * @memberof @node-red/runtime_settings
*/ */

View File

@ -129,7 +129,7 @@ function start() {
log.info(log._("runtime.version",{component:"Node.js ",version:process.version})); log.info(log._("runtime.version",{component:"Node.js ",version:process.version}));
if (settings.UNSUPPORTED_VERSION) { if (settings.UNSUPPORTED_VERSION) {
log.error("*****************************************************************"); log.error("*****************************************************************");
log.error("* "+log._("runtime.unsupported_version",{component:"Node.js",version:process.version,requires: ">=4"})+" *"); log.error("* "+log._("runtime.unsupported_version",{component:"Node.js",version:process.version,requires: ">=8.9.0"})+" *");
log.error("*****************************************************************"); log.error("*****************************************************************");
events.emit("runtime-event",{id:"runtime-unsupported-version",payload:{type:"error",text:"notification.errors.unsupportedVersion"},retain:true}); events.emit("runtime-event",{id:"runtime-unsupported-version",payload:{type:"error",text:"notification.errors.unsupportedVersion"},retain:true});
} }

View File

@ -272,7 +272,7 @@ Node.prototype.error = function(logMessage,msg) {
logMessage = logMessage || ""; logMessage = logMessage || "";
} }
var handled = false; var handled = false;
if (msg) { if (msg && typeof msg === 'object') {
handled = this._flow.handleError(this,logMessage,msg); handled = this._flow.handleError(this,logMessage,msg);
} }
if (!handled) { if (!handled) {

View File

@ -234,7 +234,7 @@ function createContext(id,seed,parent) {
if (err.code === "INVALID_EXPR") { if (err.code === "INVALID_EXPR") {
throw err; throw err;
} }
value[0] = undefined; values[0] = undefined;
} }
} }
} else { } else {
@ -246,7 +246,7 @@ function createContext(id,seed,parent) {
if (err.code === "INVALID_EXPR") { if (err.code === "INVALID_EXPR") {
throw err; throw err;
} }
value[i] = undefined; values[i] = undefined;
} }
} }
} }

View File

@ -51,6 +51,12 @@ function runSshKeygenCommand(args,cwd,env) {
resolve(stdout); resolve(stdout);
} }
}); });
child.on('error', function(err) {
if (/ENOENT/.test(err.toString())) {
err.code = "command_not_found";
}
reject(err);
});
}); });
} }

View File

@ -214,7 +214,7 @@ var log = module.exports = {
if (req) { if (req) {
msg.user = req.user; msg.user = req.user;
msg.path = req.path; msg.path = req.path;
msg.ip = (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined; msg.ip = req.ip || (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined;
} }
log.log(msg); log.log(msg);
} }

View File

@ -27,9 +27,9 @@ var apiEnabled = false;
function checkVersion(userSettings) { function checkVersion(userSettings) {
var semver = require('semver'); var semver = require('semver');
if (!semver.satisfies(process.version,">=4.8.0")) { if (!semver.satisfies(process.version,">=8.9.0")) {
// TODO: in the future, make this a hard error. // TODO: in the future, make this a hard error.
// var e = new Error("Unsupported version of node.js"); // var e = new Error("Unsupported version of Node.js");
// e.code = "unsupported_version"; // e.code = "unsupported_version";
// throw e; // throw e;
userSettings.UNSUPPORTED_VERSION = process.version; userSettings.UNSUPPORTED_VERSION = process.version;
@ -39,7 +39,7 @@ function checkVersion(userSettings) {
* This module provides the full Node-RED application, with both the runtime * This module provides the full Node-RED application, with both the runtime
* and editor components built in. * and editor components built in.
* *
* The API this module exposes allows it to be embedded within another node.js * The API this module exposes allows it to be embedded within another Node.js
* application. * application.
* *
* @namespace node-red * @namespace node-red

View File

@ -197,10 +197,8 @@ try {
RED.init(server,settings); RED.init(server,settings);
} catch(err) { } catch(err) {
if (err.code == "unsupported_version") { if (err.code == "unsupported_version") {
console.log("Unsupported version of node.js:",process.version); console.log("Unsupported version of Node.js:",process.version);
console.log("Node-RED requires node.js v4 or later"); console.log("Node-RED requires Node.js v8.9.0 or later");
} else if (err.code == "not_built") {
console.log("Node-RED has not been built. See README.md for details");
} else { } else {
console.log("Failed to start server:"); console.log("Failed to start server:");
if (err.stack) { if (err.stack) {

View File

@ -55,7 +55,7 @@ module.exports = {
// The maximum number of messages nodes will buffer internally as part of their // The maximum number of messages nodes will buffer internally as part of their
// operation. This applies across a range of nodes that operate on message sequences. // operation. This applies across a range of nodes that operate on message sequences.
// defaults to no limit. A value of 0 also means no limit is applied. // defaults to no limit. A value of 0 also means no limit is applied.
//nodeMaxMessageBufferLength: 0, //nodeMessageBufferMaxLength: 0,
// To disable the option for using local files for storing keys and certificates in the TLS configuration // To disable the option for using local files for storing keys and certificates in the TLS configuration
// node, set this to true // node, set this to true

View File

@ -0,0 +1,7 @@
npm install --no-save \
grunt-webdriver@^2.0.3 \
wdio-chromedriver-service@^0.1.5 \
wdio-mocha-framework@^0.6.4 \
wdio-spec-reporter@^0.1.5 \
webdriverio@^4.14.1 \
chromedriver@2

View File

@ -441,7 +441,7 @@ describe("api/admin/nodes", function() {
nodes.init({ nodes.init({
nodes:{ nodes:{
getModuleCatalog: function(opts) { getModuleCatalog: function(opts) {
return Promise.resolve(opts); return Promise.resolve({a:123});
} }
} }
}); });
@ -452,7 +452,7 @@ describe("api/admin/nodes", function() {
if (err) { if (err) {
throw err; throw err;
} }
res.body.should.eql({ module: 'module/set' }); res.body.should.eql({a:123});
done(); done();
}); });
}); });

View File

@ -57,7 +57,9 @@ describe("runtime-api/settings", function() {
}); });
describe("listProjects", function() { describe("listProjects", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
listProjects: sinon.spy(function(user) { listProjects: sinon.spy(function(user) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -105,7 +107,9 @@ describe("runtime-api/settings", function() {
}); });
describe("createProject", function() { describe("createProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
createProject: sinon.spy(function(user,project) { createProject: sinon.spy(function(user,project) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -138,7 +142,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("initialiseProject", function() { describe("initialiseProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
initialiseProject: sinon.spy(function(user,id,project) { initialiseProject: sinon.spy(function(user,id,project) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -172,7 +178,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getActiveProject", function() { describe("getActiveProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getActiveProject: sinon.spy(function(user) { getActiveProject: sinon.spy(function(user) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -209,7 +217,9 @@ describe("runtime-api/settings", function() {
var activeProject; var activeProject;
var runtime; var runtime;
beforeEach(function() { beforeEach(function() {
runtime = {storage: {projects: { runtime = {
log: mockLog(),
storage: {projects: {
getActiveProject: sinon.spy(function() { return activeProject;}), getActiveProject: sinon.spy(function() { return activeProject;}),
setActiveProject: sinon.spy(function(user,id) { setActiveProject: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
@ -258,7 +268,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getProject", function() { describe("getProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getProject: sinon.spy(function(user,id) { getProject: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -291,7 +303,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("updateProject", function() { describe("updateProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
updateProject: sinon.spy(function(user,id,project) { updateProject: sinon.spy(function(user,id,project) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -325,7 +339,9 @@ describe("runtime-api/settings", function() {
}); });
describe("deleteProject", function() { describe("deleteProject", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
deleteProject: sinon.spy(function(user,id) { deleteProject: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -359,7 +375,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getStatus", function() { describe("getStatus", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getStatus: sinon.spy(function(user,id,remote) { getStatus: sinon.spy(function(user,id,remote) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -392,7 +410,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("getBranches", function() { describe("getBranches", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getBranches: sinon.spy(function(user,id,remote) { getBranches: sinon.spy(function(user,id,remote) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -425,7 +445,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("getBranchStatus", function() { describe("getBranchStatus", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getBranchStatus: sinon.spy(function(user,id,branch) { getBranchStatus: sinon.spy(function(user,id,branch) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -459,7 +481,9 @@ describe("runtime-api/settings", function() {
}); });
describe("setBranch", function() { describe("setBranch", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
setBranch: sinon.spy(function(user,id,branch,create) { setBranch: sinon.spy(function(user,id,branch,create) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -493,7 +517,9 @@ describe("runtime-api/settings", function() {
}); });
describe("deleteBranch", function() { describe("deleteBranch", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
deleteBranch: sinon.spy(function(user,id,branch,something,force) { deleteBranch: sinon.spy(function(user,id,branch,something,force) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -527,7 +553,9 @@ describe("runtime-api/settings", function() {
}); });
describe("commit", function() { describe("commit", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
commit: sinon.spy(function(user,id,message) { commit: sinon.spy(function(user,id,message) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -560,7 +588,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("getCommit", function() { describe("getCommit", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getCommit: sinon.spy(function(user,id,sha) { getCommit: sinon.spy(function(user,id,sha) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -594,7 +624,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getCommits", function() { describe("getCommits", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getCommits: sinon.spy(function(user,id,options) { getCommits: sinon.spy(function(user,id,options) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -634,7 +666,9 @@ describe("runtime-api/settings", function() {
}); });
describe("abortMerge", function() { describe("abortMerge", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
abortMerge: sinon.spy(function(user,id) { abortMerge: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -668,7 +702,9 @@ describe("runtime-api/settings", function() {
}); });
describe("resolveMerge", function() { describe("resolveMerge", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
resolveMerge: sinon.spy(function(user,id,path,resolution) { resolveMerge: sinon.spy(function(user,id,path,resolution) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -702,7 +738,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getFiles", function() { describe("getFiles", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getFiles: sinon.spy(function(user,id) { getFiles: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -736,7 +774,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getFile", function() { describe("getFile", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getFile: sinon.spy(function(user,id,path,tree) { getFile: sinon.spy(function(user,id,path,tree) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -770,7 +810,9 @@ describe("runtime-api/settings", function() {
}); });
describe("stageFile", function() { describe("stageFile", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
stageFile: sinon.spy(function(user,id,path) { stageFile: sinon.spy(function(user,id,path) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -803,7 +845,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("unstageFile", function() { describe("unstageFile", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
unstageFile: sinon.spy(function(user,id,path) { unstageFile: sinon.spy(function(user,id,path) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -837,7 +881,9 @@ describe("runtime-api/settings", function() {
}); });
describe("revertFile", function() { describe("revertFile", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
revertFile: sinon.spy(function(user,id,path) { revertFile: sinon.spy(function(user,id,path) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -871,7 +917,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getFileDiff", function() { describe("getFileDiff", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getFileDiff: sinon.spy(function(user,id,path,type) { getFileDiff: sinon.spy(function(user,id,path,type) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -905,7 +953,9 @@ describe("runtime-api/settings", function() {
}); });
describe("getRemotes", function() { describe("getRemotes", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
getRemotes: sinon.spy(function(user,id) { getRemotes: sinon.spy(function(user,id) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -939,7 +989,9 @@ describe("runtime-api/settings", function() {
}); });
describe("addRemote", function() { describe("addRemote", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
addRemote: sinon.spy(function(user,id,remote) { addRemote: sinon.spy(function(user,id,remote) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -973,7 +1025,9 @@ describe("runtime-api/settings", function() {
}); });
describe("removeRemote", function() { describe("removeRemote", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
removeRemote: sinon.spy(function(user,id,remote) { removeRemote: sinon.spy(function(user,id,remote) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -1007,7 +1061,9 @@ describe("runtime-api/settings", function() {
}); });
describe("updateRemote", function() { describe("updateRemote", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
updateRemote: sinon.spy(function(user,id,name,remote) { updateRemote: sinon.spy(function(user,id,name,remote) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -1040,7 +1096,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("pull", function() { describe("pull", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
pull: sinon.spy(function(user,id,remote,track,allowUnrelatedHistories) { pull: sinon.spy(function(user,id,remote,track,allowUnrelatedHistories) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");
@ -1073,7 +1131,9 @@ describe("runtime-api/settings", function() {
}); });
}); });
describe("push", function() { describe("push", function() {
var runtime = {storage: {projects: { var runtime = {
log: mockLog(),
storage: {projects: {
push: sinon.spy(function(user,id,remote,track) { push: sinon.spy(function(user,id,remote,track) {
if (user === "error") { if (user === "error") {
var err = new Error("error"); var err = new Error("error");