Merge branch '0.14.0'

This commit is contained in:
Nick O'Leary
2016-06-17 21:30:09 +01:00
167 changed files with 6903 additions and 4341 deletions

View File

@@ -56,7 +56,7 @@ function needsPermission(permission) {
if (permissions.hasPermission(req.authInfo.scope,permission)) {
return next();
}
log.audit({event: "permission.fail"},req);
log.audit({event: "permission.fail", permissions: permission},req);
return res.status(401).end();
});
} else {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright 2015, 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,41 +20,44 @@ var readRE = /^((.+)\.)?read$/
var writeRE = /^((.+)\.)?write$/
function hasPermission(userScope,permission) {
var i;
if (util.isArray(userScope)) {
if (userScope.length === 0) {
return false;
}
for (i=0;i<userScope.length;i++) {
if (!hasPermission(userScope[i],permission)) {
return false;
}
}
return true;
}
if (permission === "") {
return true;
}
if (userScope === "*") {
return true;
}
var i;
if (util.isArray(permission)) {
// Multiple permissions requested - check each one
for (i=0;i<permission.length;i++) {
if (!hasPermission(userScope,permission[i])) {
return false;
}
}
// All permissions check out
return true;
}
if (userScope === "read") {
return readRE.test(permission);
} else {
return false; // anything not allowed is disallowed
if (util.isArray(userScope)) {
if (userScope.length === 0) {
return false;
}
for (i=0;i<userScope.length;i++) {
if (hasPermission(userScope[i],permission)) {
return true;
}
}
return false;
}
if (userScope === "*" || userScope === permission) {
return true;
}
if (userScope === "read" || userScope === "*.read") {
return readRE.test(permission);
} else if (userScope === "write" || userScope === "*.write") {
return writeRE.test(permission);
}
return false;
}
module.exports = {

View File

@@ -32,6 +32,8 @@ var sessionExpiryTime
var sessions = {};
var loadedSessions = null;
function expireSessions() {
var now = Date.now();
var modified = false;
@@ -50,49 +52,61 @@ function expireSessions() {
return when.resolve();
}
}
function loadSessions() {
if (loadedSessions === null) {
loadedSessions = storage.getSessions().then(function(_sessions) {
sessions = _sessions||{};
return expireSessions();
});
}
return loadedSessions;
}
module.exports = {
init: function(adminAuthSettings, _storage) {
storage = _storage;
sessionExpiryTime = adminAuthSettings.sessionExpiryTime || 604800; // 1 week in seconds
return storage.getSessions().then(function(_sessions) {
sessions = _sessions||{};
return expireSessions();
});
// At this point, storage will not have been initialised, so defer loading
// the sessions until there's a request for them.
loadedSessions = null;
return when.resolve();
},
get: function(token) {
if (sessions[token]) {
if (sessions[token].expires < Date.now()) {
return expireSessions().then(function() { return null });
return loadSessions().then(function() {
if (sessions[token]) {
if (sessions[token].expires < Date.now()) {
return expireSessions().then(function() { return null });
}
}
}
return when.resolve(sessions[token]);
return when.resolve(sessions[token]);
});
},
create: function(user,client,scope) {
var accessToken = generateToken(128);
var accessTokenExpiresAt = Date.now() + (sessionExpiryTime*1000);
var session = {
user:user,
client:client,
scope:scope,
accessToken: accessToken,
expires: accessTokenExpiresAt
};
sessions[accessToken] = session;
return storage.saveSessions(sessions).then(function() {
return {
return loadSessions().then(function() {
var accessToken = generateToken(128);
var accessTokenExpiresAt = Date.now() + (sessionExpiryTime*1000);
var session = {
user:user,
client:client,
scope:scope,
accessToken: accessToken,
expires_in: sessionExpiryTime
}
expires: accessTokenExpiresAt
};
sessions[accessToken] = session;
return storage.saveSessions(sessions).then(function() {
return {
accessToken: accessToken,
expires_in: sessionExpiryTime
}
});
});
},
revoke: function(token) {
delete sessions[token];
return storage.saveSessions(sessions);
return loadSessions().then(function() {
delete sessions[token];
return storage.saveSessions(sessions);
});
}
}

View File

@@ -89,6 +89,7 @@ function start() {
} else {
var completeConnection = function(userScope,sendAck) {
if (!userScope || !Permissions.hasPermission(userScope,"status.read")) {
ws.send(JSON.stringify({auth:"fail"}));
ws.close();
} else {
pendingAuth = false;

View File

@@ -131,12 +131,12 @@ function init(_server,_runtime) {
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,errorHandler);
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,errorHandler);
adminApp.get("/nodes/:mod",needsPermission("nodes.read"),nodes.getModule,errorHandler);
adminApp.put("/nodes/:mod",needsPermission("nodes.write"),nodes.putModule,errorHandler);
adminApp.delete("/nodes/:mod",needsPermission("nodes.write"),nodes.delete,errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,errorHandler);
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,errorHandler);
adminApp.get("/nodes/:mod/:set",needsPermission("nodes.read"),nodes.getSet,errorHandler);
adminApp.put("/nodes/:mod/:set",needsPermission("nodes.write"),nodes.putSet,errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,errorHandler);
adminApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,errorHandler);

View File

@@ -3,14 +3,19 @@
"label": {
"name": "Name",
"ok": "Ok",
"done":"Done",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close"
"close": "Close",
"load": "Load",
"save": "Save",
"import": "Import",
"export": "Export"
}
},
"workspace": {
"defaultName": "Flow __number__",
"renameSheet": "Rename flow",
"editFlow": "Edit flow: __name__",
"confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here"
@@ -47,7 +52,8 @@
"user": {
"loggedInAs": "Logged in as __name__",
"login": "Login",
"loginFailed": "Login failed"
"loginFailed": "Login failed",
"notAuthorized": "Not authorized"
},
"notification": {
"warning": "<strong>Warning</strong>: __message__",
@@ -58,7 +64,9 @@
"error": "<strong>Error</strong>: __message__",
"errors": {
"lostConnection": "Lost connection to server",
"lostConnection": "Lost connection to server, reconnecting...",
"lostConnectionReconnect": "Lost connection to server, reconnecting in __time__s.",
"lostConnectionTry": "Try now",
"cannotAddSubflowToItself": "Cannot add subflow to itself",
"cannotAddCircularReference": "Cannot add subflow - circular reference detected"
}
@@ -84,6 +92,7 @@
"modifiedNodes": "Modified Nodes",
"modifiedNodesDesc": "Only deploys nodes that have changed",
"successfulDeploy": "Successfully deployed",
"deployFailed": "Deploy failed: __message__",
"unusedConfigNodes":"You have some unused configuration nodes.",
"unusedConfigNodesLink":"Click here to see them",
"errors": {
@@ -101,10 +110,10 @@
}
},
"subflow": {
"editSubflow": "Edit flow __name__",
"edit": "Edit flow",
"subflowInstances": "There is __count__ instance of this subflow",
"subflowInstances_plural": "There are __count__ instances of this subflow",
"editSubflow": "Edit flow template: __name__",
"edit": "Edit flow template",
"subflowInstances": "There is __count__ instance of this subflow template",
"subflowInstances_plural": "There are __count__ instances of this subflow template",
"editSubflowProperties": "edit properties",
"input": "inputs:",
"output": "outputs:",
@@ -117,12 +126,14 @@
}
},
"editor": {
"configEdit": "edit",
"configAdd": "add",
"configEdit": "Edit",
"configAdd": "Add",
"configUpdate": "Update",
"configDelete": "Delete",
"nodesUse": "__count__ node uses this config",
"nodesUse_plural": "__count__ nodes use this config",
"addNewConfig": "Add new __type__ config node",
"editNode": "Edit __type__ node",
"editConfig": "Edit __type__ config node",
"addNewType": "Add new __type__...",
"errors": {
@@ -189,7 +200,7 @@
},
"sidebar": {
"info": {
"name": "Information",
"name": "Node information",
"label": "info",
"node": "Node",
"type": "Type",
@@ -218,7 +229,11 @@
"num": "number",
"re": "regular expression",
"bool": "boolean",
"json": "JSON"
"json": "JSON",
"date": "timestamp"
}
},
"editableList": {
"add": "add"
}
}

View File

@@ -87,7 +87,7 @@ module.exports = {
res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
return;
}
var mod = req.params.mod;
var mod = req.params[0];
try {
var promise = null;
var module = redNodes.getModuleInfo(mod);
@@ -114,7 +114,7 @@ module.exports = {
},
getSet: function(req,res) {
var id = req.params.mod + "/" + req.params.set;
var id = req.params[0] + "/" + req.params[2];
var result = null;
if (req.get("accept") === "application/json") {
result = redNodes.getNodeInfo(id);
@@ -140,7 +140,7 @@ module.exports = {
},
getModule: function(req,res) {
var module = req.params.mod;
var module = req.params[0];
var result = redNodes.getModuleInfo(module);
if (result) {
log.audit({event: "nodes.module.get",module:module},req);
@@ -163,7 +163,7 @@ module.exports = {
res.status(400).json({error:"invalid_request", message:"Invalid request"});
return;
}
var id = req.params.mod + "/" + req.params.set;
var id = req.params[0] + "/" + req.params[2];
try {
var node = redNodes.getNodeInfo(id);
var info;
@@ -195,7 +195,7 @@ module.exports = {
res.status(400).json({error:"invalid_request", message:"Invalid request"});
return;
}
var mod = req.params.mod;
var mod = req.params[0];
try {
var module = redNodes.getModuleInfo(mod);
if (!module) {

View File

@@ -63,7 +63,6 @@ module.exports = {
}
themeSettings = null;
theme = settings.editorTheme;
},
app: function() {