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:55:57 UTC
[1/4] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new
design for Admin View: User Management. (atkach)
Repository: ambari
Updated Branches:
refs/heads/trunk 8e36662ae -> 99b19e580
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
new file mode 100644
index 0000000..fcafa59
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
@@ -0,0 +1,344 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+ describe('UsersListCtrl', function() {
+
+ var scope, ctrl, $t, $httpBackend;
+
+ beforeEach(module('ambariAdminConsole', function () {}));
+
+ beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+ scope = $rootScope.$new();
+ $t = _$translate_.instant;
+ $httpBackend = _$httpBackend_;
+ ctrl = $controller('UsersListCtrl', {
+ $scope: scope
+ });
+ }));
+
+ describe('#clearFilters()', function () {
+
+ it('should clear filters and reset pagination', function () {
+ scope.currentPage = 2;
+ scope.filters.name = 'a';
+ scope.filters.status = {
+ label: $t('common.local'),
+ value: false
+ };
+ scope.filters.type = {
+ label: $t('common.local'),
+ value: 'LOCAL'
+ };
+ scope.clearFilters();
+ expect(scope.filters.name).toEqual('');
+ expect(scope.filters.status).toEqual({
+ label: $t('common.all'),
+ value: '*'
+ });
+ expect(scope.filters.type).toEqual({
+ label: $t('common.all'),
+ value: '*'
+ });
+ expect(scope.currentPage).toEqual(1);
+ });
+
+ });
+
+ describe('#isNotEmptyFilter', function () {
+
+ var cases = [
+ {
+ currentNameFilter: '',
+ currentTypeFilter: null,
+ currentActiveFilter: null,
+ isNotEmptyFilter: false,
+ title: 'no filters'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: false,
+ title: 'empty filters'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name filter'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name filter with "0" as string'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'type filter'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'activity filter'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name and type filters'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'name and activity filters'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name and admin filters'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name and type filters with "0" as string'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'name and activity filters with "0" as string'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name and admin filters with "0" as string'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'type and activity filters'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'type and admin filters'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'activity and admin filters'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters except name one'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters except type one'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters except activity one'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters except admin one'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: '*'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters with "0" as string except type one'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters with "0" as string except activity one'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: 'LOCAL'
+ },
+ currentActiveFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters with "0" as string except admin one'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: false
+ },
+ currentActiveFilter: {
+ value: 'LOCAL'
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: false
+ },
+ currentActiveFilter: {
+ value: 'LOCAL'
+ },
+ isNotEmptyFilter: true,
+ title: 'all filters with "0" as string'
+ }
+ ];
+
+ cases.forEach(function (item) {
+ it(item.title, function () {
+ $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
+ scope.filters.name = item.currentNameFilter;
+ scope.filters.status = item.currentActiveFilter;
+ scope.filters.type = item.currentTypeFilter;
+ scope.$digest();
+ expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+ });
+ });
+
+ });
+
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
deleted file mode 100644
index 9d6cd54..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
+++ /dev/null
@@ -1,383 +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.
- */
-
-describe('#Cluster', function () {
-
- describe('UsersListCtrl', function() {
-
- var scope, ctrl, $t, $httpBackend;
-
- beforeEach(module('ambariAdminConsole', function () {}));
-
- beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
- scope = $rootScope.$new();
- $t = _$translate_.instant;
- $httpBackend = _$httpBackend_;
- ctrl = $controller('UsersListCtrl', {
- $scope: scope
- });
- }));
-
- describe('#clearFilters()', function () {
-
- it('should clear filters and reset pagination', function () {
- scope.currentPage = 2;
- scope.currentNameFilter = 'a';
- scope.currentActiveFilter = {
- label: $t('common.local'),
- value: false
- };
- scope.currentTypeFilter = {
- label: $t('common.local'),
- value: 'LOCAL'
- };
- scope.adminFilter = true;
- scope.clearFilters();
- expect(scope.currentNameFilter).toEqual('');
- expect(scope.currentActiveFilter).toEqual({
- label: $t('common.all'),
- value: '*'
- });
- expect(scope.currentTypeFilter).toEqual({
- label: $t('common.all'),
- value: '*'
- });
- expect(scope.currentPage).toEqual(1);
- expect(scope.adminFilter).toBe(false);
- });
-
- });
-
- describe('#isNotEmptyFilter', function () {
-
- var cases = [
- {
- currentNameFilter: '',
- currentTypeFilter: null,
- currentActiveFilter: null,
- isNotEmptyFilter: false,
- adminFilter: false,
- title: 'no filters'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: false,
- title: 'empty filters'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name filter'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name filter with "0" as string'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'type filter'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'activity filter'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'admin filter'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name and type filters'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name and activity filters'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'name and admin filters'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name and type filters with "0" as string'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'name and activity filters with "0" as string'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'name and admin filters with "0" as string'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'type and activity filters'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'type and admin filters'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'activity and admin filters'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters except name one'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters except type one'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters except activity one'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'all filters except admin one'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: '*'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters with "0" as string except type one'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: '*'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters with "0" as string except activity one'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: 'LOCAL'
- },
- currentActiveFilter: {
- value: false
- },
- adminFilter: false,
- isNotEmptyFilter: true,
- title: 'all filters with "0" as string except admin one'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: false
- },
- currentActiveFilter: {
- value: 'LOCAL'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: false
- },
- currentActiveFilter: {
- value: 'LOCAL'
- },
- adminFilter: true,
- isNotEmptyFilter: true,
- title: 'all filters with "0" as string'
- }
- ];
-
- cases.forEach(function (item) {
- it(item.title, function () {
- $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
- scope.currentNameFilter = item.currentNameFilter;
- scope.currentActiveFilter = item.currentActiveFilter;
- scope.currentTypeFilter = item.currentTypeFilter;
- scope.adminFilter = item.adminFilter;
- scope.$digest();
- expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
- });
- });
-
- });
-
- });
-
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
index 1b76dcf..7f67de4 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
@@ -25,7 +25,13 @@ describe('Utility Service', function () {
beforeEach(function () {
module('ambariAdminConsole', function ($provide) {
- $provide.value('$window', {});
+ $provide.value('$window', {
+ localStorage: {
+ getItem: function() {return '{}';},
+ setItem: function() {}
+ },
+ location: {}
+ });
});
inject(function (_Utility_, _$httpBackend_, $rootScope, $controller, _Cluster_, _$q_) {
Utility = _Utility_;
@@ -54,7 +60,7 @@ describe('Utility Service', function () {
httpBackend.whenGET(/\/api\/v1\/views.+/).respond(200, {
items: []
});
- httpBackend.whenGET("views/clusterInformation.html").respond(200, {});
+ httpBackend.whenGET("views/clusters/clusterInformation.html").respond(200, {});
});
});
[4/4] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new
design for Admin View: User Management. (atkach)
Posted by at...@apache.org.
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 = /</g,
- gt = />/g,
- ap = /'/g,
- ic = /"/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 = /</g,
+ gt = />/g,
+ ap = /'/g,
+ ic = /"/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';
+}]);
[2/4] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new
design for Admin View: User Management. (atkach)
Posted by at...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
new file mode 100644
index 0000000..e0c1144
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
@@ -0,0 +1,86 @@
+<!--
+* 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.
+-->
+
+<form id="create-group-form" role="form" novalidate name="form.groupCreateForm">
+ <div class="modal-header">
+ <h1 class="modal-title">
+ {{'groups.createLocal' | translate}}
+ </h1>
+ </div>
+ <div class="modal-body">
+ <div class="form-group"
+ ng-class="{ 'has-error': (form.groupCreateForm.groupName.$error.required || form.groupCreateForm.groupName.$error.pattern) && form.groupCreateForm.submitted }">
+ <label for="groupName">
+ {{'groups.name' | translate}}<span> *</span>
+ </label>
+ <input type="text"
+ placeholder="{{'groups.name' | translate}}"
+ ng-pattern="/^([a-zA-Z0-9._\s]+)$/"
+ autofocus
+ ng-maxlength="80"
+ autocomplete="off"
+ class="form-control"
+ ng-model="formData.groupName"
+ name="groupName"
+ id="groupName"
+ ng-change="checkIfInstanceExist()"
+ required>
+ <span class="help-block validation-block"
+ ng-show='form.groupCreateForm.groupName.$error.required && form.groupCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ <span class="help-block validation-block"
+ ng-show='form.groupCreateForm.groupName.$error.pattern && form.groupCreateForm.submitted'>
+ {{'common.alerts.noSpecialChars' | translate}}
+ </span>
+ </div>
+
+ <div class="form-group">
+ <label>{{'groups.addUsers' | translate}}</label>
+ <div>
+ <editable-list items-source="formData.members" resource-type="User" editable="true"></editable-list>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="form-group col-sm-6"
+ ng-class="{ 'has-error': form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted }">
+ <label for="role" class="nowrap">
+ {{'groups.role' | translate}}
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <select
+ class="form-control"
+ id="role"
+ name="role"
+ ng-model="formData.role">
+ <option value="" disabled selected>{{'common.select' | translate}}</option>
+ <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+ </select>
+ <span class="help-block validation-block" ng-show='form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+ <button class="btn btn-primary" ng-click="save()" type="submit">{{'common.controls.save' | translate}}</button>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
new file mode 100644
index 0000000..0af26eb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
@@ -0,0 +1,147 @@
+<!--
+* 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.
+-->
+
+<form id="create-user-form" role="form" novalidate name="form.userCreateForm">
+ <div class="modal-header">
+ <h1 class="modal-title">
+ {{'users.create' | translate}}
+ </h1>
+ </div>
+ <div class="modal-body">
+ <div class="form-group"
+ ng-class="{ 'has-error': (form.userCreateForm.userName.$error.required || form.userCreateForm.userName.$error.pattern) && form.userCreateForm.submitted }">
+ <label for="userName">
+ {{'users.username' | translate}}<span> *</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <input type="text"
+ autofocus
+ placeholder="{{'users.user.name' | translate}}"
+ ng-pattern="/^[^<>&`|\\]+$/"
+ ng-maxlength="80"
+ tooltip="{{'users.userNameTip' | translate}}"
+ autocomplete="off"
+ tooltip-trigger="focus"
+ class="form-control"
+ ng-model="formData.userName"
+ name="userName"
+ id="userName"
+ ng-change="checkIfInstanceExist()"
+ required>
+ <span class="help-block validation-block"
+ ng-show='form.userCreateForm.userName.$error.required && form.userCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ <span class="help-block validation-block"
+ ng-show='form.userCreateForm.userName.$error.pattern && form.userCreateForm.submitted'>
+ {{'common.alerts.noSpecialChars' | translate}}
+ </span>
+ </div>
+
+ <div class="row">
+ <div class="form-group col-sm-6"
+ ng-class="{ 'has-error': form.userCreateForm.password.$error.required && form.userCreateForm.submitted }">
+ <label for="password">
+ {{'users.password' | translate}}<span> *</span>
+ </label>
+ <input type="password"
+ id="password"
+ class="form-control"
+ name="password"
+ placeholder="{{'users.password' | translate}}"
+ required
+ ng-model="formData.password"
+ autocomplete="off">
+ <span class="help-block validation-block"
+ ng-show='form.userCreateForm.password.$error.required && form.userCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+ <div class="form-group col-sm-6"
+ ng-class="{ 'has-error': form.userCreateForm.confirmPassword.$error.passwordVerify || (form.userCreateForm.confirmPassword.$error.required && form.userCreateForm.submitted) }">
+ <label for="confirmPassword">
+ {{'users.confirmPassword' | translate}}<span> *</span>
+ </label>
+ <input type="password"
+ id="confirmPassword"
+ class="form-control"
+ name="confirmPassword"
+ placeholder="{{'users.confirmPassword' | translate}}"
+ required
+ password-verify="formData.password"
+ ng-model="formData.confirmPassword"
+ autocomplete="off">
+ <span class="help-block validation-block"
+ ng-show='form.userCreateForm.confirmPassword.$error.required && form.userCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ <span class="help-block validation-block"
+ ng-show='form.userCreateForm.confirmPassword.$error.passwordVerify'>
+ {{'users.alerts.wrongPassword' | translate}}
+ </span>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="form-group col-sm-6"
+ ng-class="{ 'has-error': form.userCreateForm.role.$error.required && form.userCreateForm.submitted }">
+ <label for="role" class="nowrap">
+ {{'users.role' | translate}}<span> *</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <select
+ class="form-control"
+ id="role"
+ name="role"
+ ng-model="formData.role"
+ required>
+ <option value="" disabled selected>{{'common.select' | translate}}</option>
+ <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+ </select>
+ <span class="help-block validation-block" ng-show='form.userCreateForm.role.$error.required && form.userCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label>
+ {{'users.isAmbariAdmin' | translate}}<span> *</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <div>
+ <toggle-switch model="formData.isAdmin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label>
+ {{'users.isActive' | translate}}<span> *</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <div>
+ <toggle-switch model="formData.isActive" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+ </div>
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+ <button class="btn btn-primary" ng-click="save()" type="submit">{{'common.controls.save' | translate}}</button>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
new file mode 100644
index 0000000..0372a11
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
@@ -0,0 +1,122 @@
+<!--
+* 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 ng-show="user" class="user-edit-panel">
+ <div class="clearfix">
+ <ol class="breadcrumb pull-left">
+ <li><a href="#/userManagement">{{'common.users' | translate}}</a></li>
+ <li class="active"><span class="glyphicon glyphicon-flash" ng-show="user.admin"></span>{{user.user_name}}</li>
+ </ol>
+ <div class="pull-right top-margin-4">
+ <div ng-switch="isCurrentUser || user.user_type != 'LOCAL'">
+ <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'common.cannotDelete' | translate: '{term: constants.user}'}}">{{'common.delete' | translate: '{term: constants.user}'}}</button>
+ <button class="btn deleteuser-btn btn-danger" ng-switch-when="false" ng-click="deleteUser()">{{'common.delete' | translate: '{term: constants.user}'}}</button>
+ </div>
+ </div>
+ </div>
+ <hr>
+ <form class="form-horizontal" role="form" >
+ <div class="form-group">
+ <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+ <div class="col-sm-10">
+ <label for="" class="control-label">{{user.userTypeName}}</label>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
+ <div class="col-sm-10">
+ <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
+ <div class="col-sm-10">
+ <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
+ <div class="col-sm-10">
+ <div ng-switch="user.user_type != 'LOCAL'">
+ <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.password}'}}">{{'users.changePassword' | translate}}</button>
+ <a href ng-click="openChangePwdDialog()" ng-switch-when="false" class="btn btn-default changepassword">{{'users.changePassword' | translate}}</a>
+ </div>
+
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="groups" class="col-sm-2 control-label">{{getUserMembership(user.user_type)}}</label>
+ <div class="col-sm-10">
+ <editable-list items-source="editingGroupsList" resource-type="Group" editable="user.user_type == 'LOCAL'"></editable-list>
+ </div>
+
+ </div>
+ <div class="form-group" >
+ <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+ <div class="col-sm-10">
+ <table class="table" ng-hide="hidePrivileges || user.admin">
+ <thead>
+ <tr>
+ <th>{{'common.cluster' | translate}}</th>
+ <th>{{'common.clusterRole' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.clusters">
+ <td>
+ <span class="glyphicon glyphicon-cloud"></span>
+ <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{privilege.permission_label}}">{{privilege.permission_label}}</span>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+ </tr>
+ </tbody>
+ <thead class="view-permission-header">
+ <tr>
+ <th>{{'common.view' | translate}}</th>
+ <th>{{'common.viewPermissions' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.views">
+ <td>
+ <span class="glyphicon glyphicon-th"></span>
+ <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{item}}" ng-repeat="item in privilege.privileges track by $index">{{item | translate}}{{$last ? '' : ', '}}</span>
+ </td>
+ <td>
+ <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info" ng-show="!privileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
+ <div class="alert alert-info" ng-show="user.admin">{{'users.userIsAdmin' | translate}}</div>
+ </div>
+ </div>
+ </form>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
new file mode 100644
index 0000000..cc4789b
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
@@ -0,0 +1,119 @@
+<!--
+* 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="users-pane">
+ <div class="clearfix panel">
+ <button class="btn btn-default createuser-btn pull-right" ng-click="createUser();">
+ {{'users.create' | translate}}
+ </button>
+ </div>
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr class="fix-bottom">
+ <th>
+ <span>{{'users.username' | translate}}</span>
+ </th>
+ <th>
+ <span>{{'clusters.role' | translate}}</span>
+ </th>
+ <th>
+ <span>{{'users.status' | translate}}</span>
+ </th>
+ <th>
+ <span>{{'common.type' | translate}}</span>
+ </th>
+ <th>
+ <span>{{'common.group' | translate}}</span>
+ </th>
+ <th class="entity-actions">
+ <span>{{'common.actions' | translate}}</span>
+ </th>
+ </tr>
+ <tr class="fix-top">
+ <th>
+ <div class="search-container">
+ <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="filters.name" ng-change="resetPagination()">
+ <button type="button" class="close clearfilter" ng-show="filters.name" ng-click="filters.name=''; resetPagination()">
+ <span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span>
+ </button>
+ </div>
+ </th>
+ <th></th>
+ <th>
+ <select class="form-control statusfilter"
+ ng-model="filters.status"
+ ng-options="item.label for item in activeFilterOptions"
+ ng-change="resetPagination()">
+ </select>
+ </th>
+ <th>
+ <select class="form-control typefilter"
+ ng-model="filters.type"
+ ng-options="item.label for item in typeFilterOptions"
+ ng-change="resetPagination()">
+ </select>
+ </th>
+ <th></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="user in users">
+ <td>
+ <span>{{user.Users.user_name}}</span>
+ </td>
+ <td>
+ <span>{{user.Users.role}}</span>
+ </td>
+ <td>
+ <span>
+ {{(user.Users.active ? 'users.active' : 'users.inactive') | translate}}
+ </span>
+ </td>
+ <td><span>{{user.Users.userTypeName}}</span></td>
+ <td><span>{{user.Users.groups.length ? user.Users.groups.join(' ') : '-'}}</span></td>
+ <td class="entity-actions">
+ <a href="#/users/{{user.Users.encodedName}}/edit">
+ <i class="fa fa-pencil"></i>
+ </a>
+ <a href ng-click="deleteUser(user.Users)">
+ <i class="fa fa-trash-o"></i>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div ng-if="isLoading" class="spinner-container">
+ <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
+ </div>
+ <div class="alert empty-table-alert col-sm-12" ng-show="!users.length && !isLoading">
+ {{'common.alerts.nothingToDisplay' | translate: '{term: constants.users}'}}
+ </div>
+ <div class="col-sm-12 table-bar" ng-show="totalUsers > minRowsToShowPagination">
+ <div class="pull-left filtered-info">
+ <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.users}'}}</span>
+ <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
+ </div>
+ <div class="pull-right left-margin">
+ <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
+ </div>
+ <div class="pull-right">
+ <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
deleted file mode 100644
index 80a3b04..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
+++ /dev/null
@@ -1,82 +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.
--->
-<ol class="breadcrumb">
- <li><a href="#/users">{{'common.users' | translate}}</a></li>
- <li class="active">{{'users.create' | translate}}</li>
-</ol>
-<hr>
-<form class="form-horizontal create-user-form" role="form" novalidate name="form" autocomplete="off">
- <div class="form-group" ng-class="{'has-error' : form.user_name.$error.required && form.submitted}">
- <label for="username" class="col-sm-2 control-label">{{'users.username' | translate}}</label>
- <div class="col-sm-10"
- ng-class="{'has-error': form.user_name.$error.pattern}">
- <input
- autofocus
- type="text"
- id="username"
- class="form-control username-input"
- name="user_name"
- placeholder="{{'users.userName' | translate}}"
- ng-model="user.user_name"
- ng-required="true"
- ng-pattern="/^[^<>&`|\\]+$/"
- ng-maxlength="80"
- tooltip="{{'users.userNameTip' | translate}}"
- autocomplete="off"
- tooltip-trigger="focus">
- <div class="alert alert-danger top-margin" ng-show="form.user_name.$error.required && form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
- </div>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
- <div class="col-sm-10">
- <label for="" class="control-label">{{'common.local' | translate}}</label>
- </div>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
- <div class="col-sm-10">
- <toggle-switch model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus" data-off-color="danger"></toggle-switch>
- </div>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span>{{'users.ambariAdmin' | translate}}</label>
- <div class="col-sm-10">
- <toggle-switch ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus" data-off-color="danger"></toggle-switch>
- </div>
- </div>
- <div class="form-group" ng-class="{'has-error' : (form.password.$error.required && form.submitted) || form.confirmPassword.$error.passwordVerify}">
- <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
- <div class="col-sm-10">
- <input type="password" class="form-control bottom-margin userpassword" name="password" placeholder="{{'users.password' | translate}}" required ng-model="user.password" autocomplete="off">
- <input type="password" class="form-control bottom-margin userpasswordconfirm" name="confirmPassword" placeholder="{{'users.passwordConfirmation' | translate}}" required ng-model="user.passwordConfirmation"
- password-verify="user.password" autocomplete="off">
-
- <div class="alert alert-danger" ng-show='form.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
- <div class="alert alert-danger" ng-show='form.password.$error.required && form.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
-
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-primary pull-right left-margin saveuser" ng-click="createUser()">{{'common.controls.save' | translate}}</button>
- <a class="btn btn-default pull-right cancel" href ng-click="cancel()">{{'common.controls.cancel' | translate}}</a>
- </div>
- </div>
-
-</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
deleted file mode 100644
index 12227c3..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
+++ /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.
--->
-
-<div class="users-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{'common.users' | translate}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <link-to route="users.create" class="btn btn-default createuser-btn">
- </span> {{'users.create' | translate}}
- </link-to>
- </div>
- </div>
- <table class="table table-striped table-hover">
- <thead>
- <tr>
- <th width="30">
- <span class="bottom-margin admin-filter glyphicon glyphicon-flash"
- ng-class="{'no-filter' : !adminFilter}"
- ng-click="toggleAdminFilter()"
- tooltip="{{(adminFilter ? 'users.showAll' : 'users.showAdmin') | translate}}"
- ></span>
- </th>
- <th>
- <div class="search-container">
- <label for="">{{'users.username' | translate}}</label>
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
- <button type="button" class="close clearfilter" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- </div>
- </th>
- <th>
- <label for="">{{'common.type' | translate}}</label>
- <select class="form-control typefilter"
- ng-model="currentTypeFilter"
- ng-options="item.label for item in typeFilterOptions"
- ng-change="resetPagination()">
- </select>
-
- </th>
- <th>
- <label for="">{{'users.status' | translate}}</label>
- <select class="form-control statusfilter"
- ng-model="currentActiveFilter"
- ng-options="item.label for item in activeFilterOptions"
- ng-change="resetPagination()">
- </select>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="user in users">
- <td>
- <span class="glyphicon" tooltip="{{user.Users.admin ? constants.admin : ''}}" ng-class="{'glyphicon-flash' : user.Users.admin}"></span>
- </td>
- <td>
- <a href="#/users/{{user.Users.encoded_name}}">{{user.Users.user_name}}</a>
- </td>
- <td>{{user.Users.userTypeName}}</td>
- <td><span ng-class="user.Users.active ? 'text-success' : 'text-danger'">{{(user.Users.active ? 'users.active' : 'users.inactive') | translate}}</span></td>
- </tr>
- </tbody>
- </table>
- <div ng-if="isLoading" class="spinner-container">
- <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
- </div>
- <div class="alert empty-table-alert col-sm-12" ng-show="!users.length && !isLoading">
- {{'common.alerts.nothingToDisplay' | translate: '{term: constants.users}'}}
- </div>
- <div class="col-sm-12 table-bar">
- <div class="pull-left filtered-info">
- <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.users}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
deleted file mode 100644
index f29d315..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
+++ /dev/null
@@ -1,46 +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.
--->
-<div class="modal-header">
- <h3 class="modal-title">{{'users.changePasswordFor' | translate: '{userName: userName}'}}</h3>
-</div>
-<div class="modal-body">
- <form class="form-horizontal" novalidate name="form.passwordChangeForm" role="form" >
- <div class="form-group" ng-class="{'has-error' : (form.passwordChangeForm.currentPassword.$error.required && form.passwordChangeForm.submitted)}">
- <label for="" class="col-sm-4 control-label" >{{'users.yourPassword' | translate}}</label>
- <div class="col-sm-8">
- <input type="password" name="currentPassword" class="form-control bottom-margin" placeholder="{{'users.yourPassword' | translate}}" required ng-model="passwordData.currentUserPassword" autocomplete="off">
- <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
- </div>
- </div>
- <div class="form-group no-margin-bottom" ng-class="{'has-error' : (form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted) || form.passwordChangeForm.confirmPassword.$error.passwordVerify}">
- <label for="" class="col-sm-4 control-label">{{'users.newPassword' | translate}}:</label>
- <div class="col-sm-8">
- <input type="password" class="form-control bottom-margin" name="password" placeholder="{{'users.newPassword' | translate}}" required ng-model="passwordData.password" autocomplete="off">
- <input type="password" class="form-control bottom-margin" name="confirmPassword" placeholder="{{'users.newPasswordConfirmation' | translate}}" required ng-model="passwordData.passwordConfirmation"
- password-verify="passwordData.password" autocomplete="off">
- <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
- <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
- </div>
-
- </div>
- </form>
-</div>
-<div class="modal-footer">
- <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
- <button class="btn btn-primary" ng-click="ok()">{{'common.controls.ok' | translate}}</button>
-</div>
\ 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/views/users/show.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
deleted file mode 100644
index f965c5d..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
+++ /dev/null
@@ -1,122 +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.
--->
-
-<div ng-show="user" class="user-edit-panel">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li><a href="#/users">{{'common.users' | translate}}</a></li>
- <li class="active"><span class="glyphicon glyphicon-flash" ng-show="user.admin"></span>{{user.user_name}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <div ng-switch="isCurrentUser || user.user_type != 'LOCAL'">
- <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'common.cannotDelete' | translate: '{term: constants.user}'}}">{{'common.delete' | translate: '{term: constants.user}'}}</button>
- <button class="btn deleteuser-btn btn-danger" ng-switch-when="false" ng-click="deleteUser()">{{'common.delete' | translate: '{term: constants.user}'}}</button>
- </div>
- </div>
- </div>
- <hr>
- <form class="form-horizontal" role="form" >
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
- <div class="col-sm-10">
- <label for="" class="control-label">{{user.userTypeName}}</label>
- </div>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
- <div class="col-sm-10">
- <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
- </div>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
- <div class="col-sm-10">
- <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
- </div>
- </div>
- <div class="form-group">
- <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
- <div class="col-sm-10">
- <div ng-switch="user.user_type != 'LOCAL'">
- <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.password}'}}">{{'users.changePassword' | translate}}</button>
- <a href ng-click="openChangePwdDialog()" ng-switch-when="false" class="btn btn-default changepassword">{{'users.changePassword' | translate}}</a>
- </div>
-
- </div>
- </div>
- <div class="form-group">
- <label for="groups" class="col-sm-2 control-label">{{getUserMembership(user.user_type)}}</label>
- <div class="col-sm-10">
- <editable-list items-source="editingGroupsList" resource-type="Group" editable="user.user_type == 'LOCAL'"></editable-list>
- </div>
-
- </div>
- <div class="form-group" >
- <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
- <div class="col-sm-10">
- <table class="table" ng-hide="hidePrivileges || user.admin">
- <thead>
- <tr>
- <th>{{'common.cluster' | translate}}</th>
- <th>{{'common.clusterRole' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.clusters">
- <td>
- <span class="glyphicon glyphicon-cloud"></span>
- <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{privilege.permission_label}}">{{privilege.permission_label}}</span>
- </td>
- </tr>
- <tr>
- <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
- </tr>
- </tbody>
- <thead class="view-permission-header">
- <tr>
- <th>{{'common.view' | translate}}</th>
- <th>{{'common.viewPermissions' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.views">
- <td>
- <span class="glyphicon glyphicon-th"></span>
- <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{item}}" ng-repeat="item in privilege.privileges track by $index">{{item | translate}}{{$last ? '' : ', '}}</span>
- </td>
- <td>
- <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
- </td>
- </tr>
- <tr>
- <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
- </tr>
- </tbody>
- </table>
- <div class="alert alert-info" ng-show="!privileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
- <div class="alert alert-info" ng-show="user.admin">{{'users.userIsAdmin' | translate}}</div>
- </div>
- </div>
- </form>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/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
deleted file mode 100644
index 14c0975..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
+++ /dev/null
@@ -1,820 +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.
- */
-
-describe('#Cluster', function () {
-
- describe('UserAccessListCtrl', function() {
-
- var scope, ctrl, $t, $httpBackend, Cluster, deferred, Alert, mock;
-
- beforeEach(module('ambariAdminConsole', function () {}));
-
- beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_, _Cluster_, _$q_, _Alert_) {
- scope = $rootScope.$new();
- $t = _$translate_.instant;
- $httpBackend = _$httpBackend_;
- Cluster = _Cluster_;
- Alert = _Alert_;
- deferred = {
- createPrivileges: _$q_.defer(),
- getPrivilegesForResource: _$q_.defer(),
- getPrivilegesWithFilters: _$q_.defer(),
- deletePrivileges: _$q_.defer(),
- deleteMultiplePrivileges: _$q_.defer()
- };
- ctrl = $controller('UserAccessListCtrl', {
- $scope: scope
- });
- mock = {
- Cluster: Cluster,
- Alert: Alert,
- scope: scope
- };
- spyOn(Cluster, 'createPrivileges').andReturn(deferred.createPrivileges.promise);
- spyOn(Cluster, 'deletePrivileges').andReturn(deferred.deletePrivileges.promise);
- spyOn(Cluster, 'getPrivilegesForResource').andReturn(deferred.getPrivilegesForResource.promise);
- spyOn(Cluster, 'getPrivilegesWithFilters').andReturn(deferred.getPrivilegesWithFilters.promise);
- spyOn(Alert, 'success').andCallFake(angular.noop);
- spyOn(Alert, 'error').andCallFake(angular.noop);
- spyOn(scope, 'loadRoles').andCallFake(angular.noop);
-
- $httpBackend.expectGET(/\/api\/v1\/permissions/).respond(200, {
- items: []
- });
- $httpBackend.expectGET(/\/api\/v1\/users?.*/).respond(200, {
- items:[]
- });
- $httpBackend.flush();
- }));
-
- describe('#clearFilters()', function () {
-
- it('should clear filters and reset pagination', function () {
- scope.currentPage = 2;
- scope.currentNameFilter = 'a';
- scope.roleFilterOptions = [
- {
- label: $t('common.all'),
- value: ''
- },
- {
- label: $t('users.roles.clusterUser'),
- value: 'CLUSTER.USER'
- }
- ];
- scope.currentRoleFilter = scope.roleFilterOptions[1];
- scope.clearFilters();
- expect(scope.currentNameFilter).toEqual('');
- expect(scope.currentRoleFilter).toEqual({
- label: $t('common.all'),
- value: ''
- });
- expect(scope.currentPage).toEqual(1);
- });
-
- });
-
- describe('#isNotEmptyFilter', function () {
-
- var cases = [
- {
- currentNameFilter: '',
- currentRoleFilter: null,
- isNotEmptyFilter: false,
- title: 'no filters'
- },
- {
- currentNameFilter: '',
- currentRoleFilter: {
- value: ''
- },
- isNotEmptyFilter: false,
- title: 'empty filters'
- },
- {
- currentNameFilter: 'a',
- currentRoleFilter: {
- value: ''
- },
- isNotEmptyFilter: true,
- title: 'name filter'
- },
- {
- currentNameFilter: '0',
- currentRoleFilter: {
- value: ''
- },
- isNotEmptyFilter: true,
- title: 'name filter with "0" as string'
- },
- {
- currentNameFilter: '',
- currentRoleFilter: {
- value: 'CLUSTER.USER'
- },
- isNotEmptyFilter: true,
- title: 'role filter'
- },
- {
- currentNameFilter: 'a',
- currentRoleFilter: {
- value: 'GROUP'
- },
- isNotEmptyFilter: true,
- title: 'all filters'
- },
- {
- currentNameFilter: '0',
- currentRoleFilter: {
- value: 'GROUP'
- },
- isNotEmptyFilter: true,
- title: 'all filters with "0" as string'
- }
- ];
-
- cases.forEach(function (item) {
- it(item.title, function () {
- scope.currentNameFilter = item.currentNameFilter;
- scope.currentRoleFilter = item.currentRoleFilter;
- scope.$digest();
- expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
- });
- });
-
- });
-
- describe('#save() for Users', function(){
- var user = {};
-
- beforeEach(function() {
- items1 = {
- "href" : "http://abc.com:8080/api/v1/users/user1",
- "Users" : { "user_name" : "user1" },
- "privileges" : [
- {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/222",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup2",
- "principal_type" : "GROUP",
- "privilege_id" : 222,
- "type" : "CLUSTER",
- "user_name" : "user1"
- }
- }, {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/111",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 111,
- "type" : "CLUSTER",
- "user_name" : "user1"
- }
- }, {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Cluster Administrator",
- "permission_name" : "CLUSTER.ADMINISTRATOR",
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : 11,
- "type" : "CLUSTER",
- "user_name" : "user1"
- }
- }
- ]
- };
-
- items2 =
- {
- "href" : "http://abc.com:8080/api/v1/users/user2",
- "Users" : { "user_name" : "user2" },
- "privileges" : [
- {
- "href" : "http://abc.com:8080/api/v1/users/user2/privileges/111",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 111,
- "type" : "CLUSTER",
- "user_name" : "user2"
- }
- }, {
- "href" : "http://abc.com:8080/api/v1/users/user2/privileges/22",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "user2",
- "principal_type" : "USER",
- "privilege_id" : 22,
- "type" : "CLUSTER",
- "user_name" : "user2"
- }
- }
- ]
- };
-
- all_items = { "items": [items1, items2]};
-
- scope.loadUsers();
-
- spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
- privilege_ids.forEach(function(privilege_id) {
- items1.privileges.forEach(function(p, index) {
- if (p.PrivilegeInfo.privilege_id === privilege_id) {
- //Remove from array
- items1.privileges.splice(index, 1);
- }
- });
- });
- });
- spyOn(scope, 'addPrivilege').andCallFake(function(user) {
- var p = {};
- p.PrivilegeInfo = {};
- p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
- p.PrivilegeInfo.permission_name = user.permission_name;
- p.PrivilegeInfo.principal_type = 'USER';
-
- items1.privileges.push(p);
- scope.loadUsers();
- });
-
- deferred.getPrivilegesWithFilters.resolve(all_items);
- deferred.getPrivilegesForResource.promise.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.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);
-
- //add a new privilege of type USER only if it is also the effective privilege considering the user's Group privileges
- var curIndex = scope.getRoleRank(user.permission_name);
- var prevIndex = -1;
- if (privilegesOfTypeGroup.length !== 0) {
- prevIndex = scope.getRoleRank(effectivePrivilegeFromGroups.permission_name);
- }
- if ((curIndex === 6) || (curIndex <= prevIndex)) {
- var privilege_ids = [];
- privilegesOfTypeUser.forEach(function(privilegeOfTypeUser) {
- privilege_ids.push(privilegeOfTypeUser.privilege_id);
- });
-
- //delete all privileges of type USER, if they exist
- //then add the privilege for the user, after which the user displays the effective privilege
- if(privilege_ids.length !== 0) {
- Cluster.deleteMultiplePrivileges(
- 123,
- privilege_ids
- );
- }
- scope.addPrivilege(user);
- } else {
- Alert.error($t('common.alerts.cannotSavePermissions'), "User's effective privilege through its Group(s) is higher than your selected privilege.");
- scope.loadUsers();
- }
- });
-
- scope.$apply();
- });
-
- it('Should save the Privilege equal to the user\'s group privileges. Should also remove any individual user privileges', function() {
- //using 'user1' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "SERVICE.ADMINISTRATOR";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.permission_name);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
- var oldPrivilege = {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Cluster Administrator",
- "permission_name" : "CLUSTER.ADMINISTRATOR",
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : 11,
- "type" : "CLUSTER",
- "user_name" : "user1"
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "permission_name" : user.permission_name,
- "privilege_id" : user.privilege_id+1,
- "principal_type" : "USER",
- "principal_name" : "user1",
- "encoded_name" : "user1",
- "original_perm" : user.permission_name,
- "url" : "users/user1",
- "editable" : true
- }
- };
-
- //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
- expect(items1.privileges).toNotContain(oldPrivilege);
-
- //test if the new privilege got added to 'items1' by addPrivilege()
- expect(items1.privileges).toContain(newPrivilege);
- });
-
- it('Should save the Privilege greater than the user\'s group privileges. Should also remove any individual user privileges', function() {
- //using 'user1' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "CLUSTER.OPERATOR";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.permission_name);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
- var oldPrivilege = {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Cluster Administrator",
- "permission_name" : "CLUSTER.ADMINISTRATOR",
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : 11,
- "type" : "CLUSTER",
- "user_name" : "user1"
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "permission_name" : user.permission_name,
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : user.privilege_id + 1,
- "encoded_name" : "user1",
- "original_perm" : user.permission_name,
- "url" : "users/user1",
- "editable" : true
- }
- };
-
- //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
- expect(items1.privileges).toNotContain(oldPrivilege);
-
- //test if the new privilege got added to 'items1' by addPrivilege()
- expect(items1.privileges).toContain(newPrivilege);
- });
-
- it('Should NOT save the Privilege smaller than the user\'s group privileges. Should keep the user\'s original privileges intact', function() {
- //using 'user1' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "CLUSTER.USER";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.original_perm);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id);
-
- var oldPrivilege = {
- "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "permission_label" : "Cluster Administrator",
- "permission_name" : "CLUSTER.ADMINISTRATOR",
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : 11,
- "type" : "CLUSTER",
- "user_name" : "user1",
- "encoded_name" : "user1",
- "original_perm" : "CLUSTER.ADMINISTRATOR",
- "url" : "users/user1",
- "editable" : true
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "permission_name" : user.permission_name,
- "principal_name" : "user1",
- "principal_type" : "USER",
- "privilege_id" : user.privilege_id+1,
- "encoded_name" : "user1",
- "original_perm" : user.permission_name,
- "url" : "users/user1",
- "editable" : true
- }
- };
-
- //test if the individual user privilege CLUSTER.ADMINISTRATOR is NOT removed from 'items1'
- expect(items1.privileges).toContain(oldPrivilege);
-
- //test if the new privilege is NOT added to 'items1'
- expect(items1.privileges).toNotContain(newPrivilege);
- });
-
- });
-
- describe('#save() for Groups', function() {
- var user = {};
-
- beforeEach(function() {
- items1 = {
- "href" : "http://abc.com:8080/api/v1/groups/mygroup",
- "Groups" : { "group_name" : "mygroup" },
- "privileges" : [
- {
- "href" : "http://abc.com:8080/api/v1/groups/mygroup/privileges/3359",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "group_name" : "mygroup",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 3359,
- "type" : "CLUSTER"
- }
- }
- ]
- };
-
- items2 = {
- "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
- "Groups" : { "group_name" : "mygroup2" },
- "privileges" : [
- {
- "href" : "http://abc.com:8080/api/v1/groups/mygroup2/privileges/3356",
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "group_name" : "mygroup2",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup2",
- "principal_type" : "GROUP",
- "privilege_id" : 3356,
- "type" : "CLUSTER"
- }
- }
- ]
- };
-
- all_items = { "items": [items1, items2]};
-
- scope.loadUsers();
-
- spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
- privilege_ids.forEach(function(privilege_id) {
- items1.privileges.forEach(function(p, index) {
- if (p.PrivilegeInfo.privilege_id === privilege_id) {
- //Remove from array
- items1.privileges.splice(index, 1);
- }
- });
- });
- });
- spyOn(scope, 'addPrivilege').andCallFake(function(user) {
- var p = {};
- p.PrivilegeInfo = {};
- p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
- p.PrivilegeInfo.permission_name = user.permission_name;
- p.PrivilegeInfo.principal_type = 'GROUP';
-
- items1.privileges.push(p);
- scope.loadUsers();
- });
-
- deferred.getPrivilegesWithFilters.resolve(all_items);
- deferred.getPrivilegesForResource.promise.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.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(
- 123,
- privilege_ids
- );
- }
- scope.addPrivilege(user);
- });
-
- scope.$apply();
- });
-
- it('Should save the Privilege equal to the group\'s effective privilege. Should remove any other privileges of the group',function(){
- //using 'mygroup' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "SERVICE.ADMINISTRATOR";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.permission_name);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
- var oldPrivilege = {
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "group_name" : "mygroup",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 3359,
- "type" : "CLUSTER"
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "privilege_id" : user.privilege_id + 1,
- "permission_name" : user.permission_name,
- "principal_type" : "GROUP",
- "principal_name" : "mygroup",
- "encoded_name" : "mygroup",
- "original_perm" : user.permission_name,
- "url" : "groups/mygroup/edit",
- "editable" : true
- }
- };
-
- //test if the older privilege is no longer present in 'items1'
- expect(items1.privileges).toNotContain(oldPrivilege);
-
- //test if the new privilege is added to 'items1'
- expect(items1.privileges).toContain(newPrivilege);
- });
-
- it('Should save the Privilege greater than the group\'s effective privilege. Should remove any other privileges of the group',function(){
- //using 'mygroup' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "CLUSTER.ADMINISTRATOR";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.permission_name);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
- var oldPrivilege = {
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "group_name" : "mygroup",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 3359,
- "type" : "CLUSTER"
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "privilege_id" : user.privilege_id + 1,
- "permission_name" : user.permission_name,
- "principal_type" : "GROUP",
- "principal_name" : "mygroup",
- "encoded_name" : "mygroup",
- "original_perm" : user.permission_name,
- "url" : "groups/mygroup/edit",
- "editable" : true
- }
- };
-
- //test if the older privilege is no longer present in 'items1'
- expect(items1.privileges).toNotContain(oldPrivilege);
-
- //test if the new privilege is added to 'items1'
- expect(items1.privileges).toContain(newPrivilege);
- });
-
- it('Should save the Privilege lesser than the group\'s effective privilege. Should remove any other privileges of the group', function() {
- //using 'mygroup' for updating the new privilege
- user.principal_name = scope.users[0].principal_name;
- user.principal_type = scope.users[0].principal_type;
- user.privilege_id = scope.users[0].privilege_id;
- user.permission_name = "CLUSTER.USER";
-
- deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
- scope.$apply();
-
- expect(scope.users[0].permission_name).toEqual(user.permission_name);
- expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
- var oldPrivilege = {
- "PrivilegeInfo" : {
- "cluster_name" : "myCluster",
- "group_name" : "mygroup",
- "permission_label" : "Service Administrator",
- "permission_name" : "SERVICE.ADMINISTRATOR",
- "principal_name" : "mygroup",
- "principal_type" : "GROUP",
- "privilege_id" : 3359,
- "type" : "CLUSTER"
- }
- };
- var newPrivilege = {
- "PrivilegeInfo" : {
- "privilege_id" : user.privilege_id + 1,
- "permission_name" : user.permission_name,
- "principal_type" : "GROUP",
- "principal_name" : "mygroup",
- "encoded_name" : "mygroup",
- "original_perm" : user.permission_name,
- "url" : "groups/mygroup/edit",
- "editable" : true
- }
- };
-
- //test if the older privilege is no longer present in 'items1'
- expect(items1.privileges).toNotContain(oldPrivilege);
-
- //test if the new privilege is added to 'items1'
- expect(items1.privileges).toContain(newPrivilege);
- });
-
- });
-
- describe('#pickEffectivePrivilege()', function() {
- var cases = [{
- "test" : [{
- "href" : "http://abc.com:8080/api/v1/groups/mygroup1",
- "PrivilegeInfo" : {
- "instance_name" : "jobs_view",
- "permission_label" : "View User",
- "permission_name" : "VIEW.USER",
- "principal_name" : "mygroup1",
- "principal_type" : "GROUP",
- "privilege_id" : 111,
- "type" : "VIEW",
- "user_name" : "mygroup1",
- "view_name" : "JOBS"
- }
- }],
- "result":{
- "permission_name": "CLUSTER.NONE"
- }
- }, {
- "test": [{
- "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
- "PrivilegeInfo" : {
- "cluster_name":"mycluster",
- "permission_label" : "Cluster User",
- "permission_name" : "CLUSTER.USER",
- "principal_name" : "mygroup2",
- "principal_type" : "GROUP",
- "privilege_id" : 222,
- "type" : "CLUSTER",
- "user_name":"mygroup2"
- }
- }],
- "result":{
- "permission_name": "CLUSTER.USER"
- }
- }, {
- "test":[{
- "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
- "PrivilegeInfo" : {
- "cluster_name":"mycluster",
- "permission_label" : "Cluster User",
- "permission_name" : "CLUSTER.USER",
- "principal_name" : "mygroup3",
- "principal_type" : "GROUP",
- "privilege_id" : 333,
- "type" : "CLUSTER",
- "user_name":"mygroup3"
- }
- }, {
- "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
- "PrivilegeInfo" : {
- "instance_name": "jobs_view",
- "permission_label" : "View User",
- "permission_name" : "VIEW.USER",
- "principal_name" : "mygroup3",
- "principal_type" : "GROUP",
- "privilege_id" : 3333,
- "type" : "VIEW",
- "user_name":"mygroup3",
- "view_name":"JOBS"
- }
- }],
- "result":{
- "permission_name": "CLUSTER.USER"
- }
- }, {
- "test": [{
- "href" : "http://abc.com:8080/api/v1/users/myuser1/privileges/11",
- "PrivilegeInfo" : {
- "instance_name": "jobs_view",
- "permission_label" : "View User",
- "permission_name" : "VIEW.USER",
- "principal_name" : "myuser1",
- "principal_type" : "USER",
- "privilege_id" : 11,
- "type" : "VIEW",
- "user_name":"myuser1",
- "view_name":"JOBS"
- }
- }],
- "result":{
- "permission_name": "CLUSTER.NONE"
- }
- }, {
- "test":[{
- "href" : "http://abc.com:8080/api/v1/users/myuser2/privileges/22",
- "PrivilegeInfo" : {
- "cluster_name":"mycluster",
- "permission_label" : "Cluster Administrator",
- "permission_name" : "CLUSTER.ADMINISTRATOR",
- "principal_name" : "myuser2",
- "principal_type" : "USER",
- "privilege_id" : 22,
- "type" : "CLUSTER",
- "user_name":"myuser2"
- }
- }],
- "result":{
- "permission_name": "CLUSTER.ADMINISTRATOR"
- }
- }
- ];
-
- it('User/Group with only View User permission must show \'None\' as the Cluster Permission, otherwise show the effective privilege', function(){
- var effectivePrivilege;
- cases.forEach(function (item){
- effectivePrivilege = scope.pickEffectivePrivilege(item.test);
- scope.$apply();
- expect(effectivePrivilege.permission_name).toEqual(item.result.permission_name);
- });
- });
- });
-
- });
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
deleted file mode 100644
index 8ed228b..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
+++ /dev/null
@@ -1,129 +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.
- */
-
-describe('#Cluster', function () {
-
- describe('GroupsListCtrl', function() {
-
- var scope, ctrl, $t, $httpBackend;
-
- beforeEach(module('ambariAdminConsole', function () {}));
-
- beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
- scope = $rootScope.$new();
- $t = _$translate_.instant;
- $httpBackend = _$httpBackend_;
- ctrl = $controller('GroupsListCtrl', {
- $scope: scope
- });
- }));
-
- describe('#clearFilters()', function () {
-
- it('should clear filters and reset pagination', function () {
- scope.currentPage = 2;
- scope.currentNameFilter = 'a';
- scope.currentTypeFilter = {
- label: $t('common.local'),
- value: false
- };
- scope.clearFilters();
- expect(scope.currentNameFilter).toEqual('');
- expect(scope.currentTypeFilter).toEqual({
- label: $t('common.all'),
- value: '*'
- });
- expect(scope.currentPage).toEqual(1);
- });
-
- });
-
- describe('#isNotEmptyFilter', function () {
-
- var cases = [
- {
- currentNameFilter: '',
- currentTypeFilter: null,
- isNotEmptyFilter: false,
- title: 'no filters'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: '*'
- },
- isNotEmptyFilter: false,
- title: 'empty filters'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: '*'
- },
- isNotEmptyFilter: true,
- title: 'name filter'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: '*'
- },
- isNotEmptyFilter: true,
- title: 'name filter with "0" as string'
- },
- {
- currentNameFilter: '',
- currentTypeFilter: {
- value: false
- },
- isNotEmptyFilter: true,
- title: 'type filter'
- },
- {
- currentNameFilter: 'a',
- currentTypeFilter: {
- value: false
- },
- isNotEmptyFilter: true,
- title: 'both filters'
- },
- {
- currentNameFilter: '0',
- currentTypeFilter: {
- value: false
- },
- isNotEmptyFilter: true,
- title: 'both filters with "0" as string'
- }
- ];
-
- cases.forEach(function (item) {
- it(item.title, function () {
- $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
- scope.currentNameFilter = item.currentNameFilter;
- scope.currentTypeFilter = item.currentTypeFilter;
- scope.$digest();
- expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
- });
- });
-
- });
-
- });
-
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
new file mode 100644
index 0000000..8d04757
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
@@ -0,0 +1,129 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+ describe('GroupsListCtrl', function() {
+
+ var scope, ctrl, $t, $httpBackend;
+
+ beforeEach(module('ambariAdminConsole', function () {}));
+
+ beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+ scope = $rootScope.$new();
+ $t = _$translate_.instant;
+ $httpBackend = _$httpBackend_;
+ ctrl = $controller('GroupsListCtrl', {
+ $scope: scope
+ });
+ }));
+
+ describe('#clearFilters()', function () {
+
+ it('should clear filters and reset pagination', function () {
+ scope.currentPage = 2;
+ scope.filter.name = 'a';
+ scope.filter.type = {
+ label: $t('common.local'),
+ value: false
+ };
+ scope.clearFilters();
+ expect(scope.filter.name).toEqual('');
+ expect(scope.filter.type).toEqual({
+ label: $t('common.all'),
+ value: '*'
+ });
+ expect(scope.currentPage).toEqual(1);
+ });
+
+ });
+
+ describe('#isNotEmptyFilter', function () {
+
+ var cases = [
+ {
+ currentNameFilter: '',
+ currentTypeFilter: null,
+ isNotEmptyFilter: false,
+ title: 'no filters'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: false,
+ title: 'empty filters'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name filter'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: '*'
+ },
+ isNotEmptyFilter: true,
+ title: 'name filter with "0" as string'
+ },
+ {
+ currentNameFilter: '',
+ currentTypeFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'type filter'
+ },
+ {
+ currentNameFilter: 'a',
+ currentTypeFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'both filters'
+ },
+ {
+ currentNameFilter: '0',
+ currentTypeFilter: {
+ value: false
+ },
+ isNotEmptyFilter: true,
+ title: 'both filters with "0" as string'
+ }
+ ];
+
+ cases.forEach(function (item) {
+ it(item.title, function () {
+ $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
+ scope.filter.name = item.currentNameFilter;
+ scope.filter.type = item.currentTypeFilter;
+ scope.$digest();
+ expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+ });
+ });
+
+ });
+
+ });
+
+});
[3/4] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new
design for Admin View: User Management. (atkach)
Posted by at...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
new file mode 100644
index 0000000..abe1780
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
@@ -0,0 +1,178 @@
+/**
+ * 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('UsersListCtrl',
+['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Cluster', 'View', 'ConfirmationModal', 'Settings',
+function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, View, ConfirmationModal, Settings) {
+ var $t = $translate.instant;
+ $scope.constants = {
+ admin: $t('users.ambariAdmin'),
+ users: $t('common.users').toLowerCase()
+ };
+ $scope.minRowsToShowPagination = Settings.minRowsToShowPagination;
+ $scope.isLoading = false;
+ $scope.users = [];
+ $scope.usersPerPage = 10;
+ $scope.currentPage = 1;
+ $scope.totalUsers = 0;
+ $scope.filters = {
+ name: '',
+ status: null,
+ type: null
+ };
+ $scope.maxVisiblePages = 20;
+ $scope.tableInfo = {
+ total: 0,
+ showed: 0
+ };
+ $scope.isNotEmptyFilter = true;
+
+ $scope.pageChanged = function() {
+ $scope.loadUsers();
+ };
+ $scope.usersPerPageChanges = function() {
+ $scope.resetPagination();
+ };
+
+ $scope.loadUsers = function(){
+ $scope.isLoading = true;
+ User.list({
+ currentPage: $scope.currentPage,
+ usersPerPage: $scope.usersPerPage,
+ searchString: $scope.filters.name,
+ user_type: $scope.filters.type.value,
+ active: $scope.filters.status.value
+ }).then(function(data) {
+ $scope.isLoading = false;
+ $scope.totalUsers = data.data.itemTotal;
+ $scope.users = data.data.items.map(User.makeUser);
+ $scope.tableInfo.showed = data.data.items.length;
+ $scope.tableInfo.total = data.data.itemTotal;
+ });
+ };
+
+ $scope.resetPagination = function() {
+ $scope.currentPage = 1;
+ $scope.loadUsers();
+ };
+
+ $scope.activeFilterOptions = [
+ {label: $t('common.all'), value: '*'},
+ {label: $t('users.active'), value: true},
+ {label: $t('users.inactive'), value:false}
+ ];
+ $scope.filters.status = $scope.activeFilterOptions[0];
+
+ $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
+ .concat(Object.keys(UserConstants.TYPES).map(function(key) {
+ return {
+ label: $t(UserConstants.TYPES[key].LABEL_KEY),
+ value: UserConstants.TYPES[key].VALUE
+ };
+ }));
+
+ $scope.filters.type = $scope.typeFilterOptions[0];
+
+ $scope.clearFilters = function () {
+ $scope.filters.name = '';
+ $scope.filters.type = $scope.typeFilterOptions[0];
+ $scope.filters.status = $scope.activeFilterOptions[0];
+ $scope.resetPagination();
+ };
+
+ $scope.loadUsers();
+
+ $scope.$watch(
+ function (scope) {
+ return Boolean(scope.filters.name || (scope.filters.status && scope.filters.status.value !== '*')
+ || (scope.filters.type && scope.filters.type.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.createUser = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'views/userManagement/modals/userCreate.html',
+ controller: 'UserCreateCtrl',
+ backdrop: 'static'
+ });
+
+ modalInstance.result.finally($scope.loadUsers);
+ };
+
+ $scope.deleteUser = function(user) {
+ ConfirmationModal.show(
+ $t('common.delete', {
+ term: $t('common.user')
+ }),
+ $t('common.deleteConfirmation', {
+ instanceType: $t('common.user').toLowerCase(),
+ instanceName: '"' + user.user_name + '"'
+ })
+ ).then(function() {
+ Cluster.getPrivilegesForResource({
+ nameFilter : 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(user.user_name).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);
+ });
+ $scope.loadUsers();
+ });
+ });
+ });
+ };
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
deleted file mode 100644
index bcb7bfc..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
+++ /dev/null
@@ -1,75 +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('UsersCreateCtrl',['$scope', '$routeParams', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', function($scope, $routeParams, User, $location, Alert, UnsavedDialog, $translate) {
- var $t = $translate.instant;
- $scope.user = {
- active: true
- };
- var targetUrl = '/users';
-
- $scope.createUser = function() {
- $scope.form.submitted = true;
- if ($scope.form.$valid){
- User.create({
- 'Users/user_name': $scope.user.user_name,
- 'Users/password': $scope.user.password,
- 'Users/active': !!$scope.user.active,
- 'Users/admin': !!$scope.user.admin
- }).then(function() {
- Alert.success($t('users.alerts.userCreated', {
- userName: $scope.user.user_name,
- encUserName: encodeURIComponent($scope.user.user_name)
- }));
- $scope.form.$setPristine();
- $location.path(targetUrl);
- }).catch(function(data) {
- Alert.error($t('users.alerts.userCreationError'), data.data.message);
- });
- }
- };
-
- $scope.cancel = function() {
- $scope.form.$setPristine();
- $location.path('/users');
- };
-
- $scope.$on('$locationChangeStart', function(event, __targetUrl) {
-
- if( $scope.form.$dirty ){
- UnsavedDialog().then(function(action) {
- targetUrl = __targetUrl.split('#').pop();
- switch(action){
- case 'save':
- $scope.createUser();
- break;
- case 'discard':
- $scope.form.$setPristine();
- $location.path(targetUrl);
- break;
- case 'cancel':
- targetUrl = '/users';
- break;
- }
- });
- event.preventDefault();
- }
- });
-}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
deleted file mode 100644
index 8146163..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
+++ /dev/null
@@ -1,122 +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('UsersListCtrl',['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Settings', function($scope, User, $modal, $rootScope, UserConstants, $translate, Settings) {
- var $t = $translate.instant;
- $scope.constants = {
- admin: $t('users.ambariAdmin'),
- users: $t('common.users').toLowerCase()
- };
- $scope.isLoading = false;
- $scope.users = [];
- $scope.usersPerPage = 10;
- $scope.currentPage = 1;
- $scope.totalUsers = 1;
- $scope.currentNameFilter = '';
- $scope.maxVisiblePages=20;
- $scope.tableInfo = {
- total: 0,
- showed: 0
- };
- $scope.isNotEmptyFilter = true;
-
- $scope.pageChanged = function() {
- $scope.loadUsers();
- };
- $scope.usersPerPageChanges = function() {
- $scope.resetPagination();
- };
-
- $scope.loadUsers = function(){
- $scope.isLoading = true;
- User.list({
- currentPage: $scope.currentPage,
- usersPerPage: $scope.usersPerPage,
- searchString: $scope.currentNameFilter,
- user_type: $scope.currentTypeFilter.value,
- active: $scope.currentActiveFilter.value,
- admin: $scope.adminFilter
- }).then(function(data) {
- $scope.isLoading = false;
- $scope.totalUsers = data.data.itemTotal;
- $scope.users = data.data.items.map(User.makeUser);
- $scope.tableInfo.showed = data.data.items.length;
- $scope.tableInfo.total = data.data.itemTotal;
- });
- };
-
- $scope.resetPagination = function() {
- $scope.currentPage = 1;
- $scope.loadUsers();
- };
-
- $scope.activeFilterOptions = [
- {label: $t('common.all'), value: '*'},
- {label: $t('users.active'), value: true},
- {label: $t('users.inactive'), value:false}
- ];
- $scope.currentActiveFilter = $scope.activeFilterOptions[0];
-
- $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
- .concat(Object.keys(UserConstants.TYPES).map(function(key) {
- return {
- label: $t(UserConstants.TYPES[key].LABEL_KEY),
- value: UserConstants.TYPES[key].VALUE
- };
- }));
-
- $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
- $scope.adminFilter = false;
- $scope.toggleAdminFilter = function() {
- $scope.adminFilter = !$scope.adminFilter;
- $scope.resetPagination();
- $scope.loadUsers();
- };
-
- $scope.clearFilters = function () {
- $scope.currentNameFilter = '';
- $scope.currentTypeFilter = $scope.typeFilterOptions[0];
- $scope.currentActiveFilter = $scope.activeFilterOptions[0];
- $scope.adminFilter = false;
- $scope.resetPagination();
- };
-
- $scope.loadUsers();
-
- $scope.$watch(
- function (scope) {
- return Boolean(scope.currentNameFilter || (scope.currentActiveFilter && scope.currentActiveFilter.value !== '*')
- || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*') || $scope.adminFilter);
- },
- function (newValue, oldValue, scope) {
- scope.isNotEmptyFilter = newValue;
- }
- );
-
- $rootScope.$watch(function(scope) {
- return scope.LDAPSynced;
- }, function(LDAPSynced) {
- if(LDAPSynced === true){
- $rootScope.LDAPSynced = false;
- $scope.loadUsers();
- }
- });
-}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
deleted file mode 100644
index 200872e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
+++ /dev/null
@@ -1,290 +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('UsersShowCtrl', ['$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/users/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('/users');
- 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/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 1967dfa..de3968d 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
@@ -101,6 +101,7 @@ angular.module('ambariAdminConsole')
'common.admin': 'Admin',
'common.actions': 'Actions',
'common.error': 'Error',
+ 'common.select': 'Select',
'common.clusterNameChangeConfirmation.title': 'Confirm Cluster Name Change',
'common.clusterNameChangeConfirmation.message': 'Are you sure you want to change the cluster name to {{clusterName}}?',
@@ -276,6 +277,8 @@ angular.module('ambariAdminConsole')
'groups.createLocal': 'Add Groups',
'groups.name': 'Group name',
+ 'groups.role': 'Add roles to this group',
+ 'groups.addUsers': 'Add users to this group',
'groups.members': 'Members',
'groups.membersPlural': '{{n}} member{{n == 1 ? "" : "s"}}',
@@ -285,7 +288,7 @@ angular.module('ambariAdminConsole')
'groups.alerts.getGroupsListError': 'Get groups list error',
'users.username': 'Username',
- 'users.userName': 'User name',
+ 'users.user.name': 'User name',
'users.admin': 'Admin',
'users.ambariAdmin': 'Ambari Admin',
'users.ambariClusterURL': 'Ambari Cluster URL',
@@ -300,7 +303,11 @@ angular.module('ambariAdminConsole')
'users.inactive': 'Inactive',
'users.status': 'Status',
'users.password': 'Password',
+ 'users.role': 'Add roles for this user (Cluster Operator/Service Admin)',
+ 'users.confirmPassword': 'Confirm Password',
'users.passwordConfirmation': 'Password сonfirmation',
+ 'users.isAmbariAdmin': 'Is this user an Ambari Admin?',
+ 'users.isActive': 'Deactivate this user?',
'users.userIsAdmin': 'This user is an Ambari Admin and has all privileges.',
'users.showAll': 'Show all users',
'users.showAdmin': 'Show only admin users',
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
index dabc57a..c8d0e96 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
@@ -38,51 +38,25 @@ angular.module('ambariAdminConsole')
controller: 'LoginActivitiesMainCtrl'
}
},
- users: {
- list: {
- url: '/users',
- templateUrl: 'views/users/list.html',
- controller: 'UsersListCtrl',
+ userManagement: {
+ main: {
+ url: '/userManagement',
+ templateUrl: 'views/userManagement/main.html',
+ controller: 'UserManagementCtrl',
label: 'Users'
},
- edit: {
+ editUser: {
url: '/users/:id/edit',
- templateUrl: 'views/users/create.html',
- controller: 'UsersCreateCtrl',
+ templateUrl: 'views/userManagement/userEdit.html',
+ controller: 'UserEditCtrl',
label: 'Users'
},
- create: {
- url: '/users/new',
- templateUrl: 'views/users/create.html',
- controller: 'UsersCreateCtrl',
- label: 'Users'
- },
- show: {
- url: '/users/:id*',
- templateUrl: 'views/users/show.html',
- controller: 'UsersShowCtrl',
- label: 'Users'
- }
- },
- groups: {
- list: {
- url: '/groups',
- templateUrl: 'views/groups/list.html',
- controller: 'GroupsListCtrl',
- label: 'Groups'
- },
- edit: {
+ editGroup: {
url: '/groups/:id/edit',
- templateUrl: 'views/groups/edit.html',
- controller: 'GroupsEditCtrl',
+ templateUrl: 'views/userManagement/groupEdit.html',
+ controller: 'GroupEditCtrl',
label: 'Groups'
},
- create: {
- url: '/groups/new',
- templateUrl: 'views/groups/create.html',
- controller: 'GroupsCreateCtrl',
- label: 'Groups'
- }
},
views: {
list: {
@@ -157,20 +131,9 @@ angular.module('ambariAdminConsole')
}
},
clusters: {
- manageAccess: {
- url: '/clusters/:id/manageAccess',
- templateUrl: 'views/clusters/manageAccess.html',
- controller: 'ClustersManageAccessCtrl',
- label: 'Roles'
- },
- userAccessList: {
- url: '/clusters/:id/userAccessList',
- templateUrl: 'views/clusters/userAccessList.html',
- controller: 'UserAccessListCtrl'
- },
clusterInformation: {
url: '/clusterInformation',
- templateUrl: 'views/clusterInformation.html',
+ templateUrl: 'views/clusters/clusterInformation.html',
controller: 'ClusterInformationCtrl',
label: 'Cluster Information'
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
index ac50653..47015d1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
@@ -94,9 +94,10 @@ angular.module('ambariAdminConsole')
* @returns {Object}
*/
makeUser: function(user) {
- user.Users.encoded_name = encodeURIComponent(user.Users.user_name);
+ user.Users.encodedName = encodeURIComponent(user.Users.user_name);
user.Users.userTypeName = $t(UserConstants.TYPES[user.Users.user_type].LABEL_KEY);
- user.Users.ldap_user = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+ user.Users.ldapUser = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+ user.Users.role = user.privileges.length ? user.privileges[0].PrivilegeInfo.privilege_id : null;
return user;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/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 94bdf11..91b2fb1 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
@@ -247,6 +247,9 @@ a.gotoinstance{
.hide-soft{
display: none;
}
+.nowrap {
+ white-space: nowrap;
+}
.visible{
display: block;
}
@@ -386,16 +389,6 @@ a.gotoinstance{
.search-container input {
font-weight: normal;
}
-.groups-pane .search-container .close{
- top: 32px;
-}
-
-.groups-pane table thead th{
- border-top: 0;
-}
-.groups-pane table thead tr:first-child th{
- border: 0;
-}
ul.nav li > a{
cursor: pointer;
@@ -464,16 +457,6 @@ table.no-border tr td{
margin-top: 0;
}
-.groups-pane table ul{
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-.groups-pane table ul li {
- margin: 0;
- padding: 0;
-}
-
.property-form label{
word-wrap: break-word;
text-overflow: ellipsis;
@@ -539,6 +522,7 @@ button.btn.btn-xs{
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
+ height: 24px;
}
a.btn-primary, a.btn-primary:focus {
@@ -617,13 +601,13 @@ a.alert-link, a.alert-link:hover, a.alert-link:visited{
box-sizing: border-box;
}
-.fix-bottom{
+.fix-bottom th {
border-bottom: none !important;;
border-top: none !important;
border-width: 0;
}
-.fix-top{
+.fix-top th {
border-top: none !important;
border-width: 0;
}
@@ -1334,3 +1318,21 @@ body {
.navigation-bar-fit-height {
z-index: 1001;
}
+
+.entity-actions a {
+ color: inherit;
+ font-size: 16px;
+ cursor: pointer;
+ padding: 0 5px;
+}
+
+td.entity-actions,
+th.entity-actions {
+ width: 10%;
+}
+
+.entity-actions a:hover,
+.entity-actions a:visited:hover,
+.entity-actions a:focus:hover {
+ text-decoration: none;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
new file mode 100644
index 0000000..77c94ac
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+#user-management .table th {
+ vertical-align: baseline;
+}
+
+#user-management .nav.nav-tabs {
+ margin-bottom: 0;
+}
+
+#user-management .users-pane,
+#user-management .groups-pane {
+ margin-top: -35px;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
index 58583de..9bb84df 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
@@ -16,24 +16,6 @@
* limitations under the License.
*/
-.view-instance-actions a {
- color: inherit;
- font-size: 16px;
- cursor: pointer;
- padding: 0 5px;
-}
-
-td.view-instance-actions,
-th.view-instance-actions {
- width: 10%;
-}
-
-.view-instance-actions a:hover,
-.view-instance-actions a:visited:hover,
-.view-instance-actions a:focus:hover {
- text-decoration: none;
-}
-
#create-instance-form i {
cursor: pointer;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
index 2ff0fc4..04901f1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
@@ -29,24 +29,24 @@
<table class="table table-striped table-hover">
<thead>
<tr class="fix-bottom">
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'common.name' | translate}}</span>
</th>
- <th class="fix-bottom col-md-3">
+ <th class="col-md-3">
<span>{{'urls.url' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'views.table.viewType' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'urls.viewInstance' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2 view-instance-actions">
+ <th class="col-md-2 entity-actions">
<span>{{'common.actions' | translate}}</span>
</th>
</tr>
- <tr>
- <th class="fix-top">
+ <tr class="fix-top">
+ <th>
<div class="search-container">
<input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
ng-model="instanceNameFilter" ng-change="filterInstances()">
@@ -57,7 +57,7 @@
</button>
</div>
</th>
- <th class="fix-top">
+ <th>
<div class="search-container">
<input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
ng-model="instanceUrlFilter" ng-change="filterInstances()">
@@ -68,17 +68,15 @@
</button>
</div>
</th>
- <th class="fix-top">
+ <th>
<select class="form-control typefilter v-small-input"
ng-model="instanceTypeFilter"
ng-options="item.label for item in typeFilterOptions"
ng-change="filterInstances()">
</select>
</th>
- <th class="fix-top">
- </th>
- <th class="fix-top">
- </th>
+ <th></th>
+ <th></th>
</tr>
</thead>
@@ -98,7 +96,7 @@
<td>
<span>{{instance.instance_name}}</span>
</td>
- <td class="view-instance-actions" ng-switch="instance.versionObj.status">
+ <td class="entity-actions" ng-switch="instance.versionObj.status">
<span ng-switch-when="PENDING">
<i class="viewstatus pending"></i>
{{'views.pending' | translate}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
deleted file mode 100644
index ead73c3..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
+++ /dev/null
@@ -1,87 +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.
--->
-
-<div id="cluster-information">
- <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
- <div class="welcome-header">
- <h1>{{'main.title' | translate}}</h1>
- <span>{{'main.noClusterDescription' | translate}}</span>
- </div>
- <div class="create-cluster-section">
- <h2>{{'main.createCluster.title' | translate}}</h2>
- <div>
- <span>
- {{'main.createCluster.description' | translate}}
- </span>
- </div>
- <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
- <div>
- <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
- {{'main.createCluster.launchInstallWizard' | translate}}
- </a>
- </div>
- </div>
- </div>
-
- <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
- <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
- <div class="form-group col-xs-4 cluster-name"
- ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
- <label for="clusterName">{{'views.clusterName' | translate}}*</label>
- <input type="text"
- class="form-control"
- id="clusterName"
- name="clusterName"
- ng-change="toggleSaveButton()"
- ng-model="edit.clusterName"
- required
- autofocus
- ng-pattern="/^\w*$/"
- ng-maxlength="80"
- tooltip="{{'common.renameClusterTip' | translate}}"
- tooltip-trigger="focus"
- tooltip-placement="bottom"
- ng-class="{edited: isClusterNameEdited}">
- <button
- type="submit"
- ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
- class="btn btn-default pull-right"
- ng-show="isClusterNameEdited">
- {{'common.controls.save' | translate}}
- </button>
- </div>
- </form>
- <div>
- <div class="row dev-blueprint">
- <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
- <div class="col-sm-1">
- <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
- </div>
- </div>
- </div>
- <textarea type="text"
- rows="20"
- class="form-control"
- name="blueprint_text"
- ng-model="blueprint"
- ng-disabled="true"
- ng-readonly="true">
- </textarea>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
new file mode 100644
index 0000000..ead73c3
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
@@ -0,0 +1,87 @@
+<!--
+* 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 id="cluster-information">
+ <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
+ <div class="welcome-header">
+ <h1>{{'main.title' | translate}}</h1>
+ <span>{{'main.noClusterDescription' | translate}}</span>
+ </div>
+ <div class="create-cluster-section">
+ <h2>{{'main.createCluster.title' | translate}}</h2>
+ <div>
+ <span>
+ {{'main.createCluster.description' | translate}}
+ </span>
+ </div>
+ <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
+ <div>
+ <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
+ {{'main.createCluster.launchInstallWizard' | translate}}
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
+ <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
+ <div class="form-group col-xs-4 cluster-name"
+ ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
+ <label for="clusterName">{{'views.clusterName' | translate}}*</label>
+ <input type="text"
+ class="form-control"
+ id="clusterName"
+ name="clusterName"
+ ng-change="toggleSaveButton()"
+ ng-model="edit.clusterName"
+ required
+ autofocus
+ ng-pattern="/^\w*$/"
+ ng-maxlength="80"
+ tooltip="{{'common.renameClusterTip' | translate}}"
+ tooltip-trigger="focus"
+ tooltip-placement="bottom"
+ ng-class="{edited: isClusterNameEdited}">
+ <button
+ type="submit"
+ ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
+ class="btn btn-default pull-right"
+ ng-show="isClusterNameEdited">
+ {{'common.controls.save' | translate}}
+ </button>
+ </div>
+ </form>
+ <div>
+ <div class="row dev-blueprint">
+ <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
+ <div class="col-sm-1">
+ <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
+ </div>
+ </div>
+ </div>
+ <textarea type="text"
+ rows="20"
+ class="form-control"
+ name="blueprint_text"
+ ng-model="blueprint"
+ ng-disabled="true"
+ ng-readonly="true">
+ </textarea>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/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
deleted file mode 100644
index a399eff..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
+++ /dev/null
@@ -1,63 +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.
--->
-
-<div class="cluster-manage-access-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{clusterName}} {{'common.roles' | translate}}</li>
- </ol>
- </div>
- <hr>
- <div class="pull-right">
- <div class="layout-switch-icon-wrapper">
- <i class="glyphicon glyphicon-th-large layout-switch-icon"></i>
- <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
- </div>
- <div class="layout-switch-icon-wrapper disabled">
- <i class="glyphicon glyphicon-list layout-switch-icon" ng-click="switchToList()" tooltip-html-unsafe="{{'clusters.switchToList' | translate}}"></i>
- <p class="label-list">{{'common.listViewLabel' | translate}}</p>
- </div>
- </div>
- <table class="table">
- <thead>
- <tr>
- <th class="col-sm-2" width="20%">
- <label>{{'common.roles' | translate}}</label>
- <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("common.users")}'}}</label></th>
- <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("common.groups")}'}}</label></th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="permission in permissions">
- <td><label class="" tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_label}}</label></td>
- <td>
- <div class="" ng-switch="isEditMode">
- <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" resource-type="User" editable="true"></editable-list>
- </div>
- </td>
- <td>
- <div class="" ng-switch="isEditMode">
- <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" resource-type="Group" editable="true"></editable-list>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
-</div>
\ 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/views/clusters/userAccessList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
deleted file mode 100644
index 8b29157..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
+++ /dev/null
@@ -1,102 +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.
--->
-
-<div class="users-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{clusterId}} {{'common.roles' | translate}}</li>
- </ol>
- </div>
- <hr>
- <div class="pull-right">
- <div class="layout-switch-icon-wrapper disabled">
- <i class="glyphicon glyphicon-th-large layout-switch-icon" ng-click="switchToBlock()" tooltip-html-unsafe="{{'clusters.switchToBlock' | translate}}"></i>
- <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
- </div>
- <div class="layout-switch-icon-wrapper">
- <i class="glyphicon glyphicon-list layout-switch-icon"></i>
- <p class="label-list">{{'common.listViewLabel' | translate}}</p>
- </div>
- </div>
- <ul class="nav nav-pills">
- <li ng-class="{'active': isUserActive}"><a ng-click="switchToUser()">{{'common.users' | translate}}</a></li>
- <li ng-class="{'active': !isUserActive}"><a ng-click="switchToGroup()">{{'common.groups' | translate}}</a></li>
- </ul>
- <br/>
- <table class="table table-striped table-hover">
- <thead>
- <tr>
- <th class="role-name-column">
- <div class="search-container">
- <label for="">{{'common.name' | translate}}</label>
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
- <button type="button" class="close clearfilter" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()">
- <span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span>
- </button>
- </div>
- </th>
- <th>
- <label for="">{{'clusters.role' | translate}}</label>
- <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
- <select class="form-control statusfilter"
- ng-model="currentRoleFilter"
- ng-options="item.label for item in roleFilterOptions"
- ng-change="resetPagination()">
- </select>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="user in users">
- <td>
- <a href="#/{{user.url}}">{{user.principal_name}}</a>
- </td>
- <td>
- <div ng-show="!user.editable">{{user.permission_label}}</div>
- <select class="form-control role-select" ng-show="user.editable" ng-model="user.permission_name"
- ng-options="role.permission_name as role.permission_label for role in roleValueOptions">
- </select>
- <span ng-show="user.principal_type != $parent.currentTypeFilter.value"> {{'common.fromGroupMark' | translate}}</span>
- <span ng-show="user.permission_name != user.original_perm">
- <button class="btn btn-default btn-xs cancel" ng-click="cancel(user)">
- <span class="glyphicon glyphicon-remove cancel"></span>
- </button>
- <button class="btn btn-primary btn-xs" ng-click="save(user)">
- <span class="glyphicon glyphicon-ok"></span>
- </button>
- </span>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="alert alert-info col-sm-12" ng-show="!users.length">
- {{'common.alerts.nothingToDisplay' | translate: '{term: (isUserActive ? constants.users : constants.groups)}'}}
- </div>
- <div class="col-sm-12 table-bar">
- <div class="pull-left filtered-info">
- <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: (isUserActive ? constants.users : constants.groups)}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
deleted file mode 100644
index 9a0e0fb..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
+++ /dev/null
@@ -1,43 +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.
--->
-<ol class="breadcrumb">
- <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
- <li class="active">{{'groups.createLocal' | translate}}</li>
-</ol>
-<hr>
-<form class="form-horizontal" role="form" novalidate name="form" autocomplete="off">
- <div class="form-group" ng-class="{'has-error' : (form.group_name.$error.required || form.group_name.$error.pattern) && form.submitted}">
- <label for="groupname" class="col-sm-2 control-label">{{'groups.name' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" id="groupname" class="form-control groupname-input" name="group_name" placeholder="{{'groups.name' | translate}}" ng-model="group.group_name" required ng-pattern="/^([a-zA-Z0-9._\s]+)$/" autocomplete="off">
- <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.required && form.submitted">
- {{'common.alerts.fieldIsRequired' | translate}}
- </div>
- <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.pattern && form.submitted">
- {{'common.alerts.onlySimpleChars' | translate}}
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-primary groupcreate-btn pull-right left-margin" ng-click="createGroup()">{{'common.controls.save' | translate}}</button>
- <a href ng-click="cancel()" class="btn btn-default pull-right cancel-button">{{'common.controls.cancel' | translate}}</a>
- </div>
- </div>
-
-</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
deleted file mode 100644
index 1aafd03..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
+++ /dev/null
@@ -1,98 +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.
--->
-
-<div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
- <li class="active">{{group.group_name}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <div ng-switch="group.group_type != 'LOCAL'">
- <button ng-switch-when="true" class="btn disabled deletegroup-btn deleteuser-btn" tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">{{'common.delete' | translate: '{term: constants.group}'}}</button>
- <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">{{'common.delete' | translate: '{term: constants.group}'}}</button>
- </div>
-
- </div>
-</div>
-<hr>
-<form class="form-horizontal group-edit" role="form" novalidate name="form" >
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
- <div class="col-sm-10">
- <label for="" class="control-label">{{group.groupTypeName | translate}}</label>
- </div>
- </div>
- <div class="form-group">
- <label for="members" class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
- <div class="col-sm-10">
- <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
- </div>
- </div>
-
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
- <div class="col-sm-10">
- <table class="table" ng-hide="hidePrivileges">
- <thead>
- <tr>
- <th>{{'common.cluster' | translate}}</th>
- <th>{{'common.clusterRole' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.clusters">
- <td>
- <span class="glyphicon glyphicon-cloud"></span>
- <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
- </td>
- </tr>
- <tr>
- <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
- </tr>
- </tbody>
- <thead class="view-permission-header">
- <tr>
- <th>{{'common.view' | translate}}</th>
- <th>{{'common.viewPermissions' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.views">
- <td>
- <span class="glyphicon glyphicon-th"></span>
- <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
- </td>
- <td>
- <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
- </td>
- </tr>
- <tr>
- <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
- </tr>
- </tbody>
- </table>
- <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
- </div>
- </div>
-</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
deleted file mode 100644
index b39f55d..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
+++ /dev/null
@@ -1,80 +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.
--->
-<div class="groups-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{'common.groups' | translate}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <link-to route="groups.create" class="btn btn-default creategroup-btn">
- {{'groups.createLocal' | translate}}
- </link-to>
- </div>
- </div>
- <table class="table table-striped table-hover col-sm-12">
- <thead>
- <tr>
- <th class="col-sm-8">
- <div class="search-container">
- <label for="">{{'groups.name' | translate}}</label>
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
- <button type="button" class="close" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- </div>
- </th>
- <th class="col-sm-2">
- <label for="">{{'common.type' | translate}}</label>
- <select class="form-control typefilter"
- ng-model="currentTypeFilter"
- ng-options="item.label for item in typeFilterOptions"
- ng-change="resetPagination();">
- </select>
- </th>
- <th class="col-sm-2 vertical-top">
- <label for="">{{'groups.members' | translate}}</label>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="group in groups">
- <td class="col-sm-8">
- <link-to route="groups.edit" class="link-to-group" id="{{group.group_name}}">{{group.group_name}}</link-to>
- </td>
- <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
- <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
- </tr>
- </tbody>
- </table>
- <div ng-if="isLoading" class="spinner-container">
- <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
- </div>
- <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
- {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
- </div>
- <div class="col-sm-12 table-bar">
- <div class="pull-left filtered-info">
- <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-</div>
\ 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/views/sideNav.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
index 97dc5d3..98a95cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
@@ -59,25 +59,11 @@
</li>
</ul>
</li>
- <li class="mainmenu-li dropdown has-sub-menu">
- <a title="{{'common.userManagement' | translate}}" rel="tooltip" data-placement="right" data-toggle="collapse-sub-menu">
- <span class="toggle-icon glyphicon glyphicon-menu-down pull-right"></span>
+ <li class="mainmenu-li" ng-class="{active: isActive('userManagement.main')}">
+ <link-to route="userManagement.main" class="userslist-link" title="{{'common.users' | translate}}" rel="tooltip" data-placement="right">
<i class="navigation-icon fa fa-users" aria-hidden="true"></i>
- <span class="navigation-menu-item">{{'common.userManagement' | translate}}</span>
- </a>
- <ul class="sub-menu nav nav-pills nav-stacked">
- <li class="submenu-li"
- ng-class="{active: isActive('clusters.manageAccess') || isActive('clusters.userAccessList')}"
- ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
- <a href="#/clusters/{{cluster.Clusters.cluster_name}}/manageAccess" class="roles">{{'common.roles' | translate}}</a>
- </li>
- <li class="submenu-li" ng-class="{active: isActive('users.list')}">
- <link-to route="users.list" class="userslist-link">{{'common.users' | translate}}</link-to>
- </li>
- <li class="submenu-li" ng-class="{active: isActive('groups.list')}">
- <link-to route="groups.list" class="groupslist-link">{{'common.groups' | translate}}</link-to>
- </li>
- </ul>
+ <span class="navigation-menu-item">{{'common.users' | translate}}</span>
+ </link-to>
</li>
<li class="mainmenu-li" ng-class="{active: isActive('views.list')}">
<link-to route="views.list" class="viewslist-link" title="{{'common.views' | translate}}" rel="tooltip" data-placement="right">
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
new file mode 100644
index 0000000..90a1907
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
@@ -0,0 +1,99 @@
+<!--
+* 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="clearfix">
+ <div class="pull-right">
+ <div ng-switch="group.group_type != 'LOCAL'">
+ <button
+ ng-switch-when="true"
+ class="btn disabled deletegroup-btn"
+ tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">
+ {{'common.delete' | translate: '{term: constants.group}'}}
+ </button>
+ <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">
+ {{'common.delete' | translate: '{term: constants.group}'}}
+ </button>
+ </div>
+ </div>
+</div>
+<form class="form-horizontal group-edit" role="form" novalidate name="form" >
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+ <div class="col-sm-10">
+ <label class="control-label">{{group.groupTypeName | translate}}</label>
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
+ <div class="col-sm-10">
+ <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+ <div class="col-sm-10">
+ <table class="table" ng-hide="hidePrivileges">
+ <thead>
+ <tr>
+ <th>{{'common.cluster' | translate}}</th>
+ <th>{{'common.clusterRole' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.clusters">
+ <td>
+ <span class="glyphicon glyphicon-cloud"></span>
+ <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+ </tr>
+ </tbody>
+ <thead class="view-permission-header">
+ <tr>
+ <th>{{'common.view' | translate}}</th>
+ <th>{{'common.viewPermissions' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.views">
+ <td>
+ <span class="glyphicon glyphicon-th"></span>
+ <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
+ </td>
+ <td>
+ <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
+ </div>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
new file mode 100644
index 0000000..d79d14e
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
@@ -0,0 +1,94 @@
+<!--
+* 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="groups-pane">
+ <div class="clearfix panel">
+ <button class="btn btn-default creategroup-btn pull-right" ng-click="createGroup()">
+ {{'groups.createLocal' | translate}}
+ </button>
+ </div>
+ <table class="table table-striped table-hover col-sm-12">
+ <thead>
+ <tr>
+ <th class="col-sm-6">
+ <span>{{'groups.name' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'common.type' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'groups.members' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'common.actions' | translate}}</span>
+ </th>
+ </tr>
+ <tr>
+ <th class="col-sm-6">
+ <div class="search-container">
+ <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="filter.name" ng-change="resetPagination()">
+ <button type="button" class="close" ng-show="filter.name" ng-click="filter.name=''; resetPagination()"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
+ </div>
+ </th>
+ <th class="col-sm-2">
+ <select class="form-control typefilter"
+ ng-model="filter.type"
+ ng-options="item.label for item in typeFilterOptions"
+ ng-change="resetPagination();">
+ </select>
+ </th>
+ <th class="col-sm-2"></th>
+ <th class="col-sm-2"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="group in groups">
+ <td class="col-sm-8">
+ <span>{{group.group_name}}</span>
+ </td>
+ <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
+ <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
+ <td class="entity-actions">
+ <link-to route="userManagement.editGroup" class="link-to-group" id="{{group.group_name}}">
+ <i class="fa fa-pencil"></i>
+ </link-to>
+ <a href ng-click="deleteGroup(group)">
+ <i class="fa fa-trash-o"></i>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div ng-if="isLoading" class="spinner-container">
+ <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
+ </div>
+ <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
+ {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
+ </div>
+ <div class="col-sm-12 table-bar" ng-show="totalGroups > minRowsToShowPagination">
+ <div class="pull-left filtered-info">
+ <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
+ <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
+ </div>
+ <div class="pull-right left-margin">
+ <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
+ </div>
+ <div class="pull-right">
+ <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
+ </div>
+ </div>
+</div>
\ 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/views/userManagement/main.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
new file mode 100644
index 0000000..079eefb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
@@ -0,0 +1,36 @@
+<!--
+* 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 id="user-management">
+ <ul class="nav nav-tabs">
+ <li ng-class="{active: activeTab === 'USERS'}">
+ <a ng-click="activeTab = 'USERS'">{{'common.users' | translate}}</a>
+ </li>
+ <li ng-class="{active: activeTab === 'GROUPS'}">
+ <a ng-click="activeTab = 'GROUPS'">{{'common.groups' | translate}}</a>
+ </li>
+ </ul>
+ <div>
+ <div class="users" ng-if="activeTab === 'USERS'">
+ <div ng-include="'views/userManagement/usersList.html'" ng-controller="UsersListCtrl"></div>
+ </div>
+ <div class="groups" ng-if="activeTab === 'GROUPS'">
+ <div ng-include="'views/userManagement/groupsList.html'" ng-controller="GroupsListCtrl"></div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
new file mode 100644
index 0000000..f29d315
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
@@ -0,0 +1,46 @@
+<!--
+* 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">
+ <h3 class="modal-title">{{'users.changePasswordFor' | translate: '{userName: userName}'}}</h3>
+</div>
+<div class="modal-body">
+ <form class="form-horizontal" novalidate name="form.passwordChangeForm" role="form" >
+ <div class="form-group" ng-class="{'has-error' : (form.passwordChangeForm.currentPassword.$error.required && form.passwordChangeForm.submitted)}">
+ <label for="" class="col-sm-4 control-label" >{{'users.yourPassword' | translate}}</label>
+ <div class="col-sm-8">
+ <input type="password" name="currentPassword" class="form-control bottom-margin" placeholder="{{'users.yourPassword' | translate}}" required ng-model="passwordData.currentUserPassword" autocomplete="off">
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+ </div>
+ </div>
+ <div class="form-group no-margin-bottom" ng-class="{'has-error' : (form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted) || form.passwordChangeForm.confirmPassword.$error.passwordVerify}">
+ <label for="" class="col-sm-4 control-label">{{'users.newPassword' | translate}}:</label>
+ <div class="col-sm-8">
+ <input type="password" class="form-control bottom-margin" name="password" placeholder="{{'users.newPassword' | translate}}" required ng-model="passwordData.password" autocomplete="off">
+ <input type="password" class="form-control bottom-margin" name="confirmPassword" placeholder="{{'users.newPasswordConfirmation' | translate}}" required ng-model="passwordData.passwordConfirmation"
+ password-verify="passwordData.password" autocomplete="off">
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+ </div>
+
+ </div>
+ </form>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+ <button class="btn btn-primary" ng-click="ok()">{{'common.controls.ok' | translate}}</button>
+</div>
\ No newline at end of file