1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Better permission handling in editor

This commit is contained in:
Nick O'Leary 2018-01-12 21:00:11 +00:00
parent bb168d35a8
commit 1204cf1ba0
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
10 changed files with 240 additions and 111 deletions

View File

@ -104,6 +104,7 @@
} }
if (notificationId === "runtime-state") { if (notificationId === "runtime-state") {
if (msg.error === "credentials_load_failed") { if (msg.error === "credentials_load_failed") {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [ options.buttons = [
{ {
text: "Setup credentials", text: "Setup credentials",
@ -112,7 +113,9 @@
} }
} }
] ]
}
} else if (msg.error === "missing_flow_file") { } else if (msg.error === "missing_flow_file") {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [ options.buttons = [
{ {
text: "Setup project files", text: "Setup project files",
@ -123,7 +126,9 @@
} }
} }
] ]
}
} else if (msg.error === "project_empty") { } else if (msg.error === "project_empty") {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [ options.buttons = [
{ {
text: "No thanks", text: "No thanks",
@ -142,6 +147,7 @@
] ]
} }
} }
}
if (!persistentNotifications.hasOwnProperty(notificationId)) { if (!persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId] = RED.notify(text,options); persistentNotifications[notificationId] = RED.notify(text,options);
} else { } else {

View File

@ -63,7 +63,7 @@ RED.settings = (function () {
if (!hasLocalStorage()) { if (!hasLocalStorage()) {
return; return;
} }
if (key === "auth_tokens") { if (key === "auth-tokens") {
localStorage.removeItem(key); localStorage.removeItem(key);
} else { } else {
delete userSettings[key]; delete userSettings[key];
@ -161,6 +161,7 @@ RED.settings = (function () {
} }
function saveUserSettings() { function saveUserSettings() {
if (RED.user.hasPermission("settings.write")) {
if (pendingSave) { if (pendingSave) {
clearTimeout(pendingSave); clearTimeout(pendingSave);
} }
@ -179,6 +180,7 @@ RED.settings = (function () {
}); });
},300); },300);
} }
}
function theme(property,defaultValue) { function theme(property,defaultValue) {
if (!RED.settings.editorTheme) { if (!RED.settings.editorTheme) {

View File

@ -286,6 +286,10 @@ RED.deploy = (function() {
function save(skipValidation,force) { function save(skipValidation,force) {
if (!$("#btn-deploy").hasClass("disabled")) { if (!$("#btn-deploy").hasClass("disabled")) {
if (!RED.user.hasPermission("flows.write")) {
RED.notify(RED._("user.errors.deploy"),"error");
return;
}
if (!skipValidation) { if (!skipValidation) {
var hasUnknown = false; var hasUnknown = false;
var hasInvalid = false; var hasInvalid = false;

View File

@ -40,6 +40,11 @@ RED.projects.settings = (function() {
if (settingsVisible) { if (settingsVisible) {
return; return;
} }
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
settingsVisible = true; settingsVisible = true;
var tabContainer; var tabContainer;
@ -226,12 +231,14 @@ RED.projects.settings = (function() {
var summary = $('<div style="position: relative">').appendTo(pane); var summary = $('<div style="position: relative">').appendTo(pane);
var summaryContent = $('<div></div>',{style:"color: #999"}).appendTo(summary); var summaryContent = $('<div></div>',{style:"color: #999"}).appendTo(summary);
updateProjectSummary(activeProject.summary, summaryContent); updateProjectSummary(activeProject.summary, summaryContent);
if (RED.user.hasPermission("projects.write")) {
$('<button class="editor-button editor-button-small" style="float: right;">edit</button>') $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
.prependTo(summary) .prependTo(summary)
.click(function(evt) { .click(function(evt) {
evt.preventDefault(); evt.preventDefault();
editSummary(activeProject, activeProject.summary, summaryContent); editSummary(activeProject, activeProject.summary, summaryContent);
}); });
}
$('<hr>').appendTo(pane); $('<hr>').appendTo(pane);
var description = $('<div class="node-help" style="position: relative"></div>').appendTo(pane); var description = $('<div class="node-help" style="position: relative"></div>').appendTo(pane);
@ -239,13 +246,14 @@ RED.projects.settings = (function() {
updateProjectDescription(activeProject, descriptionContent); updateProjectDescription(activeProject, descriptionContent);
if (RED.user.hasPermission("projects.write")) {
$('<button class="editor-button editor-button-small" style="float: right;">edit</button>') $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
.prependTo(description) .prependTo(description)
.click(function(evt) { .click(function(evt) {
evt.preventDefault(); evt.preventDefault();
editDescription(activeProject, descriptionContent); editDescription(activeProject, descriptionContent);
}); });
}
return pane; return pane;
} }
function updateProjectDependencies(activeProject,depsList) { function updateProjectDependencies(activeProject,depsList) {
@ -349,12 +357,14 @@ RED.projects.settings = (function() {
function createDependenciesPane(activeProject) { function createDependenciesPane(activeProject) {
var pane = $('<div id="project-settings-tab-deps" class="project-settings-tab-pane node-help"></div>'); var pane = $('<div id="project-settings-tab-deps" class="project-settings-tab-pane node-help"></div>');
if (RED.user.hasPermission("projects.write")) {
$('<button class="editor-button editor-button-small" style="margin-top:10px;float: right;">edit</button>') $('<button class="editor-button editor-button-small" style="margin-top:10px;float: right;">edit</button>')
.appendTo(pane) .appendTo(pane)
.click(function(evt) { .click(function(evt) {
evt.preventDefault(); evt.preventDefault();
editDependencies(activeProject,null,pane,depsList) editDependencies(activeProject,null,pane,depsList)
}); });
}
var depsList = $("<ol>",{style:"position: absolute;top: 60px;bottom: 20px;left: 20px;right: 20px;"}).appendTo(pane); var depsList = $("<ol>",{style:"position: absolute;top: 60px;bottom: 20px;left: 20px;right: 20px;"}).appendTo(pane);
depsList.editableList({ depsList.editableList({
addButton: false, addButton: false,
@ -368,6 +378,7 @@ RED.projects.settings = (function() {
row.parent().addClass("palette-module-section"); row.parent().addClass("palette-module-section");
} }
headerRow.text(entry.label); headerRow.text(entry.label);
if (RED.user.hasPermission("projects.write")) {
if (entry.index === 1) { if (entry.index === 1) {
var addButton = $('<button class="editor-button editor-button-small palette-module-button">add to project</button>').appendTo(headerRow).click(function(evt) { var addButton = $('<button class="editor-button editor-button-small palette-module-button">add to project</button>').appendTo(headerRow).click(function(evt) {
evt.preventDefault(); evt.preventDefault();
@ -391,6 +402,7 @@ RED.projects.settings = (function() {
editDependencies(activeProject,JSON.stringify(deps,"",4),pane,depsList); editDependencies(activeProject,JSON.stringify(deps,"",4),pane,depsList);
}); });
} }
}
} else { } else {
headerRow.addClass("palette-module-header"); headerRow.addClass("palette-module-header");
headerRow.toggleClass("palette-module-unused",entry.count === 0); headerRow.toggleClass("palette-module-unused",entry.count === 0);
@ -630,6 +642,7 @@ RED.projects.settings = (function() {
function createFilesSection(activeProject,pane) { function createFilesSection(activeProject,pane) {
var title = $('<h3></h3>').text("Files").appendTo(pane); var title = $('<h3></h3>').text("Files").appendTo(pane);
var filesContainer = $('<div class="user-settings-section"></div>').appendTo(pane); var filesContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
if (RED.user.hasPermission("projects.write")) {
var editFilesButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>') var editFilesButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
.appendTo(title) .appendTo(title)
.click(function(evt) { .click(function(evt) {
@ -649,7 +662,7 @@ RED.projects.settings = (function() {
credentialFormRows.hide(); credentialFormRows.hide();
credentialSecretButtons.show(); credentialSecretButtons.show();
}); });
}
var row; var row;
// Flow files // Flow files

View File

@ -1753,6 +1753,10 @@ RED.projects = (function() {
} else if (!activeProject.empty) { } else if (!activeProject.empty) {
throw new Error("Cannot create default file set on a non-empty project"); throw new Error("Cannot create default file set on a non-empty project");
} }
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
createProjectOptions = {}; createProjectOptions = {};
show('default-files',{existingProject: true}); show('default-files',{existingProject: true});
// var payload = { // var payload = {
@ -1805,11 +1809,18 @@ RED.projects = (function() {
return { return {
init: init, init: init,
_show: show,
showStartup: function() { showStartup: function() {
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
show('welcome'); show('welcome');
}, },
newProject: function() { newProject: function() {
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
if (!activeProject) { if (!activeProject) {
show('welcome'); show('welcome');
} else { } else {
@ -1817,15 +1828,31 @@ RED.projects = (function() {
} }
}, },
selectProject: function() { selectProject: function() {
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
show('open') show('open')
}, },
deleteProject: function() { deleteProject: function() {
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
show('delete') show('delete')
}, },
showCredentialsPrompt: function() { //TODO: rename this function showCredentialsPrompt: function() { //TODO: rename this function
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
RED.projects.settings.show('settings'); RED.projects.settings.show('settings');
}, },
showFilesPrompt: function() { //TODO: rename this function showFilesPrompt: function() { //TODO: rename this function
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
RED.projects.settings.show('settings'); RED.projects.settings.show('settings');
}, },
createDefaultFileSet: createDefaultFileSet, createDefaultFileSet: createDefaultFileSet,

View File

@ -283,7 +283,10 @@ RED.sidebar.versionControl = (function() {
refreshFiles(result); refreshFiles(result);
}); });
} }
}) });
RED.events.on("login",function() {
refresh(true);
});
sidebarContent = $('<div>', {class:"sidebar-version-control"}); sidebarContent = $('<div>', {class:"sidebar-version-control"});
var stackContainer = $("<div>",{class:"sidebar-version-control-stack"}).appendTo(sidebarContent); var stackContainer = $("<div>",{class:"sidebar-version-control-stack"}).appendTo(sidebarContent);
sections = RED.stack.create({ sections = RED.stack.create({
@ -1175,6 +1178,10 @@ RED.sidebar.versionControl = (function() {
stagedChangesList.editableList('empty'); stagedChangesList.editableList('empty');
unmergedChangesList.editableList('empty'); unmergedChangesList.editableList('empty');
} }
if (!RED.user.hasPermission("projects.write")) {
return;
}
refreshInProgress = true; refreshInProgress = true;
refreshLocalCommits(); refreshLocalCommits();

View File

@ -29,6 +29,10 @@ RED.userSettings = (function() {
if (settingsVisible) { if (settingsVisible) {
return; return;
} }
if (!RED.user.hasPermission("settings.write")) {
RED.notify(RED._("user.errors.settings"),"error");
return;
}
settingsVisible = true; settingsVisible = true;
var tabContainer; var tabContainer;

View File

@ -188,6 +188,7 @@ RED.user = (function() {
RED.settings.load(function() { RED.settings.load(function() {
RED.notify(RED._("user.loggedInAs",{name:RED.settings.user.username}),"success"); RED.notify(RED._("user.loggedInAs",{name:RED.settings.user.username}),"success");
updateUserMenu(); updateUserMenu();
RED.events.emit("login",RED.settings.user.username);
}); });
}); });
} }
@ -230,10 +231,66 @@ RED.user = (function() {
} }
} }
var readRE = /^((.+)\.)?read$/
var writeRE = /^((.+)\.)?write$/
function hasPermission(permission) {
if (permission === "") {
return true;
}
if (!RED.settings.user) {
return true;
}
return checkPermission(RED.settings.user.permissions||"",permission);
}
function checkPermission(userScope,permission) {
if (permission === "") {
return true;
}
var i;
if (Array.isArray(permission)) {
// Multiple permissions requested - check each one
for (i=0;i<permission.length;i++) {
if (!checkPermission(userScope,permission[i])) {
return false;
}
}
// All permissions check out
return true;
}
if (Array.isArray(userScope)) {
if (userScope.length === 0) {
return false;
}
for (i=0;i<userScope.length;i++) {
if (checkPermission(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;
}
return { return {
init: init, init: init,
login: login, login: login,
logout: logout logout: logout,
hasPermission: hasPermission
} }
})(); })();

View File

@ -23,6 +23,10 @@
#project-settings-tab-settings { #project-settings-tab-settings {
overflow-y: scroll; overflow-y: scroll;
} }
.sidebar-version-control-shade {
background: #f3f3f3;
}
.projects-edit-form form { .projects-edit-form form {
margin: 0; margin: 0;
.form-row { .form-row {

View File

@ -76,7 +76,12 @@
"password": "Password", "password": "Password",
"login": "Login", "login": "Login",
"loginFailed": "Login failed", "loginFailed": "Login failed",
"notAuthorized": "Not authorized" "notAuthorized": "Not authorized",
"errors": {
"settings": "You must be logged in to access settings",
"deploy": "You must be logged in to deploy changes",
"notAuthorized": "You must be logged in to perform this action"
}
}, },
"notification": { "notification": {
"warning": "<strong>Warning</strong>: __message__", "warning": "<strong>Warning</strong>: __message__",