Added new componetnts inside page modules
[portal.git] / portal-FE-common / src / app / pages / role / bulk-upload-role / bulk-upload-role.component.ts
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
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
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
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
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
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.
33  *
34  * ============LICENSE_END============================================
35  *
36  * 
37  */
38 import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
39 import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
40 import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
41 import { RoleService, FunctionalMenuService } from 'src/app/shared/services';
42 import { MatTableDataSource } from '@angular/material';
43
44 @Component({
45   selector: 'app-bulk-upload-role',
46   templateUrl: './bulk-upload-role.component.html',
47   styleUrls: ['./bulk-upload-role.component.scss']
48 })
49 export class BulkUploadRoleComponent implements OnInit {
50
51
52   @Input() title: string;
53   closeResult: string;
54   @Input() appId: string;
55   @Input() dialogState: number;
56   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' }
61   ];
62   selectedUploadDropdown: any;
63   uploadTypeInstruction = "Function Type, Function Instance, Function Action, Function Name";
64   uploadCheck: boolean;
65   isProcessing: boolean;
66   conformMsg: string;
67   progressMsg: string;
68   uploadFile: any;
69   // Roles fetched from Role service
70   appRoleFuncsResult = [];
71   // Functions fetched from Role service
72   appFunctionsResult = [];
73   // Global  roles fetched from Role service
74   appGlobalRolesResult = [];
75   changeUploadTypeInstruction(typeInstrc) {
76     switch (typeInstrc) {
77       case 'functions':
78         this.uploadTypeInstruction = "Function Type, Function Instance, Function Action, Function Name";
79         break;
80       case 'roles':
81         this.uploadTypeInstruction = "Role Name, Priority (Optional)";
82         break;
83       case 'roleFunctions':
84         this.uploadTypeInstruction = "Role Name, Function Type, Function Instance, Function Action, Function Name";
85         break;
86       default:
87         this.uploadTypeInstruction = "Global Role Name, Function Type, Function Instance, Function Action, Function Name";
88     }
89   };
90
91   fileModel: {};
92   step1: boolean;
93   fileSelected: boolean;
94   isProcessedRecords: boolean;
95   displayedFunctionColumns: string[] = ['line', 'type', 'instance', 'action', 'name', 'status'];
96   uploadFunctionsDataSource = new MatTableDataSource(this.uploadFile);
97   displayedRoleColumns: string[] = ['line', 'name', 'priority', 'status'];
98   uploadRolesDataSource = new MatTableDataSource(this.uploadFile);
99   displayedRoleFunctionColumns: string[] = ['line', 'role', 'type', 'instance', 'action', 'name', 'status'];
100   uploadRoleFunctionsDataSource = new MatTableDataSource(this.uploadFile);
101   displayedGlobalRoleFunctionColumns: string[] = ['line', 'role', 'type', 'instance', 'action', 'name', 'status'];
102   uploadGlobalRoleFunctionsDataSource = new MatTableDataSource(this.uploadFile);
103
104   constructor(public activeModal: NgbActiveModal, public ngbModal: NgbModal, private roleService: RoleService, private functionalMenuService: FunctionalMenuService) { }
105
106   ngOnInit() {
107     this.selectedUploadDropdown = this.ngRepeatBulkUploadOptions[0];
108     this.fileModel = {};
109     // Enable modal controls
110     this.step1 = true;
111
112     this.fileSelected = false;
113
114     this.isProcessedRecords = false;
115   }
116
117   navigateUploadScreen() {
118     if (this.selectedUploadDropdown.value === 'functions') {
119       this.title = 'Bulk Upload Functions Confirmation';
120     } else if (this.selectedUploadDropdown.value === 'roles') {
121       this.title = 'Bulk Upload Roles Confirmation';
122     } else if (this.selectedUploadDropdown.value === 'roleFunctions') {
123       this.title = 'Bulk Upload Role-Functions Confirmation';
124     } else {
125       this.title = 'Bulk Upload Global-Role-Functions Confirmation';
126     }
127     this.dialogState = 2;
128   }
129
130   navigateSelectTypeUpload() {
131     this.title = 'Bulk Upload Role-Function';
132     this.dialogState = 1;
133   }
134
135   updateInDB() {
136     if (this.selectedUploadDropdown.value === 'functions') {
137       this.updateFunctionsInDB();
138     } else if (this.selectedUploadDropdown.value === 'roles') {
139       this.updateRolesInDB();
140     } else if (this.selectedUploadDropdown.value === 'roleFunctions') {
141       this.updateRoleFunctionsInDB();
142     } else {
143       this.updateGlobalRoleFunctionsInDB();
144     }
145   }
146   // Answers a function that compares properties with the specified name.
147   getSortOrder = (prop, foldCase) => {
148     return function (a, b) {
149       let aProp = foldCase ? a[prop].toLowerCase() : a[prop];
150       let bProp = foldCase ? b[prop].toLowerCase() : b[prop];
151       if (aProp > bProp)
152         return 1;
153       else if (aProp < bProp)
154         return -1;
155       else
156         return 0;
157     }
158   }
159
160   onFileLoad(fileLoadedEvent) {
161     const textFromFileLoaded = fileLoadedEvent.target.result;
162     let lines = textFromFileLoaded.split('\n');
163     var result = [];
164     var len, i, line, o;
165     switch (this.selectedUploadDropdown.value) {
166       case 'functions':
167         for (len = lines.length, i = 1; i <= len; ++i) {
168           line = lines[i - 1].trim();
169
170           if (line.length == 0) {
171             // console.log("Skipping blank line");
172             result.push({
173               line: i,
174               type: '',
175               instance: '',
176               action: '',
177               name: '',
178               status: 'Blank line'
179             });
180             continue;
181           }
182           o = line.split(',');
183           if (o.length !== 4) {
184             // other lengths not valid for upload
185             result.push({
186               line: i,
187               type: o[0],
188               instance: o[1],
189               action: o[2],
190               name: '',
191               status: 'Failed to find 4 comma-separated values'
192             });
193           }
194           else {
195             // console.log("Valid line: ", val);
196             let entry = {
197               line: i,
198               type: o[0],
199               instance: o[1],
200               action: o[2],
201               name: o[3]
202               // leave status undefined, this
203               // could be valid.
204             };
205             if (o[0].toLowerCase() === 'type') {
206               // not valid for upload, so set status
207               entry['status'] = 'Header';
208             }
209             else if (o[0].toLowerCase() === 'instance') {
210               // not valid for upload, so set status
211               entry['status'] = 'Header';
212             }
213             else if (o[0].toLowerCase() === 'action') {
214               // not valid for upload, so set status
215               entry['status'] = 'Header';
216             }
217             else if (o[0].toLowerCase() === 'name') {
218               // not valid for upload, so set status
219               entry['status'] = 'Header';
220             }
221             else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '') {
222               // defend against line with only a
223               // single comma etc.
224               entry['status'] = 'Failed to find non-empty values';
225             }
226             result.push(entry);
227           } // len 2
228         }// for
229         break;
230       case 'roles':
231         for (len = lines.length, i = 1; i <= len; ++i) {
232           line = lines[i - 1].trim();
233           if (line.length == 0) {
234             // console.log("Skipping blank line");
235             result.push({
236               line: i,
237               role: '',
238               priority: '',
239               status: 'Blank line'
240             });
241             continue;
242           }
243           o = line.split(',');
244           if (o.length === 0 && line.length !== 0) {
245             // other lengths not valid for upload
246             result.push({
247               line: i,
248               role: o[0],
249               priority: null
250             });
251           }
252           else {
253             // console.log("Valid line: ", val);
254             let entry = {
255               line: i,
256               role: o[0],
257               priority: o[1]
258               // leave status undefined, this
259               // could be valid.
260             };
261             if (o[0].toLowerCase() === 'role') {
262               // not valid for upload, so set status
263               entry['status'] = 'Header';
264             }
265             if (o[0].toLowerCase() === 'priority') {
266               // not valid for upload, so set status
267               entry['status'] = 'Header';
268             }
269             else if (o[0].trim() == '') {
270               // defend against line with only a
271               // single comma etc.
272               entry['status'] = 'Failed to find non-empty values';
273             }
274             result.push(entry);
275           } // len 2
276         }
277         break;
278       case 'roleFunctions':
279       case 'globalRoleFunctions':
280         for (len = lines.length, i = 1; i <= len; ++i) {
281           line = lines[i - 1].trim();
282           if (line.length == 0) {
283             // console.log("Skipping blank line");
284             result.push({
285               line: i,
286               role: '',
287               type: '',
288               instance: '',
289               action: '',
290               name: '',
291               status: 'Blank line'
292             });
293             continue;
294           }
295           o = line.split(',');
296           if (o.length !== 5) {
297             // other lengths not valid for upload
298             result.push({
299               line: i,
300               role: o[0],
301               type: o[1],
302               instance: o[2],
303               action: o[3],
304               name: '',
305               status: 'Failed to find 4 comma-separated values'
306             });
307           }
308           else {
309             // console.log("Valid line: ", val);
310             let entry = {
311               line: i,
312               role: o[0],
313               type: o[1],
314               instance: o[2],
315               action: o[3],
316               name: o[4]
317               // leave status undefined, this
318               // could be valid.
319             };
320             if (o[0].toLowerCase() === 'role') {
321               // not valid for upload, so set status
322               entry['status'] = 'Header';
323             } else if (o[0].toLowerCase() === 'type') {
324               // not valid for upload, so set status
325               entry['status'] = 'Header';
326             }
327             else if (o[0].toLowerCase() === 'instance') {
328               // not valid for upload, so set status
329               entry['status'] = 'Header';
330             }
331             else if (o[0].toLowerCase() === 'action') {
332               // not valid for upload, so set status
333               entry['status'] = 'Header';
334             }
335             else if (o[0].toLowerCase() === 'name') {
336               // not valid for upload, so set status
337               entry['status'] = 'Header';
338             }
339             else if (o[0].trim() == '' || o[1].trim() == '' || o[2].trim() == '' || o[3].trim() == '' || o[4].trim() == '') {
340               // defend against line with only a
341               // single comma etc.
342               entry['status'] = 'Failed to find non-empty values';
343             }
344             result.push(entry);
345           } // len 2
346         }
347         break;
348       default:
349         result = [];
350         break;
351     }
352     return result;
353   }
354
355
356   onFileSelect(input: HTMLInputElement) {
357     var validExts = new Array(".csv", ".txt");
358     var fileExt = input.value;
359     fileExt = fileExt.substring(fileExt.lastIndexOf('.'));
360     if (validExts.indexOf(fileExt) < 0) {
361       const modalFileErrorRef = this.ngbModal.open(ConfirmationModalComponent);
362       modalFileErrorRef.componentInstance.title = 'Confirmation';
363       modalFileErrorRef.componentInstance.message = 'Invalid file selected, valid files are of ' +
364         validExts.toString() + ' types.'
365       this.uploadCheck = false;
366       return false;
367     }
368     else {
369       const files = input.files;
370       this.isProcessing = true;
371       this.conformMsg = '';
372       this.isProcessedRecords = true;
373       this.progressMsg = 'Reading upload file..';
374       if (files && files.length) {
375         this.uploadCheck = true;
376         const fileToRead = files[0];
377         const fileReader = new FileReader();
378         fileReader.readAsText(fileToRead, "UTF-8");
379         fileReader.onloadend = (e) => {
380           this.uploadFile = this.onFileLoad(e);
381           if (this.selectedUploadDropdown.value === 'roles') {
382             // if (debug){
383             // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + this.uploadFile.length);
384             // }
385             this.progressMsg = 'Fetching & validating application roles...';
386             // fetch app roles
387             this.roleService.getRoles(this.appId).toPromise().then((appRoles: any) => {
388               // if (debug){
389               // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
390               // }
391               let availableRolesList = JSON.parse(appRoles.data);
392               this.appRoleFuncsResult = availableRolesList.availableRoles;
393               this.evalAppRolesCheckResults();
394               // Re sort by line for the confirmation dialog
395               this.uploadFile.sort(this.getSortOrder('line', false));
396               // We're done, confirm box may show the  table
397               // if (debug)
398               // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
399               this.progressMsg = 'Done.';
400               this.isProcessing = false;
401               this.isProcessedRecords = false;
402             }, (error) => {
403               // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
404               this.isProcessing = false;
405               this.isProcessedRecords = false;
406             });
407
408             this.uploadRolesDataSource = new MatTableDataSource(this.uploadFile);
409             this.dialogState = 3;
410           } else if (this.selectedUploadDropdown.value === 'roleFunctions') {
411             // if (debug) {
412             // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + this.uploadFile.length);
413             // }
414             this.progressMsg = 'Fetching & validating application role functions...';
415             //fetch app functions
416             this.roleService.getRoleFunctionList(this.appId).toPromise().then((appFunctions: any) => {
417               // if (debug)
418               // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
419               let availableRoleFunctionsList = JSON.parse(appFunctions.data);
420               this.appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
421               // fetch app roles
422               this.roleService.getRoles(this.appId).toPromise().then((appRoles: any) => {
423                 // if (debug) {
424                 // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
425                 // }
426                 let availableRolesList = JSON.parse(appRoles.data);
427                 this.appRoleFuncsResult = availableRolesList.availableRoles;
428                 this.evalAppRoleFuncsCheckResults(this.selectedUploadDropdown.value);
429                 // Re sort by line for the confirmation dialog
430                 this.uploadFile.sort(this.getSortOrder('line', false));
431                 // We're done, confirm box may show the  table
432                 // if (debug)
433                 // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
434                 this.progressMsg = 'Done.';
435                 this.isProcessing = false;
436                 this.isProcessedRecords = false;
437               }, (error) => {
438                 // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
439                 this.isProcessing = false;
440                 this.isProcessedRecords = false;
441               });
442             }, (error) => {
443               // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
444               this.isProcessing = false;
445             }
446             );
447             this.uploadRoleFunctionsDataSource = new MatTableDataSource(this.uploadFile);
448             this.dialogState = 3;
449           } else if (this.selectedUploadDropdown.value === 'functions') {
450             // if (debug) {
451             // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + this.uploadFile.length);
452             // }
453             this.progressMsg = 'Fetching & validating the application functions...';
454             // fetch app functions
455             this.roleService.getRoleFunctionList(this.appId).toPromise().then((appFunctions: any) => {
456               // if (debug)
457               // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
458               let availableRoleFunctionsList = JSON.parse(appFunctions.data);
459               this.appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
460               this.verifyFunctions();
461               this.evalAppFunctionsCheckResults();
462               // Re sort by line for the confirmation dialog
463               this.uploadFile.sort(this.getSortOrder('line', false));
464               // We're done, confirm box may show the  table
465               // if (debug)
466               // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
467               this.progressMsg = 'Done.';
468               this.isProcessing = false;
469               this.isProcessedRecords = false;
470             }, (error) => {
471               // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
472               this.isProcessing = false;
473               this.isProcessedRecords = false;
474             }
475             );
476             this.uploadFunctionsDataSource = new MatTableDataSource(this.uploadFile);
477             this.dialogState = 3;
478           } else if (this.selectedUploadDropdown.value === 'globalRoleFunctions') {
479             // if (debug) {
480             // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile onload: data length is ' + this.uploadFile.length);
481             // }
482             this.progressMsg = 'Fetching application global role functions...';
483             //fetch app functions
484             this.roleService.getRoleFunctionList(this.appId).toPromise().then((appFunctions: any) => {
485               // if (debug)
486               // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoleFunctionList returned " + JSON.stringify(appFunctions.data));
487               let availableRoleFunctionsList = JSON.parse(appFunctions.data);
488               this.appFunctionsResult = availableRoleFunctionsList.availableRoleFunctions;
489               // fetch app roles
490               this.roleService.getRoles(this.appId).toPromise().then((appRoles: any) => {
491                 // if (debug) {
492                 // $log.debug("BulkRoleAndFunctionsModalCtrl::readValidateFile: getRoles returned " + JSON.stringify(appFunctions.data));
493                 // }
494                 let availableRolesList = JSON.parse(appRoles.data);
495                 this.appRoleFuncsResult = availableRolesList.availableRoles;
496                 this.appRoleFuncsResult.forEach((appRole) => {
497                   if (appRole.name.toLowerCase().startsWith("global_")) {
498                     this.appGlobalRolesResult.push(appRole);
499                   }
500                 });
501                 this.evalAppRoleFuncsCheckResults(this.selectedUploadDropdown.value);
502                 // Re sort by line for the confirmation dialog
503                 this.uploadFile.sort(this.getSortOrder('line', false));
504                 // We're done, confirm box may show the  table
505                 // if (debug)
506                 // $log.debug('BulkRoleAndFunctionsModalCtrl::readValidateFile inner-then ends');
507                 this.progressMsg = 'Done.';
508                 this.isProcessing = false;
509                 this.isProcessedRecords = false;
510               }, (error) => {
511                 // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app roles info');
512                 this.isProcessing = false;
513                 this.isProcessedRecords = false;
514               });
515               this.uploadGlobalRoleFunctionsDataSource = new MatTableDataSource(this.uploadFile);
516               this.dialogState = 3;
517             }, (error) => {
518               // $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app functions info');
519               this.isProcessing = false;
520             }
521             );
522           }
523         }
524       }
525     }
526   }
527
528
529   /**
530    * Evaluates the result set returned by the role service.
531    * Sets an uploadFile array element status if a functions is not
532    * defined. Reads and writes scope variable uploadFile. Reads
533    * closure variable appFunctionsResult.
534    */
535   verifyFunctions() {
536     // if (debug)
537     // $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: appFunctions is ' + JSON.stringify(appFunctionsResult));
538     // check functions in upload file against defined app functions
539     this.uploadFile.forEach((uploadRow) => {
540       // skip rows that already have a defined status: headers etc.
541       if (uploadRow.status) {
542         // if (debug)
543         // $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: skip row ' + uploadRow.line);
544         return;
545       }
546       for (var i = 0; i < this.appFunctionsResult.length; i++) {
547         if (uploadRow.type.toUpperCase() === this.appFunctionsResult[i].type.toUpperCase()
548           && uploadRow.instance.toUpperCase() === this.appFunctionsResult[i].code.toUpperCase()
549           && uploadRow.action.toUpperCase() === this.appFunctionsResult[i].action.toUpperCase()) {
550           // if (debug)
551           // $log.debug('BulkRoleAndFunctionsModalCtrl::verifyFunctions: match on function ' + uploadRow.type,
552           // uploadRow.instance, uploadRow.type,  uploadRow.type);
553           break;
554         }
555       }
556     }); // foreach
557   }; // verifyFunctions
558
559   /**
560  * Evaluates the result set of existing functions returned by 
561  * the Roleservice and list of functions found in the upload file. 
562  * Reads and writes scope variable uploadFile. 
563  * Reads closure variable appFunctionsResult.
564  */
565   evalAppFunctionsCheckResults() {
566     // if (debug)
567     // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: uploadFile length is ' + $scope.uploadFile.length);
568     this.uploadFile.forEach((uploadRow) => {
569       if (uploadRow.status) {
570         // if (debug)
571         // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: skip row ' + uploadRow.line);
572         return;
573       }
574       // Search for the match in the app-functions
575       // array
576       let isFunctionExist = false;
577       this.appFunctionsResult.forEach((exixtingFuncObj) => {
578         if (uploadRow.type.toUpperCase() === exixtingFuncObj.type.toUpperCase()
579           && uploadRow.instance.toUpperCase() === exixtingFuncObj.code.toUpperCase()
580           && uploadRow.action.toUpperCase() === exixtingFuncObj.action.toUpperCase()) {
581           uploadRow.status = 'Function exits!';
582           uploadRow.isCreate = false;
583           isFunctionExist = true;
584         }
585       }); // for each result
586       if (!isFunctionExist) {
587         if (/[^a-zA-Z0-9\-\.\_]/.test(uploadRow.type)
588           || (uploadRow.action !== '*'
589             && /[^a-zA-Z0-9\-\.\_]/.test(uploadRow.action))
590           || /[^a-zA-Z0-9\-\:\_\./*]/.test(uploadRow.instance)
591           || /[^a-zA-Z0-9\-\_ \.]/.test(uploadRow.name)) {
592           uploadRow.status = 'Invalid function';
593           uploadRow.isCreate = false;
594         } else {
595           // if (debug){
596           // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppFunctionsCheckResults: new function ' 
597           // + uploadRow);
598           // }
599           // After much back-and-forth I decided a clear  indicator is better than blank in the table  status column.
600           uploadRow.status = 'Create';
601           uploadRow.isCreate = true;
602         }
603       }
604     }); // for each row
605   }; // evalAppFunctionsCheckResults
606
607
608   /**
609    * Evaluates the result set of existing roles returned by 
610    * the Roleservice and list of roles found in the upload file. 
611    * Reads and writes scope variable uploadFile. 
612    * Reads closure variable appRolesResult.
613    */
614   evalAppRolesCheckResults() {
615     // if (debug)
616     // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: uploadFile length is ' + this.uploadFile.length);
617     this.uploadFile.forEach((uploadRow) => {
618       if (uploadRow.status) {
619         // if (debug)
620         // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: skip row ' + uploadRow.line);
621         return;
622       }
623       // Search for the match in the app-roles
624       // array
625       let isRoleExist = false;
626       this.appRoleFuncsResult.forEach((existingRoleObj) => {
627         if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
628           uploadRow.status = 'Role exits!';
629           uploadRow.isCreate = false;
630           isRoleExist = true;
631         }
632       }); // for each result
633       if (!isRoleExist) {
634         if (/[^a-zA-Z0-9\-\_ \.\/]/.test(uploadRow.role) ||
635           uploadRow.role.toLowerCase().startsWith("global_")) {
636           uploadRow.status = 'Invalid role!';
637           uploadRow.isCreate = false;
638         } else {
639           // if (debug){
640           // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRolesCheckResults: new function ' 
641           // + uploadRow);
642           // }
643           // After much back-and-forth I decided a clear  indicator is better than blank in the table  status column.
644           uploadRow.status = 'Create';
645           uploadRow.isCreate = true;
646         }
647       }
648     }); // for each row
649   }; // evalAppRolesCheckResults
650
651   /**
652    * Evaluates the result set of existing roles returned by 
653    * the Roleservice and list of roles found in the upload file. 
654    * Reads and writes scope variable uploadFile. 
655    * Reads closure variable appRolesResult.
656    */
657   evalAppRoleFuncsCheckResults(typeUpload) {
658     // if (debug)
659     // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: uploadFile length is ' + this.uploadFile.length);
660     this.uploadFile.forEach((uploadRow) => {
661       if (uploadRow.status) {
662         // if (debug)
663         // $log.debug('BulkRoleAndFunctionsModalCtrl::evalAppRoleFuncsCheckResults: skip row ' + uploadRow.line);
664         return;
665       }
666       // Search for the match in the app-functions array
667       let isValidFunc = false;
668       this.appFunctionsResult.forEach((existingFuncObj) => {
669         if (uploadRow.type.toUpperCase() === existingFuncObj.type.toUpperCase()
670           && uploadRow.instance.toUpperCase() === existingFuncObj.code.toUpperCase()
671           && uploadRow.action.toUpperCase() === existingFuncObj.action.toUpperCase()
672           && uploadRow.name.toUpperCase() === existingFuncObj.name.toUpperCase()) {
673           isValidFunc = true;
674         }
675       });
676
677       let isValidRole = false;
678       let isRoleFuncExist = false;
679       if (typeUpload === 'globalRoleFunctions') {
680         // Search for the match in the app-role array
681         this.appGlobalRolesResult.forEach((existingRoleObj) => {
682           if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
683             isValidRole = true;
684             if (isValidFunc) {
685               existingRoleObj.roleFunctions.forEach((existingRoleFuncObj) => {
686                 if (uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
687                   && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
688                   && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()) {
689                   isRoleFuncExist = true;
690                 }
691               });
692             }
693           }
694         }); // for each result
695       } else {
696         // Search for the match in the app-role array
697         this.appRoleFuncsResult.forEach((existingRoleObj) => {
698           if (uploadRow.role.toUpperCase() === existingRoleObj.name.toUpperCase()) {
699             isValidRole = true;
700             if (isValidFunc) {
701               existingRoleObj.roleFunctions.forEach((existingRoleFuncObj) => {
702                 if (uploadRow.type.toUpperCase() === existingRoleFuncObj.type.toUpperCase()
703                   && uploadRow.instance.toUpperCase() === existingRoleFuncObj.code.toUpperCase()
704                   && uploadRow.action.toUpperCase() === existingRoleFuncObj.action.toUpperCase()) {
705                   isRoleFuncExist = true;
706                 }
707               });
708             }
709           }
710         }); // for each result
711       }
712
713       uploadRow.isCreate = false;
714       if (typeUpload === 'globalRoleFunctions' && (!isValidRole || !isValidFunc)) {
715         uploadRow.status = 'Invalid global role function!';
716       } else if (typeUpload !== 'globalRoleFunctions' && (!isValidRole || !isValidFunc)) {
717         uploadRow.status = 'Invalid role function!';
718       } else if (typeUpload === 'globalRoleFunctions' && !isRoleFuncExist) {
719         uploadRow.status = 'Add global role function!';
720         uploadRow.isCreate = true;
721       } else if (typeUpload !== 'globalRoleFunctions' && !isRoleFuncExist) {
722         uploadRow.status = 'Add role function!';
723         uploadRow.isCreate = true;
724       } else if (typeUpload === 'globalRoleFunctions') {
725         uploadRow.status = 'Global role function exists!';
726       } else {
727         uploadRow.status = 'Role function exists!';
728       }
729
730     }); // for each row
731   }; // evalAppRolesCheckResults
732
733
734   /**
735    * Sends requests to Portal BE requesting application functions assignment.
736  * That endpoint handles creation of the application functions in the 
737  * external auth system if necessary. Reads closure variable appFunctionsResult.
738  * Invoked by the Next button on the confirmation dialog.
739  */
740   updateFunctionsInDB() {
741     this.isProcessing = true;
742     this.conformMsg = '';
743     this.isProcessedRecords = true;
744     this.progressMsg = 'Sending requests to application..';
745     // if (debug)
746     // $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: request length is ' + appUserRolesRequest.length);
747     var numberFunctionsSucceeded = 0;
748     let promises = [];
749     this.uploadFile.forEach((appFuncPostData) => {
750       // if (debug)
751       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: appFuncPostData is ' + JSON.stringify(appFuncPostData));
752       let updateFunctionsFinalPostData = {
753         type: appFuncPostData.type,
754         code: appFuncPostData.instance,
755         action: appFuncPostData.action,
756         name: appFuncPostData.name
757       };
758       // if (debug)
759       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updateFunctionsFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
760       let updatePromise = {};
761       if (appFuncPostData.isCreate) {
762         updatePromise = this.functionalMenuService.saveBulkFunction(this.appId, updateFunctionsFinalPostData).toPromise().then(res => {
763           // if (debug)
764           // $log.debug('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB: updated successfully: ' + JSON.stringify(res));
765           numberFunctionsSucceeded++;
766         }).catch(err => {
767           // What to do if one of many fails??
768           // $log.error('BulkRoleAndFunctionsModalCtrl::updateFunctionsInDB failed: ', err);
769           const modalErrorRef = this.ngbModal.open(ConfirmationModalComponent);
770           modalErrorRef.componentInstance.title = 'Error';
771           modalErrorRef.componentInstance.message = 'Failed to update the application functions.' + 'Error: ' + err.status;
772         }).finally(() => {
773         });
774       }
775       promises.push(updatePromise);
776     }); // for each
777
778     // Run all the promises
779     Promise.all(promises).then(() => {
780       this.conformMsg = 'Processed ' + numberFunctionsSucceeded + ' records.';
781       this.isProcessing = false;
782       this.isProcessedRecords = true;
783       this.uploadFile = [];
784       this.dialogState = 2;
785     });
786   }; // updateFunctionsInDB
787
788   /**
789  * Sends requests to Portal BE requesting application functions assignment.
790 * That endpoint handles creation of the application role in the 
791 * external auth system if necessary. Reads closure variable appRoleFuncResult.
792 * Invoked by the Next button on the confirmation dialog.
793 */
794   updateRolesInDB() {
795     this.isProcessing = true;
796     this.conformMsg = '';
797     this.isProcessedRecords = true;
798     this.progressMsg = 'Sending requests to application..';
799     // if (debug)
800     // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: request length is ' + appUserRolesRequest.length);
801     var numberRolesSucceeded = 0;
802     let promises = [];
803     this.uploadFile.forEach((appRolePostData) => {
804       let priority = parseInt(appRolePostData.priority);
805       // if (debug)
806       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: appRolePostData is ' + JSON.stringify(appFuncPostData));
807       let uplaodRolePostData = {};
808       if (isNaN(priority)) {
809         uplaodRolePostData = {
810           name: appRolePostData.role,
811           active: true,
812         }
813       } else {
814         uplaodRolePostData = {
815           name: appRolePostData.role,
816           priority: appRolePostData.priority,
817           active: true,
818         }
819       }
820       var postData = {
821         role: uplaodRolePostData,
822         roleFunctions: [],
823         childRoles: []
824       }
825       // if (debug)
826       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: uplaodRoleFinalPostData is ' + JSON.stringify(uplaodRoleFinalPostData));
827       let updatePromise = {};
828       if (appRolePostData.isCreate) {
829         updatePromise = this.functionalMenuService.saveBulkRole(this.appId, JSON.stringify(postData)).toPromise().then(res => {
830           // if (debug)
831           // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRolesInDB: updated successfully: ' + JSON.stringify(res));
832           numberRolesSucceeded++;
833         }).catch(err => {
834           // What to do if one of many fails??
835           // $log.error('BulkRoleAndFunctionsModalCtrl::updateRolesInDB failed: ', err);
836           const modalErrorRef = this.ngbModal.open(ConfirmationModalComponent);
837           modalErrorRef.componentInstance.title = 'Error';
838           modalErrorRef.componentInstance.message = 'Failed to update the application role. ' +
839             'Error: ' + err.status;
840         }).finally(() => {
841         });
842       }
843       promises.push(updatePromise);
844     }); // for each
845
846     // Run all the promises
847     Promise.all(promises).then(() => {
848       if (numberRolesSucceeded == 0) {
849         this.conformMsg = 'Processed ' + numberRolesSucceeded + ' records';
850       } else {
851         this.conformMsg = 'Processed ' + numberRolesSucceeded + ' records. Please sync roles to reflect in portal';
852       } this.isProcessing = false;
853       this.isProcessedRecords = true;
854       this.uploadFile = [];
855       this.dialogState = 2;
856     });
857   }; // updateRolesInDB
858
859   /**
860  * Sends requests to Portal BE requesting role function assignment.
861  * That endpoint handles adding role function in the external auth system
862  * if necessary.Invoked by the Next button on the confirmation dialog.
863  */
864   updateRoleFunctionsInDB() {
865     this.isProcessing = true;
866     this.conformMsg = '';
867     this.isProcessedRecords = true;
868     this.progressMsg = 'Sending requests to application..';
869     // if (debug)
870     // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
871     var numberRoleFunctionSucceeded = 0;
872     let promises = [];
873     this.uploadFile.forEach((appRoleFuncPostData) => {
874       // if (debug)
875       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
876       let updateRoleFunctionFinalPostData = {
877         roleName: appRoleFuncPostData.role,
878         type: appRoleFuncPostData.type,
879         instance: appRoleFuncPostData.instance,
880         action: appRoleFuncPostData.action,
881         name: appRoleFuncPostData.name,
882         isGlobalRolePartnerFunc: false
883       };
884       // if (debug)
885       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
886       let updatePromise = {};
887       if (appRoleFuncPostData.isCreate) {
888         updatePromise = this.functionalMenuService.updateBulkRoleFunction(this.appId, updateRoleFunctionFinalPostData).toPromise().then(res => {
889           // if (debug)
890           // $log.debug('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
891           numberRoleFunctionSucceeded++;
892         }).catch(err => {
893           // What to do if one of many fails??
894           // $log.error('BulkRoleAndFunctionsModalCtrl::updateRoleFunctionsInDB failed: ', err);
895           const modalErrorRef = this.ngbModal.open(ConfirmationModalComponent);
896           modalErrorRef.componentInstance.title = 'Error';
897           modalErrorRef.componentInstance.message = 'Failed to update the application role function. ' +
898             'Error: ' + err.status;
899         }).finally(() => {
900         });
901       }
902       promises.push(updatePromise);
903     }); // for each
904
905     // Run all the promises
906     Promise.all(promises).then(() => {
907       if (numberRoleFunctionSucceeded == 0) {
908         this.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records';
909       } else {
910         this.conformMsg = 'Processed ' + numberRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
911       } this.isProcessing = false;
912       this.isProcessedRecords = true;
913       this.uploadFile = [];
914       this.dialogState = 2;
915     });
916   }; // updateRoleFunctionsInDB
917
918   /**
919  * Sends requests to Portal requesting global role functions assignment.
920  * That endpoint handles updating global role functions in the external auth system
921  * if necessary. Invoked by the Next button on the confirmation dialog.
922  */
923   updateGlobalRoleFunctionsInDB() {
924     this.isProcessing = true;
925     this.conformMsg = '';
926     this.isProcessedRecords = true;
927     this.progressMsg = 'Sending requests to application..';
928     // if (debug)
929     // $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: request length is ' + appUserRolesRequest.length);
930     var numberGlobalRoleFunctionSucceeded = 0;
931     let promises = [];
932     this.uploadFile.forEach((appRoleFuncPostData) => {
933       // if (debug)
934       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: appRoleFuncPostData is ' + JSON.stringify(appFuncPostData));
935       let updateGlobalRoleFunctionFinalPostData = {
936         roleName: appRoleFuncPostData.role,
937         type: appRoleFuncPostData.type,
938         instance: appRoleFuncPostData.instance,
939         action: appRoleFuncPostData.action,
940         name: appRoleFuncPostData.name,
941         isGlobalRolePartnerFunc: true
942       };
943       // if (debug)
944       // $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updateRoleFunctionFinalPostData is ' + JSON.stringify(updateFunctionsFinalPostData));
945       let updatePromise = {};
946       if (appRoleFuncPostData.isCreate) {
947         updatePromise = this.functionalMenuService.updateBulkRoleFunction(this.appId, updateGlobalRoleFunctionFinalPostData).toPromise().then(res => {
948           // if (debug)
949           // $log.debug('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB: updated successfully: ' + JSON.stringify(res));
950           numberGlobalRoleFunctionSucceeded++;
951         }).catch(err => {
952           // What to do if one of many fails??
953           // $log.error('BulkRoleAndFunctionsModalCtrl::updateGlobalRoleFunctionsInDB failed: ', err);
954           const modalErrorRef = this.ngbModal.open(ConfirmationModalComponent);
955           modalErrorRef.componentInstance.title = 'Error';
956           modalErrorRef.componentInstance.message = 'Failed to update the global role partner function. ' +
957             'Error: ' + err.status;
958         }).finally(() => {
959         });
960       }
961       promises.push(updatePromise);
962     }); // for each
963
964     // Run all the promises
965     Promise.all(promises).then(() => {
966       if (numberGlobalRoleFunctionSucceeded == 0) {
967         this.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records';
968       } else {
969         this.conformMsg = 'Processed ' + numberGlobalRoleFunctionSucceeded + ' records. Please sync roles to reflect in portal';
970       }
971       this.isProcessing = false;
972       this.isProcessedRecords = true;
973       this.uploadFile = [];
974       this.dialogState = 2;
975     });
976   }; // updateGlobalRoleFunctionsInDB
977
978 }