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