Name
sn_irm_shared_cmn.IRMGlideUtils
Description
Common utility methods for ServiceNow platform features.
Script
var IRMGlideUtils = Class.create();
IRMGlideUtils.prototype = (function() {
var TABLES = {
TABLE_SYS_USER_ROLE: 'sys_user_role',
};
/** @type {*} */
var self;
/** @type {IRMLogger} */
var logger;
var collisionAPI;
var getCollisionAPI = function() {
if (typeof collisionAPI === 'undefined') {
collisionAPI = sn_collision.CollisionAPI;
}
return collisionAPI;
};
return {
/**
* Initialize a new IRMGlideUtils instance.
* @param {IRMGlideUtilsOptions} options - Options to configure IRMGlideUtils instance.
* @typedef {Object} IRMGlideUtilsOptions - Options to configure IRMGlideUtils instance.
* @property {IRMLogger} [logger] - IRM logger instance.
*/
initialize: function(options) {
/** @type {*} */
self = this;
/** @type {IRMGlideUtilsOptions} */
var _options = options || {};
logger = _options.logger || {
info: gs.info,
warn: gs.warn,
error: gs.error,
};
},
/**
* Check if current user has a specific role(s).
* @param {string[]} roles - List of role SysIds to check.
* @returns {boolean} hasRole
*/
doesUserHaveRole: function(roles) {
/** @type {*} */
self = this;
var _roles = roles instanceof Array ? roles : [roles];
var roleRecords = self.getGlideRecordData(TABLES.TABLE_SYS_USER_ROLE, {
filter: 'sys_idIN' + _roles.join(','),
secure: false,
select: ['name'],
});
var hasRole = false;
for (var i = 0; i < roleRecords.length; i++) {
var record = roleRecords[i];
if (gs.hasRole(record.name)) {
hasRole = true;
break;
}
}
return hasRole;
},
/**
* Verify if encoded string condition apply on a Glide Record
* @param {GlideRecord} record - GlideRecord to check against encoded string query.
* @param {string} condition - Encoded query string to verify.
* @returns {boolean} isMatch
*/
doesRecordMatchCondition: function(record, condition) {
if (gs.nil(condition)) {
return true;
}
/** @type {GlideFilter} */
var filter = new GlideFilter(condition);
filter.setCaseSensitive(false);
return filter.match(record);
},
/**
* A method to retrieve Glide Records by ID.
* @param {string} table - Table name.
* @param {string} sysId - SysID for the record.
* @param {IRMGlideRecordOptions} options - options to configure GlideRecord query.
* @property {boolean} [secure=true] - Use GlideRecordSecure API.
* @returns {GlideRecordSecure | GlideRecord} record
*/
getGlideRecordById: function(table, sysId, options) {
if (gs.nil(table)) {
logger.warn('Invalid input for getGlideRecordById. Table value cannot be empty.');
return null;
}
if (gs.nil(sysId)) {
logger.warn('Invalid input for getGlideRecordById. SysID value cannot be empty.');
return null;
}
var _options = options || {};
var secure = !gs.nil(_options.secure) ? _options.secure : true;
/** @type {*} */
self = this;
var record = self.getGlideRecord(table, {
filter: 'sys_id=' + sysId,
limit: 1,
secure: secure,
});
if (!record.next()) {
return null;
}
return record;
},
/**
* A method to retrieve Glide Records with optional params.
* This method will also provide log feedback in-case the record was not found.
* @param {string} table - Table name.
* @param {IRMGlideRecordOptions} options - options to configure GlideRecord query.
* @typedef {Object} IRMGlideRecordOptions - options to configure GlideRecord query.
* @property {string} [filter] - Encoded query to filter glide record results.
* @property {number} [limit='sn_irm_shared_cmn.config.get_gliderecord_limit'] - limit the number of returned results.
* Default to 'sn_irm_shared_cmn.config.get_gliderecord_limit' GlideProperty.
* @property {string} [orderBy] - Field name to use for sorting the data.
* @property {boolean} [secure=true] - Use GlideRecordSecure API.
* @returns {GlideRecordSecure | GlideRecord} record
*/
getGlideRecord: function(table, options) {
if (gs.nil(table)) {
logger.warn('Invalid input for getGlideRecord. Table value cannot be empty.');
return null;
}
/**
* @constant
* @type {number}
*/
var DEFAULT_LIMIT_FALLBACK = 1000;
var DEFAULT_LIMIT = gs.getProperty('sn_irm_shared_cmn.config.get_gliderecord_limit', DEFAULT_LIMIT_FALLBACK);
var _options = options || {};
var filter = _options.filter || null;
var limit = _options.limit || DEFAULT_LIMIT;
var secure = !gs.nil(_options.secure) ? _options.secure : true;
var record = secure ? new GlideRecordSecure(table) : new GlideRecord(table);
var orderBy = _options.orderBy || record.getDisplayName();
if (filter) {
record.addEncodedQuery(filter);
}
if (limit && limit > 0) {
record.setLimit(limit);
}
if (orderBy) {
record.orderBy(orderBy);
}
record.query();
if (!record.hasNext()) {
logger.warn('Unable to find records for "' + table + '" with filter: ' + filter);
}
return record;
},
/**
* A method to retrieve Glide Record data with optional params.
* This method will also provide log feedback in-case the record was not found.
* @param {string} table - Table name.
* @param {IRMRecordDataOptions} options - options to configure returned Record data.
* @typedef {Object} SelectItem - options to configure the element to select.
* @property {string} element - Element (field) name to select.
* @property {boolean} [display=false] - Specify to retrieve the display value of the element.
* @typedef {Object} IRMRecordDataOptionsBase - options to configure returned Record data.
* @property {string[] | SelectItem[]} [select] - Select GlideRecord fields to return.
* @typedef {IRMGlideRecordOptions & IRMRecordDataOptionsBase} IRMRecordDataOptions
* @returns {string[] | object[]} recordData - Return records' SysIds by default,
* or record values if `select` option is passed.
*/
getGlideRecordData: function(table, options) {
if (gs.nil(table)) {
logger.warn('Invalid input for getGlideRecordData. Table value cannot be empty.');
return null;
}
/** @type {*} */
self = this;
var _options = options || {};
var select = _options.select || null;
var results = [];
var record = self.getGlideRecord(table, {
filter: _options.filter,
limit: _options.limit,
orderBy: _options.orderBy,
secure: _options.secure,
});
while (record.next()) {
if (select && select.length > 0) {
/** @type {object} */
var recordData = {};
// eslint-disable-next-line no-loop-func
select.forEach(function(selectItem) {
var item = typeof selectItem === 'object' ? selectItem : { element: selectItem };
var field = item.element;
if (!field) {
logger.warn('Invalid field to retrieve for ' + table);
return;
}
var display = item.display;
var value = display ? record.getDisplayValue(field) : record.getValue(field);
recordData[field] = value;
});
results.push(recordData);
} else {
results.push(record.getUniqueValue());
}
}
return results;
},
/**
* A method to retrieve the count for Glide Records within a table.
* @param {string} table - Table name.
* @param {IRMRecordCountOptions} options - options to configure Record count query.
* @typedef {Object} IRMRecordCountOptions - options to configure Record count query.
* @property {string} [filter] - Encoded query to filter glide record results.
* @returns {number} count
*/
getRecordCount: function(table, options) {
var count = 0;
var _options = options || {};
var filter = _options.filter || '';
var aggregate = new GlideAggregate(table);
aggregate.addAggregate('COUNT');
if (filter) {
aggregate.addEncodedQuery(filter);
}
aggregate.query();
if (!aggregate.next()) {
logger.info('No record count found for table "' + table + '" with filter: ' + filter);
return count;
}
var aggregateCount = aggregate.getAggregate('COUNT');
count = isNaN(aggregateCount) ? 0 : Number(aggregateCount);
return count;
},
/**
* Get mandatory elements for a table.
* @param {string} table - Table name to get mandatory fields for.
* @returns {string[]} elements - Elements marked as `Mandatory`.
*/
getMandatoryElements: function(table) {
var elements = [];
if (gs.nil(table)) {
logger.warn('Invalid input for getMandatoryElements. Table value cannot be empty.');
return elements;
}
var ga = new GlideAggregate('sys_dictionary');
ga.addQuery('name', table);
ga.addQuery('mandatory', '=', 'true');
ga.groupBy('element');
ga.query();
while (ga.next()) {
elements.push(ga.getValue('element'));
}
return elements;
},
/**
* Get table ACL
* @param {string} table - Table name to get ACL table.
* * @param {string} sysId - Sys Id to get ACL for record.
* @returns {Object} output - ACLs.
*/
getTableACL: function(table, sysId) {
var output = {
canRead: false,
canWrite: false,
canCreate: false,
canDelete: false,
};
if (!gs.nil(table)) {
var grObj = new GlideRecord(table);
if (!gs.nil(sysId)) {
grObj.get(sysId);
}
output.canRead = grObj.canRead();
output.canWrite = grObj.canWrite();
output.canCreate = grObj.canCreate();
output.canDelete = grObj.canDelete();
} else {
logger.warn('Invalid input for getTableACL. Table value cannot be empty.');
}
return output;
},
/**
* A method to retrieve record's related list details.
* @param {String} parentTable - Name of the parent table.
* @param {String} parentId - sys_id of the parent record.
* @param {String} relatedListName - Name of the related list to fetch the details.
* @param {String} view - Name of the view
* @returns {Object} Object containing related list label, name, and filter.
*/
getRelatedListDetails: function(parentTable, parentId, relatedListName, view) {
var self = this;
var relationshipLabel = '';
var sysRelationshipId = '';
var relationshipTable = '';
var parentRefField = '';
var prefix = 'REL:';
var filters = [];
var output = {
label: '',
name: relatedListName,
filter: '',
};
view = view || '';
if (gs.nil(relatedListName)) {
logger.warn('Passed parameter relatedListName=' + relatedListName + ', cannot be null or empty.');
return output;
}
var isScripted = relatedListName.startsWith(prefix);
if (isScripted) {
sysRelationshipId = relatedListName.substring(prefix.length, relatedListName.length);
} else {
var relNameArr = relatedListName.split('.');
if (relNameArr.length === 2) {
relationshipTable = relNameArr[0];
parentRefField = relNameArr[1];
}
}
var entryGr = new GlideRecord('sys_ui_related_list_entry');
entryGr.addQuery('related_list', relatedListName);
entryGr.addQuery('list_id.view.name', view);
entryGr.setLimit(1);
entryGr.query();
if (entryGr.next()) {
var filter = entryGr.getValue('filter');
if (filter) {
filters.push(filter);
}
}
if (isScripted) {
var relationshipGr = new GlideRecord('sys_relationship');
if (relationshipGr.get(sysRelationshipId)) {
relationshipTable = relationshipGr.getValue('basic_query_from');
var parentGR = new GlideRecord(parentTable);
parentGR.get(parentId);
var currentGR = new GlideRecord(relationshipTable);
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable('parent', parentGR);
evaluator.putVariable('current', currentGR);
evaluator.evaluateScript(relationshipGr, 'query_with', {});
currentGR = evaluator.getVariable('current');
filters.push(currentGR.getEncodedQuery());
relationshipLabel = relationshipGr.getDisplayValue('name');
}
} else if (relationshipTable && parentRefField) {
var relGr = new GlideRecord(relationshipTable);
relGr.addQuery(parentRefField, parentId);
filters.push(relGr.getEncodedQuery());
relationshipLabel = relGr.getClassDisplayValue();
}
output.label = relationshipLabel;
output.filter = filters.join('^');
return output;
},
/**
* Check if a GlideRecord is customized.
* @param {GlideRecord | string} record - GlideRecord to check for customization. (or update name string)
* @returns {boolean} isCustomized
*/
isRecordCustomized: function(record) {
var updateName = record instanceof GlideRecord ? record.getValue('sys_update_name') : record;
return !getCollisionAPI().willBeReplacedOnUpgrade(updateName);
},
/**
* A method to update a Glide Record by ID.
* @param {string} table - Table name.
* @param {string} sysId - SysID for the record.
* @param {Object} recordData - Key-value pair for fields to update on a record.
* @typedef {Object} IRMGlideUpdateOutput - Output from IRM GlideRecord update
* @property {string | null} updated - SysID for the updated record. null if the update fails.
* @property {boolean} [error] - Indicate if there was an error updating the record.
* @property {string} [message] - Informational message about the GlideRecord message; normally will contains the reason for update error.
* @returns {IRMGlideUpdateOutput} updateOutput
*/
updateGlideRecordById: function(table, sysId, recordData) {
var output = { updated: null };
if (gs.nil(table)) {
logger.warn('Invalid input for updateGlideRecordById. Table value cannot be empty.');
output.error = true;
output.message = gs.getMessage('Invalid update. You must specify a valid table to update.');
return output;
}
if (gs.nil(sysId)) {
logger.warn('Invalid input for updateGlideRecordById. SysID value cannot be empty.');
output.error = true;
output.message = gs.getMessage('Invalid update. You must specify a valid record to update.');
return output;
}
/** @type {*} */
self = this;
/** @type {GlideRecordSecure | GlideRecord} */
var record = self.getGlideRecordById(table, sysId);
if (gs.nil(record)) {
output.error = true;
output.message = gs.getMessage('Invalid update. No record found in table {0} with SysID "{1}".', [table, sysId]);
return null;
}
var fields = Object.keys(recordData);
fields.forEach(function(field) {
var value = recordData[field];
record.setValue(field, value);
});
output.updated = record.update();
if (!output.updated) {
output.error = true;
output.message = record.getLastErrorMessage();
}
return output;
},
type: 'IRMGlideUtils',
};
})();
Sys ID
d1d2d8a7c3852510a6a1f51ca140dda6