Name
global.PwdEnrollSnapshotUtilSNC
Description
Util methods related to Password Enrollment Snapshots
Script
var PwdEnrollSnapshotUtilSNC = Class.create();
PwdEnrollSnapshotUtilSNC.prototype = {
PWD_ENROLLMENT_SNAPSHOT: "pwd_enrollment_snapshot",
PWD_MAP_PROC_TO_VERIFICATION: "pwd_map_proc_to_verification",
SYS_USER: "sys_user",
PWD_VERIFICATION: "pwd_verification",
PWD_PROCESS: "pwd_process",
PWD_MAP_PROC_TO_GROUP: "pwd_map_proc_to_group",
SYS_USER_GROUP: "sys_user_group",
SYS_USER_GRMEMBER: "sys_user_grmember",
SYSAUTO_SCRIPT: "sysauto_script",
arrayUtil: null,
pwdExpirationUtil: null,
pwdVerificationManager: null,
pwdEnrollmentManager: null,
_isDomainSepActive: null,
_isEnrollmentSnapshotEnabled: null,
initialize: function() {
this._isDomainSepActive = GlidePluginManager.isRegistered('com.glide.domain.msp_extensions.installer');
this._isEnrollmentSnapshotEnabled = GlideProperties.getBoolean('pwd_reset.enable.enrollment_snapshot', true);
this.arrayUtil = new ArrayUtil();
this.pwdExpirationUtil = new PwdExpirationUtils();
this.pwdVerificationManager = new SNC.PwdVerificationManager();
this.pwdEnrollmentManager = new SNC.PwdEnrollmentManager();
},
createEnrollmentSnapshotsByProcesses: function(processIds) {
var userIds = this.getUsersByProcesses(processIds);
for (var i = 0; i < userIds.length; i++) {
this.createEnrollmentSnapshot(userIds[i]);
}
},
createEnrollmentSnapshot: function(userSysId) {
var verifications = this.pwdVerificationManager.getVerificationIdsForUser(userSysId);
for (var i = 0; i < verifications.size(); i++) {
try {
this.createOrUpdateEnrollmentSnapshot(verifications.get(i), userSysId);
} catch (ex) {
gs.error("[PwdEnrollSnapshotUtilSNC: Create enrollment snaps for a user with sys_id : " + userSysId + ", verification : " + verifications.get(i) + "]. execution error - " + ex);
}
}
},
//Create or Update enrollment snapshot record.
//Status is optional parameter, if it is not passed, then we will fetch it from api
createOrUpdateEnrollmentSnapshot: function(verification, user, status) {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
if (gs.nil(status))
status = this.pwdEnrollmentManager.isUserEnrolledByVerificationId(user, verification) ? PwdConstants.ENROLLMENT_ACTIVE_STATUS : PwdConstants.ENROLLMENT_INACTIVE_STATUS;
// make the inserted record's domain to be current user's domain
if (this._isDomainSepActive) {
var grUser = new GlideRecord(this.SYS_USER);
grUser.get(user);
gr.addDomainQuery(grUser);
}
gr.addQuery("verification", verification);
gr.addQuery("user", user);
gr.query();
if (gr.next()) {
gr.status = status;
gr.update();
} else {
gr.initialize();
gr.verification = verification;
gr.user = user;
gr.status = status;
gr.insert();
}
},
deleteEnrollmentSnapshotsForInValidUsers: function() {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("user", "");
gr.deleteMultiple();
},
deleteEnrollmentSnapshotsByUserId: function(userSysId) {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("user", userSysId);
gr.deleteMultiple();
},
deleteEnrollmentSnapshotsForInValidVerifications: function() {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("verification", "");
gr.deleteMultiple();
},
deleteEnrollmentSnapshotsByVerifications: function(verificationIds) {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("verification", "IN", verificationIds);
gr.deleteMultiple();
},
deleteEnrollmentSnapshotsByUserIdAndVerification: function(userSysId, verification) {
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("user", userSysId);
gr.addQuery("verification", verification);
gr.deleteRecord();
},
deleteInValidEnrollmentSnapshots: function() {
var snapshotGr = new GlideAggregate(this.PWD_ENROLLMENT_SNAPSHOT);
snapshotGr.groupBy('user');
snapshotGr.query();
while (snapshotGr.next()) {
this.deleteInValidEnrollmentSnapshotsByUserId(snapshotGr.user);
}
},
deleteInValidEnrollmentSnapshotsByUserId: function(userSysId) {
var currentVerifications = this.pwdVerificationManager.getVerificationIdsForUser(userSysId);
var gr = new GlideRecord(this.PWD_ENROLLMENT_SNAPSHOT);
gr.addQuery("user", userSysId);
//Don't delete the enrollment snapshot record for the user-verification pair if the user still associated with that verification via another group
gr.addQuery("verification", "NOT IN", currentVerifications);
gr.deleteMultiple();
},
getUsersByProcesses: function(processIds) {
var userIds = [];
var gr = new GlideRecord(this.PWD_PROCESS);
gr.addActiveQuery();
gr.addQuery("sys_id", "IN", processIds);
gr.addQuery('apply_to_all_users', true);
gr.query();
if (gr.next()) { //Apply to all users
var grUser = new GlideRecord(this.SYS_USER);
grUser.addActiveQuery();
grUser.query();
while (grUser.next()) {
userIds.push(grUser.getValue("sys_id"));
}
} else { //Apply to group
var groupProcessGr = new GlideRecord(this.PWD_MAP_PROC_TO_GROUP);
groupProcessGr.addQuery("process", "IN", processIds);
groupProcessGr.addQuery("process.active", true);
groupProcessGr.addQuery("user_group.active", true);
groupProcessGr.query();
var groupIds = [];
while (groupProcessGr.next()) {
var group = groupProcessGr.getValue("user_group");
if (!this.arrayUtil.contains(groupIds, group)) {
groupIds.push(group);
}
}
if (groupIds.length !== 0) {
var userGroupMemberGr = this.pwdExpirationUtil.getAllUsersForGroup(groupIds);
while (userGroupMemberGr.next()) {
var userId = userGroupMemberGr.getValue("user");
if (!this.arrayUtil.contains(userIds, userId)) {
userIds.push(userId);
}
}
}
}
return userIds;
},
getVerificationsByVerificationType: function(verificationType) {
var verificationIds = [];
var gr = new GlideRecord(this.PWD_VERIFICATION);
gr.addQuery("type", verificationType);
gr.query();
while (gr.next()) {
verificationIds.push(gr.getValue("sys_id"));
}
return verificationIds;
},
getManualVerificationsAccociatedWithProcesses: function(processIds) {
var gr = new GlideRecord(this.PWD_MAP_PROC_TO_VERIFICATION);
gr.addQuery("process", "IN", Object.keys(processIds).join());
gr.query();
var verificationIds = [];
while (gr.next()) {
var verification = gr.getValue("verification");
if (!gr.verification.type.auto_enroll && !this.arrayUtil.contains(verificationIds, verification)) {
verificationIds.push(verification);
}
}
return verificationIds;
},
getProcessAccociatedWithVerifications: function(verificationIds) {
var gr = new GlideRecord(this.PWD_MAP_PROC_TO_VERIFICATION);
gr.addQuery("verification", "IN", verificationIds);
gr.addQuery("process.active", true);
gr.query();
var processIds = [];
while (gr.next()) {
processIds.push(gr.getValue("process"));
}
return processIds;
},
isAutoEnrollVerification: function(verificationId) {
var gr = new GlideRecord(this.PWD_VERIFICATION);
return gr.get(verificationId) && gr.type.auto_enroll;
},
isActiveProcess: function(processId) {
var gr = new GlideRecord(this.PWD_PROCESS);
return gr.get(processId) && gr.active;
},
isActiveUser: function(userId) {
var gr = new GlideRecord(this.SYS_USER);
return gr.get(userId) && gr.active;
},
isActiveGroup: function(groupId) {
var gr = new GlideRecord(this.SYS_USER_GROUP);
return gr.get(groupId) && gr.active;
},
manageEnrollmentSnapshotScheduleJobForAProcess: function(processGr) {
if (!this._isEnrollmentSnapshotEnabled)
return;
var SYNC_ENROLLMENT_SNAPSHOT_DATA_SCHEDULED_JOB_PREFIX = "Sync enrollment snapshot data for pwd_process_";
var processSysId = processGr.getUniqueValue();
var startDate = this.getStartDateTime(3600); //1 Hour
var currentDate = new GlideDateTime();
var jobName = SYNC_ENROLLMENT_SNAPSHOT_DATA_SCHEDULED_JOB_PREFIX + processSysId;
var jobScript = "new global.PwdEnrollSnapshotUtil().syncEnrollmentSnapshotDataForProcessId(\"" + processSysId + "\");";
/* create a new schedule job to create expiration records which will run once after one hour.
If job already exists then check if that job is already executed. If yes, update the start time so that the same job will execute again after one hour else dont do anything*/
try {
var scheduleJobGr = this._findScheduleJob(jobName);
if (!gs.nil(scheduleJobGr)) {
scheduleJobGr.setValue("active", processGr.active);
if (scheduleJobGr.getValue("run_start") < currentDate && scheduleJobGr.getValue("run_start") < startDate)
scheduleJobGr.setValue("run_start", startDate);
scheduleJobGr.update();
} else {
scheduleJobGr = this.createSyncEnrollmentSnapshotScheduleJob(jobName, jobScript, startDate, "once", "");
}
startDate = scheduleJobGr.getDisplayValue("run_start");
if (processGr.active)
gs.addInfoMessage(gs.getMessage("The Sync enrollment snapshot data job for this process will start at {0}", startDate));
} catch (ex) {
gs.error("[PwdEnrollSnapshotUtil] manageEnrollmentSnapshotScheduleJobForAProcess() for pwd_process_" + processSysId + " execution error - " + ex);
}
},
syncEnrollmentSnapshotDataForProcessId: function(processId) {
if (!this._isEnrollmentSnapshotEnabled)
return;
if (!this._doesProcessExist(processId)) {
gs.error("[PwdEnrollSnapshotUtil] Password Reset process record not found, error while refreshing the enrollment snapshot table data for the process: " + processId);
return;
}
this.createEnrollmentSnapshotsByProcesses([processId]);
},
_findScheduleJob: function(jobName) {
var gr = new GlideRecord(this.SYSAUTO_SCRIPT);
if (gr.get("name", jobName))
return gr;
return null;
},
//Returns the current date time and adds the specified seconds in it.
getStartDateTime: function(seconds) {
var startDate = new GlideDateTime();
startDate.addSeconds(seconds);
return startDate;
},
createSyncEnrollmentSnapshotScheduleJob: function(jobName, jobScript, startDate, runType, runDay) {
var scheduleJobGr = new GlideRecord(this.SYSAUTO_SCRIPT);
scheduleJobGr.initialize();
scheduleJobGr.setValue("name", jobName);
scheduleJobGr.setValue("active", true);
scheduleJobGr.setValue("conditional", true);
scheduleJobGr.setValue("condition", "GlideProperties.getBoolean('pwd_reset.enable.enrollment_snapshot', true);");
scheduleJobGr.setValue("run_type", runType);
scheduleJobGr.setValue("script", jobScript);
switch (runType) {
case "monthly":
scheduleJobGr.setValue("run_dayofmonth", runDay);
break;
case "once":
scheduleJobGr.setValue("entered_time", new GlideTime());
scheduleJobGr.setValue("run_start", startDate);
scheduleJobGr.setValue("time_zone", "floating");
break;
}
scheduleJobGr.insert();
return scheduleJobGr;
},
_doesProcessExist: function(processSysId) {
var processGr = new GlideRecord(this.PWD_PROCESS);
processGr.addActiveQuery();
processGr.addQuery("sys_id", processSysId);
processGr.query();
if (processGr.next())
return true;
return false;
},
createOrDeleteEnrollmentSnapshotForMonthlyScheduledJob: function() {
var verificationToUserGroupMapping = {};
var processVerification = {};
// get apply to all verifications that are not auto-enroll
gr = new GlideAggregate(this.PWD_MAP_PROC_TO_VERIFICATION);
gr.groupBy('verification');
var qc = gr.addJoinQuery(this.PWD_PROCESS, 'process', 'sys_id');
qc.addCondition('active', true);
qc.addCondition('apply_to_all_users', true);
gr.query();
var verifications = {};
while (gr.next()) {
if (gr.verification.type.auto_enroll) {
continue;
}
verifications[gr.verification] = true;
}
if (Object.keys(verifications).length !== 0) {
var users = new GlideRecord(this.SYS_USER);
users.addActiveQuery();
users.query();
while (users.next()) {
for (var verification in verifications) {
if (verifications.hasOwnProperty(verification)) {
this.createOrUpdateEnrollmentSnapshot(verification, users.sys_id);
}
}
}
}
// now on to process that are associated with user groups
// first build a verification to groups mapping
var processGr = new GlideRecord(this.PWD_PROCESS);
processGr.addQuery('apply_to_all_users', false);
processGr.addActiveQuery();
processGr.query();
while (processGr.next()) {
processVerification = {};
// get verifications first
var vers = new GlideRecord(this.PWD_MAP_PROC_TO_VERIFICATION);
vers.addQuery('process', processGr.sys_id);
vers.query();
while (vers.next()) {
if (vers.verification.type.auto_enroll || (vers.verification in verifications)) {
continue;
}
if (!(vers.verification in verificationToUserGroupMapping)) {
verificationToUserGroupMapping[vers.verification] = {};
}
processVerification[vers.verification] = {};
}
// get groups next
var groups = new GlideRecord(this.PWD_MAP_PROC_TO_GROUP);
groups.addQuery('process', processGr.sys_id);
groups.query();
while (groups.next()) {
this.getChildGroups(groups.user_group, verificationToUserGroupMapping, processVerification);
}
}
for (var ver in verificationToUserGroupMapping) {
if (verificationToUserGroupMapping.hasOwnProperty(ver)) {
// get unique user contained in groups for this verification
gr = new GlideAggregate(this.SYS_USER_GRMEMBER);
var groupIds = [];
for (var grp in verificationToUserGroupMapping[ver]) {
if (verificationToUserGroupMapping[ver].hasOwnProperty(grp)) {
groupIds.push(grp);
}
}
gr.addQuery('group', groupIds);
gr.addQuery('user.active', true);
gr.groupBy('user');
gr.query();
while (gr.next()) {
this.createOrUpdateEnrollmentSnapshot(ver, gr.user);
}
}
}
//delete all the snapshot records that are no longer valid
this.deleteInValidEnrollmentSnapshots();
},
getChildGroups: function(groupId, verificationToUserGroupMapping, processVerification) {
for (var ver in processVerification) {
if (processVerification.hasOwnProperty(ver)) {
verificationToUserGroupMapping[ver][groupId] = true;
}
}
var userGroupGr = new GlideRecord(this.SYS_USER_GROUP);
userGroupGr.addActiveQuery();
userGroupGr.addQuery('parent', groupId);
userGroupGr.query();
while (userGroupGr.next()) {
this.getChildGroups(userGroupGr.getUniqueValue(), verificationToUserGroupMapping, processVerification);
}
},
type: 'PwdEnrollSnapshotUtilSNC'
};
Sys ID
7373cb5943422110d68db0e245b8f218