WebUI: User management full implementation.
Added webui user accounts management. This support
both redfish and rest based backend API calls
depending on redfishSupportEnabled flag.
It does following actions:
- View all user list and there properties like
name, privilege, enabled state, Locked etc..
- Create new user account.
- Delete existing user account.
- Update the existing user properties like
password, privilege, enabled state.
Unit Test:
- Viewed all user information is proper or not.
- Created new user and validated.
- Deleted specific user and checked.
- Modified user info and validated the change.
All tests are done by enabling and disabling
redfishSupportEnabled flag using conifg.json.
Change-Id: Ifecf63844dc42c44771509958bf75947a92997ac
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
index 877f030..2f3ded7 100644
--- a/app/common/directives/app-navigation.html
+++ b/app/common/directives/app-navigation.html
@@ -98,6 +98,6 @@
</ul>
<ul class="nav__second-level btn-users" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'users')}">
<li ng-class="{'active': (path == '/users' || path == '/users/manage-accounts')}">
- <a href="#/users/manage-accounts" tabindex="18" ng-click="closeSubnav()">Manage user account</a></li>
+ <a href="#/users/manage-accounts" tabindex="18" ng-click="closeSubnav()">Manage user accounts</a></li>
</ul>
</nav>
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 31a2958..beb63ba 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -475,19 +475,6 @@
console.log(error);
});
},
- testPassword: function(username, password) {
- // Calls /login without the current session to verify the given
- // password is correct ignore the interceptor logout on a bad password
- return $http({
- method: 'POST',
- url: DataService.getHost() + '/login',
- withCredentials: false,
- data: JSON.stringify({'data': [username, password]})
- })
- .then(function(response) {
- return response.data;
- });
- },
logout: function(callback) {
$http({
method: 'POST',
@@ -509,7 +496,7 @@
});
},
changePassword: function(user, newPassword) {
- if (DataService.configJson.redfishSupportEnabled) {
+ if (DataService.configJson.redfishSupportEnabled == true) {
return $http({
method: 'PATCH',
url: DataService.getHost() +
@@ -539,6 +526,272 @@
return deferred.promise;
}
},
+ getAllUserAccounts: function(members) {
+ var deferred = $q.defer();
+ var promises = [];
+ var users = [];
+
+ if (DataService.configJson.redfishSupportEnabled == true) {
+ $http({
+ method: 'GET',
+ url:
+ DataService.getHost() + '/redfish/v1/AccountService/Accounts',
+ withCredentials: true
+ })
+ .then(
+ function(response) {
+ var members = response.data['Members'];
+ angular.forEach(members, function(member) {
+ promises.push(
+ $http({
+ method: 'GET',
+ url: DataService.getHost() + member['@odata.id'],
+ withCredentials: true
+ }).then(function(res) {
+ return res.data;
+ }));
+ });
+
+ $q.all(promises).then(
+ function(results) {
+ deferred.resolve(results);
+ },
+ function(errors) {
+ deferred.reject(errors);
+ });
+ },
+ function(error) {
+ console.log(error);
+ deferred.reject(error);
+ });
+ } else {
+ $http({
+ method: 'GET',
+ url:
+ DataService.getHost() + '/xyz/openbmc_project/user/enumerate',
+ withCredentials: true
+ })
+ .then(
+ function(response) {
+ var json = JSON.stringify(response.data);
+ var content = JSON.parse(json);
+
+ function convertPrivToRoleId(priv) {
+ if (priv == 'priv-admin') {
+ return 'Administrator';
+ } else if (priv == 'priv-user') {
+ return 'User';
+ } else if (priv == 'priv-operator') {
+ return 'Operator';
+ } else if (priv == 'priv-callback') {
+ return 'Callback';
+ }
+ return '';
+ }
+
+ for (var key in content.data) {
+ var username = key.split('/').pop();
+ if (content.data.hasOwnProperty(key) &&
+ content.data[key].hasOwnProperty('UserPrivilege')) {
+ var val = content.data[key];
+ users.push(Object.assign({
+ Id: username,
+ UserName: username,
+ Locked: val['UserLockedForFailedAttempt'],
+ RoleId: convertPrivToRoleId(val['UserPrivilege']),
+ Enabled: val['UserEnabled'],
+ Password: null
+ }));
+ }
+ }
+ deferred.resolve(users);
+ },
+ function(error) {
+ console.log(error);
+ deferred.reject(error);
+ });
+ }
+ return deferred.promise;
+ },
+ createUser: function(user, passwd, role, enabled) {
+ if (DataService.configJson.redfishSupportEnabled == true) {
+ var data = {};
+ data['UserName'] = user;
+ data['Password'] = passwd;
+ data['RoleId'] = role;
+ data['Enabled'] = enabled;
+
+ return $http({
+ method: 'POST',
+ url:
+ DataService.getHost() + '/redfish/v1/AccountService/Accounts',
+ withCredentials: true,
+ data: data
+ });
+ } else {
+ function convertRoleIdToPriv(roleId) {
+ if (roleId == 'Administrator') {
+ return 'priv-admin';
+ } else if (roleId == 'User') {
+ return 'priv-user';
+ } else if (roleId == 'Operator') {
+ return 'priv-operator';
+ } else if (roleId == 'Callback') {
+ return 'priv-callback';
+ }
+ return '';
+ }
+ function setUserPassword(user, passwd) {
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/user/' + user +
+ '/action/SetPassword',
+ withCredentials: true,
+ data: JSON.stringify({'data': [passwd]}),
+ responseType: 'arraybuffer'
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ }
+ var priv = convertRoleIdToPriv(role);
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/user/action/CreateUser',
+ withCredentials: true,
+ data: JSON.stringify({
+ 'data':
+ [user, ['web', 'redfish', 'ssh'], priv, enabled]
+ }),
+ responseType: 'arraybuffer'
+ })
+ .then(function(response) {
+ return setUserPassword(user, passwd);
+ });
+ }
+ },
+ updateUser: function(user, newUser, passwd, role, enabled) {
+ if (DataService.configJson.redfishSupportEnabled == true) {
+ var data = {};
+ if ((newUser !== undefined) && (newUser != null)) {
+ data['UserName'] = newUser;
+ }
+ if ((role !== undefined) && (role != null)) {
+ data['RoleId'] = role;
+ }
+ if ((enabled !== undefined) && (enabled != null)) {
+ data['Enabled'] = enabled;
+ }
+ if ((passwd !== undefined) && (passwd != null)) {
+ data['Password'] = passwd;
+ }
+ return $http({
+ method: 'PATCH',
+ url: DataService.getHost() +
+ '/redfish/v1/AccountService/Accounts/' + user,
+ withCredentials: true,
+ data: data
+ });
+ } else {
+ var deferred = $q.defer();
+ var promises = [];
+ function convertRoleIdToPriv(roleId) {
+ if (roleId == 'Administrator') {
+ return 'priv-admin';
+ } else if (roleId == 'User') {
+ return 'priv-user';
+ } else if (roleId == 'Operator') {
+ return 'priv-operator';
+ } else if (roleId == 'Callback') {
+ return 'priv-callback';
+ }
+ return '';
+ }
+ function setUserProperty(user, propKey, propVal) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/user/' + user + '/attr/' +
+ propKey,
+ withCredentials: true,
+ data: JSON.stringify({'data': propVal})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ }
+ function setUserPassword(user, passwd) {
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/user/' + user +
+ '/action/SetPassword',
+ withCredentials: true,
+ data: JSON.stringify({'data': [passwd]}),
+ responseType: 'arraybuffer'
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ }
+ function renameUser(user, newUser) {
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/user/action/RenameUser',
+ withCredentials: true,
+ data: JSON.stringify({'data': [user, newUser]})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ }
+ if ((role !== undefined) && (role != null)) {
+ var priv = convertRoleIdToPriv(role);
+ promises.push(setUserProperty(user, 'UserPrivilege', priv));
+ }
+ if ((enabled !== undefined) && (enabled != null)) {
+ promises.push(setUserProperty(user, 'UserEnabled', enabled));
+ }
+ if ((passwd !== undefined) && (passwd != null)) {
+ promises.push(setUserPassword(user, passwd));
+ }
+ if ((newUser !== undefined) && (newUser != null)) {
+ promises.push(renameUser(user, newUser));
+ }
+ $q.all(promises).then(
+ function(results) {
+ deferred.resolve(results);
+ },
+ function(errors) {
+ deferred.reject(errors);
+ });
+ return deferred.promise;
+ }
+ },
+ deleteUser: function(user) {
+ if (DataService.configJson.redfishSupportEnabled == true) {
+ return $http({
+ method: 'DELETE',
+ url: DataService.getHost() +
+ '/redfish/v1/AccountService/Accounts/' + user,
+ withCredentials: true,
+ });
+ } else {
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() + '/xyz/openbmc_project/user/' +
+ user + '/action/Delete',
+ withCredentials: true,
+ data: JSON.stringify({'data': []})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ }
+ },
chassisPowerOff: function() {
var deferred = $q.defer();
$http({
@@ -1028,7 +1281,8 @@
var activationStatus = '';
// If the image is "Functional" use that for the
- // activation status, else use the value of "Activation"
+ // activation status, else use the value of
+ // "Activation"
// github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
if (content.data[key].Activation) {
activationStatus =