Skip to content

Instantly share code, notes, and snippets.

@jmbauguess
Last active December 4, 2015 19:02
Show Gist options
  • Save jmbauguess/9387a102227e382fd10f to your computer and use it in GitHub Desktop.
Save jmbauguess/9387a102227e382fd10f to your computer and use it in GitHub Desktop.
Handles validation of template strings so users cannot submit/save bad templates
/**
* @description Validates that a change request's CI is a valid type based on change type
* @type {Class}
*/
var ChangeCIValidation = Class.create();
ChangeCIValidation.prototype = Object.extendsObject(AbstractAjaxProcessor, {
/**
* @description Validates that a CI is the appropriate class
* @param {String} ci The sys_id of a CI
* @param {String} type A change type
* @return {Boolean} True if the values are acceptable
*/
validate: function(ci, type) {
var ciRecord = new GlideRecord('cmdb_ci');
if (ciRecord.get(ci)) {
if (type == 'Std-Application' &&
ciRecord.sys_class_name != "cmdb_ci_application_software") {
return false;
} else if (type != 'Std-Application' &&
ciRecord.sys_class_name == "cmdb_ci_application_software") {
return false;
}
}
return true;
},
/**
* @description AJAX wrapper for validating CIs/Change Type
* @return {Boolean} True if the values are acceptable
*/
validateAJAX: function() {
return this.validate(this.getParameter('sysparm_ci'),
this.getParameter('sysparm_ctype'));
},
type: 'ChangeCIValidation'
});
var template = current.template.split('^');
template.pop();
var templateMap = {};
for (var temp in template) {
var item = template[temp].split('=');
var fieldName = item[0];
templateMap[fieldName] = item[1];
}
if (templateMap['cmdb_ci']) {
var actionToDo = new ChangeCIValidation().validate(templateMap["cmdb_ci"], templateMap["type"]);
current.setAbortAction(!actionToDo);
gs.addErrorMessage("The Type and CI must be a valid combination");
}
if (templateMap["u_life_cycle_status"]) {
current.template = current.template.toString().replace("u_life_cycle_status=" + item[1], "u_life_cycle_status=" + validateLCS(item[1]));
}
if (templateMap["approval"]) {
current.template = current.template.toString().replace("approval=" + item[1], "approval=not requested");
}
if (templateMap["u_preapproved"]) {
current.template = current.template.toString().replace("u_preapproved=" + item[1], "u_preapproved=false");
}
/**
* @description Handles validation of template strings so users cannot submit/save bad templates
* @type {Class}
*/
var TemplateValidator = Class.create();
TemplateValidator.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
/**
* @description The table for holding template validations
* @type {String}
*/
VALIDATIONS: 'x_scni_template_va_template_validations',
/**
* @description The ServiceNow ArrayUtil
* @type {ArrayUtil}
*/
AU: new global.ArrayUtil(),
/**
* @description An array of error messages
* @type {Array}
*/
ERRORS: [],
/**
* @description Validates a template based on conditions set
* @param {String} template The template string
* @param {String} table The table for the template
* @return {String} A string of errors
*/
validate: function(template, table) {
var validations = this.getValidations(table),
templateArray = template.toString().split('^'),
temp;
while (validations.next()) {
this.validateTemplates(validations, templateArray);
}
return this.ERRORS.toString();
},
/**
* @description The AJAX Handler for the main method
* @return {String} A string of errors
*/
validateAJAX: function() {
return this.validate(this.getParameter('sysparm_template_string'),
this.getParameter('sysparm_current_table'));
},
/**
* @description Gets validation records from the validation table
* @param {String} table The name of a table
* @return {GlideRecord} Records that match the table
*/
getValidations: function(table) {
var validations = new GlideRecord(this.VALIDATIONS);
validations.addQuery('table.name', table);
validations.query();
return validations;
},
/**
* @description Processes the validations for each value in the template array
* @param {GlideRecord} validations The validation record
* @param {Array} templateArray The array of template fields and values
*/
validateTemplates: function(validations, templateArray) {
for (var temp in templateArray) {
if (templateArray.hasOwnProperty(temp)) {
this.checkValues(validations, templateArray[temp]);
}
}
},
/**
* @description Determines if the value in the template needs to be pushed to ERRORS
* @param {GlideRecord} validations The validation record
* @param {String} temp The template field and value
*/
checkValues: function(validations, temp) {
var item = temp.toString().split('=');
if (validations.field_name.element == item[0]) {
if (!this.isValueValid(validations.unacceptable_values, item[1])) {
this.ERRORS.push(this.generateMessage(validations, item));
}
}
},
/**
* @description Generates an error message
* @param {GlideRecord} validations The validation record
* @param {Array} item The template item (field/value)
* @return {String} [description]
*/
generateMessage: function(validations, item) {
return item[0] + " has an invalid value of " + item[1] +
". It cannot be " + validations.unacceptable_values + ".";
},
/**
* @description Uses the ServiceNow ArrayUtil to check if a value is ok
* @param {String} test The value to test against
* @param {String} value The value from the template
* @return {Boolean} True if the value is ok
*/
isValueValid: function(test, value) {
var testArray = test.toString().split(',');
if (this.AU.contains(testArray, value)) {
return false;
}
return true;
},
/**
* @description Returns a reference qualifier that gets fields based on the table
* Note: GlideTableHierarchy would be nice here, but it doesn't work right now. Instead, we'll hope task is all we're doing.
* @param {GlideRecord} current The current validation record
* @return {String} A reference qualifier for the field name
*/
fieldRefQual: function(current) {
return 'nameIN' + current.table.name + ",task";
},
'type' : 'TemplateValidator'
});
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue == '') {
return;
}
g_form.clearMessages();
validateTemplate(newValue);
function validateTemplate(newValue) {
var ajax = new GlideAjax('TemplateValidator');
ajax.addParam('sysparm_name', 'validateAJAX');
ajax.addParam('sysparm_template_string', newValue.toString());
ajax.addParam('sysparm_current_table', 'change_request');
ajax.getXML(HandleResponse);
function HandleResponse(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
if (answer != '') {
g_form.addErrorMessage(answer);
}
}
}
}
/**
* @description Handles validation of template strings so users cannot submit/save bad templates
* NOTE: Also replaces values with predefined default
* @type {Class}
*/
var TemplateValidator = Class.create();
TemplateValidator.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
/**
* @description The table for holding template validations
* @type {String}
*/
VALIDATIONS: 'x_scni_template_va_template_validations',
/**
* @description The ServiceNow ArrayUtil
* @type {ArrayUtil}
*/
AU: new global.ArrayUtil(),
/**
* @description An array of error messages
* @type {Array}
*/
ERRORS: [],
CURRENT : {},
/**
* @description Validates a template based on conditions set
* @param {String} template The template string
* @param {String} table The table for the template
* @return {String} A string of errors
*/
validate: function(template, table, current) {
var validations = this.getValidations(table),
templateArray = template.toString().split('^'),
temp;
this.CURRENT = current;
while (validations.next()) {
this.validateTemplates(validations, templateArray);
}
current = this.CURRENT;
return this.ERRORS.toString();
},
/**
* @description The AJAX Handler for the main method
* @return {String} A string of errors
*/
validateAJAX: function() {
return this.validate(this.getParameter('sysparm_template_string'),
this.getParameter('sysparm_current_table'));
},
/**
* @description Gets validation records from the validation table
* @param {String} table The name of a table
* @return {GlideRecord} Records that match the table
*/
getValidations: function(table) {
var validations = new GlideRecord(this.VALIDATIONS);
validations.addQuery('table.name', table);
validations.query();
return validations;
},
/**
* @description Processes the validations for each value in the template array
* @param {GlideRecord} validations The validation record
* @param {Array} templateArray The array of template fields and values
*/
validateTemplates: function(validations, templateArray) {
for (var temp in templateArray) {
if (templateArray.hasOwnProperty(temp)) {
this.checkValues(validations, templateArray[temp]);
}
}
},
/**
* @description Determines if the value in the template needs to be pushed to ERRORS
* @param {GlideRecord} validations The validation record
* @param {String} temp The template field and value
*/
checkValues: function(validations, temp) {
var item = temp.toString().split('=');
if (validations.field_name.element == item[0]) {
if (!this.isValueValid(validations.unacceptable_values, item[1])) {
this.CURRENT.template = this.CURRENT.template.toString().replace(item[0] + "=" + item[1],
item[0] + "=" + validations.default);
this.ERRORS.push(this.generateMessage(validations, item));
}
}
},
/**
* @description Generates an error message
* @param {GlideRecord} validations The validation record
* @param {Array} item The template item (field/value)
* @return {String} [description]
*/
generateMessage: function(validations, item) {
return item[0] + " has an invalid value of " + item[1] +
". It cannot be " + validations.unacceptable_values + ".";
},
/**
* @description Uses the ServiceNow ArrayUtil to check if a value is ok
* @param {String} test The value to test against
* @param {String} value The value from the template
* @return {Boolean} True if the value is ok
*/
isValueValid: function(test, value) {
var testArray = test.toString().split(',');
if (this.AU.contains(testArray, value)) {
return false;
}
return true;
},
/**
* @description Returns a reference qualifier that gets fields based on the table
* Note: GlideTableHierarchy would be nice here, but it doesn't work right now. Instead, we'll hope task is all we're doing.
* @param {GlideRecord} current The current validation record
* @return {String} A reference qualifier for the field name
*/
fieldRefQual: function(current) {
return 'nameIN' + current.table.name + ",task";
},
'type' : 'TemplateValidator'
});
function onBefore(current, previous) {
var validator = new x_scni_template_va.TemplateValidator();
var messages = validator.validate(current.template, current.table, current);
if (messages.length > 0) {
gs.addErrorMessage(messages.toString());
current.setAbortAction(true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment