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"; /// /// Updates all user details by comparing AD attributes against Disco records. /// Stores comparison metadata as UserDetails with ADCompare scope. /// 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(); 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(); } /// /// Gets user photo from AD (thumbnailPhoto attribute). /// Returns null if no photo or cache is still valid. /// 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("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 } }