Name
sn_cmdb_ws.CMDBAttestationUtil
Description
No description available
Script
var CMDBAttestationUtil = Class.create();
CMDBAttestationUtil.prototype = {
initialize: function() {
this.currentUserId = gs.getUserID();
this.ACTIONS_MAPPING = {
attest: {
key: 'attest',
action: 'attested',
attestation_status: 'Attested',
attested_by: this.currentUserId
},
unattest: {
key: 'unattest',
action: 'unattested',
attestation_status: 'Not Yet Reviewed',
attested_by: ''
},
reject: {
key: 'reject',
action: 'rejected',
attestation_status: 'Rejected',
attested_by: this.currentUserId
}
};
},
SYS_PROPS_NAME: {
ALLOW_CODE_TAG: 'glide.ui.security.allow_codetag',
DISCOVERY_SRC_EXCLUSION: "sn_cmdb_ws.attestation.smart_detection.discovery_source.exclusion",
DISCOVERY_WINDOW: "sn_cmdb_ws.attestation.smart_detection.discovery_window",
DISABLE_SMART_DETECTION: "sn_cmdb_ws.attestation.smart_detection.disabled"
},
PLUGINS: {
DISCOVERY_PLUGIN: "com.snc.discovery",
INTEGRATION_COMMONS_PLUGIN: "com.snc.cmdb.integration_util"
},
ROLES: {
DATA_MANAGER_ADMIN_ROLE: 'b156309e53722010af64ddeeff7b1227'
},
TABLES: {
TASK_TO_CI_TABLE: 'sn_cmdb_ws_attestation_task_to_ci',
DM_TASK_TABLE: 'cmdb_data_management_task',
DEDUPE_TASK_TABLE: 'reconcile_duplicate_task',
GROUP_MEMBER_TABLE: 'sys_user_grmember',
POLICY_EXCLUSION_LIST_TABLE: 'cmdb_policy_ci_exclusion_list',
SYS_USER_HAS_ROLE: 'sys_user_has_role',
ATTESTATION_TASK_STATE: 'sn_cmdb_ws_attestation_task_state'
},
ROLE: {
DATA_MANAGER_ADMIN: 'data_manager_admin'
},
SYS_USER_HAS_ROLE_FIELDS: {
ROLE: 'role',
USER: 'user',
},
GROUP_MEMBER_FIELDS: {
GROUP: 'group',
USER: 'user'
},
CI_FIELDS: {
SYS_ID: 'sys_id',
CLASS_NAME: 'sys_class_name',
DISCOVERY_SOURCE: 'discovery_source',
LAST_DISCOVERED: 'last_discovered'
},
ATTESTATION_FIELDS: {
ATTESTATION_STATUS: 'attestation_status',
ATTESTED_BY: 'attested_by',
ATTESTED_DATE: 'attested_date'
},
TASK_FIELDS: {
NUMBER: 'number',
ASSIGNED_TO: 'assigned_to',
ASSIGNMENT_GROUP: 'assignment_group',
STATE: 'state'
},
TASK_STATE_FIELDS: {
CMDB_TASK: "cmdb_data_management_task",
SMART_DETECTION_ACCEPTED: "smart_detection_accepted",
CI_COUNT: "smart_detection_ci_count",
SMART_DETECTION_RUN_ON: "smart_detection_run_on",
HIDE_POPUP_USER_PREF: "hide_popup_user_pref",
ATTESTED_CIS: "attested_ci_count",
REJECTED_CIS: "rejected_ci_count",
DUPLICATE_CIS: "duplicate_ci_count",
EXCLUDED_CIS: "excluded_ci_count",
},
TASK_TO_CI_FIELDS: {
SYS_ID: 'sys_id',
CMDB_TASK: 'cmdb_data_management_task',
CI: 'ci',
DISCOVERY_SOURCE: "ci.discovery_source",
LAST_DISCOVERED: "ci.last_discovered",
ATTESTATION_STATUS: "ci.attestation_status"
},
EXCLUSION_LIST_FIELDS: {
CI: 'ci',
POLICY_TYPE: 'policy_type'
},
_ERROR_MESSAGES: {
UNAUTHORIZED: {
error: {
code: 'UNAUTHORIZED',
message: 'This task is not assigned to you.'
}
},
INVALID_ACTION: {
error: {
code: 'INVALID_ACTION',
message: 'Invalid attestation action'
}
},
INVALID_INPUT: {
error: {
code: 'INVALID_INPUT',
message: 'At least one CI sysId required.'
}
},
DUPLICATE_MINIMUM: {
error: {
code: 'DUPLICATE_NEEDS_TWO_MINIMUM',
message: 'Cannot create a duplicate task with just 1 CI. Must select at least 2.'
}
},
MULTIPLE_IRE_RULES: {
error: {
code: 'MULTIPLE_IRE_RULES',
message: 'Cannot create a duplicate task for CIs with multiple IRE rules.'
}
},
DUPLICATE_TASK_FAILED: {
error: {
code: 'DUPLICATE_TASK_FAILED',
message: 'Failed to create De-duplication Task.'
}
}
},
NOTIFICATION_EVENTS: {
TASK_SEND_TO_ADMIN: 'sn_cmdb_ws.attestationtask.sendtoadmin',
TASK_REASSIGN: 'sn_cmdb_ws.attestationtask.reassign',
TASK_COMPLETED: 'sn_cmdb_ws.attestationtask.completed'
},
ATTESTATION_STATUS: {
ATTESTED: 'Attested',
REJECTED: 'Rejected',
NOT_YET_REVIEWED: 'Not Yet Reviewed'
},
QUERY_FILTERS: {
IN: "IN",
NOT_IN: "NOT IN",
NOT_EQUAL: "!=",
GTE: ">="
},
TASK_STATE: {
OPEN: "1",
WORK_IN_PROGRESS: "2",
CLOSED_COMPLETE: "3"
},
// if task is active get the count by grouping attestation_status field but if it's closed get it from task state table
getCisSummaryCount: function(taskSysId) {
var taskGr = new GlideRecord(this.TABLES.DM_TASK_TABLE);
if (taskGr.get(taskSysId)) {
var isTaskClosed = taskGr.getValue(this.TASK_FIELDS.STATE) === this.TASK_STATE.CLOSED_COMPLETE;
if (isTaskClosed) {
var taskState = this.getTaskState(taskSysId);
return [{
attestation_status: this.ATTESTATION_STATUS.ATTESTED,
count: taskState.attestedCis
},
{
attestation_status: this.ATTESTATION_STATUS.REJECTED,
count: taskState.rejectedCis
}
];
} else {
return this.getCountBasedOnAttestationStatus(taskSysId);
}
}
},
getCountBasedOnAttestationStatus: function(taskSysId) {
var result = [];
var ga = new GlideAggregate('sn_cmdb_ws_attestation_task_to_ci');
ga.addEncodedQuery("cmdb_data_management_task=" + taskSysId);
ga.addAggregate("COUNT");
ga.groupBy("ci.attestation_status");
ga.query();
while (ga.next()) {
var status = ga.getValue("ci.attestation_status");
var count = parseInt(ga.getAggregate('COUNT'));
var obj = {
'attestation_status': status,
'count': count
};
result.push(obj);
}
return result;
},
buildTaskToCiGr: function(taskId, sysIds, allRecordsSelected, currentAttestationStatus, excludedSysIds) {
var gr = new GlideRecord(this.TABLES.TASK_TO_CI_TABLE);
if (allRecordsSelected) {
gr.addQuery(this.TASK_TO_CI_FIELDS.CMDB_TASK, taskId);
gr.addQuery(this.TASK_TO_CI_FIELDS.ATTESTATION_STATUS, currentAttestationStatus);
if (excludedSysIds) {
gr.addQuery(this.TASK_TO_CI_FIELDS.SYS_ID, this.QUERY_FILTERS.NOT_IN, excludedSysIds);
}
} else {
gr.addQuery(this.TASK_TO_CI_FIELDS.SYS_ID, this.QUERY_FILTERS.IN, sysIds);
}
return gr;
},
removeDuplicates: function(taskId, sysIds, action, userComment, allRecordsSelected, currentAttestationStatus, excludedSysIds) {
if (!allRecordsSelected) {
var inputSysIdArr = sysIds.split(",");
if (inputSysIdArr.length < 2) {
return this._ERROR_MESSAGES.DUPLICATE_MINIMUM;
}
}
var taskGr;
var ciSysIds = [];
var ciDisplayNames = [];
var ciClassNames = {};
//first get all the ciSysIds and ciDisplayNameList from the given sysIds
var gr = this.buildTaskToCiGr(taskId, sysIds, allRecordsSelected, currentAttestationStatus, excludedSysIds);
gr.query();
while (gr.next()) {
if (!taskGr) {
taskGr = gr.cmdb_data_management_task.getRefRecord();
}
var ciGr = gr.ci.getRefRecord();
ciSysIds.push(ciGr.getUniqueValue());
ciDisplayNames.push(ciGr.getDisplayValue());
var currentClassName = ciGr.getValue(this.CI_FIELDS.CLASS_NAME);
if (!ciClassNames[currentClassName]) {
ciClassNames[currentClassName] = 1;
}
}
//pre-validation check
var dupTaskUtil = new global.CMDBDuplicateTaskUtils();
if (Object.keys(ciClassNames).length > 1) {
//ire rule check only needs to be run when there's more than 1 sys_class_name in the selected CIs
var ireRuleSet = {};
for (className in ciClassNames) {
var ireRuleObj = JSON.parse(dupTaskUtil.getIdentificationRules(className));
var currentIreTable = null;
if (ireRuleObj.table) {
currentIreTable = ireRuleObj.table;
}
if (!ireRuleSet[currentIreTable]) {
ireRuleSet[currentIreTable] = 1;
}
var ireRuleTableLength = Object.keys(ireRuleSet).length;
if (ireRuleTableLength > 1) {
return this._ERROR_MESSAGES.MULTIPLE_IRE_RULES; //if there are more than 1 ireRule table in the set, short circuit out
}
}
}
//pre-validation check passes. Let's get on creating that de-dupe task
var ciSysIdsJoined = ciSysIds.join(',');
var deDupeTask = dupTaskUtil.createDuplicateTask(ciSysIdsJoined);
if (deDupeTask && taskGr) {
//remove these sysIds from task_to_ci table
gr = new GlideRecord(this.TABLES.TASK_TO_CI_TABLE);
gr.addQuery('ci', 'IN', ciSysIdsJoined);
gr.addQuery(this.TABLES.DM_TASK_TABLE, taskGr.getUniqueValue());
gr.deleteMultiple();
// update taskGr with work_notes
var dupeGr = new GlideRecord(this.TABLES.DEDUPE_TASK_TABLE);
if (dupeGr.get(deDupeTask)) {
var deDupeTaskNumber = dupeGr.getValue(this.TASK_FIELDS.NUMBER);
var deDupeUrl = '/nav_to.do?uri=reconcile_duplicate_task.do?sysparm_query=sys_id=' + deDupeTask;
var deDupeLink = deDupeTaskNumber;
if (gs.getProperty(this.SYS_PROPS_NAME.ALLOW_CODE_TAG).toLowerCase() == "true") {
var hrefLink = "<a href='" + deDupeUrl + "'>" + deDupeTaskNumber + "</a>";
deDupeLink = '[code]' + hrefLink + '[/code]';
}
taskGr.comments = gs.getMessage("A De-duplication Task {0} has been successfully created.\nThe following CIs were removed from attestation: \n{1}", [deDupeLink, ciDisplayNames.join(", ")]);
taskGr.update();
// update the current count
var prevDuplicateCis = this.getTaskState(taskId).duplicateCis;
var totalDuplicateCis = prevDuplicateCis + ciSysIds.length;
this.insertOrUpdateTaskStateField(taskId, this.TASK_STATE_FIELDS.DUPLICATE_CIS, totalDuplicateCis);
//return success
return {
action: 'duplicate',
successCount: ciDisplayNames.length,
deDupeTaskNumber: deDupeTaskNumber,
deDupeUrl: deDupeUrl
};
}
} else {
return this._ERROR_MESSAGES.DUPLICATE_TASK_FAILED;
}
},
performAttestationAction: function(taskId, sysIds, action, userComment, allRecordsSelected, currentAttestationStatus, excludedSysIds) {
var attestationFieldsValue = this.ACTIONS_MAPPING[action];
if (!attestationFieldsValue) {
return this._ERROR_MESSAGES.INVALID_ACTION;
}
//var currentUserId = gs.getUserID();
var successfulCiNames = [];
var failureCount = 0;
var taskGr;
var gr = this.buildTaskToCiGr(taskId, sysIds, allRecordsSelected, currentAttestationStatus, excludedSysIds);
gr.query();
while (gr.next()) {
if (!taskGr) {
taskGr = gr.cmdb_data_management_task.getRefRecord();
}
var ciGr = gr.ci.getRefRecord();
ciGr.setValue(this.ATTESTATION_FIELDS.ATTESTATION_STATUS, attestationFieldsValue[this.ATTESTATION_FIELDS.ATTESTATION_STATUS]);
ciGr.setValue(this.ATTESTATION_FIELDS.ATTESTED_BY, attestationFieldsValue[this.ATTESTATION_FIELDS.ATTESTED_BY]);
ciGr.setValue(this.ATTESTATION_FIELDS.ATTESTED_DATE, new GlideDateTime().getDisplayValue());
if (ciGr.update()) {
successfulCiNames.push(ciGr.getDisplayValue());
} else {
failureCount++;
gs.error("Unable to update attestation status for CI with sys_id: " + ciGr.getValue(this.CI_FIELDS.SYS_ID));
}
}
if (taskGr) {
var reasonCommentText = "";
if (userComment) {
reasonCommentText = gs.getMessage("CIs were {0} for the following reason: {1}\n", [attestationFieldsValue.action, userComment]);
}
var impactedCiCommentText = gs.getMessage("The following CIs were {0}: \n{1}", [attestationFieldsValue.action, successfulCiNames.join(", ")]);
taskGr.comments = gs.getMessage("{0} {1}", [reasonCommentText, impactedCiCommentText]);
taskGr.update();
this.updateAttestationCount(taskId);
}
return {
action: attestationFieldsValue.key,
successCount: successfulCiNames.length,
failureCount: failureCount
};
},
excludeCis: function(taskId, sysIds, action, userComment, allRecordsSelected, currentAttestationStatus, excludedSysIds) {
var successfulCis = [];
var successfulCiNames = [];
var taskGr;
var failureCount = 0;
var gr = this.buildTaskToCiGr(taskId, sysIds, allRecordsSelected, currentAttestationStatus, excludedSysIds);
gr.query();
while (gr.next()) {
if (!taskGr) {
taskGr = gr.cmdb_data_management_task.getRefRecord();
}
//Insert into exclusion List
var taskRefRec = taskGr.policy_id.getRefRecord();
var grExclList = new GlideRecord(this.TABLES.POLICY_EXCLUSION_LIST_TABLE);
grExclList.initialize();
grExclList.setValue(this.EXCLUSION_LIST_FIELDS.CI, gr.ci);
grExclList.setValue(this.EXCLUSION_LIST_FIELDS.POLICY_TYPE, taskRefRec.getValue('cmdb_policy_type'));
var ciGr = gr.ci.getRefRecord();
if (grExclList.insert()) {
successfulCiNames.push(ciGr.getDisplayValue());
successfulCis.push(gr.getValue(this.CI_FIELDS.SYS_ID));
} else {
failureCount++;
gs.error("Unable to exclude CI with sys_id: " + gr.ci);
}
}
//Deleting all excluded CIs
var taskToCIgr = new GlideRecord(this.TABLES.TASK_TO_CI_TABLE);
taskToCIgr.addQuery(this.CI_FIELDS.SYS_ID, 'IN', successfulCis.join());
taskToCIgr.query();
taskToCIgr.deleteMultiple();
if (taskGr) {
var reasonCommentText = "";
if (userComment)
reasonCommentText = gs.getMessage("CIs were excluded for the following reason: {0}\n", userComment);
var impactedCiCommentText = gs.getMessage("The following CIs were excluded from attestation: \n{0}", successfulCiNames.join(", "));
taskGr.comments = gs.getMessage("{0} {1}", [reasonCommentText, impactedCiCommentText]);
taskGr.update();
var prevExcludedCis = this.getTaskState(taskId).excludedCis;
var totalExcludedCis = prevExcludedCis + successfulCis.length;
this.insertOrUpdateTaskStateField(taskId, this.TASK_STATE_FIELDS.EXCLUDED_CIS, totalExcludedCis);
this.updateAttestationCount(taskId);
}
return {
action: 'exclude',
successCount: successfulCis.length,
failureCount: failureCount
};
},
isTaskAssignedToCurrentUser: function(taskId) {
var taskGr = new GlideRecord(this.TABLES.DM_TASK_TABLE);
if (taskGr.get(taskId)) {
var taskAssignedTo = taskGr.getValue(this.TASK_FIELDS.ASSIGNED_TO);
if (taskAssignedTo === this.currentUserId) {
return true;
}
}
return false;
},
getUsersWithDataManagerAdminRole: function() {
var usersList = [];
var grUserRoles = new GlideRecord(this.TABLES.SYS_USER_HAS_ROLE);
grUserRoles.addQuery(this.SYS_USER_HAS_ROLE_FIELDS.ROLE, this.ROLES.DATA_MANAGER_ADMIN_ROLE);
grUserRoles.query();
while (grUserRoles.next()) {
usersList.push(grUserRoles.getValue(this.SYS_USER_HAS_ROLE_FIELDS.USER));
}
return usersList;
},
insertOrUpdateTaskStateFields: function(taskId, fieldValues) {
var taskStateGr = new GlideRecord(this.TABLES.ATTESTATION_TASK_STATE);
taskStateGr.addQuery(this.TASK_STATE_FIELDS.CMDB_TASK, taskId);
taskStateGr.query();
var grNext = taskStateGr.next();
taskStateGr.setValue(this.TASK_STATE_FIELDS.CMDB_TASK, taskId);
var fields = fieldValues ? Object.keys(fieldValues) : [];
for (var i = 0; i < fields.length; i++) {
taskStateGr.setValue(fields[i], fieldValues[fields[i]]);
}
if (grNext) {
return taskStateGr.update();
} else {
return taskStateGr.insert();
}
},
insertOrUpdateTaskStateField: function(taskId, field, value) {
var updatedFieldValue = {};
updatedFieldValue[field] = value;
this.insertOrUpdateTaskStateFields(taskId, updatedFieldValue);
},
getTaskState: function(taskId) {
var result = {};
var tsf = this.TASK_STATE_FIELDS;
var taskStateGr = new GlideRecord(this.TABLES.ATTESTATION_TASK_STATE);
taskStateGr.addQuery(tsf.CMDB_TASK, taskId);
taskStateGr.query();
if (taskStateGr.next()) {
result.smartDetectionAccepted = taskStateGr.getDisplayValue(this.TASK_STATE_FIELDS.SMART_DETECTION_ACCEPTED) === 'true';
result.ciCount = +taskStateGr.getValue(this.TASK_STATE_FIELDS.CI_COUNT);
result.runOn = taskStateGr.getValue(this.TASK_STATE_FIELDS.SMART_DETECTION_RUN_ON);
result.lastDiscovered = taskStateGr.getValue(this.TASK_STATE_FIELDS.LAST_DISCOVERED);
result.hidePopupUserPref = taskStateGr.getDisplayValue(this.TASK_STATE_FIELDS.HIDE_POPUP_USER_PREF) === 'true';
result.attestedCis = +taskStateGr.getValue(this.TASK_STATE_FIELDS.ATTESTED_CIS);
result.rejectedCis = +taskStateGr.getValue(this.TASK_STATE_FIELDS.REJECTED_CIS);
result.duplicateCis = +taskStateGr.getValue(this.TASK_STATE_FIELDS.DUPLICATE_CIS);
result.excludedCis = +taskStateGr.getValue(this.TASK_STATE_FIELDS.EXCLUDED_CIS);
return result;
} else {
// if task exists but task state doesn't exist, insert the task state
var taskGr = new GlideRecord(this.TABLES.DM_TASK_TABLE);
if (taskGr.get(taskId)) {
this.insertOrUpdateTaskStateFields(taskId, {});
result.smartDetectionAccepted = false;
result.ciCount = 0;
result.runOn = null;
result.lastDiscovered = null;
result.hidePopupUserPref = false;
result.attestedCis = 0;
result.rejectedCis = 0;
result.duplicateCis = 0;
result.excludedCis = 0;
}
return result;
}
},
updateAttestationCount: function(taskId) {
var fieldValues = {};
var status = this.getCountBasedOnAttestationStatus(taskId);
var attestedCnt = 0;
var rejectedCnt = 0;
for (var i = 0; i < status.length; i++) {
if (status[i].attestation_status === this.ATTESTATION_STATUS.ATTESTED) {
attestedCnt = status[i].count;
}
if (status[i].attestation_status === this.ATTESTATION_STATUS.REJECTED) {
rejectedCnt = status[i].count;
}
}
fieldValues[this.TASK_STATE_FIELDS.ATTESTED_CIS] = attestedCnt;
fieldValues[this.TASK_STATE_FIELDS.REJECTED_CIS] = rejectedCnt;
this.insertOrUpdateTaskStateFields(taskId, fieldValues);
return this.getTaskState(taskId);
},
deleteTaskState: function(taskId) {
var taskStateGr = new GlideRecord(this.TABLES.ATTESTATION_TASK_STATE);
taskStateGr.addQuery(this.TASK_STATE_FIELDS.CMDB_TASK, taskId);
taskStateGr.query();
if (taskStateGr.next()) {
taskStateGr.deleteRecord();
}
},
type: 'CMDBAttestationUtil'
};
Sys ID
fb1e65c277798d1023651605bc5a99d3