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.
Comparing users against AD... This may take a moment.