diff --git a/WebHandler/ADCompareWebHandler.cs b/WebHandler/ADCompareWebHandler.cs new file mode 100644 index 0000000..efedd1c --- /dev/null +++ b/WebHandler/ADCompareWebHandler.cs @@ -0,0 +1,295 @@ +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 + } +}