You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2017/11/23 12:56:00 UTC

[4/4] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)

AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)


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

Branch: refs/heads/trunk
Commit: 99b19e5805cf3ac291eca9c8e6a1290637b08ab6
Parents: 8e36662
Author: Andrii Tkach <at...@apache.org>
Authored: Thu Nov 23 14:02:00 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Nov 23 14:02:00 2017 +0200

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/index.html  |  17 +-
 .../resources/ui/admin-web/app/scripts/app.js   |   3 +-
 .../controllers/ClusterInformationCtrl.js       | 106 ---
 .../controllers/ambariViews/ViewsListCtrl.js    |   4 +-
 .../clusters/ClusterInformationCtrl.js          | 106 +++
 .../clusters/ClustersManageAccessCtrl.js        |  97 ---
 .../controllers/clusters/UserAccessListCtrl.js  | 351 --------
 .../controllers/groups/GroupsCreateCtrl.js      |  65 --
 .../controllers/groups/GroupsEditCtrl.js        | 180 ----
 .../controllers/groups/GroupsListCtrl.js        | 106 ---
 .../userManagement/GroupCreateCtrl.js           | 112 +++
 .../controllers/userManagement/GroupEditCtrl.js | 182 ++++
 .../userManagement/GroupsListCtrl.js            | 170 ++++
 .../userManagement/UserCreateCtrl.js            | 108 +++
 .../controllers/userManagement/UserEditCtrl.js  | 290 +++++++
 .../userManagement/UserManagementCtrl.js        |  23 +
 .../controllers/userManagement/UsersListCtrl.js | 178 ++++
 .../controllers/users/UsersCreateCtrl.js        |  75 --
 .../scripts/controllers/users/UsersListCtrl.js  | 122 ---
 .../scripts/controllers/users/UsersShowCtrl.js  | 290 -------
 .../ui/admin-web/app/scripts/i18n.config.js     |   9 +-
 .../ui/admin-web/app/scripts/routes.js          |  61 +-
 .../ui/admin-web/app/scripts/services/User.js   |   5 +-
 .../resources/ui/admin-web/app/styles/main.css  |  46 +-
 .../ui/admin-web/app/styles/user-management.css |  30 +
 .../resources/ui/admin-web/app/styles/views.css |  18 -
 .../app/views/ambariViews/viewsList.html        |  26 +-
 .../admin-web/app/views/clusterInformation.html |  87 --
 .../app/views/clusters/clusterInformation.html  |  87 ++
 .../app/views/clusters/manageAccess.html        |  63 --
 .../app/views/clusters/userAccessList.html      | 102 ---
 .../ui/admin-web/app/views/groups/create.html   |  43 -
 .../ui/admin-web/app/views/groups/edit.html     |  98 ---
 .../ui/admin-web/app/views/groups/list.html     |  80 --
 .../ui/admin-web/app/views/sideNav.html         |  22 +-
 .../app/views/userManagement/groupEdit.html     |  99 +++
 .../app/views/userManagement/groupsList.html    |  94 +++
 .../app/views/userManagement/main.html          |  36 +
 .../userManagement/modals/changePassword.html   |  46 ++
 .../userManagement/modals/groupCreate.html      |  86 ++
 .../views/userManagement/modals/userCreate.html | 147 ++++
 .../app/views/userManagement/userEdit.html      | 122 +++
 .../app/views/userManagement/usersList.html     | 119 +++
 .../ui/admin-web/app/views/users/create.html    |  82 --
 .../ui/admin-web/app/views/users/list.html      |  97 ---
 .../app/views/users/modals/changePassword.html  |  46 --
 .../ui/admin-web/app/views/users/show.html      | 122 ---
 .../clusters/UserAccessListCtrl_test.js         | 820 -------------------
 .../controllers/groups/GroupsListCtrl_test.js   | 129 ---
 .../userManagement/GroupsListCtrl_test.js       | 129 +++
 .../userManagement/UsersListCtrl_test.js        | 344 ++++++++
 .../controllers/users/UsersListCtrl_test.js     | 383 ---------
 .../test/unit/services/Utility_test.js          |  10 +-
 53 files changed, 2591 insertions(+), 3682 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/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 4a77e62..e3b817e 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
@@ -121,26 +121,25 @@
 <script src="scripts/app.js"></script>
 <script src="scripts/routes.js"></script>
 <script src="scripts/i18n.config.js"></script>
-<script src="scripts/controllers/ClusterInformationCtrl.js"></script>
+<script src="scripts/controllers/clusters/ClusterInformationCtrl.js"></script>
 <script src="scripts/controllers/AppCtrl.js"></script>
 <script src="scripts/controllers/SideNavCtrl.js"></script>
 <script src="scripts/controllers/authentication/AuthenticationMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/LoginActivitiesMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/LoginMessageMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/HomeDirectoryCtrl.js"></script>
-<script src="scripts/controllers/users/UsersCreateCtrl.js"></script>
-<script src="scripts/controllers/users/UsersListCtrl.js"></script>
-<script src="scripts/controllers/users/UsersShowCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsListCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsCreateCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsEditCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserManagementCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserCreateCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UsersListCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserEditCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupsListCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupCreateCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewsListCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewsEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewUrlCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewUrlEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/CreateViewInstanceCtrl.js"></script>
-<script src="scripts/controllers/clusters/ClustersManageAccessCtrl.js"></script>
-<script src="scripts/controllers/clusters/UserAccessListCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsCreateCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsListCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsEditCtrl.js"></script>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
index 80e2813..225eb12 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
@@ -33,7 +33,8 @@ angular.module('ambariAdminConsole', [
   isLDAPConfigurationSupported: false,
   isLoginActivitiesSupported: false,
   maxStackTraceLength: 1000,
-  errorStorageSize: 500000
+  errorStorageSize: 500000,
+  minRowsToShowPagination: 10
 })
 .config(['RestangularProvider', '$httpProvider', '$provide', 'Settings', function(RestangularProvider, $httpProvider, $provide, Settings) {
   // Config Ajax-module

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
deleted file mode 100644
index 059f399..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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')
-.controller('ClusterInformationCtrl',
-['$scope', '$http', '$location', 'Cluster', '$routeParams', '$translate', '$rootScope', 'ConfirmationModal', 'Alert',
-function($scope, $http, $location, Cluster, $routeParams, $translate, $rootScope, ConfirmationModal, Alert) {
-  var $t = $translate.instant;
-  $scope.isDataLoaded = false;
-  $scope.edit = {
-    clusterName: null
-  };
-  $scope.isClusterNameEdited = false;
-
-  $scope.$watch(function() {
-    return $rootScope.cluster;
-  }, function() {
-    $scope.cluster = $rootScope.cluster;
-    if ($scope.cluster) {
-      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
-      $scope.getBlueprint();
-    }
-  }, true);
-
-  $scope.getBlueprint = function () {
-    Cluster.getBlueprint({
-      clusterName: $scope.cluster.Clusters.cluster_name
-    }).then(function (data) {
-      console.debug($t('exportBlueprint.dataLoaded'), data);
-      $scope.isDataLoaded = true;
-      var response = JSON.stringify(data, null, 4),
-        lt = /&lt;/g,
-        gt = /&gt;/g,
-        ap = /&#39;/g,
-        ic = /&#34;/g;
-      $scope.blueprint = response ? response.toString().replace(lt, "<").replace(gt, ">").replace(ap, "'").replace(ic, '"') : "";
-    });
-  };
-
-  $scope.downloadBlueprint = function () {
-    if (window.navigator.msSaveOrOpenBlob) {
-      var blob = new Blob([decodeURIComponent(encodeURI($scope.blueprint))], {
-        type: "text/csv;charset=utf-8;"
-      });
-      navigator.msSaveBlob(blob, 'blueprint.json');
-    } else {
-      var a = document.createElement('a');
-      a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI($scope.blueprint);
-      a.target = '_blank';
-      a.download = 'blueprint.json';
-      document.body.appendChild(a);
-      a.click();
-    }
-  };
-
-  $scope.toggleSaveButton = function() {
-    var value = $scope.edit.clusterName;
-    $scope.isClusterNameEdited = (value !== null && $scope.cluster.Clusters.cluster_name !== value);
-  };
-
-  $scope.confirmClusterNameChange = function() {
-    ConfirmationModal.show(
-      $t('common.clusterNameChangeConfirmation.title'),
-      $t('common.clusterNameChangeConfirmation.message', {
-        clusterName: $scope.edit.clusterName
-      })
-    )
-      .then(function () {
-        $scope.saveClusterName();
-      }).catch(function () {
-      // user clicked cancel
-      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
-      $scope.toggleSaveButton();
-    });
-  };
-
-  $scope.saveClusterName = function() {
-    var oldClusterName = $scope.cluster.Clusters.cluster_name,
-        newClusterName = $scope.edit.clusterName;
-
-    Cluster.editName(oldClusterName, newClusterName).then(function(data) {
-      $scope.cluster.Clusters.cluster_name = newClusterName;
-      $scope.edit.clusterName = newClusterName;
-      $scope.toggleSaveButton();
-      Alert.success($t('common.alerts.clusterRenamed', {clusterName: newClusterName}));
-    }).catch(function(data) {
-      Alert.error($t('common.alerts.cannotRenameCluster', {clusterName: newClusterName}), data.data.message);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
index aa77b63..8b37dca 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
@@ -18,11 +18,11 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $translate) {
+.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$translate', 'Settings', function($scope, View, $modal, Alert, ConfirmationModal, $translate, Settings) {
   var $t = $translate.instant;
   var VIEWS_VERSION_STATUS_TIMEOUT = 5000;
   $scope.isLoading = false;
-  $scope.minInstanceForPagination = 10;
+  $scope.minInstanceForPagination = Settings.minRowsToShowPagination;
 
   function checkViewVersionStatus(view, versionObj, versionNumber) {
     var deferred = View.checkViewVersionStatus(view.view_name, versionNumber);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
new file mode 100644
index 0000000..059f399
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
@@ -0,0 +1,106 @@
+/**
+ * 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')
+.controller('ClusterInformationCtrl',
+['$scope', '$http', '$location', 'Cluster', '$routeParams', '$translate', '$rootScope', 'ConfirmationModal', 'Alert',
+function($scope, $http, $location, Cluster, $routeParams, $translate, $rootScope, ConfirmationModal, Alert) {
+  var $t = $translate.instant;
+  $scope.isDataLoaded = false;
+  $scope.edit = {
+    clusterName: null
+  };
+  $scope.isClusterNameEdited = false;
+
+  $scope.$watch(function() {
+    return $rootScope.cluster;
+  }, function() {
+    $scope.cluster = $rootScope.cluster;
+    if ($scope.cluster) {
+      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
+      $scope.getBlueprint();
+    }
+  }, true);
+
+  $scope.getBlueprint = function () {
+    Cluster.getBlueprint({
+      clusterName: $scope.cluster.Clusters.cluster_name
+    }).then(function (data) {
+      console.debug($t('exportBlueprint.dataLoaded'), data);
+      $scope.isDataLoaded = true;
+      var response = JSON.stringify(data, null, 4),
+        lt = /&lt;/g,
+        gt = /&gt;/g,
+        ap = /&#39;/g,
+        ic = /&#34;/g;
+      $scope.blueprint = response ? response.toString().replace(lt, "<").replace(gt, ">").replace(ap, "'").replace(ic, '"') : "";
+    });
+  };
+
+  $scope.downloadBlueprint = function () {
+    if (window.navigator.msSaveOrOpenBlob) {
+      var blob = new Blob([decodeURIComponent(encodeURI($scope.blueprint))], {
+        type: "text/csv;charset=utf-8;"
+      });
+      navigator.msSaveBlob(blob, 'blueprint.json');
+    } else {
+      var a = document.createElement('a');
+      a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI($scope.blueprint);
+      a.target = '_blank';
+      a.download = 'blueprint.json';
+      document.body.appendChild(a);
+      a.click();
+    }
+  };
+
+  $scope.toggleSaveButton = function() {
+    var value = $scope.edit.clusterName;
+    $scope.isClusterNameEdited = (value !== null && $scope.cluster.Clusters.cluster_name !== value);
+  };
+
+  $scope.confirmClusterNameChange = function() {
+    ConfirmationModal.show(
+      $t('common.clusterNameChangeConfirmation.title'),
+      $t('common.clusterNameChangeConfirmation.message', {
+        clusterName: $scope.edit.clusterName
+      })
+    )
+      .then(function () {
+        $scope.saveClusterName();
+      }).catch(function () {
+      // user clicked cancel
+      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
+      $scope.toggleSaveButton();
+    });
+  };
+
+  $scope.saveClusterName = function() {
+    var oldClusterName = $scope.cluster.Clusters.cluster_name,
+        newClusterName = $scope.edit.clusterName;
+
+    Cluster.editName(oldClusterName, newClusterName).then(function(data) {
+      $scope.cluster.Clusters.cluster_name = newClusterName;
+      $scope.edit.clusterName = newClusterName;
+      $scope.toggleSaveButton();
+      Alert.success($t('common.alerts.clusterRenamed', {clusterName: newClusterName}));
+    }).catch(function(data) {
+      Alert.error($t('common.alerts.cannotRenameCluster', {clusterName: newClusterName}), data.data.message);
+    });
+  };
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/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
deleted file mode 100644
index 3a9ad67..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * 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')
-.controller('ClustersManageAccessCtrl', ['$scope', '$location', 'Cluster', '$routeParams', 'Alert', 'PermissionLoader', 'PermissionSaver', '$translate', 'RoleDetailsModal', '$timeout', function($scope, $location, Cluster, $routeParams, Alert, PermissionLoader, PermissionSaver, $translate, RoleDetailsModal, $timeout) {
-  var $t = $translate.instant;
-  $scope.getConstant = function (key) {
-    return $t(key).toLowerCase();
-  };
-  $scope.identity = angular.identity;
-  function reloadClusterData(){
-    PermissionLoader.getClusterPermissions({
-      clusterId: $routeParams.id
-    }).then(function(permissions) {
-      // Refresh data for rendering
-      $scope.permissionsEdit = permissions;
-      $scope.permissions = angular.copy(permissions);
-      //"$scope.isDataLoaded" should be set to true on initial load after "$scope.permissionsEdit" watcher
-      $timeout(function() {
-        $scope.isDataLoaded = true;
-      });
-      var orderedRoles = Cluster.orderedRoles;
-      var pms = [];
-      for (var key=0;key<orderedRoles.length;key++) {
-        pms.push($scope.permissions[orderedRoles[key]]);
-      }
-      $scope.permissions = pms;
-    })
-    .catch(function(data) {
-      Alert.error($t('clusters.alerts.cannotLoadClusterData'), data.data.message);
-    });
-  }
-
-  $scope.isDataLoaded = false;
-  reloadClusterData();
-  $scope.isEditMode = false;
-  $scope.permissions = {};
-  $scope.clusterName = $routeParams.id;
-
-
-  $scope.toggleEditMode = function() {
-    $scope.isEditMode = !$scope.isEditMode;
-  };
-
-  $scope.cancel = function() {
-    $scope.isEditMode = false;
-    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
-  };
-
-  $scope.save = function() {
-    PermissionSaver.saveClusterPermissions(
-      $scope.permissionsEdit,
-      {
-        clusterId: $routeParams.id
-      }
-    ).then(reloadClusterData)
-    .catch(function(data) {
-      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-      reloadClusterData();
-    });
-    $scope.isEditMode = false;
-  };
-
-  $scope.$watch(function() {
-    return $scope.permissionsEdit;
-  }, function(newValue) {
-    if (newValue && $scope.isDataLoaded) {
-      $scope.save();
-    }
-  }, true);
-
-  $scope.switchToList = function() {
-    $location.url('/clusters/' + $routeParams.id + '/userAccessList');
-  };
-
-  $scope.showHelpPage = function() {
-    Cluster.getRolesWithAuthorizations().then(function(roles) {
-      RoleDetailsModal.show(roles);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
deleted file mode 100644
index 9e83b91..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
+++ /dev/null
@@ -1,351 +0,0 @@
-/**
- * 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')
-.controller('UserAccessListCtrl',['$scope', '$location', 'Cluster', '$modal', '$rootScope', '$routeParams', 'PermissionSaver', 'Alert', '$translate', 'RoleDetailsModal',
-function($scope, $location, Cluster, $modal, $rootScope, $routeParams, PermissionSaver, Alert, $translate, RoleDetailsModal) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    users: $t('common.users').toLowerCase(),
-    groups: $t('common.groups').toLowerCase()
-  };
-  $scope.users = [];
-  $scope.usersPerPage = 10;
-  $scope.currentPage = 1;
-  $scope.totalUsers = 1;
-  $scope.currentNameFilter = '';
-  $scope.maxVisiblePages = 20;
-  $scope.roles = [];
-  $scope.clusterId = $routeParams.id;
-  $scope.tableInfo = {
-    total: 0,
-    showed: 0,
-    filtered: 0
-  };
-  $scope.isNotEmptyFilter = true;
-  $scope.NONE_ROLE = {
-    "permission_label" : $t('common.none'),
-    "permission_name" : "CLUSTER.NONE"
-  };
-  $scope.ALL_ROLE = {
-    "permission_label" : $t('common.all'),
-    "permission_name" : ""
-  };
-  $scope.AMBARI_ADMIN_ROLE = {
-    "permission_label" : $t('users.roles.ambariAdmin'),
-    "permission_name" : "AMBARI.ADMINISTRATOR"
-  };
-
-  $scope.pageChanged = function() {
-    $scope.loadUsers();
-  };
-  $scope.usersPerPageChanges = function() {
-    $scope.resetPagination();
-  };
-
-  $scope.loadUsers = function(){
-    Cluster.getPrivilegesWithFilters({
-      nameFilter: $scope.currentNameFilter,
-      typeFilter: $scope.currentTypeFilter,
-      roleFilter: $scope.currentRoleFilter,
-      currentPage: $scope.currentPage,
-      usersPerPage: $scope.usersPerPage
-    }).then(function(data) {
-      $scope.totalUsers = data.itemTotal;
-      $scope.users = data.items.map(function (user) {
-        var privilege = $scope.pickEffectivePrivilege(user.privileges);
-        // Redefine principal_name and principal type in case of None
-        privilege.principal_name = user.Users? user.Users.user_name : user.Groups.group_name;
-        if (privilege.permission_label === $t('users.roles.none')) {
-          privilege.principal_type = user.Users ? 'USER' : 'GROUP';
-        }
-        var name = encodeURIComponent(privilege.principal_name);
-        privilege.encoded_name = name;
-        privilege.original_perm = privilege.permission_name;
-        privilege.url = user.Users? ('users/' + name) : ('groups/' + name + '/edit');
-        privilege.editable = Cluster.ineditableRoles.indexOf(privilege.permission_name) == -1;
-        return privilege;
-      });
-      $scope.tableInfo.total = data.itemTotal;
-      $scope.tableInfo.showed = data.items.length;
-    });
-  };
-
-  $scope.pickEffectivePrivilege = function(privileges) {
-    if (privileges && privileges.length > 1) {
-      return privileges.reduce(function(prev, cur) {
-        var prevIndex = $scope.getRoleRank(prev.PrivilegeInfo.permission_name);
-        var curIndex = $scope.getRoleRank(cur.PrivilegeInfo.permission_name)
-        return (prevIndex < curIndex) ? prev : cur;
-      }).PrivilegeInfo;
-    } else if (privileges && privileges.length == 1 && privileges[0].PrivilegeInfo.permission_name !== "VIEW.USER") {
-      return privileges[0].PrivilegeInfo;
-    } else {
-      return angular.copy($scope.NONE_ROLE);
-    }
-  };
-
-  $scope.loadRoles = function() {
-    Cluster.getPermissions().then(function(data) {
-      $scope.roles = data.map(function(item) {
-        return item.PermissionInfo;
-      });
-      // [All, Administrator, ...roles..., None]
-      $scope.roles.unshift(angular.copy($scope.AMBARI_ADMIN_ROLE));
-      $scope.roles.unshift(angular.copy($scope.ALL_ROLE));
-      $scope.roles.push(angular.copy($scope.NONE_ROLE));
-
-      // create filter select list
-      $scope.roleFilterOptions = angular.copy($scope.roles);
-      $scope.roleFilterOptions.pop();  // filter does not support None
-      $scope.roleFilterOptions = $scope.roleFilterOptions.map(function(o) {
-        return {label: o.permission_label, value: o.permission_name};
-      });
-      $scope.currentRoleFilter = $scope.roleFilterOptions[0];
-
-      // create value select list
-      $scope.roleValueOptions = angular.copy($scope.roles)
-      $scope.roleValueOptions.shift(); // value change does not support all/administrator
-      $scope.roleValueOptions.shift();
-    });
-  };
-
-  $scope.getRoleRank = function(permission_name) {
-    var orderedRoles = Cluster.orderedRoles.concat(['VIEW.USER','CLUSTER.NONE']);
-    var index = orderedRoles.indexOf(permission_name);
-    return index;
-  };
-
-  $scope.save = function(user) {
-    var fromNone = (user.original_perm === $scope.NONE_ROLE.permission_name);
-    if (fromNone) {
-      $scope.addPrivilege(user);
-      return;
-    }
-
-    if ($scope.isUserActive) {
-      Cluster.getPrivilegesForResource({
-          nameFilter : user.user_name,
-          typeFilter : $scope.currentTypeFilter
-      }).then(function(data) {
-        var arrayOfPrivileges = data.items[0].privileges;
-        var privilegesOfTypeUser = [];
-        var privilegesOfTypeGroup = [];
-        for (var i = 0; i < arrayOfPrivileges.length; i++) {
-          if(arrayOfPrivileges[i].PrivilegeInfo.permission_name != "VIEW.USER") {
-            if(arrayOfPrivileges[i].PrivilegeInfo.principal_type === "GROUP"){
-              privilegesOfTypeGroup.push(arrayOfPrivileges[i]);
-            } else {
-              privilegesOfTypeUser.push(arrayOfPrivileges[i].PrivilegeInfo);
-            }
-          }
-        }
-
-        var effectivePrivilege = $scope.pickEffectivePrivilege(arrayOfPrivileges);
-        var effectivePrivilegeFromGroups = $scope.pickEffectivePrivilege(privilegesOfTypeGroup);
-        user.principal_type = 'USER';
-        user.original_perm = effectivePrivilege.permission_name;
-        user.editable = (Cluster.ineditableRoles.indexOf(effectivePrivilege.permission_name) === -1);
-
-        var userIndex = $scope.getRoleRank(user.permission_name);
-        var groupIndex = $scope.getRoleRank(effectivePrivilegeFromGroups.permission_name);
-
-        // Process when it's NONE privilege or higher than current effective group privilege
-        if (userIndex <= groupIndex || user.permission_name == $scope.NONE_ROLE.permission_name) {
-          var privilege_ids = privilegesOfTypeUser.filter(function(privilegeOfTypeUser) {
-            return privilegeOfTypeUser.principal_type !== 'ROLE';
-          }).map(function (privilegeOfTypeUser) {
-            return privilegeOfTypeUser.privilege_id;
-          });
-
-          // Purge existing user level privileges if there is any
-          if(privilege_ids.length !== 0) {
-            Cluster.deleteMultiplePrivileges(
-                $routeParams.id,
-                privilege_ids
-            )
-            .then(function() {
-              $scope.addPrivilege(user);
-            });
-          } else {
-            $scope.addPrivilege(user);
-          }
-        } else {
-          Alert.error($t('common.alerts.cannotSavePermissions'),
-              $t('users.alerts.usersEffectivePrivilege', {user_name : user.user_name})
-          );
-          $scope.loadUsers();
-        }
-      });
-    } else {
-      Cluster.getPrivilegesForResource({
-          nameFilter : user.group_name,
-          typeFilter : $scope.currentTypeFilter
-      }).then(function(data) {
-        var arrayOfPrivileges = data.items[0].privileges;
-        var privilegesOfTypeGroup = [];
-        var privilege = $scope.pickEffectivePrivilege(arrayOfPrivileges);
-        user.principal_type = 'GROUP';
-        user.original_perm = privilege.permission_name;
-        user.editable = (Cluster.ineditableRoles.indexOf(privilege.permission_name) === -1);
-
-        arrayOfPrivileges.forEach(function(privilegeOfTypeGroup) {
-          if(privilegeOfTypeGroup.PrivilegeInfo.permission_name != "VIEW.USER") {
-            if (privilegeOfTypeGroup.PrivilegeInfo.principal_type === "GROUP") {
-              privilegesOfTypeGroup.push(privilegeOfTypeGroup.PrivilegeInfo);
-            }
-          }
-        });
-
-        var privilege_ids = [];
-        privilegesOfTypeGroup.forEach(function(privilegeOfTypeGroup) {
-          privilege_ids.push(privilegeOfTypeGroup.privilege_id);
-        });
-
-        //delete all privileges of type GROUP, if they exist
-        //then add the privilege for the group, after which the group displays the effective privilege
-        if(privilege_ids.length !== 0) {
-          Cluster.deleteMultiplePrivileges(
-              $routeParams.id,
-              privilege_ids
-          )
-          .then(function() {
-            $scope.addPrivilege(user);
-          });
-        } else {
-          $scope.addPrivilege(user);
-        }
-      });
-    }
-  };
-
-  $scope.cancel = function(user) {
-    user.permission_name = user.original_perm;
-  };
-
-  $scope.addPrivilege = function(user) {
-    var changeToNone = user.permission_name == $scope.NONE_ROLE.permission_name;
-    if (changeToNone) {
-      if ($scope.isUserActive) {
-        Alert.success($t('users.alerts.roleChangedToNone', {
-            user_name : user.user_name
-        }));
-      } else {
-        $scope.showSuccess(user);
-      }
-      $scope.loadUsers();
-      return;
-    }
-    Cluster.createPrivileges(
-      {
-        clusterId: $routeParams.id
-      },
-      [{PrivilegeInfo: {
-        permission_name: user.permission_name,
-        principal_name: user.principal_name,
-        principal_type: user.principal_type
-      }}]
-    ).then(function() {
-        $scope.showSuccess(user);
-        $scope.loadUsers();
-      })
-      .catch(function(data) {
-        Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-        $scope.loadUsers();
-      });
-  };
-
-  $scope.showSuccess = function(user) {
-    Alert.success($t('users.alerts.roleChanged', {
-      name: user.principal_name,
-      role: $scope.roles.filter(function(r){
-          return r.permission_name == user.permission_name}
-      )[0].permission_label
-    }));
-  };
-
-  $scope.resetPagination = function() {
-    $scope.currentPage = 1;
-    $scope.loadUsers();
-  };
-  $scope.currentRoleFilter = { label:$t('common.all'), value: '' };
-
-
-  $scope.typeFilterOptions = [
-    {label: $t('common.user'), value: 'USER'},
-    {label: $t('common.group'), value: 'GROUP'}
-  ];
-
-  $scope.isUserActive = true;
-
-  $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
-  $scope.switchToUser = function() {
-    if (!$scope.isUserActive) {
-      $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-      $scope.isUserActive = true;
-      $scope.resetPagination();
-    }
-  };
-
-  $scope.switchToGroup = function() {
-    if ($scope.isUserActive) {
-      $scope.currentTypeFilter = $scope.typeFilterOptions[1];
-      $scope.isUserActive = false;
-      $scope.resetPagination();
-    }
-  };
-
-  $scope.clearFilters = function() {
-    $scope.currentNameFilter = '';
-    $scope.currentRoleFilter = $scope.roleFilterOptions[0];
-    $scope.resetPagination();
-  };
-
-  $scope.loadRoles();
-  $scope.loadUsers();
-
-  $scope.$watch(
-    function (scope) {
-      return Boolean(scope.currentNameFilter || (scope.currentRoleFilter && scope.currentRoleFilter.value));
-    },
-    function (newValue, oldValue, scope) {
-      scope.isNotEmptyFilter = newValue;
-    }
-  );
-
-  $rootScope.$watch(function(scope) {
-    return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
-      $rootScope.LDAPSynced = false;
-      $scope.loadUsers();
-    }
-  });
-
-  $scope.switchToBlock = function() {
-    $location.url('/clusters/' + $routeParams.id + '/manageAccess');
-  };
-
-  $scope.showHelpPage = function() {
-    Cluster.getRolesWithAuthorizations().then(function(roles) {
-      RoleDetailsModal.show(roles);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
deleted file mode 100644
index 67743a0..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * 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')
-.controller('GroupsCreateCtrl',['$scope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', function($scope, Group, $location, Alert, UnsavedDialog, $translate) {
-  var $t = $translate.instant;
-  $scope.group = new Group();
-  var targetUrl = '/groups';
-
-  $scope.createGroup = function() {
-    $scope.form.submitted = true;
-    if ($scope.form.$valid){
-      $scope.group.save().then(function() {
-        Alert.success($t('groups.alerts.groupCreated', {groupName: $scope.group.group_name}));
-        $scope.form.$setPristine();
-        $location.path(targetUrl);
-      })
-      .catch(function(data) {
-        Alert.error($t('groups.alerts.groupCreationError'), data.data.message);
-      });
-    }
-  };
-
-  $scope.cancel = function() {
-    $scope.form.$setPristine();
-    $location.path('/groups');
-  };
-
-  $scope.$on('$locationChangeStart', function(event, __targetUrl) {
-    if( $scope.form.$dirty ){
-      UnsavedDialog().then(function(action) {
-        targetUrl = __targetUrl.split('#').pop();
-        switch(action){
-          case 'save':
-            $scope.createGroup();
-            break;
-          case 'discard':
-            $scope.form.$setPristine();
-            $location.path(targetUrl);
-            break;
-          case 'cancel':
-            targetUrl = '/groups';
-            break;
-        }
-      });
-      event.preventDefault();
-    }
-  });
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
deleted file mode 100644
index a63ebe2..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * 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')
-.controller('GroupsEditCtrl',['$scope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', 'GroupConstants', '$translate', function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location, GroupConstants, $translate) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    group: $t('common.group'),
-    view: $t('common.view').toLowerCase(),
-    cluster: $t('common.cluster').toLowerCase()
-  };
-  $scope.editMode = false;
-  $scope.group = new Group($routeParams.id);
-  $scope.group.editingUsers = [];
-  $scope.groupMembers = [];
-  $scope.dataLoaded = false;
-  
-  $scope.isMembersEditing = false;
-
-  $scope.$watch(function() {
-    return $scope.group.editingUsers;
-  }, function(newValue) {
-    if(newValue && !angular.equals(newValue, $scope.groupMembers)){
-      $scope.updateMembers();  
-    }
-  }, true);
-  
-  $scope.enableMembersEditing = function() {
-    $scope.isMembersEditing = true;
-    $scope.group.editingUsers = angular.copy($scope.groupMembers);
-  };
-  $scope.cancelUpdate = function() {
-    $scope.isMembersEditing = false;
-    $scope.group.editingUsers = '';
-  };
-  $scope.updateMembers = function() {
-    var newMembers = $scope.group.editingUsers.toString().split(',').filter(function(item) {
-      return item.trim();}
-    ).map(function(item) {
-        return item.trim()
-      }
-    );
-    $scope.group.members = newMembers;
-    $scope.group.saveMembers().catch(function(data) {
-        Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
-      }).finally(function() {
-        loadMembers();
-      });
-    $scope.isMembersEditing = false;
-  };
-
-
-  function loadMembers(){
-    $scope.group.getMembers().then(function(members) {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-      $scope.groupMembers = members;
-      $scope.group.editingUsers = angular.copy($scope.groupMembers);
-    });
-  }    
-  
-  $scope.group.isLDAP().then(function(isLDAP) {
-    $scope.group.ldap_group = isLDAP;
-    $scope.group.getGroupType().then(function() {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-    });
-    loadMembers();
-  });
-
-  $scope.group.getGroupType();
-
-  $scope.deleteGroup = function(group) {
-    ConfirmationModal.show(
-      $t('common.delete', {
-        term: $t('common.group')
-      }),
-      $t('common.deleteConfirmation', {
-        instanceType: $t('common.group').toLowerCase(),
-        instanceName: '"' + group.group_name + '"'
-      })
-    ).then(function() {
-      Cluster.getPrivilegesForResource({
-        nameFilter : group.group_name,
-        typeFilter : {value: 'GROUP'}
-      }).then(function(data) {
-        var clusterPrivilegesIds = [];
-        var viewsPrivileges = [];
-        if (data.items && data.items.length) {
-          angular.forEach(data.items[0].privileges, function(privilege) {
-            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
-              if (privilege.PrivilegeInfo.type === 'VIEW') {
-                viewsPrivileges.push({
-                  id: privilege.PrivilegeInfo.privilege_id,
-                  view_name: privilege.PrivilegeInfo.view_name,
-                  version: privilege.PrivilegeInfo.version,
-                  instance_name: privilege.PrivilegeInfo.instance_name
-                });
-              } else {
-                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
-              }
-            }
-          });
-        }
-        group.destroy().then(function() {
-          $location.path('/groups');
-          if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
-          }
-          angular.forEach(viewsPrivileges, function(privilege) {
-            View.deletePrivilege(privilege);
-          });
-        });
-      });
-    });
-  };
-
-
-  $scope.removePrivilege = function(name, privilege) {
-    var privilegeObject = {
-        id: privilege.privilege_id,
-        view_name: privilege.view_name,
-        version: privilege.version,
-        instance_name: name
-    };
-    View.deletePrivilege(privilegeObject).then(function() {
-      loadPrivileges();
-    });
-  };
-
-function loadPrivileges() {
-  // Load privileges
-  Group.getPrivileges($routeParams.id).then(function(data) {
-    var privileges = {
-      clusters: {},
-      views: {}
-    };
-    angular.forEach(data.data.items, function(privilege) {
-      privilege = privilege.PrivilegeInfo;
-      if(privilege.type === 'CLUSTER'){
-        // This is cluster
-        privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || [];
-        privileges.clusters[privilege.cluster_name].push(privilege.permission_label);
-      } else if ( privilege.type === 'VIEW'){
-        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
-        privileges.views[privilege.instance_name].version = privilege.version;
-        privileges.views[privilege.instance_name].view_name = privilege.view_name;
-        privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
-        privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
-      }
-    });
-
-    $scope.privileges = data.data.items.length ? privileges : null;
-    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
-    $scope.noViewPriv = $.isEmptyObject(privileges.views);
-    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
-    $scope.dataLoaded = true;
-  }).catch(function(data) {
-    Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
-  });
-}
-loadPrivileges();
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
deleted file mode 100644
index 7cc590e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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')
-.controller('GroupsListCtrl',['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', 'GroupConstants', '$translate', function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $translate) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    groups: $t('common.groups').toLowerCase()
-  };
-  $scope.isLoading = false;
-  $scope.groups = [];
-
-  $scope.groupsPerPage = 10;
-  $scope.currentPage = 1;
-  $scope.totalGroups = 1;
-  $scope.currentNameFilter = '';
-  $scope.maxVisiblePages=20;
-  $scope.tableInfo = {
-    total: 0,
-    showed: 0
-  };
-  $scope.isNotEmptyFilter = true;
-
-  $scope.pageChanged = function() {
-    loadGroups();
-  };
-  $scope.groupsPerPageChanges = function() {
-    loadGroups();
-  };
-
-  $scope.resetPagination = function() {
-    $scope.currentPage = 1;
-    loadGroups();
-  };
-
-  function loadGroups(){
-    $scope.isLoading = true;
-    Group.all({
-      currentPage: $scope.currentPage, 
-      groupsPerPage: $scope.groupsPerPage, 
-      searchString: $scope.currentNameFilter,
-      group_type: $scope.currentTypeFilter.value
-    }).then(function(groups) {
-      $scope.isLoading = false;
-      $scope.totalGroups = groups.itemTotal;
-      $scope.groups = groups.map(Group.makeGroup);
-      $scope.tableInfo.total = groups.itemTotal;
-      $scope.tableInfo.showed = groups.length;
-    })
-    .catch(function(data) {
-      console.error($t('groups.alerts.getGroupsListError'));
-    });
-  }
-
-  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
-    .concat(Object.keys(GroupConstants.TYPES).map(function(key) {
-      return {
-        label: $t(GroupConstants.TYPES[key].LABEL_KEY),
-        value: GroupConstants.TYPES[key].VALUE
-      };
-  }));
-  $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
-  $scope.clearFilters = function () {
-    $scope.currentNameFilter = '';
-    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-    $scope.resetPagination();
-  };
-  
-  loadGroups();
-
-  $scope.$watch(
-    function (scope) {
-      return Boolean(scope.currentNameFilter || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*'));
-    },
-    function (newValue, oldValue, scope) {
-      scope.isNotEmptyFilter = newValue;
-    }
-  );
-
-  $rootScope.$watch(function(scope) {
-    return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
-      $rootScope.LDAPSynced = false;
-      loadGroups();
-    }
-  });
-
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
new file mode 100644
index 0000000..94a2c9f
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
@@ -0,0 +1,112 @@
+/**
+ * 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')
+.controller('GroupCreateCtrl',
+['$scope', '$rootScope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', '$modalInstance', 'Cluster',
+function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate, $modalInstance, Cluster) {
+  var $t = $translate.instant;
+
+  $scope.form = {};
+  $scope.formData = {
+    groupName: '',
+    members: [],
+    role: ''
+  };
+  $scope.roleOptions = [];
+
+
+  function loadRoles() {
+    Cluster.getPermissions().then(function(data) {
+      $scope.roleOptions = data.map(function(item) {
+        return item.PermissionInfo;
+      });
+    });
+  }
+
+  function unsavedChangesCheck() {
+    if ($scope.form.groupCreateForm.$dirty) {
+      UnsavedDialog().then(function (action) {
+        switch (action) {
+          case 'save':
+            $scope.save();
+            break;
+          case 'discard':
+            $modalInstance.close('discard');
+            break;
+          case 'cancel':
+            break;
+        }
+      });
+    } else {
+      $modalInstance.close('discard');
+    }
+  }
+
+  function saveMembers(group, members) {
+    group.members = members.filter(function(item) {
+      return item.trim();
+    }).map(function(item) {
+      return item.trim();
+    });
+    group.saveMembers().catch(function(data) {
+      Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
+    });
+  }
+
+  $scope.save = function () {
+    $scope.form.groupCreateForm.submitted = true;
+    if ($scope.form.groupCreateForm.$valid) {
+      var group = new Group($scope.formData.groupName);
+      group.save().then(function () {
+        saveMembers(group, $scope.formData.members);
+        saveRole();
+        $modalInstance.dismiss('created');
+        Alert.success($t('groups.alerts.groupCreated', {groupName: $scope.formData.groupName}));
+      })
+      .catch(function (data) {
+        Alert.error($t('groups.alerts.groupCreationError'), data.data.message);
+      });
+    }
+  };
+
+  function saveRole() {
+    Cluster.createPrivileges(
+      {
+        clusterId: $rootScope.cluster.Clusters.cluster_name
+      },
+      [{PrivilegeInfo: {
+        permission_name: $scope.roleOptions.filter(function(role) {
+          return role.permission_id == Number($scope.formData.role);
+        })[0].permission_name,
+        principal_name: $scope.formData.groupName,
+        principal_type: 'GROUP'
+      }}]
+    )
+      .catch(function(data) {
+        Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+      });
+  }
+
+  $scope.cancel = function () {
+    unsavedChangesCheck();
+  };
+
+  loadRoles();
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
new file mode 100644
index 0000000..ff705eb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
@@ -0,0 +1,182 @@
+/**
+ * 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')
+.controller('GroupEditCtrl',
+['$scope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', 'GroupConstants', '$translate',
+function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location, GroupConstants, $translate) {
+  var $t = $translate.instant;
+  $scope.constants = {
+    group: $t('common.group'),
+    view: $t('common.view').toLowerCase(),
+    cluster: $t('common.cluster').toLowerCase()
+  };
+  $scope.editMode = false;
+  $scope.group = new Group($routeParams.id);
+  $scope.group.editingUsers = [];
+  $scope.groupMembers = [];
+  $scope.dataLoaded = false;
+  
+  $scope.isMembersEditing = false;
+
+  $scope.$watch(function() {
+    return $scope.group.editingUsers;
+  }, function(newValue) {
+    if(newValue && !angular.equals(newValue, $scope.groupMembers)){
+      $scope.updateMembers();  
+    }
+  }, true);
+  
+  $scope.enableMembersEditing = function() {
+    $scope.isMembersEditing = true;
+    $scope.group.editingUsers = angular.copy($scope.groupMembers);
+  };
+  $scope.cancelUpdate = function() {
+    $scope.isMembersEditing = false;
+    $scope.group.editingUsers = '';
+  };
+  $scope.updateMembers = function() {
+    var newMembers = $scope.group.editingUsers.toString().split(',').filter(function(item) {
+      return item.trim();}
+    ).map(function(item) {
+        return item.trim()
+      }
+    );
+    $scope.group.members = newMembers;
+    $scope.group.saveMembers().catch(function(data) {
+        Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
+      }).finally(function() {
+        loadMembers();
+      });
+    $scope.isMembersEditing = false;
+  };
+
+
+  function loadMembers(){
+    $scope.group.getMembers().then(function(members) {
+      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
+      $scope.groupMembers = members;
+      $scope.group.editingUsers = angular.copy($scope.groupMembers);
+    });
+  }    
+  
+  $scope.group.isLDAP().then(function(isLDAP) {
+    $scope.group.ldap_group = isLDAP;
+    $scope.group.getGroupType().then(function() {
+      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
+    });
+    loadMembers();
+  });
+
+  $scope.group.getGroupType();
+
+  $scope.deleteGroup = function(group) {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.group')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.group').toLowerCase(),
+        instanceName: '"' + group.group_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : group.group_name,
+        typeFilter : {value: 'GROUP'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        group.destroy().then(function() {
+          $location.path('/userManagement');
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+        });
+      });
+    });
+  };
+
+
+  $scope.removePrivilege = function(name, privilege) {
+    var privilegeObject = {
+        id: privilege.privilege_id,
+        view_name: privilege.view_name,
+        version: privilege.version,
+        instance_name: name
+    };
+    View.deletePrivilege(privilegeObject).then(function() {
+      loadPrivileges();
+    });
+  };
+
+function loadPrivileges() {
+  // Load privileges
+  Group.getPrivileges($routeParams.id).then(function(data) {
+    var privileges = {
+      clusters: {},
+      views: {}
+    };
+    angular.forEach(data.data.items, function(privilege) {
+      privilege = privilege.PrivilegeInfo;
+      if(privilege.type === 'CLUSTER'){
+        // This is cluster
+        privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || [];
+        privileges.clusters[privilege.cluster_name].push(privilege.permission_label);
+      } else if ( privilege.type === 'VIEW'){
+        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
+        privileges.views[privilege.instance_name].version = privilege.version;
+        privileges.views[privilege.instance_name].view_name = privilege.view_name;
+        privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
+        privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+      }
+    });
+
+    $scope.privileges = data.data.items.length ? privileges : null;
+    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
+    $scope.noViewPriv = $.isEmptyObject(privileges.views);
+    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
+    $scope.dataLoaded = true;
+  }).catch(function(data) {
+    Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
+  });
+}
+loadPrivileges();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
new file mode 100644
index 0000000..af77ba9
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
@@ -0,0 +1,170 @@
+/**
+ * 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')
+.controller('GroupsListCtrl',
+['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', 'GroupConstants', '$translate', 'Settings', 'Cluster', 'View', '$location',
+function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $translate, Settings, Cluster, View, $location) {
+  var $t = $translate.instant;
+  $scope.constants = {
+    groups: $t('common.groups').toLowerCase()
+  };
+  $scope.minRowsToShowPagination = Settings.minRowsToShowPagination;
+  $scope.isLoading = false;
+  $scope.groups = [];
+
+  $scope.groupsPerPage = 10;
+  $scope.currentPage = 1;
+  $scope.totalGroups = 0;
+  $scope.filter = {
+    name: '',
+    type: null
+  };
+  $scope.maxVisiblePages=20;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0
+  };
+  $scope.isNotEmptyFilter = true;
+
+  $scope.pageChanged = function() {
+    loadGroups();
+  };
+  $scope.groupsPerPageChanges = function() {
+    loadGroups();
+  };
+
+  $scope.resetPagination = function() {
+    $scope.currentPage = 1;
+    loadGroups();
+  };
+
+  function loadGroups(){
+    $scope.isLoading = true;
+    Group.all({
+      currentPage: $scope.currentPage, 
+      groupsPerPage: $scope.groupsPerPage, 
+      searchString: $scope.filter.name,
+      group_type: $scope.filter.type.value
+    }).then(function(groups) {
+      $scope.isLoading = false;
+      $scope.totalGroups = groups.itemTotal;
+      $scope.groups = groups.map(Group.makeGroup);
+      $scope.tableInfo.total = groups.itemTotal;
+      $scope.tableInfo.showed = groups.length;
+    })
+    .catch(function(data) {
+      console.error($t('groups.alerts.getGroupsListError'));
+    });
+  }
+
+  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
+    .concat(Object.keys(GroupConstants.TYPES).map(function(key) {
+      return {
+        label: $t(GroupConstants.TYPES[key].LABEL_KEY),
+        value: GroupConstants.TYPES[key].VALUE
+      };
+  }));
+  $scope.filter.type = $scope.typeFilterOptions[0];
+
+  $scope.clearFilters = function () {
+    $scope.filter.name = '';
+    $scope.filter.type = $scope.typeFilterOptions[0];
+    $scope.resetPagination();
+  };
+  
+  loadGroups();
+
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.filter.name || (scope.filter.type && scope.filter.type.value !== '*'));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
+  $rootScope.$watch(function(scope) {
+    return scope.LDAPSynced;
+  }, function(LDAPSynced) {
+    if(LDAPSynced === true){
+      $rootScope.LDAPSynced = false;
+      loadGroups();
+    }
+  });
+
+  $scope.createGroup = function () {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/userManagement/modals/groupCreate.html',
+      controller: 'GroupCreateCtrl',
+      backdrop: 'static'
+    });
+
+    modalInstance.result.catch(loadGroups);
+  };
+
+  $scope.deleteGroup = function(group) {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.group')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.group').toLowerCase(),
+        instanceName: '"' + group.group_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : group.group_name,
+        typeFilter : {value: 'GROUP'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        group.destroy().then(function() {
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+          loadGroups();
+        });
+      });
+    });
+  };
+
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
new file mode 100644
index 0000000..34637ae
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
@@ -0,0 +1,108 @@
+/**
+ * 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')
+.controller('UserCreateCtrl',
+['$scope', '$rootScope', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', 'Cluster', '$modalInstance',
+function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate, Cluster, $modalInstance) {
+  var $t = $translate.instant;
+
+  $scope.form = {};
+  $scope.formData = {
+    userName: '',
+    password: '',
+    confirmPassword: '',
+    role: null,
+    isAdmin: false,
+    isActive: true
+  };
+  $scope.roleOptions = [];
+
+  function loadRoles() {
+    Cluster.getPermissions().then(function(data) {
+      $scope.roleOptions = data.map(function(item) {
+        return item.PermissionInfo;
+      });
+    });
+  }
+
+  function unsavedChangesCheck() {
+    if ($scope.form.userCreateForm.$dirty) {
+      UnsavedDialog().then(function (action) {
+        switch (action) {
+          case 'save':
+            $scope.save();
+            break;
+          case 'discard':
+            $modalInstance.close('discard');
+            break;
+          case 'cancel':
+            break;
+        }
+      });
+    } else {
+      $modalInstance.close('discard');
+    }
+  }
+
+  $scope.save = function () {
+    $scope.form.userCreateForm.submitted = true;
+    if ($scope.form.userCreateForm.$valid) {
+      User.create({
+        'Users/user_name': $scope.formData.userName,
+        'Users/password': $scope.formData.password,
+        'Users/active': Boolean($scope.formData.isActive),
+        'Users/admin': Boolean($scope.formData.isAdmin)
+      }).then(function () {
+        saveRole();
+        $modalInstance.dismiss('created');
+        Alert.success($t('users.alerts.userCreated', {
+          userName: $scope.formData.userName,
+          encUserName: encodeURIComponent($scope.formData.userName)
+        }));
+      }).catch(function (data) {
+        Alert.error($t('users.alerts.userCreationError'), data.data.message);
+      });
+    }
+  };
+
+  function saveRole() {
+    Cluster.createPrivileges(
+      {
+        clusterId: $rootScope.cluster.Clusters.cluster_name
+      },
+      [{PrivilegeInfo: {
+        permission_name: $scope.roleOptions.filter(function(role) {
+          return role.permission_id == Number($scope.formData.role);
+        })[0].permission_name,
+        principal_name: $scope.formData.userName,
+        principal_type: 'USER'
+      }}]
+    )
+    .catch(function(data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  $scope.cancel = function () {
+    unsavedChangesCheck();
+  };
+
+  loadRoles();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
new file mode 100644
index 0000000..001bb1b
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
@@ -0,0 +1,290 @@
+/**
+ * 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')
+.controller('UserEditCtrl', ['$scope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', function($scope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate) {
+
+  var $t = $translate.instant;
+
+  $scope.constants = {
+    user: $t('common.user'),
+    status: $t('users.status'),
+    admin: $t('users.admin'),
+    password: $t('users.password'),
+    view: $t('common.view').toLowerCase(),
+    cluster: $t('common.cluster').toLowerCase()
+  };
+
+  function loadUserInfo(){
+    User.get($routeParams.id).then(function(data) {
+      $scope.user = User.makeUser(data).Users;
+      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
+      $scope.editingGroupsList = angular.copy($scope.user.groups);
+    });
+  }
+
+  loadUserInfo();
+  $scope.user;
+  $scope.isCurrentUser = true;
+  $scope.dataLoaded = false;
+
+  $scope.isGroupEditing = false;
+  $scope.enableGroupEditing = function() {
+    $scope.isGroupEditing = true;
+    $scope.editingGroupsList = angular.copy($scope.user.groups);
+  };
+
+  $scope.$watch(function() {
+    return $scope.editingGroupsList;
+  }, function(newValue) {
+    if(newValue){
+      if( !angular.equals(newValue, $scope.user.groups) ){
+        $scope.updateGroups();
+      }
+    }
+  }, true);
+
+  $scope.updateGroups = function() {
+    var groups = $scope.editingGroupsList.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+    var diff = getDifference($scope.user.groups, groups);
+    var promises = [];
+    // Remove user from groups
+    angular.forEach(diff.del, function(groupName) {
+      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function(data) {
+        Alert.error($t('users.alerts.removeUserError'), data.data.message);
+      }));
+    });
+    // Add user to groups
+    angular.forEach(diff.add, function(groupName) {
+      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function(data) {
+        Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
+      }));
+    });
+    $q.all(promises).then(function() {
+      loadUserInfo();
+    });
+    $scope.isGroupEditing = false;
+  };
+
+  $scope.getUserMembership = function(userType) {
+    if(userType) {
+	return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
+    }
+  };
+
+  $scope.cancelUpdate = function() {
+    $scope.isGroupEditing = false;
+    $scope.editingGroupsList = '';
+  };
+
+  $scope.openChangePwdDialog = function() {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/userManagement/modals/changePassword.html',
+      resolve: {
+        userName: function() {
+          return $scope.user.user_name;
+        }
+      },
+      controller: ['$scope', 'userName', function($scope, userName) {
+        $scope.passwordData = {
+          password: '',
+          currentUserPassword: ''
+        };
+
+        $scope.form = {};
+        $scope.userName = userName;
+
+        $scope.ok = function() {
+          $scope.form.passwordChangeForm.submitted = true;
+          if($scope.form.passwordChangeForm.$valid){
+
+            modalInstance.close({
+              password: $scope.passwordData.password, 
+              currentUserPassword: $scope.passwordData.currentUserPassword
+            });
+          }
+        };
+        $scope.cancel = function() {
+          modalInstance.dismiss('cancel');
+        };
+      }]
+    });
+
+    modalInstance.result.then(function(data) {
+      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function() {
+        Alert.success($t('users.alerts.passwordChanged'));
+      }).catch(function(data) {
+        Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
+      });
+    }); 
+  };
+
+  $scope.toggleUserActive = function() {
+    if(!$scope.isCurrentUser){
+      var newStatusKey = $scope.user.active ? 'inactive' : 'active',
+        newStatus = $t('users.' + newStatusKey).toLowerCase();
+      ConfirmationModal.show(
+        $t('users.changeStatusConfirmation.title'),
+        $t('users.changeStatusConfirmation.message', {
+          userName: $scope.user.user_name,
+          status: newStatus
+        })
+      ).then(function() {
+        User.setActive($scope.user.user_name, $scope.user.active)
+          .catch(function(data) {
+            Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
+            $scope.user.active = !$scope.user.active;
+          });
+      })
+      .catch(function() {
+        $scope.user.active = !$scope.user.active;
+      });
+    }
+  };    
+  $scope.toggleUserAdmin = function() {
+    if(!$scope.isCurrentUser){
+      var action = $scope.user.admin ?
+        $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
+      ConfirmationModal.show(
+        $t('users.changePrivilegeConfirmation.title'),
+        $t('users.changePrivilegeConfirmation.message', {
+          action: action,
+          userName: $scope.user.user_name
+        })
+      ).then(function() {
+        User.setAdmin($scope.user.user_name, $scope.user.admin)
+        .then(function() {
+          loadPrivileges();
+        })
+        .catch(function (data) {
+          Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
+          $scope.user.admin = !$scope.user.admin;
+        });
+      })
+      .catch(function() {
+        $scope.user.admin = !$scope.user.admin;
+      });
+
+    }
+  };
+
+  $scope.removePrivilege = function(name, privilege) {
+    var privilegeObject = {
+        id: privilege.privilege_id,
+        view_name: privilege.view_name,
+        version: privilege.version,
+        instance_name: name
+    };
+    View.deletePrivilege(privilegeObject).then(function() {
+      loadPrivileges();
+    });
+  };
+
+  $scope.deleteUser = function() {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.user')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.user').toLowerCase(),
+        instanceName: '"' + $scope.user.user_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : $scope.user.user_name,
+        typeFilter : {value: 'USER'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'USER') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        User.delete($scope.user.user_name).then(function() {
+          $location.path('/userManagement');
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+        });
+      });
+    });
+  };
+
+  // Load privileges
+  function loadPrivileges(){
+    User.getPrivileges($routeParams.id).then(function(data) {
+      var privileges = {
+        clusters: {},
+        views: {}
+      };
+      angular.forEach(data.data.items, function(privilege) {
+        privilege = privilege.PrivilegeInfo;
+        if(privilege.type === 'CLUSTER'){
+          // This is cluster
+          if (privileges.clusters[privilege.cluster_name]) {
+            var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
+            var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
+            // replace when cur is a more powerful role
+            if (curIndex < preIndex) {
+              privileges.clusters[privilege.cluster_name] = privilege;
+            }
+          } else {
+            privileges.clusters[privilege.cluster_name] = privilege;
+          }
+        } else if ( privilege.type === 'VIEW'){
+          privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
+          privileges.views[privilege.instance_name].version = privilege.version;
+          privileges.views[privilege.instance_name].view_name = privilege.view_name;
+          privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
+          if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) == -1) {
+            privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+          }
+        }
+      });
+
+      $scope.privileges = data.data.items.length ? privileges : null;
+      $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
+      $scope.noViewPriv = $.isEmptyObject(privileges.views);
+      $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
+      $scope.dataLoaded = true;
+
+    }).catch(function(data) {
+      Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
+    });
+  }
+  loadPrivileges();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
new file mode 100644
index 0000000..e9ec6ab
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
@@ -0,0 +1,23 @@
+/**
+ * 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')
+.controller('UserManagementCtrl', ['$scope', function($scope) {
+  $scope.activeTab = 'USERS';
+}]);