mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Better permission handling in editor
This commit is contained in:
		| @@ -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 { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|     } |     } | ||||||
|  |  | ||||||
| })(); | })(); | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
| @@ -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__", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user