130 lines
5.5 KiB
C#
130 lines
5.5 KiB
C#
using Disco.Data.Repository;
|
|
using Disco.Models.Repository;
|
|
using Disco.Services.Interop.ActiveDirectory;
|
|
using Disco.Services.Plugins;
|
|
using Disco.Services.Plugins.Features.DetailsProvider;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Disco.Plugins.ADCompare.Features
|
|
{
|
|
[PluginFeature(Id = "ADCompareDetails", Name = "AD Compare Detail Provider", PrimaryFeature = true)]
|
|
public class ADCompareDetailsProvider : DetailsProviderFeature
|
|
{
|
|
private const string DetailsScope = "Details";
|
|
private const string ADCompareScope = "ADCompare";
|
|
|
|
/// <summary>
|
|
/// Updates all user details by comparing AD attributes against Disco records.
|
|
/// Stores comparison metadata as UserDetails with ADCompare scope.
|
|
/// </summary>
|
|
public override void UpdateAllDetails(DiscoDataContext database)
|
|
{
|
|
var users = database.Users.ToList();
|
|
|
|
foreach (var user in users)
|
|
{
|
|
try
|
|
{
|
|
var adUser = ActiveDirectory.RetrieveADUserAccount(user.UserId);
|
|
if (adUser == null)
|
|
{
|
|
SetUserDetail(database, user, ADCompareScope, "ADStatus", "NotFound");
|
|
SetUserDetail(database, user, ADCompareScope, "LastChecked", DateTime.Now.ToString("o"));
|
|
continue;
|
|
}
|
|
|
|
// Store comparison results as UserDetails
|
|
SetUserDetail(database, user, ADCompareScope, "ADStatus", adUser.IsDisabled ? "Disabled" : "Active");
|
|
SetUserDetail(database, user, ADCompareScope, "LastChecked", DateTime.Now.ToString("o"));
|
|
|
|
// Store AD values for reference
|
|
SetUserDetail(database, user, ADCompareScope, "AD_DisplayName", adUser.DisplayName ?? string.Empty);
|
|
SetUserDetail(database, user, ADCompareScope, "AD_Surname", adUser.Surname ?? string.Empty);
|
|
SetUserDetail(database, user, ADCompareScope, "AD_GivenName", adUser.GivenName ?? string.Empty);
|
|
SetUserDetail(database, user, ADCompareScope, "AD_Email", adUser.Email ?? string.Empty);
|
|
SetUserDetail(database, user, ADCompareScope, "AD_Phone", adUser.Phone ?? string.Empty);
|
|
SetUserDetail(database, user, ADCompareScope, "AD_DistinguishedName", adUser.DistinguishedName ?? string.Empty);
|
|
|
|
// Check for mismatches
|
|
var mismatches = new List<string>();
|
|
if (!StringMatch(user.DisplayName, adUser.DisplayName)) mismatches.Add("DisplayName");
|
|
if (!StringMatch(user.Surname, adUser.Surname)) mismatches.Add("Surname");
|
|
if (!StringMatch(user.GivenName, adUser.GivenName)) mismatches.Add("GivenName");
|
|
if (!StringMatch(user.EmailAddress, adUser.Email)) mismatches.Add("Email");
|
|
if (!StringMatch(user.PhoneNumber, adUser.Phone)) mismatches.Add("Phone");
|
|
|
|
SetUserDetail(database, user, ADCompareScope, "MismatchedFields",
|
|
mismatches.Count > 0 ? string.Join(",", mismatches) : "None");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SetUserDetail(database, user, ADCompareScope, "ADStatus", "Error");
|
|
SetUserDetail(database, user, ADCompareScope, "ADError", ex.Message);
|
|
SetUserDetail(database, user, ADCompareScope, "LastChecked", DateTime.Now.ToString("o"));
|
|
}
|
|
}
|
|
|
|
database.SaveChanges();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets user photo from AD (thumbnailPhoto attribute).
|
|
/// Returns null if no photo or cache is still valid.
|
|
/// </summary>
|
|
public override byte[] GetUserPhoto(DiscoDataContext database, User user, DateTime? cacheTimestamp)
|
|
{
|
|
// Only refresh photos older than 24 hours
|
|
if (cacheTimestamp.HasValue && cacheTimestamp.Value > DateTime.Now.AddHours(-24))
|
|
return null;
|
|
|
|
try
|
|
{
|
|
var adUser = ActiveDirectory.RetrieveADUserAccount(user.UserId, new[] { "thumbnailPhoto" });
|
|
if (adUser == null)
|
|
return null;
|
|
|
|
var photoData = adUser.GetPropertyValue<byte[]>("thumbnailPhoto");
|
|
return photoData;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
#region Helpers
|
|
|
|
private bool StringMatch(string discoValue, string adValue)
|
|
{
|
|
var a = string.IsNullOrWhiteSpace(discoValue) ? string.Empty : discoValue.Trim();
|
|
var b = string.IsNullOrWhiteSpace(adValue) ? string.Empty : adValue.Trim();
|
|
return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
private void SetUserDetail(DiscoDataContext database, User user, string scope, string key, string value)
|
|
{
|
|
var existing = database.UserDetails
|
|
.FirstOrDefault(d => d.UserId == user.UserId && d.Scope == scope && d.Key == key);
|
|
|
|
if (existing != null)
|
|
{
|
|
existing.Value = value;
|
|
}
|
|
else
|
|
{
|
|
database.UserDetails.Add(new UserDetail
|
|
{
|
|
UserId = user.UserId,
|
|
Scope = scope,
|
|
Key = key,
|
|
Value = value
|
|
});
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|