You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rz...@apache.org on 2016/03/17 19:57:33 UTC

ambari git commit: AMBARI-15466. RBAC: Add dialog popup to explain roles (rzang)

Repository: ambari
Updated Branches:
  refs/heads/trunk 96d76f5c2 -> f2b8164e3


AMBARI-15466. RBAC: Add dialog popup to explain roles (rzang)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f2b8164e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f2b8164e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f2b8164e

Branch: refs/heads/trunk
Commit: f2b8164e3973a29012105713429cc13b52bdc89e
Parents: 96d76f5
Author: Richard Zang <rz...@apache.org>
Authored: Thu Mar 17 11:55:38 2016 -0700
Committer: Richard Zang <rz...@apache.org>
Committed: Thu Mar 17 11:55:38 2016 -0700

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/index.html  |   1 +
 .../clusters/ClustersManageAccessCtrl.js        |  15 +-
 .../ui/admin-web/app/scripts/i18n.config.js     |   1 +
 .../admin-web/app/scripts/services/Cluster.js   |  68 ++++++
 .../app/scripts/services/RoleDetailsModal.js    |  54 +++++
 .../resources/ui/admin-web/app/styles/main.css  |   8 +
 .../app/views/clusters/manageAccess.html        |   5 +-
 .../app/views/modals/RoleDetailsModal.html      |  38 ++++
 .../clusters/UserAccessListCtrl_test.js         | 207 ++-----------------
 9 files changed, 207 insertions(+), 190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/index.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
index 6557b55..fa911a6 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
@@ -163,6 +163,7 @@
     <script src="scripts/services/UnsavedDialog.js"></script>
     <script src="scripts/services/Stack.js"></script>
     <script src="scripts/services/AddRepositoryModal.js"></script>
+    <script src="scripts/services/RoleDetailsModal.js"></script>
     <!-- endbuild -->
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
index 8f932e1..26147c7 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ClustersManageAccessCtrl', ['$scope', '$location', 'Cluster', '$routeParams', 'Alert', 'PermissionLoader', 'PermissionSaver', '$translate', function($scope, $location, Cluster, $routeParams, Alert, PermissionLoader, PermissionSaver, $translate) {
+.controller('ClustersManageAccessCtrl', ['$scope', '$location', 'Cluster', '$routeParams', 'Alert', 'PermissionLoader', 'PermissionSaver', '$translate', 'RoleDetailsModal', function($scope, $location, Cluster, $routeParams, Alert, PermissionLoader, PermissionSaver, $translate, RoleDetailsModal) {
   var $t = $translate.instant;
   $scope.getConstant = function (key) {
     return $t('common.' + key).toLowerCase();
@@ -82,5 +82,18 @@ angular.module('ambariAdminConsole')
 
   $scope.switchToList = function() {
     $location.url('/clusters/' + $routeParams.id + '/userAccessList');
+  },
+
+  $scope.showHelpPage = function() {
+    Cluster.getRolesWithAuthorizations().then(function(roles) {
+      RoleDetailsModal.show(roles.map(function(role) {
+        role.authorizations = role.authorizations.map(function(authorization) {
+          return authorization.AuthorizationInfo;
+        });
+        var r = role.PermissionInfo;
+        r.authorizations = role.authorizations;
+        return r;
+      }));
+    });
   }
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
index 228be5c..2a31b39 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
@@ -80,6 +80,7 @@ angular.module('ambariAdminConsole')
       'NA': 'n/a',
       'blockViewLabel': 'BLOCK',
       'listViewLabel': 'LIST',
+      'rbac': 'Role Based Access Control',
 
       'clusterNameChangeConfirmation': {
         'title': 'Confirm Cluster Name Change',

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
index 806247a..ff388cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
@@ -30,6 +30,54 @@ angular.module('ambariAdminConsole')
       'CLUSTER.USER'
     ],
 
+    orderedAuthorizations : [
+      "SERVICE.VIEW_METRICS",
+      "SERVICE.VIEW_STATUS_INFO",
+      "SERVICE.VIEW_CONFIGS",
+      "SERVICE.COMPARE_CONFIGS",
+      "SERVICE.VIEW_ALERTS",
+      "SERVICE.START_STOP",
+      "SERVICE.DECOMMISSION_RECOMMISSION",
+      "SERVICE.RUN_SERVICE_CHECK",
+      "SERVICE.TOGGLE_MAINTENANCE",
+      "SERVICE.RUN_CUSTOM_COMMAND",
+      "SERVICE.MODIFY_CONFIGS",
+      "SERVICE.MANAGE_CONFIG_GROUPS",
+      "SERVICE.MOVE",
+      "SERVICE.ENABLE_HA",
+      "SERVICE.MANAGE_ALERTS",
+      "SERVICE.TOGGLE_ALERTS",
+      "SERVICE.ADD_DELETE_SERVICES",
+      "HOST.VIEW_CONFIGS",
+      "HOST.VIEW_METRICS",
+      "HOST.VIEW_STATUS_INFO",
+      "HOST.ADD_DELETE_COMPONENTS",
+      "HOST.ADD_DELETE_HOSTS",
+      "HOST.TOGGLE_MAINTENANCE",
+      "CLUSTER.VIEW_ALERTS",
+      "CLUSTER.VIEW_CONFIGS",
+      "CLUSTER.VIEW_METRICS",
+      "CLUSTER.VIEW_STACK_DETAILS",
+      "CLUSTER.VIEW_STATUS_INFO",
+      "CLUSTER.MANAGE_ALERTS",
+      "CLUSTER.MANAGE_CONFIG_GROUPS",
+      "CLUSTER.MANAGE_CREDENTIALS",
+      "CLUSTER.MODIFY_CONFIGS",
+      "CLUSTER.TOGGLE_ALERTS",
+      "CLUSTER.TOGGLE_KERBEROS",
+      "CLUSTER.UPGRADE_DOWNGRADE_STACK",
+      "AMBARI.ADD_DELETE_CLUSTERS",
+      "AMBARI.ASSIGN_ROLES",
+      "AMBARI.EDIT_STACK_REPOS",
+      "AMBARI.MANAGE_GROUPS",
+      "AMBARI.MANAGE_SETTINGS",
+      "AMBARI.MANAGE_STACK_VERSIONS",
+      "AMBARI.MANAGE_USERS",
+      "AMBARI.MANAGE_VIEWS",
+      "AMBARI.RENAME_CLUSTER",
+      "AMBARI.SET_SERVICE_USERS_GROUPS"
+    ],
+
     ineditableRoles : ['VIEW.USER', 'AMBARI.ADMINISTRATOR'],
 
     getAllClusters: function() {
@@ -118,6 +166,26 @@ angular.module('ambariAdminConsole')
 
       return deferred.promise;
     },
+    getRolesWithAuthorizations: function() {
+      var self = this;
+      var deferred = $q.defer();
+      $http({
+        method: 'GET',
+        url: Settings.baseUrl + '/permissions?PermissionInfo/resource_name.in(CLUSTER,AMBARI)',
+        mock: 'permission/permissions.json',
+        params: {
+          fields: 'PermissionInfo/*,authorizations/AuthorizationInfo/*'
+        }
+      })
+        .success(function(data) {
+          deferred.resolve(data.items);
+        })
+        .catch(function(data) {
+          deferred.reject(data); });
+
+      return deferred.promise;
+    },
+
     getPrivileges: function(params) {
       var deferred = $q.defer();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
new file mode 100644
index 0000000..eced664
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.factory('RoleDetailsModal', ['$modal', 'Cluster', function($modal, Cluster) {
+  return {
+    show: function(roles) {
+      var modalInstance = $modal.open({
+        templateUrl: 'views/modals/RoleDetailsModal.html',
+        size: 'lg',
+        controller: function($scope, $modalInstance) {
+          $scope.title = '';
+          $scope.orderedRoles = ['AMBARI.ADMINISTRATOR'].concat(Cluster.orderedRoles).reverse();
+          $scope.orderedAuthorizations = Cluster.orderedAuthorizations;
+          $scope.authHash = {};
+          roles.map(function(r) {
+            r.authorizations.map(function(auth) {
+              $scope.authHash[auth.authorization_id] = auth.authorization_name;
+            });
+          });
+          $scope.roles = roles.sort(function(a, b) {
+            return $scope.orderedRoles.indexOf(a.permission_name) - $scope.orderedRoles.indexOf(b.permission_name);
+          }).map(function(r) {
+            r.authHash = {};
+            r.authorizations.map(function(a) {
+              r.authHash[a.authorization_id] = true;
+            });
+            return r;
+          });
+          $scope.ok = function() {
+            $modalInstance.dismiss();
+          };
+        }
+      });
+      return modalInstance.result;
+    }
+  }
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
index b705a90..e5ebb68 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
@@ -1516,3 +1516,11 @@ thead.view-permission-header > tr > th {
 .role-actions {
   width: 400px;
 }
+
+.green-icon {
+  color: #5ab400;
+}
+
+.cursor-pointer {
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
index fd5285e..3729e7d 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
@@ -36,7 +36,10 @@
   <table class="table">
     <thead>
       <tr>
-        <th class="col-sm-2" width="20%"><label>{{'common.roles' | translate}}</label></th>
+        <th class="col-sm-2" width="20%">
+          <label>{{'common.roles' | translate}}</label>&nbsp;
+          <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
+        </th>
         <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("users")}'}}</label></th>
         <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("groups")}'}}</label></th>
       </tr>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/RoleDetailsModal.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/RoleDetailsModal.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/RoleDetailsModal.html
new file mode 100644
index 0000000..f750142
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/RoleDetailsModal.html
@@ -0,0 +1,38 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<div class="modal-header text-center">
+    <h4 class="modal-title">{{'common.rbac' | translate}}</h4>
+</div>
+<div class="modal-body">
+    <table class="table table-hover table-bordered">
+        <tr>
+            <th></th>
+            <th ng-repeat="role in roles">{{role.permission_label}}</th>
+        </tr>
+        <tr ng-repeat="auth in orderedAuthorizations">
+            <td>{{authHash[auth]}}</td>
+            <td ng-repeat="role in roles" class="text-center">
+                <i class="glyphicon glyphicon-ok green-icon" ng-show="role.authHash[auth]"></i>
+            </td>
+        </tr>
+    </table>
+</div>
+<div class="modal-footer text-center">
+    <button class="btn btn-primary" ng-click="ok()">Close</button>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2b8164e/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
index e63f34e..edf16be 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
@@ -20,7 +20,6 @@ describe('#Cluster', function () {
 
   describe('UserAccessListCtrl', function() {
 
-    /*
     var scope, ctrl, $t, $httpBackend, Cluster, deferred, Alert, mock;
 
     beforeEach(module('ambariAdminConsole', function () {}));
@@ -48,9 +47,12 @@ describe('#Cluster', function () {
       spyOn(Alert, 'success').andCallFake(angular.noop);
       spyOn(Alert, 'error').andCallFake(angular.noop);
       spyOn(scope, 'loadRoles').andCallFake(angular.noop);
-      $httpBackend.expectGET(/\/api\/v1\/clusters\/\w+\/privileges/).respond(200, {
+      $httpBackend.expectGET(/\/api\/v1\/permissions/).respond(200, {
         items: []
       });
+      $httpBackend.expectGET(/\/api\/v1\/users?.*/).respond(200, {
+        items:[]
+      });
       $httpBackend.flush();
     }));
 
@@ -59,24 +61,27 @@ describe('#Cluster', function () {
       it('should clear filters and reset pagination', function () {
         scope.currentPage = 2;
         scope.currentNameFilter = 'a';
-        scope.currentRoleFilter = {
-          label: $t('users.roles.clusterUser'),
-          value: 'CLUSTER.USER'
-        };
-        scope.currentTypeFilter = {
-          label: $t('common.group'),
-          value: 'GROUP'
-        };
+        scope.roleFilterOptions = [
+          {
+            label: $t('common.all'),
+            value: ''
+          },
+          {
+            label: $t('users.roles.clusterUser'),
+            value: 'CLUSTER.USER'
+          }
+        ];
+        scope.typeFilterOptions = [
+          {label: $t('common.user'), value: 'USER'},
+          {label: $t('common.group'), value: 'GROUP'}
+        ];
+        scope.currentRoleFilter = scope.roleFilterOptions[1];
         scope.clearFilters();
         expect(scope.currentNameFilter).toEqual('');
         expect(scope.currentRoleFilter).toEqual({
           label: $t('common.all'),
           value: ''
         });
-        expect(scope.currentTypeFilter).toEqual({
-          label: $t('common.all'),
-          value: ''
-        });
         expect(scope.currentPage).toEqual(1);
       });
 
@@ -237,180 +242,6 @@ describe('#Cluster', function () {
       });
 
     });
-
-    describe('#save()', function () {
-
-      var user,
-        labelCases = [
-          {
-            roles: [],
-            label: '',
-            title: 'roles not loaded'
-          },
-          {
-            roles: [
-              {
-                permission_name: 'CLUSTER.OPERATOR',
-                permission_label: 'Cluster Operator'
-              },
-              {
-                permission_name: 'CLUSTER.ADMINISTRATOR',
-                permission_label: 'Cluster Administrator'
-              }
-            ],
-            label: '',
-            title: 'no roles match'
-          },
-          {
-            roles: [
-              {
-                permission_name: 'CLUSTER.USER',
-                permission_label: 'Cluster User'
-              },
-              {
-                permission_name: 'CLUSTER.OPERATOR',
-                permission_label: 'Cluster Operator'
-              },
-              {
-                permission_name: 'CLUSTER.ADMINISTRATOR',
-                permission_label: 'Cluster Administrator'
-              }
-            ],
-            label: 'Cluster User',
-            title: 'roles not loaded'
-          }
-        ],
-        deferredCases = [
-          {
-            success: ['deletePrivilege', 'createPrivileges'],
-            fail: [],
-            called: [
-              {
-                context: 'Cluster',
-                methodName: 'createPrivileges'
-              },
-              {
-                context: 'Alert',
-                methodName: 'success'
-              }
-            ],
-            notCalled: [
-              {
-                context: 'Alert',
-                methodName: 'error'
-              }
-            ],
-            title: 'all requests are successful'
-          },
-          {
-            success: ['deletePrivilege'],
-            fail: ['createPrivileges'],
-            called: [
-              {
-                context: 'Cluster',
-                methodName: 'createPrivileges'
-              },
-              {
-                context: 'Alert',
-                methodName: 'error'
-              }
-            ],
-            notCalled: [
-              {
-                context: 'Alert',
-                methodName: 'success'
-              }
-            ],
-            title: 'new role request failed'
-          },
-          {
-            success: [],
-            fail: ['deletePrivilege'],
-            called: [],
-            notCalled: [
-              {
-                context: 'Cluster',
-                methodName: 'createPrivileges'
-              },
-              {
-                context: 'Alert',
-                methodName: 'success'
-              },
-              {
-                context: 'Alert',
-                methodName: 'error'
-              }
-            ],
-            title: 'delete current role request failed'
-          }
-        ];
-
-      beforeEach(function () {
-        user = {
-          permission_name: 'CLUSTER.USER',
-          permission_label: ''
-        };
-      });
-
-      labelCases.forEach(function (item) {
-
-        it(item.title, function () {
-          scope.roles = item.roles;
-          scope.save(user);
-          expect(user.permission_label).toEqual(item.label);
-        });
-
-      });
-
-      deferredCases.forEach(function (item) {
-
-        describe(item.title, function () {
-
-          beforeEach(function () {
-            scope.roles = [];
-            scope.save(user);
-            item.success.forEach(function (method) {
-              deferred[method].resolve();
-            });
-            item.fail.forEach(function (method) {
-              deferred[method].reject({
-                data: {
-                  data: {}
-                }
-              });
-            });
-            $httpBackend.expectGET(/\/api\/v1\/clusters\/\w+\/privileges/).respond(200, {
-              items: []
-            });
-            scope.$digest();
-          });
-
-          it('Cluster.deletePrivileges', function () {
-            expect(Cluster.deletePrivilege).toHaveBeenCalled();
-          });
-
-          it('scope.loadRoles', function () {
-            expect(scope.loadRoles).toHaveBeenCalled();
-          });
-
-          item.called.forEach(function (method) {
-            it(method.context + '.' + method.methodName, function () {
-              expect(mock[method.context][method.methodName]).toHaveBeenCalled();
-            });
-          });
-
-          item.notCalled.forEach(function (method) {
-            it(method.context + '.' + method.methodName, function () {
-              expect(mock[method.context][method.methodName]).not.toHaveBeenCalled();
-            });
-          });
-
-        });
-
-      });
-
-    });
-  */
   });
 
 });