summaryrefslogtreecommitdiffstats
path: root/app/common
diff options
context:
space:
mode:
authorbeccabroek <beccabroek@gmail.com>2018-11-07 12:22:31 -0600
committerGunnar Mills <gmills@us.ibm.com>2019-09-26 20:04:56 +0000
commit5e258e43070b46b9d1ec5ec01e02b9f707cbf7b8 (patch)
treedcce595926ecd55bdb86f93800dcb95886cd06e5 /app/common
parent5dac9e155e46cd8615a057ff6fe1577a9f21a0a7 (diff)
downloadphosphor-webui-5e258e43070b46b9d1ec5ec01e02b9f707cbf7b8.tar.gz
phosphor-webui-5e258e43070b46b9d1ec5ec01e02b9f707cbf7b8.zip
LDAP configuration and user groups
Adds LDAP page and ability to add and change configuration settings. Adds ability to add, remove and edit user groups for LDAP. Resolves openbmc/phosphor-webui#38 Resolves openbmc/phosphor-webui#39 Tested: Loaded on to a witherspoon and able to add initial LDAP config as well us update the configuration and role groups. Appropriate messages displayed to user when required fields are missing or in the incorrect format. Change-Id: If8a21f3f9d9334415ead73472e90b2a0823bf9ea Signed-off-by: beccabroek <beccabroek@gmail.com> Signed-off-by: Dixsie Wolmers <dixsiew@gmail.com> Signed-off-by: Derick Montague <derick.montague@ibm.com>
Diffstat (limited to 'app/common')
-rw-r--r--app/common/directives/app-navigation.html3
-rw-r--r--app/common/directives/ldap-user-roles.html185
-rw-r--r--app/common/directives/ldap-user-roles.js231
-rw-r--r--app/common/services/api-utils.js8
-rw-r--r--app/common/styles/components/form-elements.scss7
5 files changed, 433 insertions, 1 deletions
diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
index 82a4a70..02b7194 100644
--- a/app/common/directives/app-navigation.html
+++ b/app/common/directives/app-navigation.html
@@ -100,6 +100,9 @@
<a href="#/configuration/date-time" ng-click="closeSubnav()"
tabindex="{{(showSubMenu && firstLevel == 'configuration') ? 0 : -1}}">Date and time settings</a>
</li>
+ <li ng-class="{'active': (path == '/configuration' || path == '/configuration/ldap')}">
+ <a href="#/configuration/ldap" ng-click="closeSubnav()"
+ tabindex="{{(showSubMenu && firstLevel == 'configuration') ? 0 : -1}}">LDAP settings</a></li>
</ul>
</li>
<li>
diff --git a/app/common/directives/ldap-user-roles.html b/app/common/directives/ldap-user-roles.html
new file mode 100644
index 0000000..1f509b8
--- /dev/null
+++ b/app/common/directives/ldap-user-roles.html
@@ -0,0 +1,185 @@
+<div class="row column">
+ <button type="button" ng-class="{'disabled' : roleGroupType === '' }" ng-disabled="roleGroupType === ''"
+ class="btn btn-tertiary" ng-click="addGroupFn(); $parent.newGroup={}">
+ <icon aria-hidden="true" file="icon-plus.svg"></icon>
+ <span>Add role group</span>
+ </button>
+ <button type="button" ng-disabled="roleGroupType === '' || !hasSelectedGroup" class="btn btn-tertiary"
+ ng-click="removeMultipleRoleGroupsFn() ">
+ <icon aria-hidden="true" file="icon-trashcan.svg"></icon>
+ <span>Remove role groups</span>
+ </button>
+</div>
+<div class="ldap__table">
+ <div class="table__row-header row column" ng-class="{'disabled' : !enabled }">
+ <div class="row column">
+ <div class="table__cell-select">
+ <label class="control-check" aria-label="select or deselect all groups">
+ <input type="checkbox" ng-disabled="!enabled || roleGroups.length < 1 " name="events__check"
+ ng-click="toggleAll()" ng-checked="roleGroupIsSelectedChanged()" ng-model="all" />
+ <span class="control__indicator"></span>
+ </label>
+ </div>
+ <div class="table__cell-sort">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('RemoteGroup', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('RemoteGroup', true)"></button>
+ </div>
+ </div>
+ <div class="table__cell-ldap-group">
+ Group name
+ </div>
+ <div class="table__cell-sort">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('LocalRole', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('LocalRole', true)"></button>
+ </div>
+ </div>
+ <div class="table__cell-ldap-role">
+ Group privilege
+ </div>
+ </div>
+ </div>
+ <div class="empty__logs" ng-if="roleGroups.length < 1 || !enabled">
+ <p ng-if="roleGroups.length < 1 && roleGroupType === 'ad' || roleGroupType === 'ldap'">
+ No role groups have been created yet.
+ </p>
+ <p ng-if=" roleGroupType === '' " ng-class="{'disabled' : !enabled }">
+ LDAP authentication must be enabled before creating role groups.
+ </p>
+ </div>
+ <div ng-repeat="group in roleGroups | orderBy:sortPropertyName:reverse track by $index ">
+ <div class="row column table__row-value" ng-if="enabled">
+ <div class="table__cell-select select-header">
+ <label class="control-check" aria-label="select or deselect group">
+ <input type="checkbox" name="events__check" ng-model="group.isSelected"
+ ng-change="roleGroupIsSelectedChanged(); optionToggled()" />
+ <span class="control__indicator"></span>
+ </label>
+ </div>
+ <div class="table__cell-ldap">
+ {{ group.RemoteGroup }}
+ </div>
+ <div class="table__cell-ldap">
+ {{ group.LocalRole }}
+ </div>
+ <div class="table__cell-buttons">
+ <button class="btn btn-tertiary" type="button" aria-label="edit selected role group"
+ ng-click="editGroupFn(group.RemoteGroup, group.LocalRole, $index); newGroup.RemoteGroup = group.RemoteGroup; newGroup.LocalRole = group.LocalRole; selectedGroupIndex = $index">
+ <icon aria-hidden="true" file="icon-edit.svg"></icon>
+ </button>
+ <button class="btn btn-tertiary" type="button" aria-label="delete selected role group"
+ ng-class="{'disabled' : roleGroups.length < 1}"
+ ng-click="removeGroupFn($index); newGroup.RemoteGroup = group.RemoteGroup; newGroup.LocalRole = group.LocalRole; selectedGroupIndex = $index">
+ <icon aria-hidden="true" file="icon-trashcan.svg"></icon>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+<section class="modal" aria-hidden="true" role="dialog" ng-class="{'active': addGroup || editGroup}">
+ <h3 class="subhead">{{ addGroup ? "Add new role group" : "Edit group privilege" }}</h3>
+ <div class="modal__content-ldap">
+ <div ng-if="addGroup">
+ <form name="add__group__form" id="add__group__form" novalidate>
+ <div class="small-9">
+ <label for="group_name">Role group name</label>
+ <input type="text" name="group_name" id="group_name" ng-model="newGroup.RemoteGroup" required />
+ <div ng-messages="add__group__form.group_name.$error" class="form-error"
+ ng-class="{'visible' : add__group__form.group_name.$touched}">
+ <p ng-message="required">Field is required</p>
+ </div>
+ </div>
+ <div class="small-9">
+ <label for="group__role">Privilege</label>
+ <select id="group__role" class="select__group-role" name="group__role" ng-model="newGroup.LocalRole" required>
+ <option class="courier-bold" ng-value="">Select an option</option>
+ <option class="courier-bold" ng-repeat="privilege in privileges">{{
+ privilege
+ }}</option>
+ </select>
+ <div ng-messages="add__group__form.group__role.$error" class="form-error"
+ ng-class="{'visible' : add__group__form.group__role.$touched}">
+ <p ng-message="required">Field is required</p>
+ </div>
+ </div>
+ </form>
+ <div class="form-actions">
+ <button type="button" class="btn btn-primary" ng-class="{'disabled' : add__group__form.$invalid}"
+ ng-click="addRoleGroup(); $parent.addGroup=false; $parent.newGroup={}">
+ Save
+ </button>
+ <button type="button" class="btn btn-secondary" ng-click="$parent.addGroup=false; $parent.newGroup={}">
+ Cancel
+ </button>
+ </div>
+ </div>
+ <div ng-if="editGroup">
+ <form name="edit__group__form" id="edit__group__form" novalidate>
+ <label>Role group name</label>
+ <div class="small-9 edit-group-name" ng-model="newGroup.RemoteGroup">
+ {{ newGroup.RemoteGroup }}
+ </div>
+ <div class="small-9">
+ <label for="group__role__edit">Privilege</label>
+ <select id="group__role__edit" name="group__role__edit" ng-model="newGroup.LocalRole" required>
+ <option class="courier-bold" ng-repeat="privilege in privileges">{{
+ privilege
+ }}</option>
+ </select>
+ <div ng-messages="edit__group__form.group__role__edit.$error" class="form-error"
+ ng-class="{'visible' : edit__group__form.group__role__edit.$touched}">
+ <p ng-message="required">Field is required</p>
+ </div>
+ </div>
+ </form>
+ <div class="form-actions">
+ <button type="button" class="btn btn-primary"
+ ng-click="editRoleGroup();$parent.editGroup=false; $parent.newGroup={}">
+ Save
+ </button>
+ <button type="button" class="btn btn-secondary" ng-click="$parent.editGroup=false; $parent.newGroup={}">
+ Cancel
+ </button>
+ </div>
+ </div>
+ </div>
+</section>
+<section class="modal" aria-hidden="true" role="dialog" ng-class="{'active': removeGroup}">
+ <h3 class="subhead">Remove role group</h3>
+ <div class="modal__content-ldap">
+ <p>Are you sure you want to remove "{{ newGroup.RemoteGroup }}"?</p>
+ </div>
+ <div class="form-actions">
+ <button type="button" class="btn btn-primary" ng-click="removeRoleGroup(); $parent.removeGroup=false; newGroup={}">
+ Remove
+ </button>
+ <button type="button" class="btn btn-secondary"
+ ng-click="removeGroup=false; $parent.removeGroup=false; newGroup={}">
+ Cancel
+ </button>
+ </div>
+</section>
+<section class="modal" aria-hidden="true" role="dialog" ng-class="{'active': removeMultipleGroups}">
+ <div class="page-header">
+ <h3>Remove role group</h3>
+ </div>
+ <div class="modal__content-ldap">
+ <p>
+ Are you sure you want to remove
+ <span ng-repeat="groups in roleGroups | filter:{isSelected:true}">{{ $last && !$first ? " and " : $first ? "" : ", "
+ }}{{ "'" + groups.RemoteGroup + "'" }}?</span>
+ </p>
+ </div>
+ <div class="form-actions">
+ <button type="button" class="btn btn-primary"
+ ng-click="removeMultipleRoleGroups();$parent.removeMultipleGroups=false; $parent.newGroup={}">
+ Remove
+ </button>
+ <button type="button" class="btn btn-secondary" ng-click="removeMultipleGroups = false">
+ Cancel
+ </button>
+ </div>
+</section>
+<div class="modal-overlay" tabindex="-1"
+ ng-class="{'active': addGroup || editGroup || removeGroup || removeMultipleGroups}"></div> \ No newline at end of file
diff --git a/app/common/directives/ldap-user-roles.js b/app/common/directives/ldap-user-roles.js
new file mode 100644
index 0000000..4e83606
--- /dev/null
+++ b/app/common/directives/ldap-user-roles.js
@@ -0,0 +1,231 @@
+window.angular && (function(angular) {
+ 'use strict';
+
+ angular.module('app.common.directives').directive('ldapUserRoles', [
+ 'APIUtils',
+ function(APIUtils) {
+ return {
+ restrict: 'E',
+ template: require('./ldap-user-roles.html'),
+ scope: {roleGroups: '=', enabled: '=', roleGroupType: '='},
+ controller: [
+ '$scope', 'APIUtils', 'toastService', '$q',
+ function($scope, APIUtils, toastService, $q) {
+ $scope.privileges = [];
+ $scope.loading = true;
+ $scope.newGroup = {};
+ $scope.selectedGroupIndex = '';
+ $scope.editGroup = false;
+ $scope.removeGroup = false;
+ $scope.removeMultipleGroups = false;
+ $scope.all = false;
+ $scope.sortPropertyName = 'id';
+ $scope.reverse = false;
+ $scope.addGroup = false;
+ $scope.hasSelectedGroup = false;
+
+ APIUtils.getAccountServiceRoles()
+ .then(
+ (data) => {
+ $scope.privileges = data;
+ },
+ (error) => {
+ console.log(JSON.stringify(error));
+ })
+ .finally(() => {
+ $scope.loading = false;
+ });
+
+ $scope.addGroupFn = () => {
+ $scope.addGroup = true;
+ };
+
+ $scope.addRoleGroup = () => {
+ const newGroup = {};
+ newGroup.RemoteGroup = $scope.newGroup.RemoteGroup;
+ newGroup.LocalRole = $scope.newGroup.LocalRole;
+
+ $scope.loading = true;
+ const data = {};
+
+ if ($scope.roleGroupType == 'ldap') {
+ data.LDAP = {};
+ data.LDAP.RemoteRoleMapping = $scope.roleGroups;
+ data.LDAP.RemoteRoleMapping.push(newGroup);
+ } else {
+ data.ActiveDirectory = {};
+ data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
+ data.ActiveDirectory.RemoteRoleMapping.push(newGroup);
+ }
+
+ APIUtils.saveLdapProperties(data)
+ .then(
+ (response) => {
+ toastService.success(
+ 'Group has been created successfully.');
+ },
+ (error) => {
+ toastService.error('Failed to create new group.');
+ })
+ .finally(() => {
+ $scope.loading = false;
+ });
+ };
+
+ $scope.editGroupFn = (group, role, index) => {
+ $scope.editGroup = true;
+ $scope.selectedGroupIndex = index;
+ $scope.newGroup.RemoteGroup = group;
+ $scope.newGroup.LocalRole = role;
+ };
+
+ $scope.editRoleGroup = () => {
+ $scope.loading = true;
+ const data = {};
+
+ if ($scope.roleGroupType == 'ldap') {
+ data.LDAP = {};
+ data.LDAP.RemoteRoleMapping = $scope.roleGroups;
+ data.LDAP.RemoteRoleMapping[$scope.selectedGroupIndex]
+ .LocalRole = $scope.newGroup.LocalRole;
+ } else {
+ data.ActiveDirectory = {};
+ data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
+ data.ActiveDirectory
+ .RemoteRoleMapping[$scope.selectedGroupIndex]
+ .LocalRole = $scope.newGroup.LocalRole;
+ }
+
+ APIUtils.saveLdapProperties(data)
+ .then(
+ (response) => {
+ toastService.success(
+ 'Group has been edited successfully.');
+ },
+ (error) => {
+ toastService.error('Failed to edit group.');
+ })
+ .finally(() => {
+ $scope.loading = false;
+ });
+ $scope.editGroup = false;
+ };
+
+ $scope.removeGroupFn = (index) => {
+ $scope.removeGroup = true;
+ $scope.selectedGroupIndex = index;
+ };
+
+ $scope.removeRoleGroup = () => {
+ $scope.loading = true;
+ const data = {};
+
+ if ($scope.roleGroupType == 'ldap') {
+ data.LDAP = {};
+ data.LDAP.RemoteRoleMapping = $scope.roleGroups;
+ data.LDAP.RemoteRoleMapping[$scope.selectedGroupIndex] =
+ $scope.newGroup;
+ } else {
+ data.ActiveDirectory = {};
+ data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
+ data.ActiveDirectory
+ .RemoteRoleMapping[$scope.selectedGroupIndex] =
+ $scope.newGroup;
+ }
+
+ $scope.roleGroups[$scope.selectedGroupIndex] = null;
+
+ APIUtils.saveLdapProperties(data)
+ .then(
+ (response) => {
+ toastService.success(
+ 'Group has been removed successfully.');
+ },
+ (error) => {
+ toastService.error('Failed to remove group.');
+ })
+ .finally(() => {
+ $scope.loading = false;
+ $scope.$parent.loadLdap();
+ });
+ $scope.removeGroup = false;
+ };
+
+ $scope.removeMultipleRoleGroupsFn = () => {
+ $scope.removeMultipleGroups = true;
+ };
+
+ $scope.roleGroupIsSelectedChanged = () => {
+ let groupSelected = false;
+ $scope.roleGroups.forEach(group => {
+ if (group['isSelected']) {
+ groupSelected = true;
+ }
+ });
+ $scope.hasSelectedGroup = groupSelected;
+ };
+
+ $scope.removeMultipleRoleGroups = () => {
+ $scope.loading = true;
+ const data = {};
+
+ if ($scope.roleGroupType == 'ldap') {
+ data.LDAP = {};
+ data.LDAP.RemoteRoleMapping = $scope.roleGroups.map((group) => {
+ if (group['isSelected']) {
+ return null;
+ } else {
+ return group;
+ }
+ });
+ } else {
+ data.ActiveDirectory = {};
+ data.ActiveDirectory.RemoteRoleMapping =
+ $scope.roleGroups.map((group) => {
+ if (group['isSelected']) {
+ return null;
+ } else {
+ return group;
+ }
+ });
+ }
+
+ APIUtils.saveLdapProperties(data)
+ .then(
+ (response) => {
+ toastService.success(
+ 'Groups has been removed successfully.');
+ },
+ (error) => {
+ toastService.error('Failed to remove groups.');
+ })
+ .finally(() => {
+ $scope.loading = false;
+ $scope.$parent.loadLdap();
+ });
+ $scope.removeMultipleGroups = false;
+ };
+
+ $scope.toggleAll = () => {
+ let toggleStatus = !$scope.all;
+ $scope.roleGroups.forEach((group) => {
+ group.isSelected = toggleStatus;
+ });
+ };
+
+ $scope.optionToggled = () => {
+ $scope.all = $scope.roleGroups.every((group) => {
+ return group.isSelected;
+ });
+ };
+
+ $scope.sortBy = (propertyName, isReverse) => {
+ $scope.reverse = isReverse;
+ $scope.sortPropertyName = propertyName;
+ };
+ }
+ ]
+ };
+ }
+ ]);
+})(window.angular);
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 51da8bb..2b3cac9 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -604,6 +604,14 @@ window.angular && (function(angular) {
});
},
+ saveLdapProperties: function(properties) {
+ return $http({
+ method: 'PATCH',
+ url: DataService.getHost() + '/redfish/v1/AccountService',
+ withCredentials: true,
+ data: properties
+ });
+ },
createUser: function(user, passwd, role, enabled) {
var data = {};
data['UserName'] = user;
diff --git a/app/common/styles/components/form-elements.scss b/app/common/styles/components/form-elements.scss
index 61ca4d3..8ee6e66 100644
--- a/app/common/styles/components/form-elements.scss
+++ b/app/common/styles/components/form-elements.scss
@@ -78,7 +78,6 @@
// Checkbox
-
.control-check,
.control-radio {
position: relative;
@@ -106,6 +105,12 @@
font-size: 0;
}
+.control__label {
+ display: inline-block;
+ margin-left: 26px;
+ user-select: none;
+}
+
/* Hover and focus states */
.control-check:hover input ~ .control__indicator,
.control-check input:focus ~ .control__indicator {
OpenPOWER on IntegriCloud