Repository: ambari Updated Branches: refs/heads/trunk efa35f49b -> 4540d4611
AMBARI-16245. Cluster User should not have access to component logs (alexantonenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4540d461 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4540d461 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4540d461 Branch: refs/heads/trunk Commit: 4540d4611b0951a8de20e77e800f1e9789442e3f Parents: efa35f4 Author: Alex Antonenko <[email protected]> Authored: Wed May 4 11:13:24 2016 +0300 Committer: Alex Antonenko <[email protected]> Committed: Wed May 4 13:13:40 2016 +0300 ---------------------------------------------------------------------- ambari-web/app/app.js | 1 + ambari-web/app/mappers/users_mapper.js | 14 +++++++++++- ambari-web/app/models/user.js | 2 ++ ambari-web/app/router.js | 7 +++++- ambari-web/app/templates/application.hbs | 26 ++++++++++++----------- ambari-web/app/utils/host_progress_popup.js | 5 +++++ ambari-web/app/views/common/log_tail_view.js | 2 ++ ambari-web/app/views/main/host/logs_view.js | 1 + ambari-web/app/views/main/host/menu.js | 2 +- ambari-web/test/mappers/users_mapper_test.js | 11 ++++++++++ ambari-web/test/views/main/host/menu_test.js | 12 +++++++++++ 11 files changed, 68 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/app.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js index ac45874..dd400c6 100644 --- a/ambari-web/app/app.js +++ b/ambari-web/app/app.js @@ -35,6 +35,7 @@ module.exports = Em.Application.create({ }), isAdmin: false, isOperator: false, + isClusterUser: false, isPermissionDataLoaded: false, auth: null, isOnlyViewUser: function() { http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/mappers/users_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/users_mapper.js b/ambari-web/app/mappers/users_mapper.js index 4f8cd06..80d7feb 100644 --- a/ambari-web/app/mappers/users_mapper.js +++ b/ambari-web/app/mappers/users_mapper.js @@ -26,7 +26,8 @@ App.usersMapper = App.QuickDataMapper.create({ admin: 'Users.admin', operator: 'Users.operator', permissions: 'permissions', - user_type: 'Users.user_type' + user_type: 'Users.user_type', + cluster_user: 'Users.cluster_user' }, map: function (json) { var self = this; @@ -40,6 +41,7 @@ App.usersMapper = App.QuickDataMapper.create({ } item.Users.admin = self.isAdmin(item.permissions); item.Users.operator = self.isOperator(item.permissions); + item.Users.cluster_user = self.isClusterUser(item.permissions); result.push(self.parseIt(item, self.config)); App.store.loadMany(self.get('model'), result); } @@ -63,5 +65,15 @@ App.usersMapper = App.QuickDataMapper.create({ **/ isOperator: function(permissionList) { return permissionList.indexOf('CLUSTER.ADMINISTRATOR') > -1 && !(permissionList.indexOf('AMBARI.ADMINISTRATOR') > -1); + }, + + /** + * Determines that user has only one permission CLUSTER.USER. + * + * @param {String[]} permissionList + * @return {Boolean} + */ + isClusterUser: function(permissionList) { + return permissionList.length === 1 && permissionList[0] === 'CLUSTER.USER'; } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/models/user.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/user.js b/ambari-web/app/models/user.js index 2cdbdbc..4dde8ec 100644 --- a/ambari-web/app/models/user.js +++ b/ambari-web/app/models/user.js @@ -26,6 +26,8 @@ App.User = DS.Model.extend({ auditItems:DS.hasMany('App.ServiceAudit'), admin: DS.attr('boolean'), operator: DS.attr('boolean'), + clusterUser: DS.attr('boolean'), + /** * List of permissions assigned to user * Available permissions: http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/router.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/router.js b/ambari-web/app/router.js index b723275..496e3d3 100644 --- a/ambari-web/app/router.js +++ b/ambari-web/app/router.js @@ -462,7 +462,8 @@ App.Router = Em.Router.extend({ if (clusterPermissions.contains('CLUSTER.ADMINISTRATOR')) { App.setProperties({ isAdmin: true, - isOperator: true + isOperator: true, + isClusterUser: false }); } if (App.get('isOnlyViewUser')) { @@ -583,6 +584,7 @@ App.Router = Em.Router.extend({ isAdmin: false, auth: null, isOperator: false, + isClusterUser: false, isPermissionDataLoaded: false }); this.set('loggedIn', false); @@ -677,6 +679,9 @@ App.Router = Em.Router.extend({ if (user.operator) { App.set('isOperator', true); } + if (user.cluster_user) { + App.set('isClusterUser', true); + } App.set('isPermissionDataLoaded', true); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/templates/application.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/application.hbs b/ambari-web/app/templates/application.hbs index 9518b24..49cb18a 100644 --- a/ambari-web/app/templates/application.hbs +++ b/ambari-web/app/templates/application.hbs @@ -26,18 +26,20 @@ title="Apache Ambari"></a> <a class="brand" {{translateAttr href="topnav.logo.href"}} title="Apache Ambari">{{t app.name}}</a> <a class="brand cluster-name" href="javascript:void(null);" {{bindAttr title="clusterName"}}> - <span {{action "showPopup" target="App.router.backgroundOperationsController"}} >{{clusterDisplayName}} </span> - {{#with App.router.backgroundOperationsController}} - {{#if allOperationsCount}} - <i class="icon-caret-left ops-count"></i><span id="span-bg-operation-count" - class="label operations-count" {{action "showPopup" target="App.router.backgroundOperationsController"}}> - {{allOperationsCount}} {{pluralize allOperationsCount singular="t:op" plural="t:ops"}}</span> - {{else}} - <i class="icon-caret-left"></i><span id="span-bg-operation-count" - class="label" {{action "showPopup" target="App.router.backgroundOperationsController"}}> - {{allOperationsCount}} {{pluralize allOperationsCount singular="t:op" plural="t:ops"}}</span> - {{/if}} - {{/with}} + {{#unless App.isClusterUser}} + <span {{action "showPopup" target="App.router.backgroundOperationsController"}} >{{clusterDisplayName}} </span> + {{#with App.router.backgroundOperationsController}} + {{#if allOperationsCount}} + <i class="icon-caret-left ops-count"></i><span id="span-bg-operation-count" + class="label operations-count" {{action "showPopup" target="App.router.backgroundOperationsController"}}> + {{allOperationsCount}} {{pluralize allOperationsCount singular="t:op" plural="t:ops"}}</span> + {{else}} + <i class="icon-caret-left"></i><span id="span-bg-operation-count" + class="label" {{action "showPopup" target="App.router.backgroundOperationsController"}}> + {{allOperationsCount}} {{pluralize allOperationsCount singular="t:op" plural="t:ops"}}</span> + {{/if}} + {{/with}} + {{/unless}} {{#if App.router.clusterController.isAlertsLoaded}} {{#if App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} <span {{bindAttr class=":label App.router.mainAlertDefinitionsController.isCriticalAlerts:alert-crit-count:alert-warn-count"}} {{action "showPopup" target="App.router.mainAlertInstancesController"}}> http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/utils/host_progress_popup.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/host_progress_popup.js b/ambari-web/app/utils/host_progress_popup.js index 177d806..8fe928f 100644 --- a/ambari-web/app/utils/host_progress_popup.js +++ b/ambari-web/app/utils/host_progress_popup.js @@ -291,6 +291,7 @@ App.HostPopup = Em.Object.create({ * @method initPopup */ initPopup: function (serviceName, controller, isBackgroundOperations, requestId) { + if (App.get('isClusterUser')) return; if (!isBackgroundOperations) { this.clearHostPopup(); this.set("popupHeaderName", serviceName); @@ -822,6 +823,10 @@ App.HostPopup = Em.Object.create({ */ detailedProperties: self.get('detailedProperties'), + isVisible: function() { + return !(App.get('isClusterUser') && isBackgroundOperations); + }.property('App.isClusterUser'), + didInsertElement: function () { this._super(); this.set('isOpen', true); http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/views/common/log_tail_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/log_tail_view.js b/ambari-web/app/views/common/log_tail_view.js index ca66e33..d764947 100644 --- a/ambari-web/app/views/common/log_tail_view.js +++ b/ambari-web/app/views/common/log_tail_view.js @@ -40,6 +40,8 @@ App.LogTailView = Em.View.extend(App.InfiniteScrollMixin, { content: null, + isVisible: Em.computed.not('App.isClusterUser'), + /** * elements size are: * .modal margin 40px x 2 http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/views/main/host/logs_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/host/logs_view.js b/ambari-web/app/views/main/host/logs_view.js index 7ca18f8..32e6192 100644 --- a/ambari-web/app/views/main/host/logs_view.js +++ b/ambari-web/app/views/main/host/logs_view.js @@ -25,6 +25,7 @@ var fileUtils = require('utils/file_utils'); App.MainHostLogsView = App.TableView.extend({ templateName: require('templates/main/host/logs'), + isVisible: Em.computed.not('App.isClusterUser'), classNames: ['logs-tab-content'], /** http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/app/views/main/host/menu.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/host/menu.js b/ambari-web/app/views/main/host/menu.js index 155f6bb..07d9def 100644 --- a/ambari-web/app/views/main/host/menu.js +++ b/ambari-web/app/views/main/host/menu.js @@ -58,7 +58,7 @@ App.MainHostMenuView = Em.CollectionView.extend({ routing: 'logs', hidden: function () { if (App.get('supports.logSearch')) { - return !App.Service.find().someProperty('serviceName', 'LOGSEARCH'); + return !(App.Service.find().someProperty('serviceName', 'LOGSEARCH') && !App.get('isClusterUser')); } return true; }.property('App.supports.logSearch'), http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/test/mappers/users_mapper_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mappers/users_mapper_test.js b/ambari-web/test/mappers/users_mapper_test.js index 22c2466..9475c06 100644 --- a/ambari-web/test/mappers/users_mapper_test.js +++ b/ambari-web/test/mappers/users_mapper_test.js @@ -37,4 +37,15 @@ describe('App.usersMapper', function () { }); }); + describe('#isClusterUser', function() { + var tests = [ + {i:["AMBARI.ADMINISTRATOR", "CLUSTER.USER"],e:false,m:'is cluster user'}, + {i:["CLUSTER.USER"],e:true,m:'has admin role'} + ]; + tests.forEach(function(test) { + it(test.m, function() { + expect(App.usersMapper.isClusterUser(test.i)).to.equal(test.e); + }); + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/4540d461/ambari-web/test/views/main/host/menu_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/host/menu_test.js b/ambari-web/test/views/main/host/menu_test.js index c029acc..f7d35a4 100644 --- a/ambari-web/test/views/main/host/menu_test.js +++ b/ambari-web/test/views/main/host/menu_test.js @@ -30,6 +30,7 @@ describe('App.MainHostMenuView', function () { beforeEach(function () { this.mock = sinon.stub(App, 'get'); this.serviceMock = sinon.stub(App.Service, 'find'); + this.clusterUserMock = this.mock.withArgs('isClusterUser'); }); afterEach(function () { @@ -60,25 +61,36 @@ describe('App.MainHostMenuView', function () { { logSearch: false, services: [{serviceName: 'LOGSEARCH'}], + isClusterUser: false, m: '`logs` tab is invisible', e: true }, { logSearch: true, services: [], + isClusterUser: false, m: '`logs` tab is invisible because service not installed', e: true }, { logSearch: true, services: [{serviceName: 'LOGSEARCH'}], + isClusterUser: false, m: '`logs` tab is visible', e: false + }, + { + logSearch: true, + services: [{serviceName: 'LOGSEARCH'}], + isClusterUser: true, + m: '`logs` tab is hidden because user has no access', + e: true } ]).forEach(function(test) { it(test.m, function() { this.mock.withArgs('supports.logSearch').returns(test.logSearch); this.serviceMock.returns(test.services); + this.clusterUserMock.returns(test.isClusterUser); view.propertyDidChange('content'); expect(view.get('content').findProperty('name', 'logs').get('hidden')).to.equal(test.e); });
