Files
disco-ad-compare-plugin/Features/DeviceCompareService.cs
T

178 lines
6.4 KiB
C#

using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Plugins.ADCompare.Models;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Disco.Plugins.ADCompare.Features
{
public class DeviceCompareService
{
private readonly DiscoDataContext database;
public DeviceCompareService(DiscoDataContext database)
{
this.database = database;
}
public DeviceComparisonSummary CompareAllDevices()
{
var summary = new DeviceComparisonSummary();
var devices = database.Devices
.Include("AssignedUser")
.Where(d => d.DeviceDomainId != null && d.DecommissionedDate == null)
.ToList();
// Only process devices with a valid DOMAIN\ComputerName format
var validDevices = devices.Where(d => d.DeviceDomainId.Contains("\\")).ToList();
summary.TotalDevices = validDevices.Count;
summary.SkippedDevices = devices.Count - validDevices.Count;
foreach (var device in validDevices)
{
var result = CompareDevice(device);
// Skip devices not found in AD - only keep ones we can actually compare
if (!result.FoundInAD)
{
summary.DevicesNotInAD++;
continue;
}
summary.Results.Add(result);
}
summary.DevicesWithAssignment = summary.Results.Count(r => r.HasAssignment);
summary.DevicesMatched = summary.Results.Count(r => r.IsMatch);
summary.DevicesMismatched = summary.Results.Count(r => !r.IsMatch);
summary.DevicesNoAssignment = summary.Results.Count(r => !r.HasAssignment);
summary.DevicesNoManagedBy = summary.Results.Count(r => !r.HasManagedBy);
summary.DevicesADDisabled = summary.Results.Count(r => r.ADAccountDisabled);
return summary;
}
public DeviceComparisonResult CompareDevice(Device device)
{
var result = new DeviceComparisonResult();
result.SerialNumber = device.SerialNumber;
result.DeviceDomainId = device.DeviceDomainId;
result.ComputerName = device.ComputerName;
result.DiscoAssignedUserId = device.AssignedUserId;
result.DiscoAssignedUserDisplayName = device.AssignedUser != null ? device.AssignedUser.DisplayName : null;
result.HasAssignment = !string.IsNullOrEmpty(device.AssignedUserId);
try
{
var adAccount = ActiveDirectory.RetrieveADMachineAccount(device.DeviceDomainId, new[] { "managedBy" });
if (adAccount == null)
{
result.FoundInAD = false;
result.MismatchReason = "Computer not found in AD";
return result;
}
result.FoundInAD = true;
result.ADAccountDisabled = adAccount.IsDisabled;
var managedByDN = adAccount.GetPropertyValue<string>("managedBy");
result.ADManagedByDN = managedByDN;
result.HasManagedBy = !string.IsNullOrEmpty(managedByDN);
if (result.HasManagedBy)
{
result.ADManagedByDisplayName = ExtractCNFromDN(managedByDN);
}
string assignedUserDN = null;
if (result.HasAssignment)
{
try
{
var assignedUserAD = ActiveDirectory.RetrieveADUserAccount(device.AssignedUserId);
if (assignedUserAD != null)
{
assignedUserDN = assignedUserAD.DistinguishedName;
result.ADManagedByUserId = device.AssignedUserId;
}
}
catch { }
}
if (!result.HasAssignment && !result.HasManagedBy)
{
result.IsMatch = true;
}
else if (result.HasAssignment && result.HasManagedBy && assignedUserDN != null)
{
result.IsMatch = string.Equals(assignedUserDN, managedByDN, StringComparison.OrdinalIgnoreCase);
if (result.IsMatch)
{
result.ADManagedByUserId = device.AssignedUserId;
}
}
else
{
result.IsMatch = false;
}
if (!result.IsMatch)
{
result.MismatchReason = DetermineMismatchReason(result, assignedUserDN);
}
}
catch (Exception ex)
{
result.FoundInAD = false;
result.MismatchReason = "AD lookup error: " + ex.Message;
}
return result;
}
private string DetermineMismatchReason(DeviceComparisonResult result, string assignedUserDN)
{
if (!result.FoundInAD)
return "Computer not found in AD";
if (result.HasAssignment && !result.HasManagedBy)
return "Assigned in Disco but AD managedBy is empty";
if (!result.HasAssignment && result.HasManagedBy)
return string.Format("Not assigned in Disco but AD managedBy is set to {0}",
ExtractCNFromDN(result.ADManagedByDN));
if (result.HasAssignment && result.HasManagedBy)
{
var managedByName = ExtractCNFromDN(result.ADManagedByDN);
return string.Format("Different users: Disco={0} ({1}), AD managedBy={2}",
result.DiscoAssignedUserId,
result.DiscoAssignedUserDisplayName ?? "?",
managedByName);
}
return "Unknown mismatch";
}
private string ExtractCNFromDN(string dn)
{
if (string.IsNullOrEmpty(dn))
return null;
if (dn.StartsWith("CN=", StringComparison.OrdinalIgnoreCase))
{
var commaIndex = dn.IndexOf(',');
if (commaIndex > 3)
return dn.Substring(3, commaIndex - 3);
return dn.Substring(3);
}
return dn;
}
}
}