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';