mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch '0.14.0'
This commit is contained in:
@@ -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 {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -63,7 +63,6 @@ module.exports = {
|
||||
}
|
||||
themeSettings = null;
|
||||
theme = settings.editorTheme;
|
||||
|
||||
},
|
||||
|
||||
app: function() {
|
||||
|
Reference in New Issue
Block a user