Name
x_8821_code.Analysis
Description
var t = new x_8821_code.Analysis(); try{ gs.info(JSON.stringify(t.run(), , )); }catch(e){ gs.info(JSON.stringify(e)); }//
Script
var Analysis = Class.create();
Analysis.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
/*
Server Side
- [] Avoid Global BR
- [] Before BR Should not insert or update records
- [] Avoid Eval
- [] Avoid Sysids in code
- [] BR should be wrapped in a function
- [] Avoid undocumented apis
- [] Check if script/code does not make use of foreign tables without GlideRecordSecure
- [] search transform scripts onbefore for .insert() .update() as they shouldnt do that.
- [] search code for the use of getResponse() as its a soap method that should be used.
- [] search transform maps where business rules are enabled and suggest to disable them.
Client Scripts
- [x] Avoid $
- [x] Avoid top
- [x] Avoid window
- [x] Avoid $j
- [x] Avoid jQuery
- [x] Avoid document
- [x] Use GlideAjax instead of GlideRecord
- [] g_form.field.getReference() Should use a callback
UI Policies
- [x] Avoid $
- [x] Avoid top
- [x] Avoid window
- [x] Avoid $j
- [x] Avoid jQuery
- [x] Avoid document
- [x] Use GlideAjax instead of GlideRecord
- [] g_form.field.getReference() Should use a callback
Tables to Check
[x]sys_script_include,
[x]sys_script_client,
[x]sys_script,
sys_processor,
sysevent_script_action,
sysauto_script,
sys_script_fix,
sys_ui_script
sp_widget,
sys_ui_page,
sys_ui_action,
*/
run: function(){
var returnObj = {};
returnObj.businessRules = this._getBusinessRules();
returnObj.scriptIncludes = this._getScriptIncludes();
returnObj.uiPolicies = this._getUIPoliciesScripts();
returnObj.clientScripts = this._getClientScripts();
return returnObj;
},
instanceCreateDate: (function(){
var properties = new GlideRecord('sys_properties');
if(properties.get('name','instance_name')){
return new GlideDateTime(properties.sys_created_on);
} else {
var gdt = new GlideDateTime();
gdt.addYearsLocalTime(-2);
return gdt;
}
})(),
instance:(function(){
return 'https://' + gs.getProperty('instance_name') + '.service-now.com/nav_to.do?uri=';
})(),
clientTests: [
/*{
regex: /^(function on)((.*)\n)+\}$/gm,
error: "Not wrapped in function, should be function on*(){}",
expect: true
},*/{
regex: /(\s)\$(\.|\()/gm,
error: "Do not use Prototype ($) as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)\$j(\.|\()/gm,
error: "Do not use jQuery ($j) as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)jQuery(\.|\()/gm,
error: "Do not use jQuery as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)top(\.|\[)/gm,
error: "Do not use top as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)window(\.|\[)/gm,
error: "Do not use window as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)document(\.|\[)/gm,
error: "Do not use document as it's not supported on SP or Mobile",
expect: false
},{
regex: /(\s)eval\(/gm,
error: "Do not use eval, use bracket notation if possible",
expect: false
},{
regex: /new GlideRecord/gm,
error: "Use GlideAjax instead of GlideRecord",
expect: false
},{
regex: /\.getReference\(\)/gm,
error: "getReference should have a callback",
expect: false
},{
regex: /control./gm,
error: "Do not use control as it's not supported on SP or Mobile",
expect: false
},{
regex: /\.getXMLWait/gm,
error: "Do not use getXMLWait as it's not supported on SP or Mobile",
expect: false
},{
regex: /('|"|`)[a-f0-9]{32}('|"|`)/gm,
error: "Do not use hard-coded sys_ids",
expect: false
},
],
serverTests: [
{
regex: /('|"|`)[a-f0-9]{32}('|"|`)/gm,
error: "Do not use hard-coded sys_ids",
expect: false
},{
regex: /(\s)eval\(/gm,
error: "Do not use eval",
expect: false
},{
regex: /(\s)\getRowCount\(/gm,
error: "GlideAggregate should be used instead of getRowCount",
expect: false
}/*,{
regex: /(\s)\GlideRecord\(/gm,
error: "GlideRecordSecure should be used when possible",
expect: false
}*/
],
liveCheck: function(){
var inputObj = JSON.parse(this.getParameter('sysparm_obj'));
var returnObj = {
from:"server",
input: inputObj,
errors: []
};
try{
returnObj.serverTest = inputObj.type === 'server';
returnObj.clientTest = inputObj.type === 'client';
if(returnObj.serverTest){
this.serverTests.forEach(function(test){
var passes = test.regex.test(inputObj.script);
var result = passes == test.expect;
returnObj.errors.push({"test": test,"passed":result});
});
}
if(returnObj.clientTest){
this.clientTests.forEach(function(test){
var passes = test.regex.test(inputObj.script);
var result = passes == test.expect;
returnObj.errors.push({"test": test,"passed":result});
});
}
}catch(err){
returnObj.err = err;
}
return JSON.stringify(returnObj);
},
_search: function(term){
var returnArr = [];
var cs = new sn_codesearch.CodeSearch();
cs.setSearchAllScopes(true);//search all scopes
cs.setLimit(1000);
//cs.setSearchTable('sys_script');//business rule
var results = cs.search(term);
results.forEach(function(result){
if(result.hits.length>0){
var returnObj = {};
result.hits.forEach(function(hit){
returnObj.table = hit.className;
returnObj.name = hit.name;
returnObj.matches = hit.matches;
});
returnArr.push(returnObj);
}
});
return returnArr;
},
_getServerScripts: function(table){
var returnArr = [];
var scriptFields = [];
var dictionaryGR = new GlideRecord('sys_dictionary');
dictionaryGR.addEncodedQuery('internal_type=script^ORinternal_type=script_plain^ORinternal_type=script_server');
while(dictionaryGR.next()){
scriptFields.push(dictionaryGR.element + '');
}
var tableGR = new GlideRecord(table);
if(tableGR.isValidField('sys_updated_on')){
tableGR.addQuery('sys_updated_on','>', this.instanceCreateDate);//exclude these as mainy oob
}
if(tableGR.isValidField('active')){
tableGR.addQuery('active','true');
}
tableGR.query();
while(tableGR.next()){
scriptFields.forEach(function(field){
var script = record.getValue(field)||'';
this.serverTests.forEach(function(test){
var passes = test.regex.test(script);
if(passes != test.expect){
errors.push(test.error);
}
});
});
}
},
_getBusinessRules: function(){
/*
- [x] Avoid Global BR
- [x] Before BR Should not insert or update records
- [x] Avoid Eval
- [x] Avoid Sysids in code
- [x] BR should be wrapped in a function
- [] Avoid undocumented apis
- [] Check if script/code does not make use of foreign tables without GlideRecordSecure
- [] search code for the use of getResponse() as its a soap method that should be used.
*/
var returnArr = [];
var tests = this.serverTests.concat([{
regex: /^(function)((.*)\n)+}$/gm,
error: "Not wrapped in function",
expect: true
}]);
var br = new GlideRecord('sys_script');
if(arguments[0]){
br.addQuery('sys_id', arguments[0]);
} else {
br.addQuery('active','true');
br.addQuery('sys_updated_on','>', this.instanceCreateDate);//exclude these as mainy oob
}
br.query();
while(br.next()){
var script = br.getValue('script') || "";
var errors = [];
if(br.getValue('collection') === 'global'){
errors.push('Avoid Global Business Rules');
}
if(br.getValue('when') === 'before'){
if(script.indexOf('insert()')>=0){
errors.push('Avoid insert() in before business rules');
}
if(script.indexOf('update()')>=0){
errors.push('Avoid update() in before business rules');
}
}
this.serverTests.forEach(function(test){
var passes = test.regex.test(script);
if(passes != test.expect){
errors.push(test.error);
}
});
if(errors.length>0){
returnArr.push({
name: br.getValue('name'),
sys_id: br.getValue('sys_id'),
updated_by: br.getValue('sys_updated_by'),
link: this.instance + br.getValue('sys_class_name') + '.do?sys_id=' + br.getValue('sys_id'),
errors: errors
});
}
}
return returnArr;
},
_getScriptIncludes: function(){
/*
- [x] Avoid Eval
- [x] Avoid Sysids in code
- [] Avoid undocumented apis
- [] Check if script/code does not make use of foreign tables without GlideRecordSecure
- [] search code for the use of getResponse() as its a soap method that should be used.
*/
var returnArr = [];
var si = new GlideRecord('sys_script_include');
if(arguments[0]){
si.addQuery('sys_id', arguments[0]);
} else {
si.addQuery('active','true');
si.addQuery('sys_updated_on','>', this.instanceCreateDate);//exclude these as mainy oob
}
si.query();
while(si.next()){
var script = si.getValue('script') || "";
var errors = [];
this.serverTests.forEach(function(test){
var passes = test.regex.test(script);
if(passes != test.expect){
errors.push(test.error);
}
});
if(errors.length>0){
returnArr.push({
name: si.getValue('name'),
sys_id: si.getValue('sys_id'),
updated_by: si.getValue('sys_updated_by'),
link: this.instance + si.getValue('sys_class_name') + '.do?sys_id=' + si.getValue('sys_id'),
errors: errors
});
}
}
return returnArr;
},
_getUIPoliciesScripts: function(){
var returnArr = [];
var up = new GlideRecord('sys_ui_policy');
if(arguments[0]){
up.addQuery('sys_id', arguments[0]);
} else {
up.addQuery('active','true');
up.addQuery('run_scripts','true');
up.addQuery('sys_updated_on','>', this.instanceCreateDate);//exclude these as mainy oob
}
up.query();
while(up.next()){
var script_true = up.getValue('script_true') || "";
var script_false = up.getValue('script_false') || "";
var errors = [];
this.clientTests.forEach(function(test){
var passes1 = test.regex.test(script_true);
var passes2 = test.regex.test(script_false);
if(passes1 != test.expect || passes2 != test.expect){
errors.push(test.error);
}
});
if(errors.length>0){
returnArr.push({
name: up.getValue('short_description'),
sys_id: up.getValue('sys_id'),
updated_by: up.getValue('sys_updated_by'),
link: this.instance + up.getValue('sys_class_name') + '.do?sys_id=' + up.getValue('sys_id'),
errors: errors
});
}
}
return returnArr;
},
_getClientScripts: function(){
var returnArr = [];
var cs = new GlideRecord('sys_script_client');
if(arguments[0]){
cs.addQuery('sys_id', arguments[0]);
} else {
cs.addQuery('active','true');
cs.addQuery('sys_updated_on','>', this.instanceCreateDate);//exclude these as mainy oob
}
cs.query();
while (cs.next()) { // iterate through records
var script = cs.getValue('script') || "";
var errors = [];
this.clientTests.forEach(function(test){
var passes = test.regex.test(script);
if(passes != test.expect){
errors.push(test.error);
}
});
if(errors.length>0){
returnArr.push({
name: cs.getValue('name'),
sys_id: cs.getValue('sys_id'),
updated_by: cs.getValue('sys_updated_by'),
link: this.instance + cs.getValue('sys_class_name') + '.do?sys_id=' + cs.getValue('sys_id'),
errors: errors
});
}
}
return returnArr;
},
type: 'Analysis'
});
Sys ID
c5c833f54f55f700c660b1d18110c78e