2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
8 * Unless otherwise specified, all software contained herein is licensed
9 * under the Apache License, Version 2.0 (the "License");
10 * you may not use this software except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * Unless otherwise specified, all documentation contained herein is licensed
22 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23 * you may not use this documentation except in compliance with the License.
24 * You may obtain a copy of the License at
26 * https://creativecommons.org/licenses/by/4.0/
28 * Unless required by applicable law or agreed to in writing, documentation
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * ============LICENSE_END============================================
39 * bulk upload role-functions controller
43 class BulkRoleAndFunctionsModalCtrl {
44 constructor($scope, $log, $filter, $q, $modalInstance, $modal, ngDialog, message, confirmBoxService, usersService, applicationsService, functionalMenuService, RoleService) {
45 // Set to true for copious console output
47 // Roles fetched from Role service
48 var appRoleFuncsResult = [];
49 // Functions fetched from Role service
50 var appFunctionsResult = [];
51 // Global roles fetched from Role service
52 var appGlobalRolesResult = [];
54 var appId = message.appid;
56 $scope.ngRepeatBulkUploadOptions = [
57 {id: '1', title: 'Functions', value: 'functions'},
58 {id: '2', title: 'Roles', value: 'roles'},
59 {id: '3', title: 'Role Functions', value: 'roleFunctions'},
60 {id: '4', title: 'Global Role Functions', value: 'globalRoleFunctions'}
63 $scope.selectedUploadType = $scope.ngRepeatBulkUploadOptions[0];
64 $scope.UploadTypeInstruction = "Function Type, Function Instance, Function Action, Function Name";
65 $scope.changeUploadTypeInstruction = function(typeInstrc){
68 $scope.UploadTypeInstruction = "Function Type, Function Instance, Function Action, Function Name";
71 $scope.UploadTypeInstruction = "Role Name, Priority (Optional)";
74 $scope.UploadTypeInstruction = "Role Name, Function Type, Function Instance, Function Action, Function Name";
77 $scope.UploadTypeInstruction = "Global Role Name, Function Type, Function Instance, Function Action, Function Name";
83 $log.debug('BulkRoleAndFunctionsModalCtrl::init');
84 // Angular insists on this.
85 $scope.fileModel = {};
86 // Enable modal controls
89 this.fileSelected = false;
91 $scope.isProcessedRecords = false;
94 // Answers a function that compares properties with the specified name.
95 let getSortOrder = (prop, foldCase) => {
96 return function(a, b) {
97 let aProp = foldCase ? a[prop].toLowerCase() : a[prop];
98 let bProp = foldCase ? b[prop].toLowerCase() : b[prop];
101 else if (aProp < bProp)
108 // Caches the file name supplied by the event handler.
109 $scope.fileChangeHandler = (event, files) => {
110 var fileName = files[0].name;
111 var validFormats = ['csv', 'txt'];
113 var ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
114 //Check for valid format
115 if(validFormats.indexOf(ext) == -1){
116 this.fileSelected = false;
118 this.fileSelected = true;
119 this.fileToRead = files[0];
122 $log.debug("BulkRoleAndFunctionsModalCtrl::fileChangeHandler: file is ", this.fileToRead);
123 }; // file change handler
126 * Reads the contents of the file, calls portal endpoints to
127 * validate roles, userIds and existing role assignments;
128 * ultimately builds array of requests to be sent. Creates scope
129 * variable with input file contents for communication with
132 * This function performs a synchronous step-by-step process
133 * using asynchronous promises. The code could all be inline
134 * here but the nesting becomes unwieldy.
136 $scope.readValidateFile = (typeUpload) => {
137 $scope.isProcessing = true;
138 $scope.conformMsg = '';
139 $scope.isProcessedRecords = true;
140 $scope.progressMsg = 'Reading upload file...';
141 var reader = new FileReader();
142 reader.onload = function(event) {
143 if(typeUpload === 'roles'){
144 $scope.uploadFile = $filter('csvToRoleObj')(reader.result);
146 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
148 $scope.progressMsg = 'Fetching & validating application roles...';
150 RoleService.getRoles(appId).then(function (appRoles){
152 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
154 let availableRolesList = JSON.parse(appRoles.data);
155 appRoleFuncsResult = availableRolesList.availableRoles;
156 $scope.evalAppRolesCheckResults();
157 // Re sort by line for the confirmation dialog
158 $scope.uploadFile.sort(getSortOrder('line', false));
159 // We're done, confirm box may show the table
161 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
162 $scope.progressMsg = 'Done.';
163 $scope.isProcessing = false;
164 $scope.isProcessedRecords = false;
166 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
167 $scope.isProcessing = false;
168 $scope.isProcessedRecords = false;
170 } else if (typeUpload === 'roleFunctions'){
171 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
173 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
175 $scope.progressMsg = 'Fetching & validating application role functions...';
176 //fetch app functions
177 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
179 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
180 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
181 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
183 RoleService.getRoles(appId).then(function (appRoles){
185 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
187 let availableRolesList = JSON.parse(appRoles.data);
188 appRoleFuncsResult = availableRolesList.availableRoles;
189 $scope.evalAppRoleFuncsCheckResults();
190 // Re sort by line for the confirmation dialog
191 $scope.uploadFile.sort(getSortOrder('line', false));
192 // We're done, confirm box may show the table
194 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
195 $scope.progressMsg = 'Done.';
196 $scope.isProcessing = false;
197 $scope.isProcessedRecords = false;
199 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
200 $scope.isProcessing = false;
201 $scope.isProcessedRecords = false;
205 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
206 $scope.isProcessing = false;
209 } else if(typeUpload === 'functions'){
210 $scope.uploadFile = $filter('csvToFuncObj')(reader.result);
212 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
214 $scope.progressMsg = 'Fetching & validating the application functions...';
215 // fetch app functions
216 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
218 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
219 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
220 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
221 $scope.verifyFunctions();
222 $scope.evalAppFunctionsCheckResults();
223 // Re sort by line for the confirmation dialog
224 $scope.uploadFile.sort(getSortOrder('line', false));
225 // We're done, confirm box may show the table
227 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
228 $scope.progressMsg = 'Done.';
229 $scope.isProcessing = false;
230 $scope.isProcessedRecords = false;
233 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
234 $scope.isProcessing = false;
235 $scope.isProcessedRecords = false;
238 } else if(typeUpload === 'globalRoleFunctions'){
239 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
241 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
243 $scope.progressMsg = 'Fetching application global role functions...';
244 //fetch app functions
245 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
247 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
248 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
249 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
251 RoleService.getRoles(appId).then(function (appRoles){
253 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
255 let availableRolesList = JSON.parse(appRoles.data);
256 appRoleFuncsResult = availableRolesList.availableRoles;
257 appRoleFuncsResult.forEach(function(appRole) {
258 if(appRole.name.toLowerCase().startsWith("global_")){
259 appGlobalRolesResult.push(appRole);
262 $scope.evalAppRoleFuncsCheckResults(typeUpload);
263 // Re sort by line for the confirmation dialog
264 $scope.uploadFile.sort(getSortOrder('line', false));
265 // We're done, confirm box may show the table
267 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
268 $scope.progressMsg = 'Done.';
269 $scope.isProcessing = false;
270 $scope.isProcessedRecords = false;
272 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
273 $scope.isProcessing = false;
274 $scope.isProcessedRecords = false;
278 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
279 $scope.isProcessing = false;
286 // Invoke the reader on the selected file
287 reader.readAsText(this.fileToRead);
291 * Evaluates the result set returned by the role service.
292 * Sets an uploadFile array element status if a functions is not
293 * defined. Reads and writes scope variable uploadFile. Reads
294 * closure variable appFunctionsResult.
296 $scope.verifyFunctions = () => {
298 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: appFunctions is ' + JSON.stringify(appFunctionsResult));
299 // check functions in upload file against defined app functions
300 $scope.uploadFile.forEach( function (uploadRow) {
301 // skip rows that already have a defined status: headers etc.
302 if (uploadRow.status) {
304 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: skip row ' + uploadRow.line);
307 for (var i=0; i < appFunctionsResult.length; i++) {
308 if (uploadRow.type.toUpperCase() === appFunctionsResult[i].type.toUpperCase()
309 && uploadRow.instance.toUpperCase() === appFunctionsResult[i].code.toUpperCase()
310 && uploadRow.action.toUpperCase() === appFunctionsResult[i].action.toUpperCase()) {
312 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: match on function ' + uploadRow.type,
313 uploadRow.instance, uploadRow.type, uploadRow.type);
318 }; // verifyFunctions
321 * Evaluates the result set of existing functions returned by
322 * the Roleservice and list of functions found in the upload file.
323 * Reads and writes scope variable uploadFile.
324 * Reads closure variable appFunctionsResult.
326 $scope.evalAppFunctionsCheckResults = () => {
328 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
329 $scope.uploadFile.forEach(function (uploadRow) {
330 if (uploadRow.status) {
332 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: skip row ' + uploadRow.line);
335 // Search for the match in the app-functions
337 let isFunctionExist = false;
338 appFunctionsResult.forEach( function (exixtingFuncObj) {
339 if (uploadRow.type.toUpperCase() === exixtingFuncObj.type.toUpperCase()
340 && uploadRow.instance.toUpperCase() === exixtingFuncObj.code.toUpperCase()
341 && uploadRow.action.toUpperCase() === exixtingFuncObj.action.toUpperCase()) {
342 uploadRow.status = 'Function exits!';
343 uploadRow.isCreate = false;
344 isFunctionExist = true;
346 }); // for each result
347 if(!isFunctionExist) {
348 if(/[^a-zA-Z0-9\-\.\_]/.test(uploadRow.type)
349 || (uploadRow.action !== '*'
350 && /[^a-zA-Z0-9\-\.\_]/.test(uploadRow.action))
351 || /[^a-zA-Z0-9\-\:\_\./*]/.test(uploadRow.instance)
352 || /[^a-zA-Z0-9\-\_ \.]/.test(uploadRow.name)){
353 uploadRow.status = 'Invalid function';
354 uploadRow.isCreate = false;
357 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: new function '
360 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
361 uploadRow.status = 'Create';
362 uploadRow.isCreate = true;
366 }; // evalAppFunctionsCheckResults
369 * Evaluates the result set of existing roles returned by
370 * the Roleservice and list of roles found in the upload file.
371 * Reads and writes scope variable uploadFile.
372 * Reads closure variable appRolesResult.
374 $scope.evalAppRolesCheckResults = () => {
376 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: uploadFile length is ' + $scope.uploadFile.length);
377 $scope.uploadFile.forEach(function (uploadRow) {
378 if (uploadRow.status) {
380 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: skip row ' + uploadRow.line);
383 // Search for the match in the app-roles
385 let isRoleExist = false;
386 appRoleFuncsResult.forEach( function (existingRoleObj) {
387 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
388 uploadRow.status = 'Role exits!';
389 uploadRow.isCreate = false;
392 }); // for each result
394 if(/[^a-zA-Z0-9\-\_ \.\/]/.test(uploadRow.role) ||
395 uploadRow.role.toLowerCase().startsWith("global_")){
396 uploadRow.status = 'Invalid role!';
397 uploadRow.isCreate = false;
400 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: new function '
403 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
404 uploadRow.status = 'Create';
405 uploadRow.isCreate = true;
409 }; // evalAppRolesCheckResults
412 * Evaluates the result set of existing roles returned by
413 * the Roleservice and list of roles found in the upload file.
414 * Reads and writes scope variable uploadFile.
415 * Reads closure variable appRolesResult.
417 $scope.evalAppRoleFuncsCheckResults = (typeUpload) => {
419 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
420 $scope.uploadFile.forEach(function (uploadRow) {
421 if (uploadRow.status) {
423 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: skip row ' + uploadRow.line);
426 // Search for the match in the app-functions array
427 let isValidFunc = false;
428 appFunctionsResult.forEach(function (existingFuncObj){
429 if(uploadRow.type.toUpperCase() === existingFuncObj.type.toUpperCase()
430 && uploadRow.instance.toUpperCase() === existingFuncObj.code.toUpperCase()
431 && uploadRow.action.toUpperCase() === existingFuncObj.action.toUpperCase()
432 && uploadRow.name.toUpperCase() === existingFuncObj.name.toUpperCase()){
437 let isValidRole = false;
438 let isRoleFuncExist = false;
439 if(typeUpload === 'globalRoleFunctions'){
440 // Search for the match in the app-role array
441 appGlobalRolesResult.forEach( function (existingRoleObj) {
442 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
445 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
446 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
447 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
448 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
449 isRoleFuncExist = true;
454 }); // for each result
456 // Search for the match in the app-role array
457 appRoleFuncsResult.forEach( function (existingRoleObj) {
458 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
461 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
462 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
463 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
464 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
465 isRoleFuncExist = true;
470 }); // for each result
473 uploadRow.isCreate = false;
474 if(typeUpload === 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
475 uploadRow.status = 'Invalid global role function!';
476 } else if(typeUpload !== 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
477 uploadRow.status = 'Invalid role function!';
478 } else if(typeUpload === 'globalRoleFunctions' && !isRoleFuncExist) {
479 uploadRow.status = 'Add global role function!';
480 uploadRow.isCreate = true;
481 } else if(typeUpload !== 'globalRoleFunctions' && !isRoleFuncExist){
482 uploadRow.status = 'Add role function!';
483 uploadRow.isCreate = true;
484 } else if(typeUpload === 'globalRoleFunctions'){
485 uploadRow.status = 'Global role function exists!';
487 uploadRow.status = 'Role function exists!';
491 }; // evalAppRolesCheckResults
495 * Sends requests to Portal BE requesting application functions assignment.
496 * That endpoint handles creation of the application functions in the
497 * external auth system if necessary. Reads closure variable appFunctionsResult.
498 * Invoked by the Next button on the confirmation dialog.
500 $scope.updateFunctionsInDB = () => {
501 $scope.isProcessing = true;
502 $scope.conformMsg = '';
503 $scope.isProcessedRecords = true;
504 $scope.progressMsg = 'Sending requests to application..';
506 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: request length is ' + appUserRolesRequest.length);
507 var numberFunctionsSucceeded = 0;
509 $scope.uploadFile.forEach(function(appFuncPostData) {
511 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: appFuncPostData is ' + JSON.stringify(appFuncPostData));
512 let updateFunctionsFinalPostData = {
513 type: appFuncPostData.type,
514 code: appFuncPostData.instance,
515 action: appFuncPostData.action,
516 name: appFuncPostData.name
519 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updateFunctionsFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
520 let updatePromise = {};
521 if(appFuncPostData.isCreate){
522 updatePromise = functionalMenuService.saveBulkFunction(appId, updateFunctionsFinalPostData).promise().then(res => {
524 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updated successfully: ' + JSON.stringify(res));
525 numberFunctionsSucceeded++;
527 // What to do if one of many fails??
528 $log.error('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB failed: ', err);
529 confirmBoxService.showInformation(
530 'Failed to update the application functions. ' +
531 'Error: ' + err.status).then(isConfirmed => { });
535 promises.push(updatePromise);
538 // Run all the promises
539 $q.all(promises).then(function(){
540 $scope.conformMsg = 'Processed ' + numberFunctionsSucceeded + ' records.';
541 $scope.isProcessing = false;
542 $scope.isProcessedRecords = true;
543 $scope.uploadFile = [];
545 }; // updateFunctionsInDB
548 * Sends requests to Portal BE requesting application functions assignment.
549 * That endpoint handles creation of the application role in the
550 * external auth system if necessary. Reads closure variable appRoleFuncResult.
551 * Invoked by the Next button on the confirmation dialog.
553 $scope.updateRolesInDB = () => {
554 $scope.isProcessing = true;
555 $scope.conformMsg = '';
556 $scope.isProcessedRecords = true;
557 $scope.progressMsg = 'Sending requests to application..';
559 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: request length is ' + appUserRolesRequest.length);
560 var numberRolesSucceeded = 0;
562 $scope.uploadFile.forEach(function(appRolePostData) {
563 let priority = parseInt(appRolePostData.priority);
565 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: appRolePostData is ' + JSON.stringify(appFuncPostData));
566 let uplaodRolePostData = "";
568 uplaodRolePostData = {
569 name: appRolePostData.role,
573 uplaodRolePostData = {
574 name: appRolePostData.role,
575 priority: appRolePostData.priority,
580 role: uplaodRolePostData,
585 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: uplaodRoleFinalPostData is ' + JSON.stringify(uplaodRoleFinalPostData));
586 let updatePromise = {};
587 if(appRolePostData.isCreate){
588 updatePromise = functionalMenuService.saveBulkRole(appId, JSON.stringify(postData)).promise().then(res => {
590 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: updated successfully: ' + JSON.stringify(res));
591 numberRolesSucceeded++;
593 // What to do if one of many fails??
594 $log.error('BulkRoleAndFunctionsModalCtrl::updateRolesInDB failed: ', err);
595 confirmBoxService.showInformation(
596 'Failed to update the application role. ' +
597 'Error: ' + err.status).then(isConfirmed => { });
601 promises.push(updatePromise);
604 // Run all the promises
605 $q.all(promises).then(function(){
606 if(numberRolesSucceeded == 0){
607 $scope.conformMsg = 'Processed ' + numberRolesSucceeded + ' records';
609 $scope.conformMsg = 'Processed ' + numberRolesSucceeded + ' records. Please sync roles to reflect in portal';
610 } $scope.isProcessing = false;
611 $scope.isProcessedRecords = true;
612 $scope.uploadFile = [];
614 }; // updateRolesInDB
617 * Sends requests to Portal BE requesting role function assignment.
618 * That endpoint handles adding role function in the external auth system
619 * if necessary.Invoked by the Next button on the confirmation dialog.
621 $scope.updateRoleFunctionsInDB = () => {
622 $scope.isProcessing = true;
623 $scope.conformMsg = '';
624 $scope.isProcessedRecords = true;
625 $scope.progressMsg = 'Sending requests to application..';
627 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
628 var numberRoleFunctionSucceeded = 0;
630 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
632 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
633 let updateRoleFunctionFinalPostData = {
634 roleName: appRoleFuncPostData.role,
635 type: appRoleFuncPostData.type,
636 instance: appRoleFuncPostData.instance,
637 action: appRoleFuncPostData.action,
638 name: appRoleFuncPostData.name,
639 isGlobalRolePartnerFunc: false
642 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
643 let updatePromise = {};
644 if(appRoleFuncPostData.isCreate){
645 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateRoleFunctionFinalPostData).promise().then(res => {
647 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
648 numberRoleFunctionSucceeded++;
650 // What to do if one of many fails??
651 $log.error('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB failed: ', err);
652 confirmBoxService.showInformation(
653 'Failed to update the application role function. ' +
654 'Error: ' + err.status).then(isConfirmed => { });
658 promises.push(updatePromise);
661 // Run all the promises
662 $q.all(promises).then(function(){
663 if(numberRoleFunctionSucceeded == 0){
664 $scope.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records';
666 $scope.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
667 } $scope.isProcessing = false;
668 $scope.isProcessedRecords = true;
669 $scope.uploadFile = [];
671 }; // updateRoleFunctionsInDB
674 * Sends requests to Portal requesting global role functions assignment.
675 * That endpoint handles updating global role functions in the external auth system
676 * if necessary. Invoked by the Next button on the confirmation dialog.
678 $scope.updateGlobalRoleFunctionsInDB = () => {
679 $scope.isProcessing = true;
680 $scope.conformMsg = '';
681 $scope.isProcessedRecords = true;
682 $scope.progressMsg = 'Sending requests to application..';
684 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
685 var numberGlobalRoleFunctionSucceeded = 0;
687 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
689 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
690 let updateGlobalRoleFunctionFinalPostData = {
691 roleName: appRoleFuncPostData.role,
692 type: appRoleFuncPostData.type,
693 instance: appRoleFuncPostData.instance,
694 action: appRoleFuncPostData.action,
695 name: appRoleFuncPostData.name,
696 isGlobalRolePartnerFunc: true
699 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
700 let updatePromise = {};
701 if(appRoleFuncPostData.isCreate){
702 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateGlobalRoleFunctionFinalPostData).promise().then(res => {
704 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
705 numberGlobalRoleFunctionSucceeded++;
707 // What to do if one of many fails??
708 $log.error('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB failed: ', err);
709 confirmBoxService.showInformation(
710 'Failed to update the global role partner function. ' +
711 'Error: ' + err.status).then(isConfirmed => { });
715 promises.push(updatePromise);
718 // Run all the promises
719 $q.all(promises).then(function(){
720 if(numberGlobalRoleFunctionSucceeded == 0){
721 $scope.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records';
723 $scope.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
725 $scope.isProcessing = false;
726 $scope.isProcessedRecords = true;
727 $scope.uploadFile = [];
729 }; // updateGlobalRoleFunctionsInDB
731 // Sets the variable that hides/reveals the user controls
732 $scope.step2 = () => {
733 this.fileSelected = false;
734 $scope.selectedFile = null;
735 $scope.fileModel = null;
739 // Navigate between dialog screens using step number: 1,2,...
740 $scope.navigateBack = () => {
742 this.fileSelected = false;
745 // Opens a dialog to show the data to be uploaded.
746 // Invoked by the upload button on the bulk user dialog.
747 $scope.confirmUpload = (typeUpload) => {
749 $scope.readValidateFile(typeUpload);
750 // Dialog shows progress
751 if(typeUpload === 'functions'){
753 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-functions-confirm.html',
755 sizeClass: 'modal-medium',
759 } else if(typeUpload === 'roleFunctions'){
761 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-role-functions-confirm.html',
763 sizeClass: 'modal-medium',
768 } else if(typeUpload === 'roles'){
770 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-roles-confirm.html',
772 sizeClass: 'modal-medium',
776 } else if(typeUpload === 'globalRoleFunctions'){
778 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-global-role-functions-confirm.html',
780 sizeClass: 'modal-medium',
787 // Invoked by the Cancel button on the confirmation dialog.
788 $scope.cancelUpload = () => {
795 BulkRoleAndFunctionsModalCtrl.$inject = ['$scope', '$log', '$filter', '$q', '$modalInstance', '$modal', 'ngDialog', 'message', 'confirmBoxService', 'usersService', 'applicationsService', 'functionalMenuService', 'RoleService'];
796 angular.module('ecompApp').controller('BulkRoleAndFunctionsModalCtrl', BulkRoleAndFunctionsModalCtrl);
798 angular.module('ecompApp').directive('fileChange', ['$parse', function($parse){
802 link : function($scope, element, attrs, ngModel) {
803 var attrHandler = $parse(attrs['fileChange']);
804 var handler=function(e) {
805 $scope.$apply(function() {
806 attrHandler($scope, { $event:e, files:e.target.files } );
807 $scope.selectedFile = e.target.files[0].name;
810 element[0].addEventListener('change',handler,false);
815 angular.module('ecompApp').filter('csvToFuncObj',function() {
816 return function(input) {
819 var lines = input.split('\n');
820 // Need 1-based index below
821 for (len = lines.length, i = 1; i <= len; ++i) {
822 // Use 0-based index for array
823 line = lines[i - 1].trim();
824 if (line.length == 0) {
825 // console.log("Skipping blank line");
837 if (o.length !== 4) {
838 // other lengths not valid for upload
845 status: 'Failed to find 4 comma-separated values'
849 // console.log("Valid line: ", val);
856 // leave status undefined, this
859 if (o[0].toLowerCase() === 'type') {
860 // not valid for upload, so set status
861 entry.status = 'Header';
863 else if (o[0].toLowerCase() === 'instance') {
864 // not valid for upload, so set status
865 entry.status = 'Header';
867 else if (o[0].toLowerCase() === 'action') {
868 // not valid for upload, so set status
869 entry.status = 'Header';
871 else if (o[0].toLowerCase() === 'name') {
872 // not valid for upload, so set status
873 entry.status = 'Header';
875 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '') {
876 // defend against line with only a
878 entry.status = 'Failed to find non-empty values';
887 angular.module('ecompApp').filter('csvToRoleFuncObj',function() {
888 return function(input) {
891 var lines = input.split('\n');
892 // Need 1-based index below
893 for (len = lines.length, i = 1; i <= len; ++i) {
894 // Use 0-based index for array
895 line = lines[i - 1].trim();
896 if (line.length == 0) {
897 // console.log("Skipping blank line");
910 if (o.length !== 5) {
911 // other lengths not valid for upload
919 status: 'Failed to find 4 comma-separated values'
923 // console.log("Valid line: ", val);
931 // leave status undefined, this
934 if (o[0].toLowerCase() === 'role') {
935 // not valid for upload, so set status
936 entry.status = 'Header';
937 } else if (o[0].toLowerCase() === 'type') {
938 // not valid for upload, so set status
939 entry.status = 'Header';
941 else if (o[0].toLowerCase() === 'instance') {
942 // not valid for upload, so set status
943 entry.status = 'Header';
945 else if (o[0].toLowerCase() === 'action') {
946 // not valid for upload, so set status
947 entry.status = 'Header';
949 else if (o[0].toLowerCase() === 'name') {
950 // not valid for upload, so set status
951 entry.status = 'Header';
953 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '' || o[4].trim() == '') {
954 // defend against line with only a
956 entry.status = 'Failed to find non-empty values';
965 angular.module('ecompApp').filter('csvToRoleObj',function() {
966 return function(input) {
969 var lines = input.split('\n');
970 // Need 1-based index below
971 for (len = lines.length, i = 1; i <= len; ++i) {
972 // Use 0-based index for array
973 line = lines[i - 1].trim();
974 if (line.length == 0) {
975 // console.log("Skipping blank line");
985 if (o.length === 0 && line.length !== 0) {
986 // other lengths not valid for upload
994 // console.log("Valid line: ", val);
999 // leave status undefined, this
1002 if (o[0].toLowerCase() === 'role') {
1003 // not valid for upload, so set status
1004 entry.status = 'Header';
1006 if (o[0].toLowerCase() === 'priority') {
1007 // not valid for upload, so set status
1008 entry.status = 'Header';
1010 else if (o[0].trim() == '') {
1011 // defend against line with only a
1012 // single comma etc.
1013 entry.status = 'Failed to find non-empty values';