Name

global.PwdWFRequestProcessor

Description

No description available

Script

var PwdWFRequestProcessor = Class.create();
PwdWFRequestProcessor.prototype = {
  TYPE_INFO: "Info",
  TYPE_WARNING: "Warning",
  TYPE_ERROR: "Error",
  RESET_PASSWORD_ACTION : "1",
  STAGE_RESET: "Reset",
  COMPLETED_WITH_SUCCESS: 1,
  COMPLETED_WITH_FAILURE: -1,
  PENDING: 3,
  MASTER_WORKFLOW: "Pwd Reset - Master",

  responseMsg: null,
  history: [],
  activity: [],
  wfResult: {
      pass: false,
      message: ""
  },

  initialize: function() {},

  validatePassword: function(processId, newPwd, userName) {
      var credMgr = new SNC.PwdCredentialStoreManager();
      var credId = credMgr.getCredentialStoreIdByProcessId(processId);
      var isPasswordPolicyEnabled = credMgr.getEnablePasswordPolicy(processId);
      var result = {
          "isPwdValid": false,
          "errorMessage": gs.getMessage("Invalid password")
      };
      if (isPasswordPolicyEnabled) {
          var passwordPolicyId = credMgr.getPasswordPolicyId(processId);
          var jsonResponse = SNC.PasswordPolicyEvaluator.isValidPwdPerPolicyWithMessage(newPwd, passwordPolicyId, userName);
          var validationResponse = JSON.parse(jsonResponse);
          if (validationResponse.success == true) {
              result.isPwdValid = true;
              result.errorMessage = "";
          } else {
              result.errorMessage = gs.getMessage("Invalid password - {0}", validationResponse.message);
          }
      } else {
          var credGr = new GlideRecord('pwd_cred_store');
          if (credGr.get(credId)) {
              var pwdRule = credGr.getValue('pwd_rule');
              var pwdRuleCall = pwdRule + '\nisPasswordValid(password);';
              credGr.setValue('pwd_rule', pwdRuleCall);
              var vars = {
                  'password': newPwd
              };
              var evaluator = new GlideScopedEvaluator();
              var isPwdValid = evaluator.evaluateScript(credGr, 'pwd_rule', vars);
              if (isPwdValid) {
                  result.isPwdValid = true;
                  result.errorMessage = "";
              }
          }
      }
      return JSON.stringify(result);
  },

  startWorkflow: function(sysparm_request_id, sysparm_new_password, isSecure) {
      var LOG_ID = "[PwdAjaxWFRequestProcessor:startWorkflow] ";
      var ctxId = "";
      var trackingMgr = new SNC.PwdTrackingManager();
      var requestId = sysparm_request_id;
      var newPasswd = sysparm_new_password;
      var historyCheckErrorMessage = gs.getMessage("You used that password recently. Choose a different password.");
      var pwdFlowHelper = new PwdFlowHelper();

      // Retrieve request by request id
      var requestVerified = trackingMgr.requestVerified(requestId);

      try {
          // return error if the request is not verified:
          if (!requestVerified) {
              var requestMsg = "Could not verify request: " + requestId;
              trackingMgr.createActivity(PwdConstants.TYPE_WARNING, PwdConstants.STAGE_RESET, requestMsg, requestId);
              var reqMsg = gs.getMessage("{0} Could not verify request: {1}", [LOG_ID, requestId]);
              this._setResponseMessage("failure", reqMsg, requestId);
              return this.responseMsg;
          }

          var processId = trackingMgr.getProcessIdByRequestId(requestId);
          var acceptsPassword = false;
          var gr = new GlideRecord("pwd_process");
          if (gr.get(processId))
              acceptsPassword = !gr.cred_store.type.use_flow || gr.cred_store.type.password_delivery_mechanism == '' || gr.cred_store.type.password_delivery_mechanism == '0';
          var encryptedPassword;

          this._updateRequestAction(processId, requestId);

          // If the cred store does not accept password then skip the encryption logic
          if (acceptsPassword) {
              // auto-generate new password, if needed
              if (gs.nil(newPasswd)) {
                  newPasswd = new SNC.PwdProcessManager().generatePasswordByProcessId(processId);

                  // Fail workflow if we get an empty response
                  if (typeof(newPasswd) == 'undefined' || newPasswd == null || newPasswd == '') {
                      var passwordMsg = 'Empty password generated';
                      trackingMgr.createActivity(PwdConstants.TYPE_WARNING, PwdConstants.STAGE_RESET, passwordMsg, requestId);
                      var genPasswordMsg = gs.getMessage("{0} Empty password generated", LOG_ID);
                      this._setResponseMessage("failure", genPasswordMsg, requestId);
                      return this.responseMsg;
                  }
                  gs.getSession().putProperty('temp_password', newPasswd);
              }
              encryptedPassword = newPasswd;
              if (isSecure == null || isSecure == false) {
                  encryptedPassword = new PasswordResetUtil().encryptWithKMFModule(encryptedPassword);
              }
          }
          trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, "Starting Password Reset Master Subflow", requestId);
          var outputs = pwdFlowHelper.startMasterSubFlow(requestId, encryptedPassword, '', this.RESET_PASSWORD_ACTION);
          if (outputs.is_flow == false && outputs.context_id) {
              ctxId = outputs.context_id.sys_id;
          }

          if (outputs.is_flow == true && outputs.status != 'Error') {
              if (outputs.status == "Success") {
                  trackingMgr.updateRequestStatus(requestId, this.COMPLETED_WITH_SUCCESS);
                  trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, "Flow Completed Successfully", requestId);
              } else {
                  gs.getSession().putProperty('async_pwd_request', 'true');
                  trackingMgr.updateRequestStatus(requestId, this.PENDING);
                  trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, "Password Reset request is Pending with external system", requestId);
              }
          }

          if (outputs.is_flow == false && outputs.context_id == undefined) {
              var errorMsg = "Failed to start password reset process";
              trackingMgr.createActivity(PwdConstants.TYPE_ERROR, PwdConstants.STAGE_RESET, errorMsg, requestId);
              responseErrorMsg = gs.getMessage("{0} Failed to start workflow process", [LOG_ID]);
              this._setResponseMessage("failure", responseErrorMsg, requestId);
              return this.responseMsg;
          } else if (outputs.is_flow == true && outputs.status == 'Error') {
          	if(outputs.error_message != historyCheckErrorMessage)
          		trackingMgr.updateRequestStatus(requestId, this.COMPLETED_WITH_FAILURE);
              trackingMgr.createActivity(PwdConstants.TYPE_ERROR, PwdConstants.STAGE_RESET, 'Password reset failed', requestId);
              this._setResponseMessage("failure", outputs.error_message, requestId);
              return this.responseMsg;
          }


          //Invalidate the token for the user if he/she is resetting the password through a URL
          var request = new GlideRecord("pwd_reset_request");
          if (request.get(requestId))
              SNC.PasswordResetUtil.invalidateTokenForUser(request.user, '');

  		if (!outputs.is_flow || outputs.status == "Success") 
  			this._setResponseMessage("success", "The request has been successfully completed", ctxId);
  		else 
  			this._setResponseMessage("pending", "The request has been successfully submitted and is pending with the external system", ctxId);
          return this.responseMsg;

      } catch (error) {
          var exceptionMsg = gs.getMessage("Exception: {0}", error);
          trackingMgr.createActivity(PwdConstants.TYPE_ERROR, PwdConstants.STAGE_RESET, exceptionMsg, requestId);
          var responseExceptionMsg = gs.getMessage("{0} Exception: {1}", [LOG_ID, error]);
          this._setResponseMessage("failure", responseExceptionMsg, ctxId);
          return this.responseMsg;
      }

  },

  runPostProcessor: function(requestId, processId, status) {
      var LOG_ID = "[PwdWFRequestProcessor:runPostProcessor] ";
      var trackingMgr = new SNC.PwdTrackingManager();
      var gr = new GlideRecord('pwd_process');
      if (!gr.get(processId))
          return false;

      if (!gs.nil(gr.post_processor)) {
          var postProcessorId = gr.post_processor;
          var postProcessorName = gr.post_processor.name;

          try {
              var params = new SNC.PwdExtensionScriptParameter();
              params.resetRequestId = requestId;
              params.wfSuccess = status == "true" ? true : false;
              var postResetExtension = new SNC.PwdExtensionScript(postProcessorId);

              var infoMsg = "Starting post-processor script: " + postProcessorName;
              trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, infoMsg, requestId);

              postResetExtension.process(params);
          } catch (error) {
              var exceptionMsg = gs.getMessage("Error while executing post-processor script: {0}. Error:{1}", [postProcessorName, error]);
              trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, exceptionMsg, requestId);
              var responseExceptionMsg = gs.getMessage("{0} Error while executing post-processor script {1}. Error: {2}",
                  [LOG_ID, postProcessorName, error]);
              return false;
          }
          var successMsg = gs.getMessage("Completed post-processor script: {0}", postProcessorName);
          trackingMgr.createActivity(PwdConstants.TYPE_INFO, PwdConstants.STAGE_RESET, successMsg, requestId);
          var responseSuccessMsg = gs.getMessage("{0} Completed post-processor script: {1}", [LOG_ID, postProcessorName]);
          return true;
      }
  },

  buildWorkflowDetails: function(contextId) {
      var gr = new GlideRecord('wf_history');
      gr.addQuery('context', contextId);
      gr.orderBy('activity_index');
      gr.addJoinQuery('wf_activity', 'activity', 'sys_id');
      gr.query();

      while (gr.next()) {
          var historyDetails = {};
          var activity = gr.getValue('activity');
          this.getWorkFlowActivity(activity);
          historyDetails.activity_result = gr.getValue('result');
          historyDetails.fault_description = gr.getValue('fault_description');
          historyDetails.activity_index = gr.getValue('activity_index');
          historyDetails.sys_id = gr.getValue('sys_id');
          this.history.push(historyDetails);
      }
  },

  getWorkFlowActivity: function(activityId) {
      var gr = new GlideRecord('wf_activity');
      if (gr.get(activityId)) {
          var activityDetials = {};
          activityDetials.name = gr.getValue('name');
          this.activity.push(activityDetials);
      }
  },

  getErrrorMessage: function(executionResult, contextId) {
      this.buildWorkflowDetails(contextId);
      var allActivitiesSucceeded = true;
      // An array of obj representing the state of an activity
      var allActivitiesObj = [];

      // Grab all the activities in the workflow and build an array of objects
      for (var i = 0; i < this.history.length; i++) {
          var tmp = {};
          tmp.name = this.activity[i].name;
          tmp.index = this.history[i].activity_index;
          tmp.result = this.history[i].activity_result;
          if (tmp.result == undefined) {
              tmp.result = "";
          }
          tmp.faultDescription = this.history[i].fault_description;
          if (tmp.faultDescription == undefined) {
              tmp.faultDescription = "";
          }
          allActivitiesObj.push(tmp);
      }

      // Iterate through activity history list to find the first error
      allActivitiesObj.sort(function(a, b) {
          return b.index - a.index;
      });

      var failingActivityObj = {};
      for (var j in allActivitiesObj) {
          var activity = allActivitiesObj[j];
          if (activity.result == undefined)
              continue;

          if (activity.result.match(/failure/i)) {
              allActivitiesSucceeded = false;

              // Check if faultDescription is an json object. If so, this was created via SNC.PwdWorkflowManager().creatError().
              try {
                  failingActivityObj = eval("(" + activity.faultDescription + ")");
              } catch (e) {
                  //The faultDescription was created manually, and not via new SNC.PwdWorkflowManager().getErrorJSONString(...)
                  failingActivityObj.message = activity.faultDescription;
                  failingActivityObj.isFatal = true;
              }
              break;
          }
      }

      var wfGeneralStatus = executionResult.status;
      var message = executionResult.message;
      var value = executionResult.value;

      if (!wfGeneralStatus.match(/success/i) || (!allActivitiesSucceeded)) {
          //Check failure via by workflow result
          this.wfResult.pass = false;
          this.wfResult.message = failingActivityObj.message || "Password reset request failed.";
      } else { //pass
          this.wfResult.pass = true;
      }
      return this.wfResult;
  },


  _setResponseMessage: function(status, msg, value) {
      this.responseMsg = {
          "status": status,
          "message": msg,
          "value": value
      };
  },


  //------------------------------------------------------------------------------------------------------------------
  // Starts a new workflow and returns the new workflow sys Id.
  //------------------------------------------------------------------------------------------------------------------
  _startWorkflow: function(requestId, newPasswd) {
      var workflowName = this.MASTER_WORKFLOW;
      var wf = new Workflow();
      var workflowId = wf.getWorkflowFromName(workflowName);
      var request = new GlideRecord("pwd_reset_request");
      var getRequest = request.get(requestId);

      var gr = wf.startFlow(workflowId, request, 'update', {
          u_request_id: requestId,
          u_new_password: newPasswd
      });
      gr.next();
      var ctxId = gr.getValue('sys_id');
      return ctxId;
  },

  _updateRequestAction: function(processId, requestId) {
      var processSupportsUnlock = 0;
      var proc = new GlideRecord('pwd_process');
      if (proc.get(processId)) {
          processSupportsUnlock = proc.getValue('unlock_account');
      }

      var value = '1'; // Reset Password
      var gr = new GlideRecord('pwd_reset_request');
      if (gr.get(requestId)) {
          var lockState = gr.getValue('lock_state');
          if (processSupportsUnlock == '1' && lockState == '1') {
              value = '3'; // Reset and Unlock
          }
          gr.setValue('action_type', value);
          gr.update();
      }
  },

  type: 'PwdWFRequestProcessor'
};

Sys ID

f2b47c0b67100200a5a0f3b457415afd

Offical Documentation

Official Docs: