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 this.fileSelected = true;
111 this.fileToRead = files[0];
113 $log.debug("BulkRoleAndFunctionsModalCtrl::fileChangeHandler: file is ", this.fileToRead);
114 }; // file change handler
117 * Reads the contents of the file, calls portal endpoints to
118 * validate roles, userIds and existing role assignments;
119 * ultimately builds array of requests to be sent. Creates scope
120 * variable with input file contents for communication with
123 * This function performs a synchronous step-by-step process
124 * using asynchronous promises. The code could all be inline
125 * here but the nesting becomes unwieldy.
127 $scope.readValidateFile = (typeUpload) => {
128 $scope.isProcessing = true;
129 $scope.conformMsg = '';
130 $scope.isProcessedRecords = true;
131 $scope.progressMsg = 'Reading upload file...';
132 var reader = new FileReader();
133 reader.onload = function(event) {
134 if(typeUpload === 'roles'){
135 $scope.uploadFile = $filter('csvToRoleObj')(reader.result);
137 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
139 $scope.progressMsg = 'Fetching & validating application roles...';
141 RoleService.getRoles(appId).then(function (appRoles){
143 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
145 let availableRolesList = JSON.parse(appRoles.data);
146 appRoleFuncsResult = availableRolesList.availableRoles;
147 $scope.evalAppRolesCheckResults();
148 // Re sort by line for the confirmation dialog
149 $scope.uploadFile.sort(getSortOrder('line', false));
150 // We're done, confirm box may show the table
152 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
153 $scope.progressMsg = 'Done.';
154 $scope.isProcessing = false;
155 $scope.isProcessedRecords = false;
157 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
158 $scope.isProcessing = false;
159 $scope.isProcessedRecords = false;
161 } else if (typeUpload === 'roleFunctions'){
162 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
164 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
166 $scope.progressMsg = 'Fetching & validating application role functions...';
167 //fetch app functions
168 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
170 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
171 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
172 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
174 RoleService.getRoles(appId).then(function (appRoles){
176 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
178 let availableRolesList = JSON.parse(appRoles.data);
179 appRoleFuncsResult = availableRolesList.availableRoles;
180 $scope.evalAppRoleFuncsCheckResults();
181 // Re sort by line for the confirmation dialog
182 $scope.uploadFile.sort(getSortOrder('line', false));
183 // We're done, confirm box may show the table
185 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
186 $scope.progressMsg = 'Done.';
187 $scope.isProcessing = false;
188 $scope.isProcessedRecords = false;
190 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
191 $scope.isProcessing = false;
192 $scope.isProcessedRecords = false;
196 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
197 $scope.isProcessing = false;
200 } else if(typeUpload === 'functions'){
201 $scope.uploadFile = $filter('csvToFuncObj')(reader.result);
203 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
205 $scope.progressMsg = 'Fetching & validating the application functions...';
206 // fetch app functions
207 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
209 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
210 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
211 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
212 $scope.verifyFunctions();
213 $scope.evalAppFunctionsCheckResults();
214 // Re sort by line for the confirmation dialog
215 $scope.uploadFile.sort(getSortOrder('line', false));
216 // We're done, confirm box may show the table
218 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
219 $scope.progressMsg = 'Done.';
220 $scope.isProcessing = false;
221 $scope.isProcessedRecords = false;
224 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
225 $scope.isProcessing = false;
226 $scope.isProcessedRecords = false;
229 } else if(typeUpload === 'globalRoleFunctions'){
230 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
232 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
234 $scope.progressMsg = 'Fetching application global role functions...';
235 //fetch app functions
236 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
238 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
239 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
240 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
242 RoleService.getRoles(appId).then(function (appRoles){
244 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
246 let availableRolesList = JSON.parse(appRoles.data);
247 appRoleFuncsResult = availableRolesList.availableRoles;
248 appRoleFuncsResult.forEach(function(appRole) {
249 if(appRole.name.toLowerCase().startsWith("global_")){
250 appGlobalRolesResult.push(appRole);
253 $scope.evalAppRoleFuncsCheckResults(typeUpload);
254 // Re sort by line for the confirmation dialog
255 $scope.uploadFile.sort(getSortOrder('line', false));
256 // We're done, confirm box may show the table
258 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
259 $scope.progressMsg = 'Done.';
260 $scope.isProcessing = false;
261 $scope.isProcessedRecords = false;
263 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
264 $scope.isProcessing = false;
265 $scope.isProcessedRecords = false;
269 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
270 $scope.isProcessing = false;
277 // Invoke the reader on the selected file
278 reader.readAsText(this.fileToRead);
282 * Evaluates the result set returned by the role service.
283 * Sets an uploadFile array element status if a functions is not
284 * defined. Reads and writes scope variable uploadFile. Reads
285 * closure variable appFunctionsResult.
287 $scope.verifyFunctions = () => {
289 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: appFunctions is ' + JSON.stringify(appFunctionsResult));
290 // check functions in upload file against defined app functions
291 $scope.uploadFile.forEach( function (uploadRow) {
292 // skip rows that already have a defined status: headers etc.
293 if (uploadRow.status) {
295 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: skip row ' + uploadRow.line);
298 for (var i=0; i < appFunctionsResult.length; i++) {
299 if (uploadRow.type.toUpperCase() === appFunctionsResult[i].type.toUpperCase()
300 && uploadRow.instance.toUpperCase() === appFunctionsResult[i].code.toUpperCase()
301 && uploadRow.action.toUpperCase() === appFunctionsResult[i].action.toUpperCase()) {
303 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: match on function ' + uploadRow.type,
304 uploadRow.instance, uploadRow.type, uploadRow.type);
309 }; // verifyFunctions
312 * Evaluates the result set of existing functions returned by
313 * the Roleservice and list of functions found in the upload file.
314 * Reads and writes scope variable uploadFile.
315 * Reads closure variable appFunctionsResult.
317 $scope.evalAppFunctionsCheckResults = () => {
319 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
320 $scope.uploadFile.forEach(function (uploadRow) {
321 if (uploadRow.status) {
323 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: skip row ' + uploadRow.line);
326 // Search for the match in the app-functions
328 let isFunctionExist = false;
329 appFunctionsResult.forEach( function (exixtingFuncObj) {
330 if (uploadRow.type.toUpperCase() === exixtingFuncObj.type.toUpperCase()
331 && uploadRow.instance.toUpperCase() === exixtingFuncObj.code.toUpperCase()
332 && uploadRow.action.toUpperCase() === exixtingFuncObj.action.toUpperCase()) {
333 uploadRow.status = 'Function exits!';
334 uploadRow.isCreate = false;
335 isFunctionExist = true;
337 }); // for each result
338 if(!isFunctionExist) {
339 if(/[^a-zA-Z0-9\-\.\_]/.test(uploadRow.type)
340 || (uploadRow.action !== '*'
341 && /[^a-zA-Z0-9\-\.\_]/.test(uploadRow.action))
342 || /[^a-zA-Z0-9\-\:\_\./*]/.test(uploadRow.instance)
343 || /[^a-zA-Z0-9\-\_ \.]/.test(uploadRow.name)){
344 uploadRow.status = 'Invalid function';
345 uploadRow.isCreate = false;
348 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: new function '
351 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
352 uploadRow.status = 'Create';
353 uploadRow.isCreate = true;
357 }; // evalAppFunctionsCheckResults
360 * Evaluates the result set of existing roles returned by
361 * the Roleservice and list of roles found in the upload file.
362 * Reads and writes scope variable uploadFile.
363 * Reads closure variable appRolesResult.
365 $scope.evalAppRolesCheckResults = () => {
367 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: uploadFile length is ' + $scope.uploadFile.length);
368 $scope.uploadFile.forEach(function (uploadRow) {
369 if (uploadRow.status) {
371 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: skip row ' + uploadRow.line);
374 // Search for the match in the app-roles
376 let isRoleExist = false;
377 appRoleFuncsResult.forEach( function (existingRoleObj) {
378 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
379 uploadRow.status = 'Role exits!';
380 uploadRow.isCreate = false;
383 }); // for each result
385 if(/[^a-zA-Z0-9\-\_ \.\/]/.test(uploadRow.role) ||
386 uploadRow.role.toLowerCase().startsWith("global_")){
387 uploadRow.status = 'Invalid role!';
388 uploadRow.isCreate = false;
391 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: new function '
394 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
395 uploadRow.status = 'Create';
396 uploadRow.isCreate = true;
400 }; // evalAppRolesCheckResults
403 * Evaluates the result set of existing roles returned by
404 * the Roleservice and list of roles found in the upload file.
405 * Reads and writes scope variable uploadFile.
406 * Reads closure variable appRolesResult.
408 $scope.evalAppRoleFuncsCheckResults = (typeUpload) => {
410 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
411 $scope.uploadFile.forEach(function (uploadRow) {
412 if (uploadRow.status) {
414 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: skip row ' + uploadRow.line);
417 // Search for the match in the app-functions array
418 let isValidFunc = false;
419 appFunctionsResult.forEach(function (existingFuncObj){
420 if(uploadRow.type.toUpperCase() === existingFuncObj.type.toUpperCase()
421 && uploadRow.instance.toUpperCase() === existingFuncObj.code.toUpperCase()
422 && uploadRow.action.toUpperCase() === existingFuncObj.action.toUpperCase()
423 && uploadRow.name.toUpperCase() === existingFuncObj.name.toUpperCase()){
428 let isValidRole = false;
429 let isRoleFuncExist = false;
430 if(typeUpload === 'globalRoleFunctions'){
431 // Search for the match in the app-role array
432 appGlobalRolesResult.forEach( function (existingRoleObj) {
433 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
436 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
437 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
438 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
439 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
440 isRoleFuncExist = true;
445 }); // for each result
447 // Search for the match in the app-role array
448 appRoleFuncsResult.forEach( function (existingRoleObj) {
449 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
452 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
453 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
454 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
455 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
456 isRoleFuncExist = true;
461 }); // for each result
464 uploadRow.isCreate = false;
465 if(typeUpload === 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
466 uploadRow.status = 'Invalid global role function!';
467 } else if(typeUpload !== 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
468 uploadRow.status = 'Invalid role function!';
469 } else if(typeUpload === 'globalRoleFunctions' && !isRoleFuncExist) {
470 uploadRow.status = 'Add global role function!';
471 uploadRow.isCreate = true;
472 } else if(typeUpload !== 'globalRoleFunctions' && !isRoleFuncExist){
473 uploadRow.status = 'Add role function!';
474 uploadRow.isCreate = true;
475 } else if(typeUpload === 'globalRoleFunctions'){
476 uploadRow.status = 'Global role function exists!';
478 uploadRow.status = 'Role function exists!';
482 }; // evalAppRolesCheckResults
486 * Sends requests to Portal BE requesting application functions assignment.
487 * That endpoint handles creation of the application functions in the
488 * external auth system if necessary. Reads closure variable appFunctionsResult.
489 * Invoked by the Next button on the confirmation dialog.
491 $scope.updateFunctionsInDB = () => {
492 $scope.isProcessing = true;
493 $scope.conformMsg = '';
494 $scope.isProcessedRecords = true;
495 $scope.progressMsg = 'Sending requests to application..';
497 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: request length is ' + appUserRolesRequest.length);
498 var numberFunctionsSucceeded = 0;
500 $scope.uploadFile.forEach(function(appFuncPostData) {
502 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: appFuncPostData is ' + JSON.stringify(appFuncPostData));
503 let updateFunctionsFinalPostData = {
504 type: appFuncPostData.type,
505 code: appFuncPostData.instance,
506 action: appFuncPostData.action,
507 name: appFuncPostData.name
510 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updateFunctionsFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
511 let updatePromise = {};
512 if(appFuncPostData.isCreate){
513 updatePromise = functionalMenuService.saveBulkFunction(appId, updateFunctionsFinalPostData).promise().then(res => {
515 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updated successfully: ' + JSON.stringify(res));
516 numberFunctionsSucceeded++;
518 // What to do if one of many fails??
519 $log.error('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB failed: ', err);
520 confirmBoxService.showInformation(
521 'Failed to update the application functions. ' +
522 'Error: ' + err.status).then(isConfirmed => { });
526 promises.push(updatePromise);
529 // Run all the promises
530 $q.all(promises).then(function(){
531 $scope.conformMsg = 'Processed ' + numberFunctionsSucceeded + ' records.';
532 $scope.isProcessing = false;
533 $scope.isProcessedRecords = true;
534 $scope.uploadFile = [];
536 }; // updateFunctionsInDB
539 * Sends requests to Portal BE requesting application functions assignment.
540 * That endpoint handles creation of the application role in the
541 * external auth system if necessary. Reads closure variable appRoleFuncResult.
542 * Invoked by the Next button on the confirmation dialog.
544 $scope.updateRolesInDB = () => {
545 $scope.isProcessing = true;
546 $scope.conformMsg = '';
547 $scope.isProcessedRecords = true;
548 $scope.progressMsg = 'Sending requests to application..';
550 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: request length is ' + appUserRolesRequest.length);
551 var numberRolesSucceeded = 0;
553 $scope.uploadFile.forEach(function(appRolePostData) {
554 let priority = parseInt(appRolePostData.priority);
556 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: appRolePostData is ' + JSON.stringify(appFuncPostData));
557 let uplaodRolePostData = "";
559 uplaodRolePostData = {
560 name: appRolePostData.role,
564 uplaodRolePostData = {
565 name: appRolePostData.role,
566 priority: appRolePostData.priority,
571 role: uplaodRolePostData,
576 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: uplaodRoleFinalPostData is ' + JSON.stringify(uplaodRoleFinalPostData));
577 let updatePromise = {};
578 if(appRolePostData.isCreate){
579 updatePromise = functionalMenuService.saveBulkRole(appId, JSON.stringify(postData)).promise().then(res => {
581 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: updated successfully: ' + JSON.stringify(res));
582 numberRolesSucceeded++;
584 // What to do if one of many fails??
585 $log.error('BulkRoleAndFunctionsModalCtrl::updateRolesInDB failed: ', err);
586 confirmBoxService.showInformation(
587 'Failed to update the application role. ' +
588 'Error: ' + err.status).then(isConfirmed => { });
592 promises.push(updatePromise);
595 // Run all the promises
596 $q.all(promises).then(function(){
597 if(numberRolesSucceeded == 0){
598 $scope.conformMsg = 'Processed ' + numberRolesSucceeded + ' records';
600 $scope.conformMsg = 'Processed ' + numberRolesSucceeded + ' records. Please sync roles to reflect in portal';
601 } $scope.isProcessing = false;
602 $scope.isProcessedRecords = true;
603 $scope.uploadFile = [];
605 }; // updateRolesInDB
608 * Sends requests to Portal BE requesting role function assignment.
609 * That endpoint handles adding role function in the external auth system
610 * if necessary.Invoked by the Next button on the confirmation dialog.
612 $scope.updateRoleFunctionsInDB = () => {
613 $scope.isProcessing = true;
614 $scope.conformMsg = '';
615 $scope.isProcessedRecords = true;
616 $scope.progressMsg = 'Sending requests to application..';
618 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
619 var numberRoleFunctionSucceeded = 0;
621 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
623 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
624 let updateRoleFunctionFinalPostData = {
625 roleName: appRoleFuncPostData.role,
626 type: appRoleFuncPostData.type,
627 instance: appRoleFuncPostData.instance,
628 action: appRoleFuncPostData.action,
629 name: appRoleFuncPostData.name,
630 isGlobalRolePartnerFunc: false
633 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
634 let updatePromise = {};
635 if(appRoleFuncPostData.isCreate){
636 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateRoleFunctionFinalPostData).promise().then(res => {
638 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
639 numberRoleFunctionSucceeded++;
641 // What to do if one of many fails??
642 $log.error('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB failed: ', err);
643 confirmBoxService.showInformation(
644 'Failed to update the application role function. ' +
645 'Error: ' + err.status).then(isConfirmed => { });
649 promises.push(updatePromise);
652 // Run all the promises
653 $q.all(promises).then(function(){
654 if(numberRoleFunctionSucceeded == 0){
655 $scope.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records';
657 $scope.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
658 } $scope.isProcessing = false;
659 $scope.isProcessedRecords = true;
660 $scope.uploadFile = [];
662 }; // updateRoleFunctionsInDB
665 * Sends requests to Portal requesting global role functions assignment.
666 * That endpoint handles updating global role functions in the external auth system
667 * if necessary. Invoked by the Next button on the confirmation dialog.
669 $scope.updateGlobalRoleFunctionsInDB = () => {
670 $scope.isProcessing = true;
671 $scope.conformMsg = '';
672 $scope.isProcessedRecords = true;
673 $scope.progressMsg = 'Sending requests to application..';
675 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
676 var numberGlobalRoleFunctionSucceeded = 0;
678 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
680 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
681 let updateGlobalRoleFunctionFinalPostData = {
682 roleName: appRoleFuncPostData.role,
683 type: appRoleFuncPostData.type,
684 instance: appRoleFuncPostData.instance,
685 action: appRoleFuncPostData.action,
686 name: appRoleFuncPostData.name,
687 isGlobalRolePartnerFunc: true
690 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
691 let updatePromise = {};
692 if(appRoleFuncPostData.isCreate){
693 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateGlobalRoleFunctionFinalPostData).promise().then(res => {
695 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
696 numberGlobalRoleFunctionSucceeded++;
698 // What to do if one of many fails??
699 $log.error('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB failed: ', err);
700 confirmBoxService.showInformation(
701 'Failed to update the global role partner function. ' +
702 'Error: ' + err.status).then(isConfirmed => { });
706 promises.push(updatePromise);
709 // Run all the promises
710 $q.all(promises).then(function(){
711 if(numberGlobalRoleFunctionSucceeded == 0){
712 $scope.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records';
714 $scope.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
716 $scope.isProcessing = false;
717 $scope.isProcessedRecords = true;
718 $scope.uploadFile = [];
720 }; // updateGlobalRoleFunctionsInDB
722 // Sets the variable that hides/reveals the user controls
723 $scope.step2 = () => {
724 this.fileSelected = false;
725 $scope.selectedFile = null;
726 $scope.fileModel = null;
730 // Navigate between dialog screens using step number: 1,2,...
731 $scope.navigateBack = () => {
733 this.fileSelected = false;
736 // Opens a dialog to show the data to be uploaded.
737 // Invoked by the upload button on the bulk user dialog.
738 $scope.confirmUpload = (typeUpload) => {
740 $scope.readValidateFile(typeUpload);
741 // Dialog shows progress
742 if(typeUpload === 'functions'){
744 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-functions-confirm.html',
746 sizeClass: 'modal-medium',
750 } else if(typeUpload === 'roleFunctions'){
752 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-role-functions-confirm.html',
754 sizeClass: 'modal-medium',
759 } else if(typeUpload === 'roles'){
761 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-roles-confirm.html',
763 sizeClass: 'modal-medium',
767 } else if(typeUpload === 'globalRoleFunctions'){
769 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-global-role-functions-confirm.html',
771 sizeClass: 'modal-medium',
778 // Invoked by the Cancel button on the confirmation dialog.
779 $scope.cancelUpload = () => {
786 BulkRoleAndFunctionsModalCtrl.$inject = ['$scope', '$log', '$filter', '$q', '$modalInstance', '$modal', 'ngDialog', 'message', 'confirmBoxService', 'usersService', 'applicationsService', 'functionalMenuService', 'RoleService'];
787 angular.module('ecompApp').controller('BulkRoleAndFunctionsModalCtrl', BulkRoleAndFunctionsModalCtrl);
789 angular.module('ecompApp').directive('fileChange', ['$parse', function($parse){
793 link : function($scope, element, attrs, ngModel) {
794 var attrHandler = $parse(attrs['fileChange']);
795 var handler=function(e) {
796 $scope.$apply(function() {
797 attrHandler($scope, { $event:e, files:e.target.files } );
798 $scope.selectedFile = e.target.files[0].name;
801 element[0].addEventListener('change',handler,false);
806 angular.module('ecompApp').filter('csvToFuncObj',function() {
807 return function(input) {
810 var lines = input.split('\n');
811 // Need 1-based index below
812 for (len = lines.length, i = 1; i <= len; ++i) {
813 // Use 0-based index for array
814 line = lines[i - 1].trim();
815 if (line.length == 0) {
816 // console.log("Skipping blank line");
828 if (o.length !== 4) {
829 // other lengths not valid for upload
836 status: 'Failed to find 4 comma-separated values'
840 // console.log("Valid line: ", val);
847 // leave status undefined, this
850 if (o[0].toLowerCase() === 'type') {
851 // not valid for upload, so set status
852 entry.status = 'Header';
854 else if (o[0].toLowerCase() === 'instance') {
855 // not valid for upload, so set status
856 entry.status = 'Header';
858 else if (o[0].toLowerCase() === 'action') {
859 // not valid for upload, so set status
860 entry.status = 'Header';
862 else if (o[0].toLowerCase() === 'name') {
863 // not valid for upload, so set status
864 entry.status = 'Header';
866 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '') {
867 // defend against line with only a
869 entry.status = 'Failed to find non-empty values';
878 angular.module('ecompApp').filter('csvToRoleFuncObj',function() {
879 return function(input) {
882 var lines = input.split('\n');
883 // Need 1-based index below
884 for (len = lines.length, i = 1; i <= len; ++i) {
885 // Use 0-based index for array
886 line = lines[i - 1].trim();
887 if (line.length == 0) {
888 // console.log("Skipping blank line");
901 if (o.length !== 5) {
902 // other lengths not valid for upload
910 status: 'Failed to find 4 comma-separated values'
914 // console.log("Valid line: ", val);
922 // leave status undefined, this
925 if (o[0].toLowerCase() === 'role') {
926 // not valid for upload, so set status
927 entry.status = 'Header';
928 } else if (o[0].toLowerCase() === 'type') {
929 // not valid for upload, so set status
930 entry.status = 'Header';
932 else if (o[0].toLowerCase() === 'instance') {
933 // not valid for upload, so set status
934 entry.status = 'Header';
936 else if (o[0].toLowerCase() === 'action') {
937 // not valid for upload, so set status
938 entry.status = 'Header';
940 else if (o[0].toLowerCase() === 'name') {
941 // not valid for upload, so set status
942 entry.status = 'Header';
944 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '' || o[4].trim() == '') {
945 // defend against line with only a
947 entry.status = 'Failed to find non-empty values';
956 angular.module('ecompApp').filter('csvToRoleObj',function() {
957 return function(input) {
960 var lines = input.split('\n');
961 // Need 1-based index below
962 for (len = lines.length, i = 1; i <= len; ++i) {
963 // Use 0-based index for array
964 line = lines[i - 1].trim();
965 if (line.length == 0) {
966 // console.log("Skipping blank line");
976 if (o.length === 0 && line.length !== 0) {
977 // other lengths not valid for upload
985 // console.log("Valid line: ", val);
990 // leave status undefined, this
993 if (o[0].toLowerCase() === 'role') {
994 // not valid for upload, so set status
995 entry.status = 'Header';
997 if (o[0].toLowerCase() === 'priority') {
998 // not valid for upload, so set status
999 entry.status = 'Header';
1001 else if (o[0].trim() == '') {
1002 // defend against line with only a
1003 // single comma etc.
1004 entry.status = 'Failed to find non-empty values';