Skip to content

Instantly share code, notes, and snippets.

@msd-sal
Created December 8, 2021 00:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msd-sal/0704bd77f5c1de9afebbaf387af0cbdc to your computer and use it in GitHub Desktop.
Save msd-sal/0704bd77f5c1de9afebbaf387af0cbdc to your computer and use it in GitHub Desktop.
using Microsoft.Extensions.DependencyInjection;
using PasswordGenerator;
using Quartz;
using Cornerstone.Model.iwise;
using Cornerstone.Model.Cornerstone.Actions.LDAP;
using Cornerstone.Services;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Cornerstone.Model.Cornerstone.Actions;
using Cornerstone.Model.Cornerstone;
namespace Cornerstone.Jobs
{
internal class ContactMonitoringJob : IJob
{
private readonly ContactService contactService;
private readonly LdapService ldapService;
private readonly ActionService actionService;
private readonly IwzCommonService iwzCommonService;
private readonly SettingsService settingsService;
public ContactMonitoringJob(ContactService contactService, LdapService ldapService, ActionService actionService, IwzCommonService iwzCommonService, SettingsService settingsService)
{
this.contactService = contactService;
this.ldapService = ldapService;
this.actionService = actionService;
this.iwzCommonService = iwzCommonService;
this.settingsService = settingsService;
}
private static ContactKeyMapping GetKeyMappingForContact(ICollection<ContactKeyMapping> keyMappings, WmContact iwzContact)
{
return keyMappings.SingleOrDefault(m => m.DefaultSamAccountName == iwzContact.GetSamAccountName() && m.FirstName == iwzContact.FirstName && m.Surname == iwzContact.Surname);
}
private (bool foundPartialMatch, UserPrincipal matchingDomainAccount) SearchForMatchInDomain(WmContact iwzContact, string contactSam, List<UserPrincipal> domainAccounts)
{
int domainUsersIndex = 0;
bool samsMatch = false;
bool fullNamesMatch = false;
UserPrincipal matchingDomainAccount = null;
while (domainUsersIndex < domainAccounts.Count && !samsMatch)
{
var domainAccount = domainAccounts[domainUsersIndex++];
samsMatch = string.Compare(contactSam, domainAccount.SamAccountName, true) == 0;
if (samsMatch)
{
fullNamesMatch =
string.Compare(iwzContact.FirstName, domainAccount.GivenName, true) == 0
&& string.Compare(iwzContact.Surname, domainAccount.Surname, true) == 0;
if (fullNamesMatch)
{
matchingDomainAccount = domainAccount;
}
}
}
bool partialMatch = samsMatch && !fullNamesMatch;
return (partialMatch, matchingDomainAccount);
}
private (string contactOU, List<string> contactGroups) DetermineOuAndGroupsForContact(WmContact iwzContact, ApplicationSettings settings)
{
string contactOU = null;
List<string> contactGroups = new();
if (iwzContact.IsStudent)
{
int campusId = int.Parse(iwzContact.Campus);
if (iwzContact.SchoolYear.HasValue)
{
if (settings.PrimarySchoolYears.Contains(iwzContact.SchoolYear.Value))
{
contactOU = settings.PrimaryStudentOusByCampus?.GetValueOrDefault(campusId);
contactGroups.Add(settings.PrimaryStudentGroupsByCampus?.GetValueOrDefault(campusId));
}
else if (settings.SecondarySchoolYears.Contains(iwzContact.SchoolYear.Value))
{
contactOU = settings.SecondaryStudentOusByCampus?.GetValueOrDefault(campusId);
contactGroups.Add(settings.SecondaryStudentGroupsByCampus?.GetValueOrDefault(campusId));
}
}
}
else
{
var facultyNames = iwzContact.Faculties.ToList();
if (facultyNames.Count == 0)
{
contactOU = null;
}
else
{
var facultyMappings = iwzCommonService.GetFacultyMappings(facultyNames);
contactOU = facultyMappings.FirstOrDefault()?.OU;
contactGroups.AddRange(facultyMappings.SelectMany(m => m.AdGroups).Distinct());
}
}
return (contactOU, contactGroups);
}
private static bool CheckIfContactMissingKeyData(WmContact iwzContact, string contactSam)
{
return contactSam == null || string.IsNullOrWhiteSpace(iwzContact.FirstName) || string.IsNullOrWhiteSpace(iwzContact.Surname);
}
private void GenerateDataCheckMessagesForContact(WmContact contact, ApplicationSettings settings, StringBuilder sb)
{
int campusId = int.Parse(contact.Campus);
if (contact.IsStudent)
{
if (!contact.SchoolYear.HasValue)
{
sb.AppendLine($"Student \"{contact.GetSamAccountName()}\" without School Year");
}
else
{
string ou = null, group = null;
string studentLevel = "";
bool isPrimaryStudent = settings.PrimarySchoolYears.Contains(contact.SchoolYear.Value);
bool isSecondaryStudent = settings.SecondarySchoolYears.Contains(contact.SchoolYear.Value);
if (!isPrimaryStudent && !isSecondaryStudent)
{
sb.AppendLine($"School Year ({contact.SchoolYear.Value})[{contact.SchoolYearDesc}] assigned to student \"{contact.GetSamAccountName()}\" is not classified as Primary nor Secondary.");
}
else
{
if (isPrimaryStudent)
{
studentLevel = "Primary";
ou = settings.PrimaryStudentOusByCampus?.GetValueOrDefault(campusId);
group = settings.PrimaryStudentGroupsByCampus?.GetValueOrDefault(campusId);
}
else if (isSecondaryStudent)
{
studentLevel = "Secondary";
ou = settings.SecondaryStudentOusByCampus?.GetValueOrDefault(campusId);
group = settings.SecondaryStudentGroupsByCampus?.GetValueOrDefault(campusId);
}
if (string.IsNullOrWhiteSpace(ou))
{
sb.AppendLine($"Missing configuration \"{studentLevel} Student OU\" for campus of ID \"{campusId}\".");
}
if (string.IsNullOrWhiteSpace(group))
{
sb.AppendLine($"Missing configuration \"{studentLevel} Student Group\" for campus of ID \"{campusId}\".");
}
}
}
}
if (contact.IsStudent && string.IsNullOrWhiteSpace(contact.ForeignKey))
{
sb.AppendLine("Missing ForeignKey in contact record.");
}
if (string.IsNullOrWhiteSpace(contact.FirstName))
{
sb.AppendLine("Missing FirstName in contact record.");
}
if (string.IsNullOrWhiteSpace(contact.Surname))
{
sb.AppendLine("Missing Surname in contact record.");
}
if (!contact.IsStudent)
{
if (contact.Faculties.Count == 0)
{
sb.AppendLine("Contact is not a memeber of any faculty.");
}
else
{
var facultyNames = contact.Faculties.ToList();
var facultyMapping = iwzCommonService.GetFacultyMappings(facultyNames).FirstOrDefault();
if (facultyMapping == null)
{
sb.AppendLine($"Could not find a mapping for any of the following faculties: [{facultyNames.Aggregate((a, b) => $"{a}, {b}")}]");
}
}
}
}
private string GetUniqueCnForContact(WmContact contact, List<UserPrincipal> domainUsers)
{
string contactCN = $"{contact.FirstName} {contact.Surname}";
List<string> cnMatches =
domainUsers
.Where(du =>
{
var de = du.GetUnderlyingObject() as DirectoryEntry;
string duCn = de.Properties["cn"].Value.ToString();
return duCn.StartsWith(contactCN);
})
.Select(du =>
{
var de = du.GetUnderlyingObject() as DirectoryEntry;
return de.Properties["cn"].Value.ToString();
})
.ToList();
for (int i = 2; i < 10 && cnMatches.Contains(contactCN); i++)
{
contactCN = $"{contactCN} {i}";
}
return contactCN;
}
public async Task Execute(IJobExecutionContext context)
{
Console.WriteLine("Executing ContactMonitoringJob");
var iwzCurrentContacts = contactService.GetAllCurrentContacts();
Console.WriteLine($"Found {iwzCurrentContacts.Count} contacts in IWZ.");
List<CornerstoneAction> actions = new();
StringBuilder sbNotes = new();
var settings = settingsService.GetSettings();
var keyMappings = settingsService.GetContactKeyMappings();
var domainUsersIncludingDisabled = ldapService.GetDomainAccounts(true);
foreach (var iwzContact in iwzCurrentContacts)
{
var keyMapping = GetKeyMappingForContact(keyMappings, iwzContact);
var contactSam = keyMapping?.SamAccountName ?? iwzContact.GetSamAccountName();
if (!CheckIfContactMissingKeyData(iwzContact, contactSam))
{
if (iwzContact.IsCurrentStudent || iwzContact.IsCurrentStaff) // not a student relative
{
var (foundPartialMatch, matchingDomainAccount) =
SearchForMatchInDomain(iwzContact, contactSam, domainUsersIncludingDisabled);
if (foundPartialMatch) // do not continue processing this contact in case of partial match
{
if (keyMapping == null)
{
settingsService.CreateKeyMappingForContact(iwzContact.FirstName, iwzContact.Surname, contactSam, iwzContact.IsStaff);
}
}
else
{
if (matchingDomainAccount == null || matchingDomainAccount.IsDisabled())
{
sbNotes.Clear();
GenerateDataCheckMessagesForContact(iwzContact, settings, sbNotes);
string contactEmail = $"{contactSam}@{(iwzContact.IsStudent ? settings.StudentDomain : settings.StaffDomain)}";
var (contactOU, contactGroups) = DetermineOuAndGroupsForContact(iwzContact, settings);
if (matchingDomainAccount != null) //disabled user
{
string contactCN = matchingDomainAccount.DisplayName;
actions.Add(new EnableUserAction(iwzContact, contactSam, contactCN, contactOU, contactGroups, contactEmail, sbNotes.ToString()));
}
else
{
string contactCN = GetUniqueCnForContact(iwzContact, domainUsersIncludingDisabled);
var password = new Password().IncludeLowercase().IncludeNumeric().IncludeUppercase();
actions.Add(new AddUserAction(iwzContact, contactSam, contactCN, contactOU, contactGroups, contactEmail, password.Next(), sbNotes.ToString()));
}
}
}
}
}
}
if (actions.Count > 0)
{
var filteredActions = actionService.FilterOutExistingActions(actions);
actionService.AddUserActions(filteredActions);
}
Console.WriteLine($"{actions.Count} actions");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment