Files
disco-ad-compare-plugin/Features/DeviceUIExtension.cs
T

191 lines
7.8 KiB
C#

using Disco.Data.Repository;
using Disco.Models.UI.Device;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.UIExtension;
using System;
using System.Text;
using System.Web.Mvc;
namespace Disco.Plugins.ADCompare.Features
{
[PluginFeature(Id = "ADCompareDeviceUI", Name = "Device Page - AD Compare")]
public class DeviceUIExtension : UIExtensionFeature<DeviceShowModel>
{
public override void Initialize(DiscoDataContext Database)
{
Register();
}
public override UIExtensionResult ExecuteAction(ControllerContext context, DeviceShowModel model)
{
var device = model.Device;
if (device == null || string.IsNullOrEmpty(device.DeviceDomainId))
return Nothing();
var html = new StringBuilder();
html.Append("<div class='form-group' style='margin-top:15px;'>");
html.Append("<h4 style='border-bottom:1px solid #ddd;padding-bottom:5px;'>");
html.Append("<i class='fa fa-exchange'></i> AD Compare</h4>");
try
{
var adAccount = ActiveDirectory.RetrieveADMachineAccount(
device.DeviceDomainId,
new[] { "managedBy", "lastLogonTimestamp" });
if (adAccount == null)
{
html.Append("<div class='alert alert-danger'>");
html.Append("<i class='fa fa-times-circle'></i> Computer not found in Active Directory");
html.Append("</div>");
}
else
{
var managedByDN = adAccount.GetPropertyValue<string>("managedBy");
var discoAssignedUser = device.AssignedUserId;
var hasManagedBy = !string.IsNullOrEmpty(managedByDN);
var hasAssignment = !string.IsNullOrEmpty(discoAssignedUser);
string managedByDisplayName = hasManagedBy ? ExtractCNFromDN(managedByDN) : null;
string assignedUserDN = null;
if (hasAssignment)
{
try
{
var assignedUserAD = ActiveDirectory.RetrieveADUserAccount(discoAssignedUser);
if (assignedUserAD != null)
assignedUserDN = assignedUserAD.DistinguishedName;
}
catch { }
}
bool isMatch = false;
if (!hasAssignment && !hasManagedBy)
isMatch = true;
else if (hasAssignment && hasManagedBy && assignedUserDN != null)
isMatch = string.Equals(assignedUserDN, managedByDN, StringComparison.OrdinalIgnoreCase);
html.Append("<table class='table table-condensed' style='margin-bottom:10px;'>");
if (isMatch)
{
html.Append("<tr class='success'><td colspan='2'>");
html.Append("<i class='fa fa-check-circle'></i> <strong>Managed By matches Assigned User</strong>");
html.Append("</td></tr>");
}
else
{
html.Append("<tr class='warning'><td colspan='2'>");
html.Append("<i class='fa fa-exclamation-triangle'></i> <strong>Managed By does NOT match Assigned User</strong>");
html.Append("</td></tr>");
}
html.Append("<tr><td style='width:180px;'><strong>Disco Assigned User</strong></td><td>");
if (hasAssignment)
{
html.Append(Encode(discoAssignedUser));
if (device.AssignedUser != null)
{
html.Append(" <span class='text-muted'>(");
html.Append(Encode(device.AssignedUser.DisplayName));
html.Append(")</span>");
}
}
else
{
html.Append("<em class='text-muted'>Not assigned</em>");
}
html.Append("</td></tr>");
html.Append("<tr><td><strong>AD Managed By</strong></td><td>");
if (hasManagedBy)
{
html.Append(Encode(managedByDisplayName ?? managedByDN));
}
else
{
html.Append("<em class='text-muted'>Empty</em>");
}
html.Append("</td></tr>");
var lastLogonTicks = adAccount.GetPropertyValue<long>("lastLogonTimestamp");
html.Append("<tr><td><strong>Last Login</strong></td><td>");
if (lastLogonTicks > 0)
{
try
{
var lastLogon = DateTime.FromFileTime(lastLogonTicks);
var ago = DateTime.Now.Subtract(lastLogon);
html.Append(Encode(lastLogon.ToString("dd/MM/yyyy hh:mm tt")));
html.Append(" <span class='text-muted'>(");
html.Append(FormatTimeAgo(ago));
html.Append(")</span>");
}
catch
{
html.Append("<em class='text-muted'>Unable to parse</em>");
}
}
else
{
html.Append("<em class='text-muted'>Never</em>");
}
html.Append("</td></tr>");
if (adAccount.IsDisabled)
{
html.Append("<tr class='danger'><td><strong>AD Status</strong></td><td>");
html.Append("<i class='fa fa-ban'></i> <strong>Disabled</strong>");
html.Append("</td></tr>");
}
html.Append("</table>");
}
}
catch (Exception ex)
{
html.Append("<div class='alert alert-warning'>");
html.Append("<i class='fa fa-exclamation-triangle'></i> AD lookup error: ");
html.Append(Encode(ex.Message));
html.Append("</div>");
}
html.Append("</div>");
return Literal(html.ToString());
}
private string ExtractCNFromDN(string dn)
{
if (string.IsNullOrEmpty(dn)) return null;
if (dn.StartsWith("CN=", StringComparison.OrdinalIgnoreCase))
{
var commaIndex = dn.IndexOf(',');
if (commaIndex > 3) return dn.Substring(3, commaIndex - 3);
return dn.Substring(3);
}
return dn;
}
private string Encode(string value)
{
if (string.IsNullOrEmpty(value)) return "";
return System.Web.HttpUtility.HtmlEncode(value);
}
private string FormatTimeAgo(TimeSpan span)
{
if (span.TotalDays >= 365)
return string.Format("{0} year(s) ago", (int)(span.TotalDays / 365));
if (span.TotalDays >= 30)
return string.Format("{0} month(s) ago", (int)(span.TotalDays / 30));
if (span.TotalDays >= 1)
return string.Format("{0} day(s) ago", (int)span.TotalDays);
if (span.TotalHours >= 1)
return string.Format("{0} hour(s) ago", (int)span.TotalHours);
return "Just now";
}
}
}