blob: b5ed1a5fedfc782bc6f8dcb1c6c80ed7eb85b617 [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 = [];
Yoshie Muranakabb688792019-08-12 09:31:52 -050022 $scope.tableModel.header = ['Username', 'Privilege', 'Account status'];
Yoshie Muranakafa562732019-07-17 11:23:15 -050023
24 /**
25 * Data table mapper
26 * @param {*} user
Yoshie Muranakabb688792019-08-12 09:31:52 -050027 * @returns user
Yoshie Muranakafa562732019-07-17 11:23:15 -050028 */
29 function mapTableData(user) {
Yoshie Muranakabb688792019-08-12 09:31:52 -050030 const accountStatus =
Yoshie Muranakafa562732019-07-17 11:23:15 -050031 user.Locked ? 'Locked' : user.Enabled ? 'Enabled' : 'Disabled';
Yoshie Muranakabb688792019-08-12 09:31:52 -050032 const editAction = {type: 'Edit', enabled: true, file: 'icon-edit.svg'};
33 const deleteAction = {
34 type: 'Delete',
35 enabled: user.UserName === 'root' ? false : true,
36 file: 'icon-trashcan.svg'
37 };
38
39 user.actions = [editAction, deleteAction];
Yoshie Muranakafa562732019-07-17 11:23:15 -050040 user.uiData = [user.UserName, user.RoleId, accountStatus];
41 return user;
42 }
43
44 /**
Yoshie Muranakab4d9c092019-08-01 16:19:40 -050045 * Returns lockout method based on the lockout duration property
46 * If the lockoutDuration is greater than 0 the lockout method
47 * is automatic otherwise the lockout method is manual
48 * @param {number} lockoutDuration
49 * @returns {number} : returns the account lockout method
50 * 1(automatic) / 0(manual)
51 */
52 function mapLockoutMethod(lockoutDuration) {
53 return lockoutDuration > 0 ? 1 : 0;
54 }
55
56 /**
Yoshie Muranakafa562732019-07-17 11:23:15 -050057 * API call to get all user accounts
58 */
59 function getLocalUsers() {
AppaRao Puli28711a62018-10-17 16:07:55 +053060 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -050061 APIUtils.getAllUserAccounts()
62 .then((users) => {
63 $scope.localUsers = users;
64 $scope.tableModel.data = users.map(mapTableData);
65 })
66 .catch((error) => {
67 console.log(JSON.stringify(error));
68 toastService.error('Failed to load users.');
69 })
70 .finally(() => {
71 $scope.loading = false;
72 })
73 }
AppaRao Pulia83cd052019-01-07 23:25:43 +053074
Yoshie Muranakafa562732019-07-17 11:23:15 -050075 /**
76 * API call to get current Account settings
77 */
78 function getAccountSettings() {
79 APIUtils.getAllUserAccountProperties()
80 .then((settings) => {
81 $scope.accountSettings = settings;
82 })
83 .catch((error) => {
84 console.log(JSON.stringify(error));
85 $scope.accountSettings = null;
86 })
87 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +053088
Yoshie Muranakafa562732019-07-17 11:23:15 -050089 /**
90 * API call to get local user roles
91 */
92 function getUserRoles() {
93 APIUtils.getAccountServiceRoles()
94 .then((roles) => {
95 $scope.userRoles = roles;
96 })
97 .catch((error) => {
98 console.log(JSON.stringify(error));
99 $scope.userRoles = null;
100 })
101 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530102
Yoshie Muranakafa562732019-07-17 11:23:15 -0500103 /**
104 * API call to create new user
105 * @param {*} user
106 */
107 function createUser(username, password, role, enabled) {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530108 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500109 APIUtils.createUser(username, password, role, enabled)
110 .then(() => {
111 getLocalUsers();
112 toastService.success(`User '${username}' has been created.`);
113 })
114 .catch((error) => {
115 console.log(JSON.stringify(error));
116 toastService.error(`Failed to create new user '${username}'.`);
117 })
118 .finally(() => {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530119 $scope.loading = false;
120 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500121 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530122
Yoshie Muranakafa562732019-07-17 11:23:15 -0500123 /**
124 * API call to update existing user
125 */
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500126 function updateUser(
127 originalUsername, username, password, role, enabled, locked) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530128 $scope.loading = true;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500129 APIUtils
130 .updateUser(
131 originalUsername, username, password, role, enabled, locked)
Yoshie Muranakafa562732019-07-17 11:23:15 -0500132 .then(() => {
133 getLocalUsers();
134 toastService.success('User has been updated successfully.')
135 })
136 .catch((error) => {
137 console.log(JSON.stringify(error));
138 toastService.error(`Unable to update user '${originalUsername}'.`)
139 })
140 .finally(() => {
141 $scope.loading = false;
142 })
143 }
144
145 /**
146 * API call to delete user
147 * @param {*} username
148 */
149 function deleteUser(username) {
150 $scope.loading = true;
151 APIUtils.deleteUser(username)
152 .then(() => {
153 getLocalUsers();
154 toastService.success(`User '${username}' has been deleted.`);
155 })
156 .catch((error) => {
157 console.log(JSON.stringify(error));
158 toastService.error(`Failed to delete user '${username}'.`);
159 })
160 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530161 $scope.loading = false;
Gunnar Millsb3d48d42018-05-25 08:34:35 -0500162 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500163 }
AppaRao Puli28711a62018-10-17 16:07:55 +0530164
Yoshie Muranakafa562732019-07-17 11:23:15 -0500165 /**
166 * API call to save account policy settings
167 * @param {number} lockoutDuration
168 * @param {number} lockoutThreshold
169 */
170 function updateAccountSettings(lockoutDuration, lockoutThreshold) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530171 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500172 APIUtils.saveUserAccountProperties(lockoutDuration, lockoutThreshold)
173 .then(() => {
174 $scope.accountSettings['AccountLockoutDuration'] =
175 lockoutDuration;
176 $scope.accountSettings['AccountLockoutThreshold'] =
177 lockoutThreshold;
178 toastService.success(
179 'Account policy settings have been updated.');
180 })
181 .catch((error) => {
182 console.log(JSON.stringify(error));
183 toastService.error('Failed to update account policy settings.');
184 })
185 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530186 $scope.loading = false;
187 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500188 }
AppaRao Pulicf7219c2018-12-27 16:17:46 +0530189
Yoshie Muranakafa562732019-07-17 11:23:15 -0500190 /**
191 * Initiate account settings modal
192 */
193 function initAccountSettingsModal() {
194 const template = require('./user-accounts-modal-settings.html');
195 $uibModal
196 .open({
197 template,
198 windowTopClass: 'uib-modal',
199 ariaLabelledBy: 'dialog_label',
200 controllerAs: 'modalCtrl',
201 controller: function() {
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500202 const lockoutMethod = mapLockoutMethod(
203 $scope.accountSettings.AccountLockoutDuration);
204
Yoshie Muranakafa562732019-07-17 11:23:15 -0500205 this.settings = {};
206 this.settings.maxLogin =
207 $scope.accountSettings.AccountLockoutThreshold;
208 this.settings.lockoutMethod = lockoutMethod;
209 this.settings.timeoutDuration = !lockoutMethod ?
210 null :
211 $scope.accountSettings.AccountLockoutDuration;
212 }
213 })
214 .result
215 .then((form) => {
216 if (form.$valid) {
217 const lockoutDuration = form.lockoutMethod.$modelValue ?
218 form.timeoutDuration.$modelValue :
219 0;
220 const lockoutThreshold = form.maxLogin.$modelValue;
221 updateAccountSettings(lockoutDuration, lockoutThreshold);
222 }
223 })
224 .catch(
225 () => {
226 // do nothing
227 })
228 }
229
230 /**
231 * Initiate user modal
232 * Can be triggered by clicking edit in table or 'Add user' button
233 * If triggered from the table, user parameter will be provided
234 * If triggered by add user button, user parameter will be undefined
235 * @optional @param {*} user
236 */
237 function initUserModal(user) {
238 if ($scope.userRoles === null || $scope.userRoles === undefined) {
239 // If userRoles failed to load, do not allow add/edit
240 // functionality
241 return;
242 }
243 const newUser = user ? false : true;
244 const originalUsername = user ? angular.copy(user.UserName) : null;
245 const template = require('./user-accounts-modal-user.html');
246 $uibModal
247 .open({
248 template,
249 windowTopClass: 'uib-modal',
250 ariaLabelledBy: 'dialog_label',
251 controllerAs: 'modalCtrl',
252 controller: function() {
253 // Set default status to Enabled
254 const status = newUser ? true : user.Enabled;
255 // Check if UserName is root
256 // Some form controls will be disabled for root users:
257 // edit enabled status, edit username, edit role
258 const isRoot =
259 newUser ? false : user.UserName === 'root' ? true : false;
260 // Array of existing usernames (excluding current user instance)
261 const existingUsernames =
262 $scope.localUsers.reduce((acc, val) => {
263 if (user && (val.UserName === user.UserName)) {
264 return acc;
265 }
266 acc.push(val.UserName);
267 return acc;
268 }, []);
269
270 this.user = {};
271 this.user.isRoot = isRoot;
272 this.user.new = newUser;
273 this.user.accountStatus = status;
274 this.user.username = newUser ? '' : user.UserName;
275 this.user.privilege = newUser ? '' : user.RoleId;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500276 this.user.locked = newUser ? null : user.Locked;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500277
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500278 this.manualUnlockProperty = false;
279 this.automaticLockout = mapLockoutMethod(
280 $scope.accountSettings.AccountLockoutDuration);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500281 this.privilegeRoles = $scope.userRoles;
282 this.existingUsernames = existingUsernames;
283 this.minPasswordLength = $scope.accountSettings ?
284 $scope.accountSettings.MinPasswordLength :
285 null;
286 this.maxPasswordLength = $scope.accountSettings ?
287 $scope.accountSettings.MaxPasswordLength :
288 null;
289 }
290 })
291 .result
292 .then((form) => {
293 if (form.$valid) {
294 // If form control is pristine set property to null
295 // this will make sure only changed values are updated when
296 // modifying existing users
297 // API utils checks for null values
298 const username =
299 form.username.$pristine ? null : form.username.$modelValue;
300 const password =
301 form.password.$pristine ? null : form.password.$modelValue;
302 const role = form.privilege.$pristine ?
303 null :
304 form.privilege.$modelValue;
305 const enabled = (form.accountStatus.$pristine &&
306 form.accountStatus1.$pristine) ?
307 null :
308 form.accountStatus.$modelValue;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500309 const locked = (form.lock && form.lock.$dirty) ?
310 form.lock.$modelValue :
311 null;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500312
313 if (!newUser) {
314 updateUser(
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500315 originalUsername, username, password, role, enabled,
316 locked);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500317 } else {
318 createUser(
319 username, password, role, form.accountStatus.$modelValue);
320 }
321 }
322 })
323 .catch(
324 () => {
325 // do nothing
326 })
327 }
328
329 /**
330 * Intiate remove user modal
331 * @param {*} user
332 */
333 function initRemoveModal(user) {
334 const template = require('./user-accounts-modal-remove.html');
335 $uibModal
336 .open({
337 template,
338 windowTopClass: 'uib-modal',
339 ariaLabelledBy: 'dialog_label',
340 controllerAs: 'modalCtrl',
341 controller: function() {
342 this.user = user.UserName;
343 }
344 })
345 .result
346 .then(() => {
347 const isRoot = user.UserName === 'root' ? true : false;
348 if (isRoot) {
349 toastService.error(`Cannot delete 'root' user.`)
350 return;
351 }
352 deleteUser(user.UserName);
353 })
354 .catch(
355 () => {
356 // do nothing
357 })
358 }
359
360 /**
361 * Callback when action emitted from table
362 * @param {*} value
363 */
364 $scope.onEmitAction = (value) => {
365 switch (value.action) {
366 case 'Edit':
367 initUserModal(value.row);
368 break;
369 case 'Delete':
370 initRemoveModal(value.row);
371 break;
372 default:
beccabroeka5deeea2019-03-22 15:38:49 -0500373 }
374 };
Yoshie Muranakafa562732019-07-17 11:23:15 -0500375
376 /**
377 * Callback when 'Account settings policy' button clicked
378 */
379 $scope.onClickAccountSettingsPolicy = () => {
380 initAccountSettingsModal();
381 };
382
383 /**
384 * Callback when 'Add user' button clicked
385 */
386 $scope.onClickAddUser = () => {
387 initUserModal();
388 };
389
390 /**
391 * Callback when controller view initially loaded
392 */
393 $scope.$on('$viewContentLoaded', () => {
394 getLocalUsers();
395 getUserRoles();
396 getAccountSettings();
397 })
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700398 }
399 ]);
Iftekharul Islamcd789502017-04-19 14:37:55 -0500400})(angular);