blob: 3d63d6923bcf52ba03c11a34d957979e880bce76 [file] [log] [blame]
Iftekharul Islamcd789502017-04-19 14:37:55 -05001/**
2 * Controller for user Accounts
3 *
4 * @module app/users
5 * @exports userAccountsController
6 * @name userAccountsController
Iftekharul Islamcd789502017-04-19 14:37:55 -05007 */
8
Andrew Geisslerba5e3f32018-05-24 10:58:00 -07009window.angular && (function(angular) {
10 'use strict';
Iftekharul Islamcd789502017-04-19 14:37:55 -050011
Andrew Geisslerd27bb132018-05-24 11:07:27 -070012 angular.module('app.users').controller('userAccountsController', [
Yoshie Muranakafa562732019-07-17 11:23:15 -050013 '$scope', 'APIUtils', 'toastService', '$uibModal',
14 function($scope, APIUtils, toastService, $uibModal) {
15 $scope.loading;
16 $scope.accountSettings;
17 $scope.userRoles;
18 $scope.localUsers;
Gunnar Mills08744f82018-03-19 16:24:41 -050019
Yoshie Muranakafa562732019-07-17 11:23:15 -050020 $scope.tableModel = {};
21 $scope.tableModel.data = [];
22 $scope.tableModel.header = ['Username', 'Privilege', 'Account status']
23 $scope.tableModel.actions = ['Edit', 'Delete'];
24
25 /**
26 * Data table mapper
27 * @param {*} user
28 */
29 function mapTableData(user) {
30 let accountStatus =
31 user.Locked ? 'Locked' : user.Enabled ? 'Enabled' : 'Disabled';
32 user.uiData = [user.UserName, user.RoleId, accountStatus];
33 return user;
34 }
35
36 /**
Yoshie Muranakab4d9c092019-08-01 16:19:40 -050037 * Returns lockout method based on the lockout duration property
38 * If the lockoutDuration is greater than 0 the lockout method
39 * is automatic otherwise the lockout method is manual
40 * @param {number} lockoutDuration
41 * @returns {number} : returns the account lockout method
42 * 1(automatic) / 0(manual)
43 */
44 function mapLockoutMethod(lockoutDuration) {
45 return lockoutDuration > 0 ? 1 : 0;
46 }
47
48 /**
Yoshie Muranakafa562732019-07-17 11:23:15 -050049 * API call to get all user accounts
50 */
51 function getLocalUsers() {
AppaRao Puli28711a62018-10-17 16:07:55 +053052 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -050053 APIUtils.getAllUserAccounts()
54 .then((users) => {
55 $scope.localUsers = users;
56 $scope.tableModel.data = users.map(mapTableData);
57 })
58 .catch((error) => {
59 console.log(JSON.stringify(error));
60 toastService.error('Failed to load users.');
61 })
62 .finally(() => {
63 $scope.loading = false;
64 })
65 }
AppaRao Pulia83cd052019-01-07 23:25:43 +053066
Yoshie Muranakafa562732019-07-17 11:23:15 -050067 /**
68 * API call to get current Account settings
69 */
70 function getAccountSettings() {
71 APIUtils.getAllUserAccountProperties()
72 .then((settings) => {
73 $scope.accountSettings = settings;
74 })
75 .catch((error) => {
76 console.log(JSON.stringify(error));
77 $scope.accountSettings = null;
78 })
79 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +053080
Yoshie Muranakafa562732019-07-17 11:23:15 -050081 /**
82 * API call to get local user roles
83 */
84 function getUserRoles() {
85 APIUtils.getAccountServiceRoles()
86 .then((roles) => {
87 $scope.userRoles = roles;
88 })
89 .catch((error) => {
90 console.log(JSON.stringify(error));
91 $scope.userRoles = null;
92 })
93 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +053094
Yoshie Muranakafa562732019-07-17 11:23:15 -050095 /**
96 * API call to create new user
97 * @param {*} user
98 */
99 function createUser(username, password, role, enabled) {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530100 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500101 APIUtils.createUser(username, password, role, enabled)
102 .then(() => {
103 getLocalUsers();
104 toastService.success(`User '${username}' has been created.`);
105 })
106 .catch((error) => {
107 console.log(JSON.stringify(error));
108 toastService.error(`Failed to create new user '${username}'.`);
109 })
110 .finally(() => {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530111 $scope.loading = false;
112 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500113 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530114
Yoshie Muranakafa562732019-07-17 11:23:15 -0500115 /**
116 * API call to update existing user
117 */
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500118 function updateUser(
119 originalUsername, username, password, role, enabled, locked) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530120 $scope.loading = true;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500121 APIUtils
122 .updateUser(
123 originalUsername, username, password, role, enabled, locked)
Yoshie Muranakafa562732019-07-17 11:23:15 -0500124 .then(() => {
125 getLocalUsers();
126 toastService.success('User has been updated successfully.')
127 })
128 .catch((error) => {
129 console.log(JSON.stringify(error));
130 toastService.error(`Unable to update user '${originalUsername}'.`)
131 })
132 .finally(() => {
133 $scope.loading = false;
134 })
135 }
136
137 /**
138 * API call to delete user
139 * @param {*} username
140 */
141 function deleteUser(username) {
142 $scope.loading = true;
143 APIUtils.deleteUser(username)
144 .then(() => {
145 getLocalUsers();
146 toastService.success(`User '${username}' has been deleted.`);
147 })
148 .catch((error) => {
149 console.log(JSON.stringify(error));
150 toastService.error(`Failed to delete user '${username}'.`);
151 })
152 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530153 $scope.loading = false;
Gunnar Millsb3d48d42018-05-25 08:34:35 -0500154 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500155 }
AppaRao Puli28711a62018-10-17 16:07:55 +0530156
Yoshie Muranakafa562732019-07-17 11:23:15 -0500157 /**
158 * API call to save account policy settings
159 * @param {number} lockoutDuration
160 * @param {number} lockoutThreshold
161 */
162 function updateAccountSettings(lockoutDuration, lockoutThreshold) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530163 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500164 APIUtils.saveUserAccountProperties(lockoutDuration, lockoutThreshold)
165 .then(() => {
166 $scope.accountSettings['AccountLockoutDuration'] =
167 lockoutDuration;
168 $scope.accountSettings['AccountLockoutThreshold'] =
169 lockoutThreshold;
170 toastService.success(
171 'Account policy settings have been updated.');
172 })
173 .catch((error) => {
174 console.log(JSON.stringify(error));
175 toastService.error('Failed to update account policy settings.');
176 })
177 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530178 $scope.loading = false;
179 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500180 }
AppaRao Pulicf7219c2018-12-27 16:17:46 +0530181
Yoshie Muranakafa562732019-07-17 11:23:15 -0500182 /**
183 * Initiate account settings modal
184 */
185 function initAccountSettingsModal() {
186 const template = require('./user-accounts-modal-settings.html');
187 $uibModal
188 .open({
189 template,
190 windowTopClass: 'uib-modal',
191 ariaLabelledBy: 'dialog_label',
192 controllerAs: 'modalCtrl',
193 controller: function() {
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500194 const lockoutMethod = mapLockoutMethod(
195 $scope.accountSettings.AccountLockoutDuration);
196
Yoshie Muranakafa562732019-07-17 11:23:15 -0500197 this.settings = {};
198 this.settings.maxLogin =
199 $scope.accountSettings.AccountLockoutThreshold;
200 this.settings.lockoutMethod = lockoutMethod;
201 this.settings.timeoutDuration = !lockoutMethod ?
202 null :
203 $scope.accountSettings.AccountLockoutDuration;
204 }
205 })
206 .result
207 .then((form) => {
208 if (form.$valid) {
209 const lockoutDuration = form.lockoutMethod.$modelValue ?
210 form.timeoutDuration.$modelValue :
211 0;
212 const lockoutThreshold = form.maxLogin.$modelValue;
213 updateAccountSettings(lockoutDuration, lockoutThreshold);
214 }
215 })
216 .catch(
217 () => {
218 // do nothing
219 })
220 }
221
222 /**
223 * Initiate user modal
224 * Can be triggered by clicking edit in table or 'Add user' button
225 * If triggered from the table, user parameter will be provided
226 * If triggered by add user button, user parameter will be undefined
227 * @optional @param {*} user
228 */
229 function initUserModal(user) {
230 if ($scope.userRoles === null || $scope.userRoles === undefined) {
231 // If userRoles failed to load, do not allow add/edit
232 // functionality
233 return;
234 }
235 const newUser = user ? false : true;
236 const originalUsername = user ? angular.copy(user.UserName) : null;
237 const template = require('./user-accounts-modal-user.html');
238 $uibModal
239 .open({
240 template,
241 windowTopClass: 'uib-modal',
242 ariaLabelledBy: 'dialog_label',
243 controllerAs: 'modalCtrl',
244 controller: function() {
245 // Set default status to Enabled
246 const status = newUser ? true : user.Enabled;
247 // Check if UserName is root
248 // Some form controls will be disabled for root users:
249 // edit enabled status, edit username, edit role
250 const isRoot =
251 newUser ? false : user.UserName === 'root' ? true : false;
252 // Array of existing usernames (excluding current user instance)
253 const existingUsernames =
254 $scope.localUsers.reduce((acc, val) => {
255 if (user && (val.UserName === user.UserName)) {
256 return acc;
257 }
258 acc.push(val.UserName);
259 return acc;
260 }, []);
261
262 this.user = {};
263 this.user.isRoot = isRoot;
264 this.user.new = newUser;
265 this.user.accountStatus = status;
266 this.user.username = newUser ? '' : user.UserName;
267 this.user.privilege = newUser ? '' : user.RoleId;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500268 this.user.locked = newUser ? null : user.Locked;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500269
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500270 this.manualUnlockProperty = false;
271 this.automaticLockout = mapLockoutMethod(
272 $scope.accountSettings.AccountLockoutDuration);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500273 this.privilegeRoles = $scope.userRoles;
274 this.existingUsernames = existingUsernames;
275 this.minPasswordLength = $scope.accountSettings ?
276 $scope.accountSettings.MinPasswordLength :
277 null;
278 this.maxPasswordLength = $scope.accountSettings ?
279 $scope.accountSettings.MaxPasswordLength :
280 null;
281 }
282 })
283 .result
284 .then((form) => {
285 if (form.$valid) {
286 // If form control is pristine set property to null
287 // this will make sure only changed values are updated when
288 // modifying existing users
289 // API utils checks for null values
290 const username =
291 form.username.$pristine ? null : form.username.$modelValue;
292 const password =
293 form.password.$pristine ? null : form.password.$modelValue;
294 const role = form.privilege.$pristine ?
295 null :
296 form.privilege.$modelValue;
297 const enabled = (form.accountStatus.$pristine &&
298 form.accountStatus1.$pristine) ?
299 null :
300 form.accountStatus.$modelValue;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500301 const locked = (form.lock && form.lock.$dirty) ?
302 form.lock.$modelValue :
303 null;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500304
305 if (!newUser) {
306 updateUser(
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500307 originalUsername, username, password, role, enabled,
308 locked);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500309 } else {
310 createUser(
311 username, password, role, form.accountStatus.$modelValue);
312 }
313 }
314 })
315 .catch(
316 () => {
317 // do nothing
318 })
319 }
320
321 /**
322 * Intiate remove user modal
323 * @param {*} user
324 */
325 function initRemoveModal(user) {
326 const template = require('./user-accounts-modal-remove.html');
327 $uibModal
328 .open({
329 template,
330 windowTopClass: 'uib-modal',
331 ariaLabelledBy: 'dialog_label',
332 controllerAs: 'modalCtrl',
333 controller: function() {
334 this.user = user.UserName;
335 }
336 })
337 .result
338 .then(() => {
339 const isRoot = user.UserName === 'root' ? true : false;
340 if (isRoot) {
341 toastService.error(`Cannot delete 'root' user.`)
342 return;
343 }
344 deleteUser(user.UserName);
345 })
346 .catch(
347 () => {
348 // do nothing
349 })
350 }
351
352 /**
353 * Callback when action emitted from table
354 * @param {*} value
355 */
356 $scope.onEmitAction = (value) => {
357 switch (value.action) {
358 case 'Edit':
359 initUserModal(value.row);
360 break;
361 case 'Delete':
362 initRemoveModal(value.row);
363 break;
364 default:
beccabroeka5deeea2019-03-22 15:38:49 -0500365 }
366 };
Yoshie Muranakafa562732019-07-17 11:23:15 -0500367
368 /**
369 * Callback when 'Account settings policy' button clicked
370 */
371 $scope.onClickAccountSettingsPolicy = () => {
372 initAccountSettingsModal();
373 };
374
375 /**
376 * Callback when 'Add user' button clicked
377 */
378 $scope.onClickAddUser = () => {
379 initUserModal();
380 };
381
382 /**
383 * Callback when controller view initially loaded
384 */
385 $scope.$on('$viewContentLoaded', () => {
386 getLocalUsers();
387 getUserRoles();
388 getAccountSettings();
389 })
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700390 }
391 ]);
Iftekharul Islamcd789502017-04-19 14:37:55 -0500392})(angular);