2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017 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============================================
36 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
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;
92 // Answers a function that compares properties with the specified name.
93 let getSortOrder = (prop, foldCase) => {
94 return function(a, b) {
95 let aProp = foldCase ? a[prop].toLowerCase() : a[prop];
96 let bProp = foldCase ? b[prop].toLowerCase() : b[prop];
99 else if (aProp < bProp)
106 // Caches the file name supplied by the event handler.
107 $scope.fileChangeHandler = (event, files) => {
108 this.fileSelected = true;
109 this.fileToRead = files[0];
111 $log.debug("BulkRoleAndFunctionsModalCtrl::fileChangeHandler: file is ", this.fileToRead);
112 }; // file change handler
115 * Reads the contents of the file, calls portal endpoints to
116 * validate roles, userIds and existing role assignments;
117 * ultimately builds array of requests to be sent. Creates scope
118 * variable with input file contents for communication with
121 * This function performs a synchronous step-by-step process
122 * using asynchronous promises. The code could all be inline
123 * here but the nesting becomes unwieldy.
125 $scope.readValidateFile = (typeUpload) => {
126 $scope.isProcessing = true;
127 $scope.progressMsg = 'Reading upload file...';
128 var reader = new FileReader();
129 reader.onload = function(event) {
130 if(typeUpload === 'roles'){
131 $scope.uploadFile = $filter('csvToRoleObj')(reader.result);
133 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
135 $scope.progressMsg = 'Fetching & validating application roles...';
137 RoleService.getRoles(appId).then(function (appRoles){
139 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
141 let availableRolesList = JSON.parse(appRoles.data);
142 appRoleFuncsResult = availableRolesList.availableRoles;
143 $scope.evalAppRolesCheckResults();
144 // Re sort by line for the confirmation dialog
145 $scope.uploadFile.sort(getSortOrder('line', false));
146 // We're done, confirm box may show the table
148 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
149 $scope.progressMsg = 'Done.';
150 $scope.isProcessing = false;
152 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
153 $scope.isProcessing = false;
155 } else if (typeUpload === 'roleFunctions'){
156 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
158 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
160 $scope.progressMsg = 'Fetching & validating application role functions...';
161 //fetch app functions
162 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
164 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
165 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
166 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
168 RoleService.getRoles(appId).then(function (appRoles){
170 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
172 let availableRolesList = JSON.parse(appRoles.data);
173 appRoleFuncsResult = availableRolesList.availableRoles;
174 $scope.evalAppRoleFuncsCheckResults();
175 // Re sort by line for the confirmation dialog
176 $scope.uploadFile.sort(getSortOrder('line', false));
177 // We're done, confirm box may show the table
179 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
180 $scope.progressMsg = 'Done.';
181 $scope.isProcessing = false;
183 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
184 $scope.isProcessing = false;
188 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
189 $scope.isProcessing = false;
192 } else if(typeUpload === 'functions'){
193 $scope.uploadFile = $filter('csvToFuncObj')(reader.result);
195 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
197 $scope.progressMsg = 'Fetching & validating the application functions...';
198 // fetch app functions
199 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
201 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
202 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
203 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
204 $scope.verifyFunctions();
205 $scope.evalAppFunctionsCheckResults();
206 // Re sort by line for the confirmation dialog
207 $scope.uploadFile.sort(getSortOrder('line', false));
208 // We're done, confirm box may show the table
210 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
211 $scope.progressMsg = 'Done.';
212 $scope.isProcessing = false;
215 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
216 $scope.isProcessing = false;
219 } else if(typeUpload === 'globalRoleFunctions'){
220 $scope.uploadFile = $filter('csvToRoleFuncObj')(reader.result);
222 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
224 $scope.progressMsg = 'Fetching application global role functions...';
225 //fetch app functions
226 RoleService.getRoleFunctionList(appId).then(function (appFunctions){
228 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
229 let availableRoleFunctionsList = JSON.parse(appFunctions.data);
230 appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
232 RoleService.getRoles(appId).then(function (appRoles){
234 $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
236 let availableRolesList = JSON.parse(appRoles.data);
237 appRoleFuncsResult = availableRolesList.availableRoles;
238 appRoleFuncsResult.forEach(function(appRole) {
239 if(appRole.name.toLowerCase().startsWith("global_")){
240 appGlobalRolesResult.push(appRole);
243 $scope.evalAppRoleFuncsCheckResults(typeUpload);
244 // Re sort by line for the confirmation dialog
245 $scope.uploadFile.sort(getSortOrder('line', false));
246 // We're done, confirm box may show the table
248 $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
249 $scope.progressMsg = 'Done.';
250 $scope.isProcessing = false;
252 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
253 $scope.isProcessing = false;
257 $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
258 $scope.isProcessing = false;
265 // Invoke the reader on the selected file
266 reader.readAsText(this.fileToRead);
270 * Evaluates the result set returned by the role service.
271 * Sets an uploadFile array element status if a functions is not
272 * defined. Reads and writes scope variable uploadFile. Reads
273 * closure variable appFunctionsResult.
275 $scope.verifyFunctions = () => {
277 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: appFunctions is ' + JSON.stringify(appFunctionsResult));
278 // check functions in upload file against defined app functions
279 $scope.uploadFile.forEach( function (uploadRow) {
280 // skip rows that already have a defined status: headers etc.
281 if (uploadRow.status) {
283 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: skip row ' + uploadRow.line);
286 for (var i=0; i < appFunctionsResult.length; i++) {
287 if (uploadRow.type.toUpperCase() === appFunctionsResult[i].type.toUpperCase()
288 && uploadRow.instance.toUpperCase() === appFunctionsResult[i].code.toUpperCase()
289 && uploadRow.action.toUpperCase() === appFunctionsResult[i].action.toUpperCase()) {
291 $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: match on function ' + uploadRow.type,
292 uploadRow.instance, uploadRow.type, uploadRow.type);
297 }; // verifyFunctions
300 * Evaluates the result set of existing functions returned by
301 * the Roleservice and list of functions found in the upload file.
302 * Reads and writes scope variable uploadFile.
303 * Reads closure variable appFunctionsResult.
305 $scope.evalAppFunctionsCheckResults = () => {
307 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
308 $scope.uploadFile.forEach(function (uploadRow) {
309 if (uploadRow.status) {
311 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: skip row ' + uploadRow.line);
314 // Search for the match in the app-functions
316 let isFunctionExist = false;
317 appFunctionsResult.forEach( function (exixtingFuncObj) {
318 if (uploadRow.type.toUpperCase() === exixtingFuncObj.type.toUpperCase()
319 && uploadRow.instance.toUpperCase() === exixtingFuncObj.code.toUpperCase()
320 && uploadRow.action.toUpperCase() === exixtingFuncObj.action.toUpperCase()) {
321 uploadRow.status = 'Function exits!';
322 uploadRow.isCreate = false;
323 isFunctionExist = true;
325 }); // for each result
326 if(!isFunctionExist) {
327 if(/[^a-zA-Z0-9\-\.\_]/.test(uploadRow.type)
328 || (uploadRow.action !== '*'
329 && /[^a-zA-Z0-9\-\.\_]/.test(uploadRow.action))
330 || /[^a-zA-Z0-9\-\:\_\./*]/.test(uploadRow.instance)
331 || /[^a-zA-Z0-9\-\_ \.]/.test(uploadRow.name)){
332 uploadRow.status = 'Invalid function';
333 uploadRow.isCreate = false;
336 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: new function '
339 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
340 uploadRow.status = 'Create';
341 uploadRow.isCreate = true;
345 }; // evalAppFunctionsCheckResults
348 * Evaluates the result set of existing roles returned by
349 * the Roleservice and list of roles found in the upload file.
350 * Reads and writes scope variable uploadFile.
351 * Reads closure variable appRolesResult.
353 $scope.evalAppRolesCheckResults = () => {
355 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: uploadFile length is ' + $scope.uploadFile.length);
356 $scope.uploadFile.forEach(function (uploadRow) {
357 if (uploadRow.status) {
359 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: skip row ' + uploadRow.line);
362 // Search for the match in the app-roles
364 let isRoleExist = false;
365 appRoleFuncsResult.forEach( function (existingRoleObj) {
366 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
367 uploadRow.status = 'Role exits!';
368 uploadRow.isCreate = false;
371 }); // for each result
373 if(/[^a-zA-Z0-9\-\_ \.\/]/.test(uploadRow.role) ||
374 uploadRow.role.toLowerCase().startsWith("global_")){
375 uploadRow.status = 'Invalid role!';
376 uploadRow.isCreate = false;
379 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: new function '
382 // After much back-and-forth I decided a clear indicator is better than blank in the table status column.
383 uploadRow.status = 'Create';
384 uploadRow.isCreate = true;
388 }; // evalAppRolesCheckResults
391 * Evaluates the result set of existing roles returned by
392 * the Roleservice and list of roles found in the upload file.
393 * Reads and writes scope variable uploadFile.
394 * Reads closure variable appRolesResult.
396 $scope.evalAppRoleFuncsCheckResults = (typeUpload) => {
398 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
399 $scope.uploadFile.forEach(function (uploadRow) {
400 if (uploadRow.status) {
402 $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: skip row ' + uploadRow.line);
405 // Search for the match in the app-functions array
406 let isValidFunc = false;
407 appFunctionsResult.forEach(function (existingFuncObj){
408 if(uploadRow.type.toUpperCase() === existingFuncObj.type.toUpperCase()
409 && uploadRow.instance.toUpperCase() === existingFuncObj.code.toUpperCase()
410 && uploadRow.action.toUpperCase() === existingFuncObj.action.toUpperCase()
411 && uploadRow.name.toUpperCase() === existingFuncObj.name.toUpperCase()){
416 let isValidRole = false;
417 let isRoleFuncExist = false;
418 if(typeUpload === 'globalRoleFunctions'){
419 // Search for the match in the app-role array
420 appGlobalRolesResult.forEach( function (existingRoleObj) {
421 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
424 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
425 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
426 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
427 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
428 isRoleFuncExist = true;
433 }); // for each result
435 // Search for the match in the app-role array
436 appRoleFuncsResult.forEach( function (existingRoleObj) {
437 if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
440 existingRoleObj.roleFunctions.forEach(function (existingRoleFuncObj){
441 if(uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
442 && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
443 && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()){
444 isRoleFuncExist = true;
449 }); // for each result
452 uploadRow.isCreate = false;
453 if(typeUpload === 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
454 uploadRow.status = 'Invalid global role function!';
455 } else if(typeUpload !== 'globalRoleFunctions' && (!isValidRole || !isValidFunc)){
456 uploadRow.status = 'Invalid role function!';
457 } else if(typeUpload === 'globalRoleFunctions' && !isRoleFuncExist) {
458 uploadRow.status = 'Add global role function!';
459 uploadRow.isCreate = true;
460 } else if(typeUpload !== 'globalRoleFunctions' && !isRoleFuncExist){
461 uploadRow.status = 'Add role function!';
462 uploadRow.isCreate = true;
463 } else if(typeUpload === 'globalRoleFunctions'){
464 uploadRow.status = 'Global role function exists!';
466 uploadRow.status = 'Role function exists!';
470 }; // evalAppRolesCheckResults
474 * Sends requests to Portal BE requesting application functions assignment.
475 * That endpoint handles creation of the application functions in the
476 * external auth system if necessary. Reads closure variable appFunctionsResult.
477 * Invoked by the Next button on the confirmation dialog.
479 $scope.updateFunctionsInDB = () => {
480 $scope.isProcessing = true;
481 $scope.progressMsg = 'Sending requests to application..';
483 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: request length is ' + appUserRolesRequest.length);
484 var numberFunctionsSucceeded = 0;
486 $scope.uploadFile.forEach(function(appFuncPostData) {
488 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: appFuncPostData is ' + JSON.stringify(appFuncPostData));
489 let updateFunctionsFinalPostData = {
490 type: appFuncPostData.type,
491 code: appFuncPostData.instance,
492 action: appFuncPostData.action,
493 name: appFuncPostData.name
496 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updateFunctionsFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
497 let updatePromise = {};
498 if(appFuncPostData.isCreate){
499 updatePromise = functionalMenuService.saveBulkFunction(appId, updateFunctionsFinalPostData).promise().then(res => {
501 $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updated successfully: ' + JSON.stringify(res));
502 numberFunctionsSucceeded++;
504 // What to do if one of many fails??
505 $log.error('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB failed: ', err);
506 confirmBoxService.showInformation(
507 'Failed to update the application functions. ' +
508 'Error: ' + err.status).then(isConfirmed => { });
512 promises.push(updatePromise);
515 // Run all the promises
516 $q.all(promises).then(function(){
517 $scope.isProcessing = false;
518 confirmBoxService.showInformation('Processed ' + numberFunctionsSucceeded + ' records.').then(isConfirmed => {
519 // Close the upload-confirm dialog
523 }; // updateFunctionsInDB
526 * Sends requests to Portal BE requesting application functions assignment.
527 * That endpoint handles creation of the application role in the
528 * external auth system if necessary. Reads closure variable appRoleFuncResult.
529 * Invoked by the Next button on the confirmation dialog.
531 $scope.updateRolesInDB = () => {
532 $scope.isProcessing = true;
533 $scope.progressMsg = 'Sending requests to application..';
535 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: request length is ' + appUserRolesRequest.length);
536 var numberRolesSucceeded = 0;
538 $scope.uploadFile.forEach(function(appRolePostData) {
539 let priority = parseInt(appRolePostData.priority);
541 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: appRolePostData is ' + JSON.stringify(appFuncPostData));
542 let uplaodRolePostData = "";
544 uplaodRolePostData = {
545 name: appRolePostData.role,
549 uplaodRolePostData = {
550 name: appRolePostData.role,
551 priority: appRolePostData.priority,
556 role: uplaodRolePostData,
561 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: uplaodRoleFinalPostData is ' + JSON.stringify(uplaodRoleFinalPostData));
562 let updatePromise = {};
563 if(appRolePostData.isCreate){
564 updatePromise = functionalMenuService.saveBulkRole(appId, JSON.stringify(postData)).promise().then(res => {
566 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: updated successfully: ' + JSON.stringify(res));
567 numberRolesSucceeded++;
569 // What to do if one of many fails??
570 $log.error('BulkRoleAndFunctionsModalCtrl::updateRolesInDB failed: ', err);
571 confirmBoxService.showInformation(
572 'Failed to update the application role. ' +
573 'Error: ' + err.status).then(isConfirmed => { });
577 promises.push(updatePromise);
580 // Run all the promises
581 $q.all(promises).then(function(){
582 $scope.isProcessing = false;
583 confirmBoxService.showInformation('Processed ' + numberRolesSucceeded + ' records. Please sync roles').then(isConfirmed => {
584 // Close the upload-confirm dialog
588 }; // updateRolesInDB
591 * Sends requests to Portal BE requesting role function assignment.
592 * That endpoint handles adding role function in the external auth system
593 * if necessary.Invoked by the Next button on the confirmation dialog.
595 $scope.updateRoleFunctionsInDB = () => {
596 $scope.isProcessing = true;
597 $scope.progressMsg = 'Sending requests to application..';
599 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
600 var numberRoleFunctionSucceeded = 0;
602 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
604 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
605 let updateRoleFunctionFinalPostData = {
606 roleName: appRoleFuncPostData.role,
607 type: appRoleFuncPostData.type,
608 instance: appRoleFuncPostData.instance,
609 action: appRoleFuncPostData.action,
610 name: appRoleFuncPostData.name,
611 isGlobalRolePartnerFunc: false
614 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
615 let updatePromise = {};
616 if(appRoleFuncPostData.isCreate){
617 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateRoleFunctionFinalPostData).promise().then(res => {
619 $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
620 numberRoleFunctionSucceeded++;
622 // What to do if one of many fails??
623 $log.error('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB failed: ', err);
624 confirmBoxService.showInformation(
625 'Failed to update the application role function. ' +
626 'Error: ' + err.status).then(isConfirmed => { });
630 promises.push(updatePromise);
633 // Run all the promises
634 $q.all(promises).then(function(){
635 $scope.isProcessing = false;
636 confirmBoxService.showInformation('Processed ' + numberRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal').then(isConfirmed => {
637 // Close the upload-confirm dialog
641 }; // updateRoleFunctionsInDB
644 * Sends requests to Portal requesting global role functions assignment.
645 * That endpoint handles updating global role functions in the external auth system
646 * if necessary. Invoked by the Next button on the confirmation dialog.
648 $scope.updateGlobalRoleFunctionsInDB = () => {
649 $scope.isProcessing = true;
650 $scope.progressMsg = 'Sending requests to application..';
652 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
653 var numberGlobalRoleFunctionSucceeded = 0;
655 $scope.uploadFile.forEach(function(appRoleFuncPostData) {
657 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
658 let updateGlobalRoleFunctionFinalPostData = {
659 roleName: appRoleFuncPostData.role,
660 type: appRoleFuncPostData.type,
661 instance: appRoleFuncPostData.instance,
662 action: appRoleFuncPostData.action,
663 name: appRoleFuncPostData.name,
664 isGlobalRolePartnerFunc: true
667 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
668 let updatePromise = {};
669 if(appRoleFuncPostData.isCreate){
670 updatePromise = functionalMenuService.updateBulkRoleFunction(appId, updateGlobalRoleFunctionFinalPostData).promise().then(res => {
672 $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
673 numberGlobalRoleFunctionSucceeded++;
675 // What to do if one of many fails??
676 $log.error('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB failed: ', err);
677 confirmBoxService.showInformation(
678 'Failed to update the global role partner function. ' +
679 'Error: ' + err.status).then(isConfirmed => { });
683 promises.push(updatePromise);
686 // Run all the promises
687 $q.all(promises).then(function(){
688 $scope.isProcessing = false;
689 confirmBoxService.showInformation('Processed ' + numberGlobalRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal').then(isConfirmed => {
690 // Close the upload-confirm dialog
694 }; // updateGlobalRoleFunctionsInDB
696 // Sets the variable that hides/reveals the user controls
697 $scope.step2 = () => {
698 this.fileSelected = false;
699 $scope.selectedFile = null;
700 $scope.fileModel = null;
704 // Navigate between dialog screens using step number: 1,2,...
705 $scope.navigateBack = () => {
707 this.fileSelected = false;
710 // Opens a dialog to show the data to be uploaded.
711 // Invoked by the upload button on the bulk user dialog.
712 $scope.confirmUpload = (typeUpload) => {
714 $scope.readValidateFile(typeUpload);
715 // Dialog shows progress
716 if(typeUpload === 'functions'){
718 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-functions-confirm.html',
720 sizeClass: 'modal-medium',
724 } else if(typeUpload === 'roleFunctions'){
726 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-role-functions-confirm.html',
728 sizeClass: 'modal-medium',
733 } else if(typeUpload === 'roles'){
735 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-roles-confirm.html',
737 sizeClass: 'modal-medium',
741 } else if(typeUpload === 'globalRoleFunctions'){
743 templateUrl: 'app/views/role/bulk-upload-dialogs/bulk-upload-global-role-functions-confirm.html',
745 sizeClass: 'modal-medium',
752 // Invoked by the Cancel button on the confirmation dialog.
753 $scope.cancelUpload = () => {
760 BulkRoleAndFunctionsModalCtrl.$inject = ['$scope', '$log', '$filter', '$q', '$modalInstance', '$modal', 'ngDialog', 'message', 'confirmBoxService', 'usersService', 'applicationsService', 'functionalMenuService', 'RoleService'];
761 angular.module('ecompApp').controller('BulkRoleAndFunctionsModalCtrl', BulkRoleAndFunctionsModalCtrl);
763 angular.module('ecompApp').directive('fileChange', ['$parse', function($parse){
767 link : function($scope, element, attrs, ngModel) {
768 var attrHandler = $parse(attrs['fileChange']);
769 var handler=function(e) {
770 $scope.$apply(function() {
771 attrHandler($scope, { $event:e, files:e.target.files } );
772 $scope.selectedFile = e.target.files[0].name;
775 element[0].addEventListener('change',handler,false);
780 angular.module('ecompApp').filter('csvToFuncObj',function() {
781 return function(input) {
784 var lines = input.split('\n');
785 // Need 1-based index below
786 for (len = lines.length, i = 1; i <= len; ++i) {
787 // Use 0-based index for array
788 line = lines[i - 1].trim();
789 if (line.length == 0) {
790 // console.log("Skipping blank line");
802 if (o.length !== 4) {
803 // other lengths not valid for upload
810 status: 'Failed to find 4 comma-separated values'
814 // console.log("Valid line: ", val);
821 // leave status undefined, this
824 if (o[0].toLowerCase() === 'type') {
825 // not valid for upload, so set status
826 entry.status = 'Header';
828 else if (o[0].toLowerCase() === 'instance') {
829 // not valid for upload, so set status
830 entry.status = 'Header';
832 else if (o[0].toLowerCase() === 'action') {
833 // not valid for upload, so set status
834 entry.status = 'Header';
836 else if (o[0].toLowerCase() === 'name') {
837 // not valid for upload, so set status
838 entry.status = 'Header';
840 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '') {
841 // defend against line with only a
843 entry.status = 'Failed to find non-empty values';
852 angular.module('ecompApp').filter('csvToRoleFuncObj',function() {
853 return function(input) {
856 var lines = input.split('\n');
857 // Need 1-based index below
858 for (len = lines.length, i = 1; i <= len; ++i) {
859 // Use 0-based index for array
860 line = lines[i - 1].trim();
861 if (line.length == 0) {
862 // console.log("Skipping blank line");
875 if (o.length !== 5) {
876 // other lengths not valid for upload
884 status: 'Failed to find 4 comma-separated values'
888 // console.log("Valid line: ", val);
896 // leave status undefined, this
899 if (o[0].toLowerCase() === 'role') {
900 // not valid for upload, so set status
901 entry.status = 'Header';
902 } else if (o[0].toLowerCase() === 'type') {
903 // not valid for upload, so set status
904 entry.status = 'Header';
906 else if (o[0].toLowerCase() === 'instance') {
907 // not valid for upload, so set status
908 entry.status = 'Header';
910 else if (o[0].toLowerCase() === 'action') {
911 // not valid for upload, so set status
912 entry.status = 'Header';
914 else if (o[0].toLowerCase() === 'name') {
915 // not valid for upload, so set status
916 entry.status = 'Header';
918 else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '' || o[4].trim() == '') {
919 // defend against line with only a
921 entry.status = 'Failed to find non-empty values';
930 angular.module('ecompApp').filter('csvToRoleObj',function() {
931 return function(input) {
934 var lines = input.split('\n');
935 // Need 1-based index below
936 for (len = lines.length, i = 1; i <= len; ++i) {
937 // Use 0-based index for array
938 line = lines[i - 1].trim();
939 if (line.length == 0) {
940 // console.log("Skipping blank line");
950 if (o.length === 0 && line.length !== 0) {
951 // other lengths not valid for upload
959 // console.log("Valid line: ", val);
964 // leave status undefined, this
967 if (o[0].toLowerCase() === 'role') {
968 // not valid for upload, so set status
969 entry.status = 'Header';
971 if (o[0].toLowerCase() === 'priority') {
972 // not valid for upload, so set status
973 entry.status = 'Header';
975 else if (o[0].trim() == '') {
976 // defend against line with only a
978 entry.status = 'Failed to find non-empty values';