blob: 9f31bebf217da30f745221c10ef3c917810b2d92 [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 Muranakab1f64242019-09-04 11:40:51 -070020 $scope.tableData = [];
21 $scope.tableHeader = [
22 {label: 'Username'}, {label: 'Privilege'}, {label: 'Account status'}
23 ];
Yoshie Muranakafa562732019-07-17 11:23:15 -050024
25 /**
26 * Data table mapper
27 * @param {*} user
Yoshie Muranakabb688792019-08-12 09:31:52 -050028 * @returns user
Yoshie Muranakafa562732019-07-17 11:23:15 -050029 */
30 function mapTableData(user) {
Yoshie Muranakabb688792019-08-12 09:31:52 -050031 const accountStatus =
Yoshie Muranakafa562732019-07-17 11:23:15 -050032 user.Locked ? 'Locked' : user.Enabled ? 'Enabled' : 'Disabled';
Yoshie Muranakabb688792019-08-12 09:31:52 -050033 const editAction = {type: 'Edit', enabled: true, file: 'icon-edit.svg'};
34 const deleteAction = {
35 type: 'Delete',
36 enabled: user.UserName === 'root' ? false : true,
37 file: 'icon-trashcan.svg'
38 };
39
40 user.actions = [editAction, deleteAction];
Yoshie Muranakafa562732019-07-17 11:23:15 -050041 user.uiData = [user.UserName, user.RoleId, accountStatus];
42 return user;
43 }
44
45 /**
Yoshie Muranakab4d9c092019-08-01 16:19:40 -050046 * Returns lockout method based on the lockout duration property
47 * If the lockoutDuration is greater than 0 the lockout method
48 * is automatic otherwise the lockout method is manual
49 * @param {number} lockoutDuration
50 * @returns {number} : returns the account lockout method
51 * 1(automatic) / 0(manual)
52 */
53 function mapLockoutMethod(lockoutDuration) {
54 return lockoutDuration > 0 ? 1 : 0;
55 }
56
57 /**
Yoshie Muranakafa562732019-07-17 11:23:15 -050058 * API call to get all user accounts
59 */
60 function getLocalUsers() {
AppaRao Puli28711a62018-10-17 16:07:55 +053061 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -050062 APIUtils.getAllUserAccounts()
63 .then((users) => {
64 $scope.localUsers = users;
Yoshie Muranakab1f64242019-09-04 11:40:51 -070065 $scope.tableData = users.map(mapTableData);
Yoshie Muranakafa562732019-07-17 11:23:15 -050066 })
67 .catch((error) => {
68 console.log(JSON.stringify(error));
69 toastService.error('Failed to load users.');
70 })
71 .finally(() => {
72 $scope.loading = false;
73 })
74 }
AppaRao Pulia83cd052019-01-07 23:25:43 +053075
Yoshie Muranakafa562732019-07-17 11:23:15 -050076 /**
77 * API call to get current Account settings
78 */
79 function getAccountSettings() {
80 APIUtils.getAllUserAccountProperties()
81 .then((settings) => {
82 $scope.accountSettings = settings;
83 })
84 .catch((error) => {
85 console.log(JSON.stringify(error));
86 $scope.accountSettings = null;
87 })
88 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +053089
Yoshie Muranakafa562732019-07-17 11:23:15 -050090 /**
91 * API call to get local user roles
92 */
93 function getUserRoles() {
94 APIUtils.getAccountServiceRoles()
95 .then((roles) => {
96 $scope.userRoles = roles;
97 })
98 .catch((error) => {
99 console.log(JSON.stringify(error));
100 $scope.userRoles = null;
101 })
102 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530103
Yoshie Muranakafa562732019-07-17 11:23:15 -0500104 /**
105 * API call to create new user
106 * @param {*} user
107 */
108 function createUser(username, password, role, enabled) {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530109 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500110 APIUtils.createUser(username, password, role, enabled)
111 .then(() => {
112 getLocalUsers();
113 toastService.success(`User '${username}' has been created.`);
114 })
115 .catch((error) => {
116 console.log(JSON.stringify(error));
117 toastService.error(`Failed to create new user '${username}'.`);
118 })
119 .finally(() => {
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530120 $scope.loading = false;
121 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500122 }
AppaRao Pulib1e7c862019-03-12 14:56:40 +0530123
Yoshie Muranakafa562732019-07-17 11:23:15 -0500124 /**
125 * API call to update existing user
126 */
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500127 function updateUser(
128 originalUsername, username, password, role, enabled, locked) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530129 $scope.loading = true;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500130 APIUtils
131 .updateUser(
132 originalUsername, username, password, role, enabled, locked)
Yoshie Muranakafa562732019-07-17 11:23:15 -0500133 .then(() => {
134 getLocalUsers();
135 toastService.success('User has been updated successfully.')
136 })
137 .catch((error) => {
138 console.log(JSON.stringify(error));
139 toastService.error(`Unable to update user '${originalUsername}'.`)
140 })
141 .finally(() => {
142 $scope.loading = false;
143 })
144 }
145
146 /**
147 * API call to delete user
148 * @param {*} username
149 */
150 function deleteUser(username) {
151 $scope.loading = true;
152 APIUtils.deleteUser(username)
153 .then(() => {
154 getLocalUsers();
155 toastService.success(`User '${username}' has been deleted.`);
156 })
157 .catch((error) => {
158 console.log(JSON.stringify(error));
159 toastService.error(`Failed to delete user '${username}'.`);
160 })
161 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530162 $scope.loading = false;
Gunnar Millsb3d48d42018-05-25 08:34:35 -0500163 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500164 }
AppaRao Puli28711a62018-10-17 16:07:55 +0530165
Yoshie Muranakafa562732019-07-17 11:23:15 -0500166 /**
167 * API call to save account policy settings
168 * @param {number} lockoutDuration
169 * @param {number} lockoutThreshold
170 */
171 function updateAccountSettings(lockoutDuration, lockoutThreshold) {
AppaRao Puli28711a62018-10-17 16:07:55 +0530172 $scope.loading = true;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500173 APIUtils.saveUserAccountProperties(lockoutDuration, lockoutThreshold)
174 .then(() => {
175 $scope.accountSettings['AccountLockoutDuration'] =
176 lockoutDuration;
177 $scope.accountSettings['AccountLockoutThreshold'] =
178 lockoutThreshold;
179 toastService.success(
180 'Account policy settings have been updated.');
181 })
182 .catch((error) => {
183 console.log(JSON.stringify(error));
184 toastService.error('Failed to update account policy settings.');
185 })
186 .finally(() => {
AppaRao Puli28711a62018-10-17 16:07:55 +0530187 $scope.loading = false;
188 });
Yoshie Muranakafa562732019-07-17 11:23:15 -0500189 }
AppaRao Pulicf7219c2018-12-27 16:17:46 +0530190
Yoshie Muranakafa562732019-07-17 11:23:15 -0500191 /**
192 * Initiate account settings modal
193 */
194 function initAccountSettingsModal() {
195 const template = require('./user-accounts-modal-settings.html');
196 $uibModal
197 .open({
198 template,
199 windowTopClass: 'uib-modal',
200 ariaLabelledBy: 'dialog_label',
201 controllerAs: 'modalCtrl',
202 controller: function() {
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500203 const lockoutMethod = mapLockoutMethod(
204 $scope.accountSettings.AccountLockoutDuration);
205
Yoshie Muranakafa562732019-07-17 11:23:15 -0500206 this.settings = {};
207 this.settings.maxLogin =
208 $scope.accountSettings.AccountLockoutThreshold;
209 this.settings.lockoutMethod = lockoutMethod;
210 this.settings.timeoutDuration = !lockoutMethod ?
211 null :
212 $scope.accountSettings.AccountLockoutDuration;
213 }
214 })
215 .result
216 .then((form) => {
217 if (form.$valid) {
218 const lockoutDuration = form.lockoutMethod.$modelValue ?
219 form.timeoutDuration.$modelValue :
220 0;
221 const lockoutThreshold = form.maxLogin.$modelValue;
222 updateAccountSettings(lockoutDuration, lockoutThreshold);
223 }
224 })
225 .catch(
226 () => {
227 // do nothing
228 })
229 }
230
231 /**
232 * Initiate user modal
233 * Can be triggered by clicking edit in table or 'Add user' button
234 * If triggered from the table, user parameter will be provided
235 * If triggered by add user button, user parameter will be undefined
236 * @optional @param {*} user
237 */
238 function initUserModal(user) {
239 if ($scope.userRoles === null || $scope.userRoles === undefined) {
240 // If userRoles failed to load, do not allow add/edit
241 // functionality
242 return;
243 }
244 const newUser = user ? false : true;
245 const originalUsername = user ? angular.copy(user.UserName) : null;
246 const template = require('./user-accounts-modal-user.html');
247 $uibModal
248 .open({
249 template,
250 windowTopClass: 'uib-modal',
251 ariaLabelledBy: 'dialog_label',
252 controllerAs: 'modalCtrl',
253 controller: function() {
254 // Set default status to Enabled
255 const status = newUser ? true : user.Enabled;
256 // Check if UserName is root
257 // Some form controls will be disabled for root users:
258 // edit enabled status, edit username, edit role
259 const isRoot =
260 newUser ? false : user.UserName === 'root' ? true : false;
261 // Array of existing usernames (excluding current user instance)
262 const existingUsernames =
263 $scope.localUsers.reduce((acc, val) => {
264 if (user && (val.UserName === user.UserName)) {
265 return acc;
266 }
267 acc.push(val.UserName);
268 return acc;
269 }, []);
270
271 this.user = {};
272 this.user.isRoot = isRoot;
273 this.user.new = newUser;
274 this.user.accountStatus = status;
275 this.user.username = newUser ? '' : user.UserName;
276 this.user.privilege = newUser ? '' : user.RoleId;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500277 this.user.locked = newUser ? null : user.Locked;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500278
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500279 this.manualUnlockProperty = false;
280 this.automaticLockout = mapLockoutMethod(
281 $scope.accountSettings.AccountLockoutDuration);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500282 this.privilegeRoles = $scope.userRoles;
283 this.existingUsernames = existingUsernames;
284 this.minPasswordLength = $scope.accountSettings ?
285 $scope.accountSettings.MinPasswordLength :
286 null;
287 this.maxPasswordLength = $scope.accountSettings ?
288 $scope.accountSettings.MaxPasswordLength :
289 null;
290 }
291 })
292 .result
293 .then((form) => {
294 if (form.$valid) {
295 // If form control is pristine set property to null
296 // this will make sure only changed values are updated when
297 // modifying existing users
298 // API utils checks for null values
299 const username =
300 form.username.$pristine ? null : form.username.$modelValue;
301 const password =
302 form.password.$pristine ? null : form.password.$modelValue;
303 const role = form.privilege.$pristine ?
304 null :
305 form.privilege.$modelValue;
306 const enabled = (form.accountStatus.$pristine &&
307 form.accountStatus1.$pristine) ?
308 null :
309 form.accountStatus.$modelValue;
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500310 const locked = (form.lock && form.lock.$dirty) ?
311 form.lock.$modelValue :
312 null;
Yoshie Muranakafa562732019-07-17 11:23:15 -0500313
314 if (!newUser) {
315 updateUser(
Yoshie Muranakab4d9c092019-08-01 16:19:40 -0500316 originalUsername, username, password, role, enabled,
317 locked);
Yoshie Muranakafa562732019-07-17 11:23:15 -0500318 } else {
319 createUser(
320 username, password, role, form.accountStatus.$modelValue);
321 }
322 }
323 })
324 .catch(
325 () => {
326 // do nothing
327 })
328 }
329
330 /**
331 * Intiate remove user modal
332 * @param {*} user
333 */
334 function initRemoveModal(user) {
335 const template = require('./user-accounts-modal-remove.html');
336 $uibModal
337 .open({
338 template,
339 windowTopClass: 'uib-modal',
340 ariaLabelledBy: 'dialog_label',
341 controllerAs: 'modalCtrl',
342 controller: function() {
343 this.user = user.UserName;
344 }
345 })
346 .result
347 .then(() => {
348 const isRoot = user.UserName === 'root' ? true : false;
349 if (isRoot) {
350 toastService.error(`Cannot delete 'root' user.`)
351 return;
352 }
353 deleteUser(user.UserName);
354 })
355 .catch(
356 () => {
357 // do nothing
358 })
359 }
360
361 /**
362 * Callback when action emitted from table
363 * @param {*} value
364 */
Yoshie Muranaka5b8cef82019-09-10 08:09:43 -0700365 $scope.onEmitRowAction = (value) => {
Yoshie Muranakafa562732019-07-17 11:23:15 -0500366 switch (value.action) {
367 case 'Edit':
368 initUserModal(value.row);
369 break;
370 case 'Delete':
371 initRemoveModal(value.row);
372 break;
373 default:
beccabroeka5deeea2019-03-22 15:38:49 -0500374 }
375 };
Yoshie Muranakafa562732019-07-17 11:23:15 -0500376
377 /**
378 * Callback when 'Account settings policy' button clicked
379 */
380 $scope.onClickAccountSettingsPolicy = () => {
381 initAccountSettingsModal();
382 };
383
384 /**
385 * Callback when 'Add user' button clicked
386 */
387 $scope.onClickAddUser = () => {
388 initUserModal();
389 };
390
391 /**
392 * Callback when controller view initially loaded
393 */
394 $scope.$on('$viewContentLoaded', () => {
395 getLocalUsers();
396 getUserRoles();
397 getAccountSettings();
398 })
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700399 }
400 ]);
Iftekharul Islamcd789502017-04-19 14:37:55 -0500401})(angular);