Name

sn_anon_rc.ARCReportKeyBase

Description

Base class of methods used for anonymizes report secret key generation. Edit script include ARCReportKey to override specific methods or add custom functionality.

Script

var ARCReportKeyBase = Class.create();
ARCReportKeyBase.prototype = {
  REPORT_FIELDS: ["state", "assignment_group", "sys_created_on"],

  initialize: function() {},

  /* Generate key for report with sys_id and table
   *  @param reportSysId the sys_id of the report 
   *  @param tableName the table where the report exists
   *  @return Object JSON including status (success/failure). When successful, the JSON contains the secret key and report details.
   */
  generateReportKeyForRecordLookUp: function(reportSysId, tableName) {
      //get the report record to generate a record for
      if (!gs.tableExists(tableName))
          return this._getErrorResponse(gs.getMessage("Table doesn't exist"));

      var anonymousReport = new GlideRecord(tableName);
      if (anonymousReport.get(reportSysId))
          return this.generateReportKeyForRecord(anonymousReport);

      return this._getErrorResponse(gs.getMessage("Record not found"));
  },

  /* Generate key for report
   *  @param anonymousReport GlideRecord of the anonymous report
   *  @return Object JSON including status (success/failure). When successful, the JSON contains the secret key and report details.
   */
  generateReportKeyForRecord: function(anonymousReport) {
      //validate the report exists
      if (anonymousReport === null || !anonymousReport.isValid())
          return this._getErrorResponse(gs.getMessage("Invalid report"));

      //validate the table extends task
      var tableName = anonymousReport.getRecordClassName();
      var reportSysId = anonymousReport.getUniqueValue();
      if (!(new GlideTableHierarchy(tableName).getRoot() === "task"))
          return this._getErrorResponse(gs.getMessage("Invalid report type"));

      //check if a secret key already exist for the report
      var findReportKeyGr = new GlideRecord("sn_anon_rc_report_key");
      findReportKeyGr.addQuery("report", reportSysId);
      findReportKeyGr.query();

      if (findReportKeyGr.hasNext())
          return this._getErrorResponse(gs.getMessage("Secret key already exists for selected report"));

      //there is no key generated for the case, generate a key
  	var keyLength = gs.getProperty("sn_anon_rc.secret_key_length", ARCConstants.MIN_SECRET_KEY_LENGTH);
      var key = GlideSecureRandomUtil.getSecureRandomString(keyLength >= ARCConstants.MIN_SECRET_KEY_LENGTH ? keyLength : ARCConstants.MIN_SECRET_KEY_LENGTH);
      var newReportKeyGr = new GlideRecord("sn_anon_rc_report_key");
      newReportKeyGr.initialize();
      newReportKeyGr.setValue("key_hash", new GlideDigest().getSHA256Hex("" + key + reportSysId));
      newReportKeyGr.setValue("table_name", tableName);
      newReportKeyGr.setValue("report", reportSysId);
      newReportKeyGr.insert();

      //get data to display. return the key on first time report creation
      var jsonReponse = this._getJsonReportData(anonymousReport);
      jsonReponse["secret_key"] = key;
      return jsonReponse;
  },

  /* Log error and return object containing error message
   *  @param message the error to produce
   *  @return Object JSON containing the error
   */
  _getErrorResponse: function(message) {
      gs.error(message);
      return {
          "status": "failure",
          "message": message
      };
  },

  /* Return the report matching the report number and report key
   *  @param reportNumber the number on the report
   *  @param testKey the key to check against the report
   *  @return GlideRecord of the anonymous report when successful, otherwise return a String error message
   */
  _findReportMatchingNumberAndKey: function(reportNumber, testKey) {
      if (reportNumber && testKey) {
          var findReportKeyGr = new GlideRecord("sn_anon_rc_report_key");
          findReportKeyGr.addQuery("report.number", reportNumber);
          findReportKeyGr.query();

          while (findReportKeyGr.next()) {
              var testHash = new GlideDigest().getSHA256Hex("" + testKey + findReportKeyGr.getValue("report"));
              if (findReportKeyGr.getValue("key_hash") === testHash) {
                  var report = findReportKeyGr.report.getRefRecord();
                  if (report !== null && report.isValid() && report.getValue("sys_class_name") === findReportKeyGr.getValue("table_name"))
                      return report;
              }
          }
      }

      return gs.getMessage("Report not found");
  },

  /* Submit report data from user given report number and key
   *  @param reportNumber the number on the report
   *  @param testKey the user-submitted key to check against the report
   *  @param additionalComments the comments the user submitted
   *  @return Object JSON with status success/failure
   */
  validateAndSubmitReportData: function(reportNumber, testKey, additionalComments) {
      var reportResponse = this._findReportMatchingNumberAndKey(reportNumber, testKey);
      if (typeof reportResponse === 'string') 
          return this._getErrorResponse(reportResponse);
      else if (reportResponse !== null && reportResponse.isValid()) {
          //add the notes to the case and update the report
          var notes = reportResponse.comments = additionalComments;
          reportResponse.update();
          return {
              "status": "success",
              "message": gs.getMessage("Successfully added comments to report.")
          };
      }
  },

  /* Get report data for user to view given report number and key
   *  @param reportNumber the number on the report
   *  @param testKey the user-submitted key to check against the report
   *  @return jsonResponse containing report data when successful, otherwise return error response
   */
  validateAndGetReportData: function(reportNumber, testKey) {
      var reportResponse = this._findReportMatchingNumberAndKey(reportNumber, testKey);
      if (typeof reportResponse === "string") 
          return this._getErrorResponse(reportResponse);
      else 
          return this._getJsonReportData(reportResponse);
  },

  /* Create a JSON object for ARC ticket widget from an anonymous report
   *  @param reportGr the GlideRecord of the report to create the JSON object
   *  @return a JSON obect with report data
   */
  _getJsonReportData: function(reportGr) {
      var jsonResponse = {};
      if (reportGr !== null && reportGr.isValid()) {
          //indicate the function success
          jsonResponse["status"] = "success";

          //add fields with metadata
          this.REPORT_FIELDS.forEach(function(field) {
              var data = {};
  			var elementDescriptor = reportGr[field].getED();
  			data["value"] = reportGr.getValue(field);
  			data["name"] = field;
  			data["display_value"] = reportGr.getDisplayValue(field);
  			data["label"] = elementDescriptor.getLabel();
  			//Replace assigment group label to assigned to
  			if(field == "assignment_group")
  				data["label"] = gs.getMessage("Assigned to");
  			data["type"] = elementDescriptor.getInternalType();
  			jsonResponse[field] = data;
          });
  		
  		//add comments
  		var journal = new GlideRecord('sys_journal_field');
  		journal.addQuery('element_id', reportGr.getUniqueValue());
  		journal.orderBy('sys_created_on');
  		journal.query();
  		var journalEntries = [];
  		var isFirstMessage = true;
  		while(journal.next()){
  			var entry = {};
  			if(journal.getValue('element') != 'comments')
  				continue;
  			
  			entry["value"] = GlideSecurityUtils.escapeScript(journal.getValue('value'));
  			//if first system generated message, replace guest with anonymous user
  			if(isFirstMessage) {
  				entry["value"] = entry["value"].replace("Guest", gs.getMessage("Anonymous User"));
  				isFirstMessage = false;
  			}
  			entry["element"] = journal.getValue('element');
  			entry["sys_created_on"] = journal.getValue('sys_created_on');
  			entry["sys_created_by"] = journal.getValue('sys_created_by');
  			entry["field_label"] = gs.getMessage("Additional comments");
  			var commentUser = new GlideRecord('sys_user');
  			commentUser.addQuery('user_name', journal.getValue('sys_created_by'));
  			commentUser.query();
  			if(commentUser.next()){
  				entry["user_sys_id"] = commentUser.getUniqueValue();
  				entry["name"] = commentUser.getDisplayValue("name");
  				//Replace guest with anonymous user
  				if(commentUser.getValue("name") == "Guest")
  					entry["name"] = gs.getMessage("Anonymous User");
  			}
  			journalEntries.unshift(entry);
  		}
  		jsonResponse["journal_entries"] = journalEntries;
  		
          //add report number
          jsonResponse["number"] = reportGr.getDisplayValue("number");
      } else 
          jsonResponse = this._getErrorResponse(gs.getMessage("Report is invalid."));
      return jsonResponse;
  },

  type: 'ARCReportKeyBase'
};

Sys ID

50dc2aef77823010acc5f95ecc5a997c

Offical Documentation

Official Docs: