using Disco.Plugins.ADCompare.Features; using Disco.Plugins.ADCompare.Models; using Disco.Services.Plugins; using Newtonsoft.Json; using System; using System.Text; using System.Web.Mvc; namespace Disco.Plugins.ADCompare.WebHandler { public class ADCompareWebHandler : PluginWebHandler { public override ActionResult ExecuteAction(string ActionName) { switch (ActionName?.ToLower()) { case null: case "": case "index": return Index(); case "compare": return Compare(); case "compareuser": return CompareUser(); case "export": return ExportCsv(); default: return new HttpNotFoundResult(); } } /// /// Landing page with a button to run comparison /// private ActionResult Index() { var html = BuildIndexPage(); return new ContentResult { Content = html, ContentType = "text/html", ContentEncoding = Encoding.UTF8 }; } /// /// Run full comparison and return results as JSON /// private ActionResult Compare() { var service = new ADCompareService(Database); var summary = service.CompareAllUsers(); return new ContentResult { Content = JsonConvert.SerializeObject(summary, Formatting.Indented), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } /// /// Compare a single user - expects ?userId=DOMAIN\username /// private ActionResult CompareUser() { var userId = HostController.Request.QueryString["userId"]; if (string.IsNullOrWhiteSpace(userId)) { return new HttpStatusCodeResult(400, "userId parameter required"); } var user = Database.Users.Find(userId); if (user == null) { return new HttpStatusCodeResult(404, "User not found in Disco"); } var service = new ADCompareService(Database); var result = service.CompareUser(user); return new ContentResult { Content = JsonConvert.SerializeObject(result, Formatting.Indented), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } /// /// Export comparison results as CSV /// private ActionResult ExportCsv() { var service = new ADCompareService(Database); var summary = service.CompareAllUsers(); var sb = new StringBuilder(); sb.AppendLine("UserId,DisplayName,FoundInAD,ADDisabled,MismatchedFields,Details"); foreach (var result in summary.Results) { var mismatchFields = result.HasMismatches ? string.Join("; ", result.Mismatches.ConvertAll(m => m.FieldName)) : "None"; var details = result.HasMismatches ? string.Join("; ", result.Mismatches.ConvertAll(m => $"{m.FieldName}: Disco='{m.DiscoValue}' AD='{m.ADValue}'")) : ""; sb.AppendLine($"\"{CsvEscape(result.UserId)}\",\"{CsvEscape(result.DisplayName)}\",{result.UserFoundInAD},{result.ADAccountDisabled},\"{CsvEscape(mismatchFields)}\",\"{CsvEscape(details)}\""); } var fileName = $"AD_Compare_{DateTime.Now:yyyyMMdd_HHmmss}.csv"; HostController.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{fileName}\""); return new ContentResult { Content = sb.ToString(), ContentType = "text/csv", ContentEncoding = Encoding.UTF8 }; } private string CsvEscape(string value) { if (string.IsNullOrEmpty(value)) return ""; return value.Replace("\"", "\"\""); } #region HTML Page Builder private string BuildIndexPage() { var pluginUrl = Url.Action(MVC.API.Disco.Plugin.PluginWebAction(Manifest.Id, null)); return $@"

AD Compare - User Detail Comparison

Compare Active Directory user details against Disco ICT records to identify mismatches.

"; } #endregion } }