Name
sn_agent.AgentNowAssetValidiator
Description
Uitlity script containing the following functions validate Check that the attachments to agent asset record are valid updateAssetChoiceList update the sn_agent_asset_name table based on names of records in sn_agent_asset
Script
var AgentNowAssetValidiator = Class.create();
AgentNowAssetValidiator.prototype = {
initialize: function() {},
validateAsset: function(currentAssetGr) {
// Find attachment
var attachGr = this.getAttachmentForAsset(currentAssetGr);
if (!attachGr.next()) {
if (currentAssetGr.sys_overrides) {
gs.addErrorMessage(gs.getMessage("Update of plugins from other domains are not allowed."));
} else if (currentAssetGr.operation() == "insert") {
gs.addErrorMessage(gs.getMessage('No attachment found on record. Please add an attachment.'));
current.setAbortAction(true);
}
return false;
}
var validated = this.validateAssetFields(currentAssetGr, attachGr) && this.validateNameAndPopulate(currentAssetGr, attachGr);
if (!validated) {
if (currentAssetGr.operation() == "insert")
current.setAbortAction(true);
return false;
}
},
validateAssetFields: function(currentAssetGr, attachGr) {
if (currentAssetGr.operation() == "insert") {
// Check there are no additional attachments
if (attachGr.hasNext()) {
gs.addErrorMessage(gs.getMessage('The record cannot have more than one attachment.'));
return false;
}
if (this.isRecordExist(currentAssetGr, attachGr.file_name)) {
gs.addErrorMessage(gs.getMessage('A record with the same name and path already exists.'));
return false;
}
//we are restricted by the length of name column in sys_attchemnt which is 100 characters, when exceeding 100 characters, the name is cut and '.tar' suffix is removed
if (attachGr.getValue('file_name').length >= 100) {
gs.addErrorMessage(gs.getMessage('The attached file name exceeds 100 characters.'));
return false;
}
// Check the file name and os version does not contain spaces or special characters
if (!/^[A-Za-z0-9_.-]+$/i.test(attachGr.getValue('file_name'))) {
gs.addErrorMessage(gs.getMessage('The attached file name must only contain alphanumeric characters and: . , - , _'));
return false;
}
}
if (!/^[A-Za-z0-9_.-]+$/i.test(currentAssetGr.os_version)) {
gs.addErrorMessage(gs.getMessage('The os version must only contain alphanumeric characters and: . , - , _'));
return false;
}
return true;
},
validateNameAndPopulate: function(currentAssetGr, attachGr) {
var fileName = '';
fileName = attachGr.getValue('file_name');
if (!fileName.endsWith(".tar.gz")) {
gs.addErrorMessage(gs.getMessage('Attached file must be in tar.gz format.'));
return false;
}
var indexOfSuffixTarGz = fileName.lastIndexOf(".tar.gz");
if (indexOfSuffixTarGz != -1) {
//There is always an index because it is checked that the name ends with .tar.gz
current.name = fileName.substring(0, indexOfSuffixTarGz);
}
if (current.name.startsWith('.') || current.name.endsWith('.')) {
gs.addErrorMessage(gs.getMessage('Attachment name cannot start or end with a period.'));
return false;
}
return true;
},
// Is record with same name and path exist
isRecordExist: function(current, name) {
var absoluteName = name.replace('.tar.gz', '');
var pluginGR = new GlideRecord('sn_agent_asset');
pluginGR.addQuery('sys_id', "!=", current.getUniqueValue());
pluginGR.addQuery('name', absoluteName);
pluginGR.addQuery('arch', current.arch);
pluginGR.addQuery('os', current.os);
pluginGR.addQuery('os_version', current.os_version);
pluginGR.addQuery('platform', current.platform);
pluginGR.query();
return pluginGR.hasNext();
},
getAttachmentForAsset: function(currentAssetGr) {
var attachGr = new GlideRecord('sys_attachment');
attachGr.addQuery('table_name', 'sn_agent_asset');
attachGr.addQuery('table_sys_id', currentAssetGr.getUniqueValue());
attachGr.query();
return attachGr;
},
hasAttachment: function(sysID) {
var attachGr = new GlideRecord('sys_attachment');
attachGr.addQuery('table_name', 'sn_agent_asset');
attachGr.addQuery('table_sys_id', sysID);
attachGr.query();
return attachGr.hasNext();
},
updateAssetChoiceList: function() {
var assetNames = {};
var assetGr = new GlideRecord('sn_agent_asset');
assetGr.addQuery('directory', false);
assetGr.query();
while (assetGr.next()) {
assetNames[assetGr.name + ''] = 1;
}
// Find existing choices
var currentChoices = {};
var choiceGr = new GlideRecord('sn_agent_asset_name');
choiceGr.query();
while (choiceGr.next()) {
currentChoices[choiceGr.name + ''] = choiceGr.getUniqueValue();
}
// Add choices if needed
var assetName;
for (assetName in assetNames) {
if (!currentChoices[assetName]) {
// insert new choice
choiceGr = new GlideRecord('sn_agent_asset_name');
choiceGr.setValue('name', assetName);
choiceGr.insert();
}
}
// Remove choices if needed
for (assetName in currentChoices) {
if (!assetNames[assetName]) {
// Remove a choice
choiceGr = new GlideRecord('sn_agent_asset_name');
var recordFound = choiceGr.get(currentChoices[assetName]);
if (recordFound) {
choiceGr.deleteRecord();
}
}
}
},
/*
* check if asset name is being used on record other than the the current record
*/
isAssetNameUsed: function(assetName, current) {
var choiceGr = new GlideRecord('sn_agent_asset_name');
choiceGr.addQuery('name', assetName);
choiceGr.query();
if (!choiceGr.next()) {
//gs.info('====== asset name ' + assetName + ' not found');
return '';
}
// Check if this asset name is used in check definitions
var checkGr = new GlideRecord('sn_agent_check_def');
checkGr.addQuery('assets', 'CONTAINS', choiceGr.getUniqueValue());
checkGr.query();
if (checkGr.next()) {
// there are check definitions using this asset name. Check if there are other assets with the same name
var assetGr = new GlideRecord('sn_agent_asset');
assetGr.addQuery('name', assetName);
assetGr.addQuery('sys_id', "!=", current.getUniqueValue());
assetGr.query();
if (!assetGr.next()) {
gs.info('===== asset name ' + assetName + ' found in check ' + checkGr.name);
return checkGr.name + '';
}
}
//gs.info('====== asset name ' + assetName + ' not used by checks, or there are other assets with same name');
return '';
},
addAssetsToCheck: function(check_def, check, payloadVersion) {
if (!check_def || !check_def.assets)
return;
gs.debug('Assets : ' + check_def.assets + '');
var assetsArray = check_def.assets.toString().split(',');
assetNamesTemp = [];
for (var idx in assetsArray) {
var assetId = assetsArray[idx];
var assetName = this.getAssetName(assetId);
if (assetName)
assetNamesTemp.push(assetName);
}
if (!payloadVersion || payloadVersion < 2)
check['assets'] = assetNamesTemp.toString();
else
check['assets'] = assetNamesTemp;
},
/*
* get the asset name from map between sys IDs in sn_agent_asset_name and names. If the map was not created yet, create it now
*/
getAssetName: function(assetNameId) {
if (!assetNameId)
return;
if (!this.assetNames) {
this.assetNames = {};
var assetNameGr = new GlideRecord('sn_agent_asset_name');
assetNameGr.query();
while (assetNameGr.next())
this.assetNames[assetNameGr.getUniqueValue()] = assetNameGr.name + '';
}
if (this.assetNames[assetNameId]) {
return this.assetNames[assetNameId];
}
},
/*
* check if we are allowed to delete asset. We block asset deletion if the asset name is being used by check definition and there is no other asset with the same name
*/
shouldAllowDeleteOfAsset: function(current) {
var choiceGr = new GlideRecord('sn_agent_asset_name');
var assetName = current.name + '';
choiceGr.addQuery('name', assetName);
var checkname = this.isAssetNameUsed(assetName, current);
if (checkname != '') {
current.setAbortAction(true);
gs.addErrorMessage(gs.getMessage("Plugin named {0} cannot be deleted since it is being used by check definition {1}", [assetName, checkname]));
return;
}
},
type: 'AgentNowAssetValidiator'
};
Sys ID
78752bd0b74733003e766068de11a9ab