Feature #42: Active Directory Interop Upgrade
AD Interop moved to Disco.Services; Supports multi-domain environments, sites, and searching restricted with OUs.
This commit is contained in:
+105
-54
@@ -1,13 +1,14 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.ClientServices;
|
using Disco.Models.ClientServices;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Tamir.SharpSsh;
|
using Tamir.SharpSsh;
|
||||||
@@ -242,7 +243,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -252,7 +253,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
RepoDevice = new Device
|
RepoDevice = new Device
|
||||||
{
|
{
|
||||||
SerialNumber = Request.DeviceSerialNumber,
|
SerialNumber = Request.DeviceSerialNumber,
|
||||||
ComputerName = Request.DeviceComputerName,
|
DeviceDomainId = Request.DeviceComputerName,
|
||||||
DeviceProfile = deviceProfile,
|
DeviceProfile = deviceProfile,
|
||||||
DeviceModel = deviceModel,
|
DeviceModel = deviceModel,
|
||||||
AllowUnauthenticatedEnrol = false,
|
AllowUnauthenticatedEnrol = false,
|
||||||
@@ -267,7 +268,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
|
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
|
||||||
{
|
{
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -280,7 +281,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
|
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
|
||||||
}
|
}
|
||||||
RepoDevice.ComputerName = Request.DeviceComputerName;
|
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
|
||||||
if (!RepoDevice.EnrolledDate.HasValue)
|
if (!RepoDevice.EnrolledDate.HasValue)
|
||||||
{
|
{
|
||||||
RepoDevice.EnrolledDate = DateTime.Now;
|
RepoDevice.EnrolledDate = DateTime.Now;
|
||||||
@@ -294,14 +295,14 @@ namespace Disco.BI.DeviceBI
|
|||||||
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||||
{
|
{
|
||||||
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
|
ActiveDirectoryUserAccount AssignedUserInfo = Disco.Services.Interop.ActiveDirectory.ActiveDirectory.RetrieveUserAccount(RepoDevice.AssignedUser.UserId);
|
||||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
||||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
|
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
|
||||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier;
|
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier;
|
||||||
}
|
}
|
||||||
response.DeviceComputerName = RepoDevice.ComputerName;
|
response.DeviceComputerName = RepoDevice.DeviceDomainId;
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||||
}
|
}
|
||||||
catch (EnrolSafeException ex)
|
catch (EnrolSafeException ex)
|
||||||
@@ -323,14 +324,26 @@ namespace Disco.BI.DeviceBI
|
|||||||
}
|
}
|
||||||
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
||||||
{
|
{
|
||||||
ActiveDirectoryMachineAccount MachineInfo = null;
|
ActiveDirectoryMachineAccount adMachineAccount = null;
|
||||||
|
|
||||||
EnrolResponse response = new EnrolResponse();
|
EnrolResponse response = new EnrolResponse();
|
||||||
|
|
||||||
AuthorizationToken authenticatedToken = null;
|
AuthorizationToken authenticatedToken = null;
|
||||||
bool isAuthenticated = false;
|
bool isAuthenticated = false;
|
||||||
|
|
||||||
|
ActiveDirectoryDomain domain = null;
|
||||||
|
Lazy<DomainController> domainController = new Lazy<DomainController>(() => {
|
||||||
|
if (domain == null)
|
||||||
|
throw new InvalidOperationException("The [domain] variable must be initialized first");
|
||||||
|
return domain.RetrieveWritableDomainController();
|
||||||
|
});
|
||||||
|
|
||||||
string sessionId = System.Guid.NewGuid().ToString("B");
|
string sessionId = System.Guid.NewGuid().ToString("B");
|
||||||
response.SessionId = sessionId;
|
response.SessionId = sessionId;
|
||||||
|
|
||||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
||||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
||||||
@@ -348,9 +361,9 @@ namespace Disco.BI.DeviceBI
|
|||||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||||
{
|
{
|
||||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.Id));
|
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||||
if (!authenticatedToken.User.Id.Equals(string.Format("{0}$", Request.DeviceComputerName), System.StringComparison.InvariantCultureIgnoreCase))
|
if (!authenticatedToken.User.UserId.Equals(string.Format("{0}$", Request.DeviceComputerName), System.StringComparison.InvariantCultureIgnoreCase))
|
||||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.Id));
|
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -380,10 +393,16 @@ namespace Disco.BI.DeviceBI
|
|||||||
System.Guid? uuidGuid = null;
|
System.Guid? uuidGuid = null;
|
||||||
System.Guid? macAddressGuid = null;
|
System.Guid? macAddressGuid = null;
|
||||||
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
||||||
uuidGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(Request.DeviceUUID);
|
uuidGuid = ActiveDirectoryExtensions.NetbootGUIDFromUUID(Request.DeviceUUID);
|
||||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||||
macAddressGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
macAddressGuid = ActiveDirectoryExtensions.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(Request.DeviceComputerName, uuidGuid, macAddressGuid);
|
|
||||||
|
if (domain == null)
|
||||||
|
domain = ActiveDirectory.GetDomainByDnsName(Request.DeviceDNSDomainName);
|
||||||
|
|
||||||
|
var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName);
|
||||||
|
|
||||||
|
adMachineAccount = ActiveDirectory.RetrieveMachineAccount(domainController.Value, requestDeviceId, uuidGuid, macAddressGuid);
|
||||||
}
|
}
|
||||||
if (RepoDevice == null)
|
if (RepoDevice == null)
|
||||||
{
|
{
|
||||||
@@ -392,7 +411,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||||
|
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -402,7 +421,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
RepoDevice = new Device
|
RepoDevice = new Device
|
||||||
{
|
{
|
||||||
SerialNumber = Request.DeviceSerialNumber,
|
SerialNumber = Request.DeviceSerialNumber,
|
||||||
ComputerName = Request.DeviceComputerName,
|
DeviceDomainId = Request.DeviceComputerName,
|
||||||
DeviceProfile = deviceProfile,
|
DeviceProfile = deviceProfile,
|
||||||
DeviceModel = deviceModel,
|
DeviceModel = deviceModel,
|
||||||
AllowUnauthenticatedEnrol = false,
|
AllowUnauthenticatedEnrol = false,
|
||||||
@@ -423,7 +442,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
||||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -442,88 +461,120 @@ namespace Disco.BI.DeviceBI
|
|||||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MachineInfo == null)
|
if (adMachineAccount == null)
|
||||||
{
|
{
|
||||||
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
|
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
|
||||||
{
|
{
|
||||||
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
||||||
if (string.IsNullOrEmpty(RepoDevice.ComputerName) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
|
||||||
RepoDevice.ComputerName = RepoDevice.ComputerNameRender(Database);
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.ComputerName);
|
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(RepoDevice.ComputerName);
|
if (domain == null)
|
||||||
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
|
domain = ActiveDirectory.GetDomainByDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||||
|
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
|
||||||
|
|
||||||
|
string offlineProvisionDiagnosicInfo;
|
||||||
|
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
|
||||||
|
adMachineAccount = ActiveDirectory.RetrieveMachineAccount(domainController.Value, RepoDevice.DeviceDomainId);
|
||||||
|
|
||||||
|
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(domain, domainController.Value, RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
|
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
if (MachineInfo != null)
|
if (adMachineAccount != null)
|
||||||
{
|
{
|
||||||
response.DeviceComputerName = MachineInfo.Name;
|
response.DeviceComputerName = adMachineAccount.Name;
|
||||||
response.DeviceDomainName = MachineInfo.Domain;
|
response.DeviceDomainName = adMachineAccount.Domain;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
response.DeviceComputerName = RepoDevice.ComputerName;
|
var computerId = Disco.Services.UserExtensions.SplitUserId(RepoDevice.DeviceDomainId);
|
||||||
response.DeviceDomainName = RepoDevice.ComputerName;
|
response.DeviceDomainName = computerId.Item1;
|
||||||
|
response.DeviceComputerName = computerId.Item2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RepoDevice.ComputerName = Request.DeviceComputerName;
|
|
||||||
response.DeviceComputerName = Request.DeviceComputerName;
|
response.DeviceComputerName = Request.DeviceComputerName;
|
||||||
response.DeviceDomainName = RepoDevice.ComputerName;
|
response.DeviceDomainName = Request.DeviceDNSDomainName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RepoDevice.ComputerName = MachineInfo.Name;
|
RepoDevice.DeviceDomainId = adMachineAccount.Name;
|
||||||
response.DeviceComputerName = MachineInfo.Name;
|
response.DeviceComputerName = adMachineAccount.Name;
|
||||||
response.DeviceDomainName = MachineInfo.Domain;
|
response.DeviceDomainName = adMachineAccount.Domain;
|
||||||
|
|
||||||
// Enforce Computer Name Convention
|
// Enforce Computer Name Convention
|
||||||
if (!MachineInfo.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||||
{
|
{
|
||||||
var calculatedComputerName = RepoDevice.ComputerNameRender(Database);
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
if (!Request.DeviceComputerName.Equals(calculatedComputerName, StringComparison.InvariantCultureIgnoreCase))
|
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||||
|
if (domain == null)
|
||||||
|
domain = ActiveDirectory.GetDomainByDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
|
||||||
|
var calculatedComputerName = RepoDevice.ComputerNameRender(Database, domain);
|
||||||
|
var computerNameSplit = Disco.Services.UserExtensions.SplitUserId(calculatedComputerName);
|
||||||
|
|
||||||
|
if (!Request.DeviceComputerName.Equals(computerNameSplit.Item2, StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
|
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
|
||||||
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
||||||
|
|
||||||
RepoDevice.ComputerName = calculatedComputerName;
|
RepoDevice.DeviceDomainId = calculatedComputerName;
|
||||||
response.DeviceComputerName = calculatedComputerName;
|
response.DeviceDomainName = computerNameSplit.Item1;
|
||||||
|
response.DeviceComputerName = computerNameSplit.Item2;
|
||||||
|
|
||||||
// Create New Account
|
// Create New Account
|
||||||
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
|
string offlineProvisionDiagnosicInfo;
|
||||||
|
|
||||||
|
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(domain, domainController.Value, RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
|
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce Organisation Unit
|
// Enforce Organisational Unit
|
||||||
if (!MachineInfo.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
||||||
{
|
{
|
||||||
var parentDistinguishedName = MachineInfo.ParentDistinguishedName();
|
var parentDistinguishedName = adMachineAccount.ParentDistinguishedName();
|
||||||
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
|
throw new InvalidOperationException(string.Format("The Organisational Unit for the Device Profile '{0}' [{1}] is not set.", RepoDevice.DeviceProfile.Name, RepoDevice.DeviceProfile.Id));
|
||||||
|
|
||||||
if ((RepoDevice.DeviceProfile.OrganisationalUnit == null && parentDistinguishedName != null
|
if (!parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.InvariantCultureIgnoreCase)) // Custom OU
|
||||||
&& parentDistinguishedName.Equals("CN=Computers", StringComparison.InvariantCultureIgnoreCase)) // Null (Default) OU
|
|
||||||
|| !parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.InvariantCultureIgnoreCase)) // Custom OU
|
|
||||||
{
|
{
|
||||||
string newOU = RepoDevice.DeviceProfile.OrganisationalUnit ?? "CN=Computers";
|
var proposedDomain = ActiveDirectory.GetDomainByDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
var currentDomain = ActiveDirectory.GetDomainByDistinguishedName(parentDistinguishedName);
|
||||||
|
if (currentDomain != proposedDomain)
|
||||||
|
throw new NotSupportedException("Unable to move the devices organisational unit when the source and destination domains are different.");
|
||||||
|
if (domain == null)
|
||||||
|
domain = proposedDomain;
|
||||||
|
else if (domain != proposedDomain)
|
||||||
|
throw new NotSupportedException("To many domains involved in this enrolment, contact support regarding your scenario.");
|
||||||
|
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisation Unit: {0} -> {1}", parentDistinguishedName, newOU));
|
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisational Unit: {0} -> {1}", parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit));
|
||||||
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, newOU);
|
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
MachineInfo.MoveOrganisationUnit(RepoDevice.DeviceProfile.OrganisationalUnit);
|
adMachineAccount.MoveOrganisationalUnit(domainController.Value, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(MachineInfo.SamAccountName);
|
adMachineAccount = ActiveDirectory.RetrieveMachineAccount(domainController.Value, adMachineAccount.NetBiosId);
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (MachineInfo != null && !MachineInfo.IsCriticalSystemObject)
|
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
||||||
MachineInfo.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
||||||
if (RepoDevice.AssignedUser != null)
|
if (RepoDevice.AssignedUser != null)
|
||||||
MachineInfo.SetDescription(RepoDevice);
|
adMachineAccount.SetDescription(RepoDevice);
|
||||||
}
|
}
|
||||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
||||||
{
|
{
|
||||||
@@ -534,7 +585,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
||||||
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
|
ActiveDirectoryUserAccount AssignedUserInfo = Services.Interop.ActiveDirectory.ActiveDirectory.RetrieveUserAccount(RepoDevice.AssignedUser.UserId);
|
||||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
||||||
response.AllowBootstrapperUninstall = true;
|
response.AllowBootstrapperUninstall = true;
|
||||||
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using Disco.BI.Extensions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.BI.Extensions;
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
using System;
|
||||||
|
|
||||||
namespace Disco.BI.Expressions.Extensions
|
namespace Disco.BI.Expressions.Extensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using Disco.BI.Extensions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.BI.Extensions;
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
using System;
|
||||||
|
|
||||||
namespace Disco.BI.Expressions.Extensions
|
namespace Disco.BI.Expressions.Extensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
WhoAmIResponse response = new WhoAmIResponse()
|
WhoAmIResponse response = new WhoAmIResponse()
|
||||||
{
|
{
|
||||||
Username = token.User.Id,
|
Username = token.User.UserId,
|
||||||
DisplayName = token.User.DisplayName,
|
DisplayName = token.User.DisplayName,
|
||||||
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
|
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Users;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
@@ -90,7 +88,7 @@ namespace Disco.BI.Extensions
|
|||||||
d.DecommissionReason = Reason;
|
d.DecommissionReason = Reason;
|
||||||
|
|
||||||
// Disable AD Account
|
// Disable AD Account
|
||||||
if (d.ComputerName != null)
|
if (d.DeviceDomainId != null)
|
||||||
{
|
{
|
||||||
var adAccount = d.ActiveDirectoryAccount();
|
var adAccount = d.ActiveDirectoryAccount();
|
||||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||||
@@ -117,7 +115,7 @@ namespace Disco.BI.Extensions
|
|||||||
d.DecommissionReason = null;
|
d.DecommissionReason = null;
|
||||||
|
|
||||||
// Enable AD Account
|
// Enable AD Account
|
||||||
if (d.ComputerName != null)
|
if (d.DeviceDomainId != null)
|
||||||
{
|
{
|
||||||
var adAccount = d.ActiveDirectoryAccount();
|
var adAccount = d.ActiveDirectoryAccount();
|
||||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||||
@@ -157,10 +155,10 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = UserService.CurrentUser.Id,
|
TechUserId = UserService.CurrentUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
|
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
|
||||||
Environment.NewLine, d.SerialNumber, d.ComputerName, d.DeviceModel, d.DeviceProfile)
|
Environment.NewLine, d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
|
||||||
};
|
};
|
||||||
Database.JobLogs.Add(jobLog);
|
Database.JobLogs.Add(jobLog);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Data.Configuration;
|
using Disco.Data.Configuration;
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.BI.DocumentTemplates;
|
using Disco.Models.BI.DocumentTemplates;
|
||||||
@@ -10,14 +9,18 @@ using System.IO;
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
public static class DeviceExtensions
|
public static class DeviceExtensions
|
||||||
{
|
{
|
||||||
|
|
||||||
public static string ComputerNameRender(this Device device, DiscoDataContext Database)
|
public static string ComputerNameRender(this Device device, DiscoDataContext Database, ActiveDirectoryDomain Domain)
|
||||||
{
|
{
|
||||||
|
if (Domain == null)
|
||||||
|
throw new ArgumentNullException("Domain");
|
||||||
|
|
||||||
DeviceProfile deviceProfile = device.DeviceProfile;
|
DeviceProfile deviceProfile = device.DeviceProfile;
|
||||||
Expressions.Expression computerNameTemplateExpression = null;
|
Expressions.Expression computerNameTemplateExpression = null;
|
||||||
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||||
@@ -40,7 +43,8 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||||
}
|
}
|
||||||
return rendered.ToString();
|
|
||||||
|
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
|
||||||
}
|
}
|
||||||
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
||||||
{
|
{
|
||||||
@@ -52,7 +56,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
||||||
{
|
{
|
||||||
return ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDate(Device);
|
return Disco.Services.Interop.ActiveDirectory.Internal.ADUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDate(Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||||
@@ -63,7 +67,7 @@ namespace Disco.BI.Extensions
|
|||||||
DeviceAttachment da = new DeviceAttachment()
|
DeviceAttachment da = new DeviceAttachment()
|
||||||
{
|
{
|
||||||
DeviceSerialNumber = Device.SerialNumber,
|
DeviceSerialNumber = Device.SerialNumber,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -160,12 +164,12 @@ namespace Disco.BI.Extensions
|
|||||||
newDua = new DeviceUserAssignment()
|
newDua = new DeviceUserAssignment()
|
||||||
{
|
{
|
||||||
DeviceSerialNumber = d.SerialNumber,
|
DeviceSerialNumber = d.SerialNumber,
|
||||||
AssignedUserId = u.Id,
|
AssignedUserId = u.UserId,
|
||||||
AssignedDate = DateTime.Now
|
AssignedDate = DateTime.Now
|
||||||
};
|
};
|
||||||
Database.DeviceUserAssignments.Add(newDua);
|
Database.DeviceUserAssignments.Add(newDua);
|
||||||
|
|
||||||
d.AssignedUserId = u.Id;
|
d.AssignedUserId = u.UserId;
|
||||||
d.AssignedUser = u;
|
d.AssignedUser = u;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -174,9 +178,9 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update AD Account
|
// Update AD Account
|
||||||
if (!string.IsNullOrEmpty(d.ComputerName) && d.ComputerName.Length <= 24)
|
if (!string.IsNullOrEmpty(d.DeviceDomainId))
|
||||||
{
|
{
|
||||||
var adMachineAccount = Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(d.ComputerName);
|
var adMachineAccount = ActiveDirectory.RetrieveMachineAccount(d.DeviceDomainId);
|
||||||
if (adMachineAccount != null)
|
if (adMachineAccount != null)
|
||||||
{
|
{
|
||||||
adMachineAccount.SetDescription(d);
|
adMachineAccount.SetDescription(d);
|
||||||
@@ -188,8 +192,8 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
public static ActiveDirectoryMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
public static ActiveDirectoryMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(Device.ComputerName))
|
if (!string.IsNullOrEmpty(Device.DeviceDomainId))
|
||||||
return Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(Device.ComputerName, AdditionalProperties: AdditionalProperties);
|
return ActiveDirectory.RetrieveMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ namespace Disco.BI.Extensions
|
|||||||
if (!(Data is User))
|
if (!(Data is User))
|
||||||
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
||||||
User d3 = (User)Data;
|
User d3 = (User)Data;
|
||||||
return d3.Id;
|
return d3.UserId;
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException("Invalid Document Template Scope");
|
throw new InvalidOperationException("Invalid Document Template Scope");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Holding Device was Denied");
|
throw new InvalidOperationException("Holding Device was Denied");
|
||||||
|
|
||||||
j.DeviceHeld = DateTime.Now;
|
j.DeviceHeld = DateTime.Now;
|
||||||
j.DeviceHeldTechUserId = Technician.Id;
|
j.DeviceHeldTechUserId = Technician.UserId;
|
||||||
j.DeviceReadyForReturn = null;
|
j.DeviceReadyForReturn = null;
|
||||||
j.DeviceReadyForReturnTechUserId = null;
|
j.DeviceReadyForReturnTechUserId = null;
|
||||||
j.DeviceReturnedDate = null;
|
j.DeviceReturnedDate = null;
|
||||||
@@ -64,7 +64,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Device Ready for Return was Denied");
|
throw new InvalidOperationException("Device Ready for Return was Denied");
|
||||||
|
|
||||||
j.DeviceReadyForReturn = DateTime.Now;
|
j.DeviceReadyForReturn = DateTime.Now;
|
||||||
j.DeviceReadyForReturnTechUserId = Technician.Id;
|
j.DeviceReadyForReturnTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Device Return was Denied");
|
throw new InvalidOperationException("Device Return was Denied");
|
||||||
|
|
||||||
j.DeviceReturnedDate = DateTime.Now;
|
j.DeviceReturnedDate = DateTime.Now;
|
||||||
j.DeviceReturnedTechUserId = Technician.Id;
|
j.DeviceReturnedTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
|
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
|
||||||
};
|
};
|
||||||
@@ -133,7 +133,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
|
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
|
||||||
};
|
};
|
||||||
@@ -178,7 +178,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
|
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
|
||||||
};
|
};
|
||||||
@@ -248,7 +248,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = techUser.Id,
|
TechUserId = techUser.UserId,
|
||||||
Cost = component.Cost,
|
Cost = component.Cost,
|
||||||
Description = component.Description
|
Description = component.Description
|
||||||
});
|
});
|
||||||
@@ -258,7 +258,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = techUser.Id,
|
TechUserId = techUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
|
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
|
||||||
};
|
};
|
||||||
@@ -302,7 +302,7 @@ namespace Disco.BI.Extensions
|
|||||||
var techUser = UserService.CurrentUser;
|
var techUser = UserService.CurrentUser;
|
||||||
|
|
||||||
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
|
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
|
||||||
j.JobMetaInsurance.ClaimFormSentUserId = techUser.Id;
|
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -356,7 +356,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Close was Denied");
|
throw new InvalidOperationException("Close was Denied");
|
||||||
|
|
||||||
j.ClosedDate = DateTime.Now;
|
j.ClosedDate = DateTime.Now;
|
||||||
j.ClosedTechUserId = Technician.Id;
|
j.ClosedTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null)
|
private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null)
|
||||||
@@ -475,14 +475,14 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
|
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
|
||||||
};
|
};
|
||||||
Database.JobLogs.Add(jobLog);
|
Database.JobLogs.Add(jobLog);
|
||||||
|
|
||||||
j.ClosedDate = DateTime.Now;
|
j.ClosedDate = DateTime.Now;
|
||||||
j.ClosedTechUserId = Technician.Id;
|
j.ClosedTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobAttachment ja = new JobAttachment()
|
JobAttachment ja = new JobAttachment()
|
||||||
{
|
{
|
||||||
JobId = Job.Id,
|
JobId = Job.Id,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -148,7 +148,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobLogs.Add(new JobLog()
|
Database.JobLogs.Add(new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = logBuilder.ToString()
|
Comments = logBuilder.ToString()
|
||||||
});
|
});
|
||||||
@@ -182,7 +182,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Cost = c.Cost,
|
Cost = c.Cost,
|
||||||
Description = c.Description
|
Description = c.Description
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Removing job from queue is Denied");
|
throw new InvalidOperationException("Removing job from queue is Denied");
|
||||||
|
|
||||||
jqj.RemovedDate = DateTime.Now;
|
jqj.RemovedDate = DateTime.Now;
|
||||||
jqj.RemovedUserId = Technician.Id;
|
jqj.RemovedUserId = Technician.UserId;
|
||||||
jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim();
|
jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -201,7 +201,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobQueueId = jq.Id,
|
JobQueueId = jq.Id,
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
AddedDate = DateTime.Now,
|
AddedDate = DateTime.Now,
|
||||||
AddedUserId = Technician.Id,
|
AddedUserId = Technician.UserId,
|
||||||
AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(),
|
AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(),
|
||||||
SLAExpiresDate = SLAExpires,
|
SLAExpiresDate = SLAExpires,
|
||||||
Priority = Priority
|
Priority = Priority
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
UserAttachment ua = new UserAttachment()
|
UserAttachment ua = new UserAttachment()
|
||||||
{
|
{
|
||||||
UserId = User.Id,
|
UserId = User.UserId,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -59,7 +59,7 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
public static ActiveDirectoryUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
public static ActiveDirectoryUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||||
{
|
{
|
||||||
return Interop.ActiveDirectory.ActiveDirectory.GetUserAccount(User.Id, AdditionalProperties);
|
return Disco.Services.Interop.ActiveDirectory.ActiveDirectory.RetrieveUserAccount(User.UserId, AdditionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CanCreateJob(this User u)
|
public static bool CanCreateJob(this User u)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public static class ActiveDirectoryGroupExtensions
|
|
||||||
{
|
|
||||||
|
|
||||||
public static IEnumerable<Tuple<string, string>> GetMembers(ActiveDirectoryGroup group)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,198 +1,198 @@
|
|||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.DirectoryServices;
|
//using System.DirectoryServices;
|
||||||
using System.DirectoryServices.ActiveDirectory;
|
//using System.DirectoryServices.ActiveDirectory;
|
||||||
using System.Runtime.CompilerServices;
|
//using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
//using System.Runtime.InteropServices;
|
||||||
using System.Security.Principal;
|
//using System.Security.Principal;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
//namespace Disco.BI.Interop.ActiveDirectory
|
||||||
{
|
//{
|
||||||
internal static class ActiveDirectoryHelpers
|
// internal static class ActiveDirectoryHelpers
|
||||||
{
|
// {
|
||||||
#region Static Cached Properties
|
// #region Static Cached Properties
|
||||||
private static string _DefaultDomainName;
|
// private static string _DefaultDomainName;
|
||||||
private static string _DefaultDomainPDCName;
|
// private static string _DefaultDomainPDCName;
|
||||||
private static System.Collections.Generic.List<string> _DefaultDomainDCNames;
|
// private static System.Collections.Generic.List<string> _DefaultDomainDCNames;
|
||||||
private static string _DefaultDomainNetBiosName;
|
// private static string _DefaultDomainNetBiosName;
|
||||||
private static string _DefaultDomainQualifiedName;
|
// private static string _DefaultDomainQualifiedName;
|
||||||
private static string _DefaultLdapPath;
|
// private static string _DefaultLdapPath;
|
||||||
private static bool _DetermineDomainProperties_Loaded = false;
|
// private static bool _DetermineDomainProperties_Loaded = false;
|
||||||
private static object _DetermineDomainProperties_Lock = new object();
|
// private static object _DetermineDomainProperties_Lock = new object();
|
||||||
internal static string DefaultDomainName
|
// internal static string DefaultDomainName
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultDomainName;
|
// return ActiveDirectoryHelpers._DefaultDomainName;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static string DefaultDomainPDCName
|
// internal static string DefaultDomainPDCName
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultDomainPDCName;
|
// return ActiveDirectoryHelpers._DefaultDomainPDCName;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static System.Collections.Generic.List<string> DefaultDomainDCNames
|
// internal static System.Collections.Generic.List<string> DefaultDomainDCNames
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultDomainDCNames;
|
// return ActiveDirectoryHelpers._DefaultDomainDCNames;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static string DefaultDomainNetBiosName
|
// internal static string DefaultDomainNetBiosName
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultDomainNetBiosName;
|
// return ActiveDirectoryHelpers._DefaultDomainNetBiosName;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static string DefaultDomainQualifiedName
|
// internal static string DefaultDomainQualifiedName
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
// return ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static string DefaultLdapPath
|
// internal static string DefaultLdapPath
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
// ActiveDirectoryHelpers.DetermineDomainProperties();
|
||||||
return ActiveDirectoryHelpers._DefaultLdapPath;
|
// return ActiveDirectoryHelpers._DefaultLdapPath;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static string DefaultDCLdapPath(string DC)
|
// internal static string DefaultDCLdapPath(string DC)
|
||||||
{
|
// {
|
||||||
return string.Format("LDAP://{0}/", DC);
|
// return string.Format("LDAP://{0}/", DC);
|
||||||
}
|
// }
|
||||||
internal static DirectoryEntry DefaultLdapRoot
|
// internal static DirectoryEntry DefaultLdapRoot
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
// return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
internal static DirectoryEntry DefaultDCLdapRoot(string DC)
|
// internal static DirectoryEntry DefaultDCLdapRoot(string DC)
|
||||||
{
|
// {
|
||||||
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultDCLdapPath(DC), ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
// return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultDCLdapPath(DC), ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static void DetermineDomainProperties()
|
// private static void DetermineDomainProperties()
|
||||||
{
|
// {
|
||||||
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
// if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
||||||
{
|
// {
|
||||||
lock (ActiveDirectoryHelpers._DetermineDomainProperties_Lock)
|
// lock (ActiveDirectoryHelpers._DetermineDomainProperties_Lock)
|
||||||
{
|
// {
|
||||||
|
|
||||||
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
// if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
||||||
{
|
// {
|
||||||
using (Domain domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain)))
|
// using (Domain domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain)))
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers._DefaultDomainName = domain.Name;
|
// ActiveDirectoryHelpers._DefaultDomainName = domain.Name;
|
||||||
ActiveDirectoryHelpers._DefaultDomainPDCName = domain.PdcRoleOwner.Name;
|
// ActiveDirectoryHelpers._DefaultDomainPDCName = domain.PdcRoleOwner.Name;
|
||||||
ActiveDirectoryHelpers._DefaultDomainDCNames = new System.Collections.Generic.List<string>(domain.DomainControllers.Count);
|
// ActiveDirectoryHelpers._DefaultDomainDCNames = new System.Collections.Generic.List<string>(domain.DomainControllers.Count);
|
||||||
foreach (DomainController dc in domain.DomainControllers)
|
// foreach (DomainController dc in domain.DomainControllers)
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers._DefaultDomainDCNames.Add(dc.Name);
|
// ActiveDirectoryHelpers._DefaultDomainDCNames.Add(dc.Name);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
ActiveDirectoryHelpers._DefaultDomainQualifiedName = string.Format("DC={0}", ActiveDirectoryHelpers._DefaultDomainName.Replace(".", ",DC="));
|
// ActiveDirectoryHelpers._DefaultDomainQualifiedName = string.Format("DC={0}", ActiveDirectoryHelpers._DefaultDomainName.Replace(".", ",DC="));
|
||||||
ActiveDirectoryHelpers._DefaultLdapPath = string.Format("LDAP://{0}/", ActiveDirectoryHelpers._DefaultDomainPDCName);
|
// ActiveDirectoryHelpers._DefaultLdapPath = string.Format("LDAP://{0}/", ActiveDirectoryHelpers._DefaultDomainPDCName);
|
||||||
using (DirectoryEntry entry = new DirectoryEntry(string.Format("{0}CN=Partitions,CN=Configuration,{1}", ActiveDirectoryHelpers._DefaultLdapPath, ActiveDirectoryHelpers._DefaultDomainQualifiedName)))
|
// using (DirectoryEntry entry = new DirectoryEntry(string.Format("{0}CN=Partitions,CN=Configuration,{1}", ActiveDirectoryHelpers._DefaultLdapPath, ActiveDirectoryHelpers._DefaultDomainQualifiedName)))
|
||||||
{
|
// {
|
||||||
using (DirectorySearcher searcher = new DirectorySearcher(entry, "(&(objectClass=crossRef)(nETBIOSName=*))", new string[] { "nETBIOSName" }))
|
// using (DirectorySearcher searcher = new DirectorySearcher(entry, "(&(objectClass=crossRef)(nETBIOSName=*))", new string[] { "nETBIOSName" }))
|
||||||
{
|
// {
|
||||||
SearchResult result = searcher.FindOne();
|
// SearchResult result = searcher.FindOne();
|
||||||
if (result != null)
|
// if (result != null)
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers._DefaultDomainNetBiosName = result.Properties["nETBIOSName"][0].ToString();
|
// ActiveDirectoryHelpers._DefaultDomainNetBiosName = result.Properties["nETBIOSName"][0].ToString();
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
ActiveDirectoryHelpers._DefaultDomainNetBiosName = ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
// ActiveDirectoryHelpers._DefaultDomainNetBiosName = ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
ActiveDirectoryHelpers._DetermineDomainProperties_Loaded = true;
|
// ActiveDirectoryHelpers._DetermineDomainProperties_Loaded = true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
#endregion
|
// #endregion
|
||||||
|
|
||||||
internal static string ConvertBytesToSDDLString(byte[] SID)
|
// internal static string ConvertBytesToSDDLString(byte[] SID)
|
||||||
{
|
// {
|
||||||
SecurityIdentifier sID = new SecurityIdentifier(SID, 0);
|
// SecurityIdentifier sID = new SecurityIdentifier(SID, 0);
|
||||||
|
|
||||||
return sID.ToString();
|
// return sID.ToString();
|
||||||
}
|
// }
|
||||||
|
|
||||||
internal static byte[] ConvertSDDLStringToBytes(string SidSsdlString)
|
// internal static byte[] ConvertSDDLStringToBytes(string SidSsdlString)
|
||||||
{
|
// {
|
||||||
SecurityIdentifier sID = new SecurityIdentifier(SidSsdlString);
|
// SecurityIdentifier sID = new SecurityIdentifier(SidSsdlString);
|
||||||
|
|
||||||
var sidBytes = new byte[sID.BinaryLength];
|
// var sidBytes = new byte[sID.BinaryLength];
|
||||||
|
|
||||||
sID.GetBinaryForm(sidBytes, 0);
|
// sID.GetBinaryForm(sidBytes, 0);
|
||||||
|
|
||||||
return sidBytes;
|
// return sidBytes;
|
||||||
}
|
// }
|
||||||
|
|
||||||
internal static byte[] BuildPrimaryGroupSid(byte[] UserSID, int PrimaryGroupId)
|
// internal static byte[] BuildPrimaryGroupSid(byte[] UserSID, int PrimaryGroupId)
|
||||||
{
|
// {
|
||||||
var groupSid = (byte[])UserSID.Clone();
|
// var groupSid = (byte[])UserSID.Clone();
|
||||||
|
|
||||||
int ridOffset = groupSid.Length - 4;
|
// int ridOffset = groupSid.Length - 4;
|
||||||
int groupId = PrimaryGroupId;
|
// int groupId = PrimaryGroupId;
|
||||||
for (int i = 0; i < 4; i++)
|
// for (int i = 0; i < 4; i++)
|
||||||
{
|
// {
|
||||||
groupSid[ridOffset + i] = (byte)(groupId & 0xFF);
|
// groupSid[ridOffset + i] = (byte)(groupId & 0xFF);
|
||||||
groupId >>= 8;
|
// groupId >>= 8;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return groupSid;
|
// return groupSid;
|
||||||
}
|
// }
|
||||||
|
|
||||||
internal static string ConvertBytesToBinarySidString(byte[] SID)
|
// internal static string ConvertBytesToBinarySidString(byte[] SID)
|
||||||
{
|
// {
|
||||||
StringBuilder escapedSid = new StringBuilder();
|
// StringBuilder escapedSid = new StringBuilder();
|
||||||
|
|
||||||
foreach (var sidByte in SID)
|
// foreach (var sidByte in SID)
|
||||||
{
|
// {
|
||||||
escapedSid.Append('\\');
|
// escapedSid.Append('\\');
|
||||||
escapedSid.Append(sidByte.ToString("x2"));
|
// escapedSid.Append(sidByte.ToString("x2"));
|
||||||
}
|
// }
|
||||||
|
|
||||||
return escapedSid.ToString();
|
// return escapedSid.ToString();
|
||||||
}
|
// }
|
||||||
|
|
||||||
internal static string EscapeLdapQuery(string query)
|
// internal static string EscapeLdapQuery(string query)
|
||||||
{
|
// {
|
||||||
return query.Replace("*", "\\2a").Replace("(", "\\28").Replace(")", "\\29").Replace("\\", "\\5c").Replace("NUL", "\\00").Replace("/", "\\2f");
|
// return query.Replace("*", "\\2a").Replace("(", "\\28").Replace(")", "\\29").Replace("\\", "\\5c").Replace("NUL", "\\00").Replace("/", "\\2f");
|
||||||
}
|
// }
|
||||||
internal static string FormatGuidForLdapQuery(System.Guid g)
|
// internal static string FormatGuidForLdapQuery(System.Guid g)
|
||||||
{
|
// {
|
||||||
checked
|
// checked
|
||||||
{
|
// {
|
||||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
// System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
byte[] array = g.ToByteArray();
|
// byte[] array = g.ToByteArray();
|
||||||
for (int i = 0; i < array.Length; i++)
|
// for (int i = 0; i < array.Length; i++)
|
||||||
{
|
// {
|
||||||
byte b = array[i];
|
// byte b = array[i];
|
||||||
sb.Append("\\");
|
// sb.Append("\\");
|
||||||
sb.Append(b.ToString("X2"));
|
// sb.Append(b.ToString("X2"));
|
||||||
}
|
// }
|
||||||
return sb.ToString();
|
// return sb.ToString();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,301 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Management;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public static class ActiveDirectoryMachineAccountExtensions
|
|
||||||
{
|
|
||||||
public static void DeleteAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
DeleteAccountRecursive(machineDE);
|
|
||||||
|
|
||||||
using (var machineDEParent = machineDE.Parent)
|
|
||||||
{
|
|
||||||
machineDEParent.Children.Remove(machineDE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void DeleteAccountRecursive(DirectoryEntry parent)
|
|
||||||
{
|
|
||||||
List<DirectoryEntry> children = new List<DirectoryEntry>();
|
|
||||||
foreach (DirectoryEntry child in parent.Children)
|
|
||||||
children.Add(child);
|
|
||||||
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
|
||||||
DeleteAccountRecursive(child);
|
|
||||||
parent.Children.Remove(child);
|
|
||||||
child.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void SetNetbootGUID(this ActiveDirectoryMachineAccount account, System.Guid updatedNetbootGUID)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
PropertyValueCollection netbootGUIDProp = machineDE.Properties["netbootGUID"];
|
|
||||||
bool flag = netbootGUIDProp.Count > 0;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUIDProp.Clear();
|
|
||||||
}
|
|
||||||
netbootGUIDProp.Add(updatedNetbootGUID.ToByteArray());
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void SetDescription(this ActiveDirectoryMachineAccount account, string Description)
|
|
||||||
{
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
PropertyValueCollection descriptionProp = machineDE.Properties["description"];
|
|
||||||
if (descriptionProp.Count > 0)
|
|
||||||
{
|
|
||||||
descriptionProp.Clear();
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(Description))
|
|
||||||
{
|
|
||||||
descriptionProp.Add(Description);
|
|
||||||
}
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void SetDescription(this ActiveDirectoryMachineAccount account, Device Device)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
|
|
||||||
|
|
||||||
if (Device.AssignedUserId != null)
|
|
||||||
{
|
|
||||||
descriptionBuilder.Append(Device.AssignedUser.Id).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Device.DeviceModelId.HasValue)
|
|
||||||
{
|
|
||||||
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
|
|
||||||
|
|
||||||
string description = descriptionBuilder.ToString().Trim();
|
|
||||||
if (description.Length > 1024)
|
|
||||||
{
|
|
||||||
description = description.Substring(0, 1024);
|
|
||||||
}
|
|
||||||
account.SetDescription(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DisableAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
|
|
||||||
int updatedAccountControl = (accountControl | 2);
|
|
||||||
if (accountControl != updatedAccountControl)
|
|
||||||
{
|
|
||||||
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void EnableAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
|
|
||||||
if ((accountControl & 2) == 2)
|
|
||||||
{
|
|
||||||
int updatedAccountControl = (accountControl ^ 2);
|
|
||||||
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool UpdateNetbootGUID(this ActiveDirectoryMachineAccount account, string UUID, string MACAddress)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
System.Guid netbootGUID = System.Guid.Empty;
|
|
||||||
bool flag = !string.IsNullOrWhiteSpace(UUID);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(UUID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = !string.IsNullOrWhiteSpace(MACAddress);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(MACAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flag = (netbootGUID != System.Guid.Empty && netbootGUID != account.NetbootGUID);
|
|
||||||
bool UpdateNetbootGUID;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
account.SetNetbootGUID(netbootGUID);
|
|
||||||
UpdateNetbootGUID = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateNetbootGUID = false;
|
|
||||||
}
|
|
||||||
return UpdateNetbootGUID;
|
|
||||||
}
|
|
||||||
internal static System.Guid NetbootGUIDFromMACAddress(string MACAddress)
|
|
||||||
{
|
|
||||||
string strippedMACAddress = MACAddress.Trim().Replace(":", string.Empty).Replace("-", string.Empty);
|
|
||||||
bool flag = strippedMACAddress.Length == 12;
|
|
||||||
System.Guid NetbootGUIDFromMACAddress;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
System.Guid guid = new System.Guid(string.Format("00000000-0000-0000-0000-{0}", strippedMACAddress));
|
|
||||||
NetbootGUIDFromMACAddress = guid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetbootGUIDFromMACAddress = System.Guid.Empty;
|
|
||||||
}
|
|
||||||
return NetbootGUIDFromMACAddress;
|
|
||||||
}
|
|
||||||
internal static System.Guid NetbootGUIDFromUUID(string UUID)
|
|
||||||
{
|
|
||||||
System.Guid result = new System.Guid(UUID);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object GetPropertyValue(this ActiveDirectoryMachineAccount account, string PropertyName, int Index = 0)
|
|
||||||
{
|
|
||||||
switch (PropertyName.ToLower())
|
|
||||||
{
|
|
||||||
case "name":
|
|
||||||
return account.Name;
|
|
||||||
case "samaccountname":
|
|
||||||
return account.SamAccountName;
|
|
||||||
case "distinguishedname":
|
|
||||||
return account.DistinguishedName;
|
|
||||||
case "objectsid":
|
|
||||||
return account.SecurityIdentifier;
|
|
||||||
case "netbootguid":
|
|
||||||
return account.NetbootGUID;
|
|
||||||
default:
|
|
||||||
object[] adProperty;
|
|
||||||
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
|
||||||
return adProperty[Index];
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPStatus PingComputer(this ActiveDirectoryMachineAccount account, int Timeout = 2000)
|
|
||||||
{
|
|
||||||
using (var p = new Ping())
|
|
||||||
{
|
|
||||||
PingReply reply = p.Send(account.DnsName, Timeout);
|
|
||||||
return reply.Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Didn't Work - WMI Limitation?
|
|
||||||
// G# - 2012-06-18
|
|
||||||
//public static void OnlineRenameComputer(this ActiveDirectoryMachineAccount account, string NewComputerName)
|
|
||||||
//{
|
|
||||||
// if (account.IsCriticalSystemObject)
|
|
||||||
// throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// IPStatus pingResult = account.PingComputer();
|
|
||||||
// if (pingResult != IPStatus.Success)
|
|
||||||
// throw new Exception(string.Format("Ping Error Result: {0}", pingResult.ToString()));
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// throw new Exception(string.Format("Error trying to Ping the Device: {0}; {1}", account.DnsName, ex.Message), ex);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ConnectionOptions wmiConnectionOptions = new ConnectionOptions()
|
|
||||||
// {
|
|
||||||
// Authentication = AuthenticationLevel.PacketPrivacy,
|
|
||||||
// Impersonation = ImpersonationLevel.Impersonate,
|
|
||||||
// EnablePrivileges = true,
|
|
||||||
// Timeout = new TimeSpan(0, 0, 6)
|
|
||||||
// };
|
|
||||||
// ManagementPath wmiPath = new ManagementPath()
|
|
||||||
// {
|
|
||||||
// Server = account.DnsName,
|
|
||||||
// NamespacePath = @"root\cimv2",
|
|
||||||
// ClassName = "Win32_ComputerSystem"
|
|
||||||
// };
|
|
||||||
|
|
||||||
// ManagementScope wmiScope = new ManagementScope(wmiPath, wmiConnectionOptions);
|
|
||||||
|
|
||||||
// ObjectGetOptions wmiGetOptions = new ObjectGetOptions() { Timeout = new TimeSpan(0, 1, 0) };
|
|
||||||
|
|
||||||
// using (ManagementClass wmiClass = new ManagementClass(wmiScope, wmiPath, wmiGetOptions))
|
|
||||||
// {
|
|
||||||
// foreach (ManagementObject wmiWin32ComputerSystem in wmiClass.GetInstances())
|
|
||||||
// {
|
|
||||||
// UInt32 result = (UInt32)wmiWin32ComputerSystem.InvokeMethod("Rename", new object[] { NewComputerName });
|
|
||||||
// if (result != 0)
|
|
||||||
// throw new Exception(string.Format("Error Renaming Computer; WMI Remote Method 'Rename' returned: {0}", result));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static void MoveOrganisationUnit(this ActiveDirectoryMachineAccount account, string NewOrganisationUnit)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
var parentDistinguishedName = account.ParentDistinguishedName();
|
|
||||||
|
|
||||||
if (parentDistinguishedName != null && !parentDistinguishedName.Equals(NewOrganisationUnit, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
string ouPath;
|
|
||||||
if (string.IsNullOrWhiteSpace(NewOrganisationUnit))
|
|
||||||
ouPath = string.Format("{0}CN=Computers,{1}", ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
else
|
|
||||||
ouPath = string.Format("{0}{1},{2}", ActiveDirectoryHelpers.DefaultLdapPath, NewOrganisationUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
|
|
||||||
using (DirectoryEntry ou = new DirectoryEntry(ouPath))
|
|
||||||
{
|
|
||||||
using (DirectoryEntry i = new DirectoryEntry(account.Path) { UsePropertyCache = false })
|
|
||||||
{
|
|
||||||
i.MoveTo(ou);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ParentDistinguishedName(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
// Determine Parent
|
|
||||||
if (!string.IsNullOrWhiteSpace(account.DistinguishedName))
|
|
||||||
return account.DistinguishedName.Substring(0, account.DistinguishedName.IndexOf(",DC=")).Substring(account.DistinguishedName.IndexOf(",") + 1);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
//using System;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
//namespace Disco.BI.Interop.ActiveDirectory
|
||||||
{
|
//{
|
||||||
public class ActiveDirectoryOrganisationalUnit
|
// public class ActiveDirectoryOrganisationalUnit
|
||||||
{
|
// {
|
||||||
public string Name { get; set; }
|
// public string Name { get; set; }
|
||||||
public string Path { get; set; }
|
// public string Path { get; set; }
|
||||||
public List<ActiveDirectoryOrganisationalUnit> Children { get; set; }
|
// public List<ActiveDirectoryOrganisationalUnit> Children { get; set; }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
+244
-244
@@ -1,264 +1,264 @@
|
|||||||
using Disco.Data.Repository;
|
//using Disco.Data.Repository;
|
||||||
using Disco.Services.Logging;
|
//using Disco.Services.Logging;
|
||||||
using Disco.Models.Repository;
|
//using Disco.Models.Repository;
|
||||||
using Quartz;
|
//using Quartz;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
//using System.Diagnostics;
|
||||||
using System.DirectoryServices;
|
//using System.DirectoryServices;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Linq.Expressions;
|
//using System.Linq.Expressions;
|
||||||
using System.Net.NetworkInformation;
|
//using System.Net.NetworkInformation;
|
||||||
using System.Reflection;
|
//using System.Reflection;
|
||||||
using Disco.Services.Tasks;
|
//using Disco.Services.Tasks;
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
//namespace Disco.BI.Interop.ActiveDirectory
|
||||||
{
|
//{
|
||||||
public class ActiveDirectoryUpdateLastNetworkLogonDateJob : ScheduledTask
|
// public class ActiveDirectoryUpdateLastNetworkLogonDateJob : ScheduledTask
|
||||||
{
|
// {
|
||||||
|
|
||||||
public override string TaskName { get { return "Active Directory - Update Last Network Logon Dates Task"; } }
|
// public override string TaskName { get { return "Active Directory - Update Last Network Logon Dates Task"; } }
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
// public override bool SingleInstanceTask { get { return true; } }
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
// public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
// public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||||
{
|
// {
|
||||||
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
|
// // ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
|
||||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
|
// TriggerBuilder triggerBuilder = TriggerBuilder.Create().
|
||||||
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 30));
|
// WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 30));
|
||||||
|
|
||||||
this.ScheduleTask(triggerBuilder);
|
// this.ScheduleTask(triggerBuilder);
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected override void ExecuteTask()
|
// protected override void ExecuteTask()
|
||||||
{
|
// {
|
||||||
int changeCount;
|
// int changeCount;
|
||||||
|
|
||||||
this.Status.UpdateStatus(1, "Starting", "Connecting to the Database and initializing the environment");
|
// this.Status.UpdateStatus(1, "Starting", "Connecting to the Database and initializing the environment");
|
||||||
using (DiscoDataContext database = new DiscoDataContext())
|
// using (DiscoDataContext database = new DiscoDataContext())
|
||||||
{
|
// {
|
||||||
UpdateLastNetworkLogonDates(database, this.Status);
|
// UpdateLastNetworkLogonDates(database, this.Status);
|
||||||
this.Status.UpdateStatus(95, "Updating Database", "Writing last network logon dates to the Database");
|
// this.Status.UpdateStatus(95, "Updating Database", "Writing last network logon dates to the Database");
|
||||||
changeCount = database.SaveChanges();
|
// changeCount = database.SaveChanges();
|
||||||
this.Status.Finished(string.Format("{0} Device last network logon dates updated", changeCount), "/Config/SystemConfig");
|
// this.Status.Finished(string.Format("{0} Device last network logon dates updated", changeCount), "/Config/SystemConfig");
|
||||||
}
|
// }
|
||||||
|
|
||||||
SystemLog.LogInformation(new string[]
|
// SystemLog.LogInformation(new string[]
|
||||||
{
|
// {
|
||||||
"Updated LastNetworkLogon Device Property for Device/s",
|
// "Updated LastNetworkLogon Device Property for Device/s",
|
||||||
changeCount.ToString()
|
// changeCount.ToString()
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static ScheduledTaskStatus ScheduleImmediately()
|
// public static ScheduledTaskStatus ScheduleImmediately()
|
||||||
{
|
// {
|
||||||
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ActiveDirectoryUpdateLastNetworkLogonDateJob)).Where(s => s.IsRunning).FirstOrDefault();
|
// var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ActiveDirectoryUpdateLastNetworkLogonDateJob)).Where(s => s.IsRunning).FirstOrDefault();
|
||||||
if (existingTask != null)
|
// if (existingTask != null)
|
||||||
return existingTask;
|
// return existingTask;
|
||||||
|
|
||||||
var instance = new ActiveDirectoryUpdateLastNetworkLogonDateJob();
|
// var instance = new ActiveDirectoryUpdateLastNetworkLogonDateJob();
|
||||||
return instance.ScheduleTask();
|
// return instance.ScheduleTask();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static bool UpdateLastNetworkLogonDate(Device Device)
|
// public static bool UpdateLastNetworkLogonDate(Device Device)
|
||||||
{
|
// {
|
||||||
System.DateTime? computerLastLogonDate = Device.LastNetworkLogonDate;
|
// System.DateTime? computerLastLogonDate = Device.LastNetworkLogonDate;
|
||||||
if (!string.IsNullOrEmpty(Device.ComputerName))
|
// if (!string.IsNullOrEmpty(Device.ComputerName))
|
||||||
{
|
// {
|
||||||
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
// foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
Ping p = new Ping();
|
// Ping p = new Ping();
|
||||||
PingReply pr;
|
// PingReply pr;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
pr = p.Send(dcName, 500);
|
// pr = p.Send(dcName, 500);
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
if (p != null)
|
// if (p != null)
|
||||||
{
|
// {
|
||||||
((System.IDisposable)p).Dispose();
|
// ((System.IDisposable)p).Dispose();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (pr.Status == IPStatus.Success)
|
// if (pr.Status == IPStatus.Success)
|
||||||
{
|
// {
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
// using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
||||||
{
|
// {
|
||||||
DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Computer)(sAMAccountName={0}$))", ActiveDirectoryHelpers.EscapeLdapQuery(Device.ComputerName)), new string[]
|
// DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Computer)(sAMAccountName={0}$))", ActiveDirectoryHelpers.EscapeLdapQuery(Device.ComputerName)), new string[]
|
||||||
{
|
// {
|
||||||
"lastLogon"
|
// "lastLogon"
|
||||||
}, SearchScope.Subtree);
|
// }, SearchScope.Subtree);
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
// SearchResult dResult = dSearcher.FindOne();
|
||||||
if (dResult != null)
|
// if (dResult != null)
|
||||||
{
|
// {
|
||||||
ResultPropertyValueCollection dProp = dResult.Properties["lastLogon"];
|
// ResultPropertyValueCollection dProp = dResult.Properties["lastLogon"];
|
||||||
if (dProp != null && dProp.Count > 0)
|
// if (dProp != null && dProp.Count > 0)
|
||||||
{
|
// {
|
||||||
long lastLogonInt = (long)dProp[0];
|
// long lastLogonInt = (long)dProp[0];
|
||||||
if (lastLogonInt > 0L)
|
// if (lastLogonInt > 0L)
|
||||||
{
|
// {
|
||||||
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
// System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
||||||
if (computerLastLogonDate.HasValue)
|
// if (computerLastLogonDate.HasValue)
|
||||||
{
|
// {
|
||||||
if (System.DateTime.Compare(computerLastLogonDate.Value, computerNameDate) < 0)
|
// if (System.DateTime.Compare(computerLastLogonDate.Value, computerNameDate) < 0)
|
||||||
{
|
// {
|
||||||
computerLastLogonDate = computerNameDate;
|
// computerLastLogonDate = computerNameDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
computerLastLogonDate = computerNameDate;
|
// computerLastLogonDate = computerNameDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
SystemLog.LogError(new string[]
|
// SystemLog.LogError(new string[]
|
||||||
{
|
// {
|
||||||
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateDeviceLastNetworkLogonDate)", dcName)
|
// string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateDeviceLastNetworkLogonDate)", dcName)
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
catch (System.Exception ex)
|
// catch (System.Exception ex)
|
||||||
{
|
// {
|
||||||
SystemLog.LogException("UpdateDeviceLastNetworkLogonDate", ex);
|
// SystemLog.LogException("UpdateDeviceLastNetworkLogonDate", ex);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
bool UpdateLastNetworkLogonDate;
|
// bool UpdateLastNetworkLogonDate;
|
||||||
if (computerLastLogonDate.HasValue)
|
// if (computerLastLogonDate.HasValue)
|
||||||
{
|
// {
|
||||||
if (!Device.LastNetworkLogonDate.HasValue)
|
// if (!Device.LastNetworkLogonDate.HasValue)
|
||||||
{
|
// {
|
||||||
Device.LastNetworkLogonDate = computerLastLogonDate;
|
// Device.LastNetworkLogonDate = computerLastLogonDate;
|
||||||
UpdateLastNetworkLogonDate = true;
|
// UpdateLastNetworkLogonDate = true;
|
||||||
return UpdateLastNetworkLogonDate;
|
// return UpdateLastNetworkLogonDate;
|
||||||
}
|
// }
|
||||||
if (System.DateTime.Compare(computerLastLogonDate.Value, Device.LastNetworkLogonDate.Value) > 0)
|
// if (System.DateTime.Compare(computerLastLogonDate.Value, Device.LastNetworkLogonDate.Value) > 0)
|
||||||
{
|
// {
|
||||||
Device.LastNetworkLogonDate = computerLastLogonDate;
|
// Device.LastNetworkLogonDate = computerLastLogonDate;
|
||||||
UpdateLastNetworkLogonDate = true;
|
// UpdateLastNetworkLogonDate = true;
|
||||||
return UpdateLastNetworkLogonDate;
|
// return UpdateLastNetworkLogonDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
UpdateLastNetworkLogonDate = false;
|
// UpdateLastNetworkLogonDate = false;
|
||||||
return UpdateLastNetworkLogonDate;
|
// return UpdateLastNetworkLogonDate;
|
||||||
}
|
// }
|
||||||
private static void UpdateLastNetworkLogonDates(DiscoDataContext Database, ScheduledTaskStatus status)
|
// private static void UpdateLastNetworkLogonDates(DiscoDataContext Database, ScheduledTaskStatus status)
|
||||||
{
|
// {
|
||||||
System.Collections.Generic.Dictionary<string, System.DateTime> computerLastLogonDates = new System.Collections.Generic.Dictionary<string, System.DateTime>();
|
// System.Collections.Generic.Dictionary<string, System.DateTime> computerLastLogonDates = new System.Collections.Generic.Dictionary<string, System.DateTime>();
|
||||||
|
|
||||||
int progressDCCountTotal = ActiveDirectoryHelpers.DefaultDomainDCNames.Count;
|
// int progressDCCountTotal = ActiveDirectoryHelpers.DefaultDomainDCNames.Count;
|
||||||
int progressDCCount = 0;
|
// int progressDCCount = 0;
|
||||||
double progressDCProgress = 0;
|
// double progressDCProgress = 0;
|
||||||
if (progressDCCountTotal > 0)
|
// if (progressDCCountTotal > 0)
|
||||||
progressDCProgress = 90 / progressDCCountTotal;
|
// progressDCProgress = 90 / progressDCCountTotal;
|
||||||
|
|
||||||
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
// foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
PingReply pr;
|
// PingReply pr;
|
||||||
using (Ping p = new Ping())
|
// using (Ping p = new Ping())
|
||||||
{
|
// {
|
||||||
pr = p.Send(dcName, 2000);
|
// pr = p.Send(dcName, 2000);
|
||||||
}
|
// }
|
||||||
if (pr.Status == IPStatus.Success)
|
// if (pr.Status == IPStatus.Success)
|
||||||
{
|
// {
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
// using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
||||||
{
|
// {
|
||||||
double progressDCStart = 5 + (progressDCCount * progressDCProgress);
|
// double progressDCStart = 5 + (progressDCCount * progressDCProgress);
|
||||||
status.UpdateStatus(progressDCStart, string.Format("Querying Domain Controller: {0}", dcName), "Searching...");
|
// status.UpdateStatus(progressDCStart, string.Format("Querying Domain Controller: {0}", dcName), "Searching...");
|
||||||
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, "(objectCategory=Computer)", new string[] { "sAMAccountName", "lastLogon" }, SearchScope.Subtree))
|
// using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, "(objectCategory=Computer)", new string[] { "sAMAccountName", "lastLogon" }, SearchScope.Subtree))
|
||||||
{
|
// {
|
||||||
using (SearchResultCollection dResults = dSearcher.FindAll())
|
// using (SearchResultCollection dResults = dSearcher.FindAll())
|
||||||
{
|
// {
|
||||||
|
|
||||||
int progressItemCount = 0;
|
// int progressItemCount = 0;
|
||||||
double progressItemProgress = dResults.Count == 0 ? 0 : (progressDCProgress / dResults.Count);
|
// double progressItemProgress = dResults.Count == 0 ? 0 : (progressDCProgress / dResults.Count);
|
||||||
|
|
||||||
foreach (SearchResult dResult in dResults)
|
// foreach (SearchResult dResult in dResults)
|
||||||
{
|
// {
|
||||||
ResultPropertyValueCollection dProp = dResult.Properties["sAMAccountName"];
|
// ResultPropertyValueCollection dProp = dResult.Properties["sAMAccountName"];
|
||||||
if (dProp != null && dProp.Count > 0)
|
// if (dProp != null && dProp.Count > 0)
|
||||||
{
|
// {
|
||||||
string computerName = ((string)dProp[0]).TrimEnd(new char[] { '$' }).ToUpper();
|
// string computerName = ((string)dProp[0]).TrimEnd(new char[] { '$' }).ToUpper();
|
||||||
|
|
||||||
if (progressItemCount % 150 == 0) // Only Update Status every 150 devices
|
// if (progressItemCount % 150 == 0) // Only Update Status every 150 devices
|
||||||
status.UpdateStatus(progressDCStart + (progressItemProgress * progressItemCount), string.Format("Analysing Device: {0}", computerName));
|
// status.UpdateStatus(progressDCStart + (progressItemProgress * progressItemCount), string.Format("Analysing Device: {0}", computerName));
|
||||||
|
|
||||||
dProp = dResult.Properties["lastLogon"];
|
// dProp = dResult.Properties["lastLogon"];
|
||||||
if (dProp != null && dProp.Count > 0)
|
// if (dProp != null && dProp.Count > 0)
|
||||||
{
|
// {
|
||||||
long lastLogonInt = (long)dProp[0];
|
// long lastLogonInt = (long)dProp[0];
|
||||||
if (lastLogonInt > 0L)
|
// if (lastLogonInt > 0L)
|
||||||
{
|
// {
|
||||||
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
// System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
||||||
System.DateTime existingDate;
|
// System.DateTime existingDate;
|
||||||
if (computerLastLogonDates.TryGetValue(computerName, out existingDate))
|
// if (computerLastLogonDates.TryGetValue(computerName, out existingDate))
|
||||||
{
|
// {
|
||||||
if (System.DateTime.Compare(existingDate, computerNameDate) < 0)
|
// if (System.DateTime.Compare(existingDate, computerNameDate) < 0)
|
||||||
{
|
// {
|
||||||
computerLastLogonDates[computerName] = computerNameDate;
|
// computerLastLogonDates[computerName] = computerNameDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
computerLastLogonDates[computerName] = computerNameDate;
|
// computerLastLogonDates[computerName] = computerNameDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
progressItemCount++;
|
// progressItemCount++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
SystemLog.LogError(new string[]
|
// SystemLog.LogError(new string[]
|
||||||
{
|
// {
|
||||||
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDates)", dcName)
|
// string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDates)", dcName)
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
catch (System.Exception ex)
|
// catch (System.Exception ex)
|
||||||
{
|
// {
|
||||||
SystemLog.LogException("UpdateLastNetworkLogonDates", ex);
|
// SystemLog.LogException("UpdateLastNetworkLogonDates", ex);
|
||||||
}
|
// }
|
||||||
progressDCCount++;
|
// progressDCCount++;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
foreach (Device d in Database.Devices.Where(device => device.ComputerName != null))
|
// foreach (Device d in Database.Devices.Where(device => device.ComputerName != null))
|
||||||
{
|
// {
|
||||||
DateTime computerLastLogonDate;
|
// DateTime computerLastLogonDate;
|
||||||
if (computerLastLogonDates.TryGetValue(d.ComputerName.ToUpper(), out computerLastLogonDate))
|
// if (computerLastLogonDates.TryGetValue(d.ComputerName.ToUpper(), out computerLastLogonDate))
|
||||||
{
|
// {
|
||||||
if (d.LastNetworkLogonDate.HasValue)
|
// if (d.LastNetworkLogonDate.HasValue)
|
||||||
{
|
// {
|
||||||
// Change accuracy to the second
|
// // Change accuracy to the second
|
||||||
computerLastLogonDate = new DateTime((computerLastLogonDate.Ticks / 10000000L) * 10000000L);
|
// computerLastLogonDate = new DateTime((computerLastLogonDate.Ticks / 10000000L) * 10000000L);
|
||||||
|
|
||||||
if (System.DateTime.Compare(d.LastNetworkLogonDate.Value, computerLastLogonDate) < 0)
|
// if (System.DateTime.Compare(d.LastNetworkLogonDate.Value, computerLastLogonDate) < 0)
|
||||||
{
|
// {
|
||||||
d.LastNetworkLogonDate = computerLastLogonDate;
|
// d.LastNetworkLogonDate = computerLastLogonDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
d.LastNetworkLogonDate = computerLastLogonDate;
|
// d.LastNetworkLogonDate = computerLastLogonDate;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
//using Disco.Models.Interop.ActiveDirectory;
|
||||||
using System;
|
//using System;
|
||||||
using Disco.Models.Repository;
|
//using Disco.Models.Repository;
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
//namespace Disco.BI.Interop.ActiveDirectory
|
||||||
{
|
//{
|
||||||
internal static class ActiveDirectoryUserAccountExtensions
|
// internal static class ActiveDirectoryUserAccountExtensions
|
||||||
{
|
// {
|
||||||
public static object GetPropertyValue(this ActiveDirectoryUserAccount account, string PropertyName, int Index = 0)
|
// public static object GetPropertyValue(this ActiveDirectoryUserAccount account, string PropertyName, int Index = 0)
|
||||||
{
|
// {
|
||||||
switch (PropertyName.ToLower())
|
// switch (PropertyName.ToLower())
|
||||||
{
|
// {
|
||||||
case "name":
|
// case "name":
|
||||||
return account.Name;
|
// return account.Name;
|
||||||
case "samaccountname":
|
// case "samaccountname":
|
||||||
return account.SamAccountName;
|
// return account.SamAccountName;
|
||||||
case "distinguishedname":
|
// case "distinguishedname":
|
||||||
return account.DistinguishedName;
|
// return account.DistinguishedName;
|
||||||
case "objectsid":
|
// case "objectsid":
|
||||||
return account.SecurityIdentifier;
|
// return account.SecurityIdentifier;
|
||||||
case "sn":
|
// case "sn":
|
||||||
return account.Surname;
|
// return account.Surname;
|
||||||
case "givenname":
|
// case "givenname":
|
||||||
return account.GivenName;
|
// return account.GivenName;
|
||||||
case "mail":
|
// case "mail":
|
||||||
return account.Email;
|
// return account.Email;
|
||||||
case "telephonenumber":
|
// case "telephonenumber":
|
||||||
return account.Phone;
|
// return account.Phone;
|
||||||
default:
|
// default:
|
||||||
object[] adProperty;
|
// object[] adProperty;
|
||||||
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
// if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
||||||
return adProperty[Index];
|
// return adProperty[Index];
|
||||||
else
|
// else
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
DataObjects = new object[DataObjectsIds.Length];
|
DataObjects = new object[DataObjectsIds.Length];
|
||||||
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
||||||
{
|
{
|
||||||
|
string dataObjectId = DataObjectsIds[idIndex];
|
||||||
|
if (!dataObjectId.Contains('\\'))
|
||||||
|
dataObjectId = Disco.Services.Interop.ActiveDirectory.ActiveDirectory.PrimaryDomain.NetBiosName + @"\" + dataObjectId;
|
||||||
|
|
||||||
DataObjects[idIndex] = UserService.GetUser(DataObjectsIds[idIndex], Database, true);
|
DataObjects[idIndex] = UserService.GetUser(DataObjectsIds[idIndex], Database, true);
|
||||||
if (DataObjects[idIndex] == null)
|
if (DataObjects[idIndex] == null)
|
||||||
throw new Exception(string.Format("Unknown Username specified: {0}", DataObjectsIds[idIndex]));
|
throw new Exception(string.Format("Unknown Username specified: {0}", DataObjectsIds[idIndex]));
|
||||||
@@ -122,7 +126,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.InvariantCultureIgnoreCase))
|
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
||||||
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.Id, TimeStamp);
|
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.UserId, TimeStamp);
|
||||||
if (FlattenFields)
|
if (FlattenFields)
|
||||||
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
||||||
else
|
else
|
||||||
@@ -132,7 +136,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
||||||
{
|
{
|
||||||
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
||||||
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.Id, TimeStamp, pdfFieldPosition.page);
|
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.UserId, TimeStamp, pdfFieldPosition.page);
|
||||||
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
||||||
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
||||||
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||||
@@ -237,7 +241,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
JobLog jl = new JobLog()
|
JobLog jl = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Timestamp = DateTime.Now
|
Timestamp = DateTime.Now
|
||||||
};
|
};
|
||||||
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
|
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace Disco.BI.Interop.SignalRHandlers
|
|||||||
{
|
{
|
||||||
User u = (User)e.Entity;
|
User u = (User)e.Entity;
|
||||||
|
|
||||||
var userDevices = e.Database.Devices.Where(d => d.AssignedUserId == u.Id);
|
var userDevices = e.Database.Devices.Where(d => d.AssignedUserId == u.UserId);
|
||||||
|
|
||||||
foreach (var userDevice in userDevices)
|
foreach (var userDevice in userDevices)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Disco.BI.Interop.SignalRHandlers
|
|||||||
{
|
{
|
||||||
User u = (User)e.Entity;
|
User u = (User)e.Entity;
|
||||||
|
|
||||||
notificationContext.Connection.Broadcast(u.Id);
|
notificationContext.Connection.Broadcast(u.UserId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Disco.BI.JobBI
|
|||||||
Job j = new Job()
|
Job j = new Job()
|
||||||
{
|
{
|
||||||
JobType = type,
|
JobType = type,
|
||||||
OpenedTechUserId = initialTech.Id,
|
OpenedTechUserId = initialTech.UserId,
|
||||||
OpenedTechUser = initialTech,
|
OpenedTechUser = initialTech,
|
||||||
OpenedDate = DateTime.Now
|
OpenedDate = DateTime.Now
|
||||||
};
|
};
|
||||||
@@ -31,7 +31,7 @@ namespace Disco.BI.JobBI
|
|||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
j.User = user;
|
j.User = user;
|
||||||
j.UserId = user.Id;
|
j.UserId = user.UserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub Types
|
// Sub Types
|
||||||
@@ -61,7 +61,7 @@ namespace Disco.BI.JobBI
|
|||||||
JobQueueId = queue.queue.Id,
|
JobQueueId = queue.queue.Id,
|
||||||
Job = j,
|
Job = j,
|
||||||
AddedDate = DateTime.Now,
|
AddedDate = DateTime.Now,
|
||||||
AddedUserId = initialTech.Id,
|
AddedUserId = initialTech.UserId,
|
||||||
AddedComment = commentBuilder.ToString(),
|
AddedComment = commentBuilder.ToString(),
|
||||||
SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null,
|
SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null,
|
||||||
Priority = JobQueuePriority.Normal
|
Priority = JobQueuePriority.Normal
|
||||||
@@ -110,7 +110,7 @@ namespace Disco.BI.JobBI
|
|||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = initialTech.Id,
|
TechUserId = initialTech.UserId,
|
||||||
Cost = c.Cost,
|
Cost = c.Cost,
|
||||||
Description = c.Description
|
Description = c.Description
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -175,10 +175,7 @@
|
|||||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
||||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
|
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryCachedGroups.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryGroupExtensions.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
|
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryMachineAccountExtensions.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
|
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
|
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace Disco.Client.Extensions
|
|||||||
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
||||||
|
|
||||||
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
||||||
|
enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName;
|
||||||
|
|
||||||
// LAN
|
// LAN
|
||||||
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace Disco.Client.Interop
|
|||||||
public static string DeviceType { get; private set; }
|
public static string DeviceType { get; private set; }
|
||||||
public static string DeviceUUID { get; private set; }
|
public static string DeviceUUID { get; private set; }
|
||||||
public static bool DeviceIsPartOfDomain { get; private set; }
|
public static bool DeviceIsPartOfDomain { get; private set; }
|
||||||
|
public static string DeviceDNSDomainName { get; private set; }
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
@@ -56,7 +57,7 @@ namespace Disco.Client.Interop
|
|||||||
// Get System Information
|
// Get System Information
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType FROM Win32_ComputerSystem"))
|
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
|
||||||
{
|
{
|
||||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||||
{
|
{
|
||||||
@@ -74,6 +75,8 @@ namespace Disco.Client.Interop
|
|||||||
|
|
||||||
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||||
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
||||||
|
|
||||||
|
DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Data.Configuration.Modules
|
||||||
|
{
|
||||||
|
public class ActiveDirectoryConfiguration : ConfigurationBase
|
||||||
|
{
|
||||||
|
public ActiveDirectoryConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||||
|
|
||||||
|
public override string Scope
|
||||||
|
{
|
||||||
|
get { return "ActiveDirectory"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> SearchContainers
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetFromJson<List<string>>(null);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetAsJson(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool? SearchEntireForest
|
||||||
|
{
|
||||||
|
get { return GetFromJson<bool?>(null); }
|
||||||
|
set { SetAsJson(value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ namespace Disco.Data.Configuration
|
|||||||
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
||||||
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
||||||
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
||||||
|
this.moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Configuration Modules
|
#region Configuration Modules
|
||||||
@@ -29,6 +30,7 @@ namespace Disco.Data.Configuration
|
|||||||
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
||||||
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
||||||
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
|
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
|
||||||
|
private Lazy<Modules.ActiveDirectoryConfiguration> moduleActiveDirectoryConfiguration;
|
||||||
|
|
||||||
public Modules.BootstrapperConfiguration Bootstrapper
|
public Modules.BootstrapperConfiguration Bootstrapper
|
||||||
{
|
{
|
||||||
@@ -58,6 +60,13 @@ namespace Disco.Data.Configuration
|
|||||||
return moduleJobPreferencesConfiguration.Value;
|
return moduleJobPreferencesConfiguration.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public Modules.ActiveDirectoryConfiguration ActiveDirectory
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return moduleActiveDirectoryConfiguration.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data.Entity" />
|
<Reference Include="System.Data.Entity" />
|
||||||
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Reactive.Core">
|
<Reference Include="System.Reactive.Core">
|
||||||
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
|
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
<Compile Include="Configuration\CommunityHelpers.cs" />
|
<Compile Include="Configuration\CommunityHelpers.cs" />
|
||||||
<Compile Include="Configuration\ConfigurationBase.cs" />
|
<Compile Include="Configuration\ConfigurationBase.cs" />
|
||||||
<Compile Include="Configuration\ConfigurationCache.cs" />
|
<Compile Include="Configuration\ConfigurationCache.cs" />
|
||||||
|
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
|
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
|
||||||
<Compile Include="Configuration\SystemConfiguration.cs" />
|
<Compile Include="Configuration\SystemConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
|
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
|
||||||
@@ -130,6 +132,10 @@
|
|||||||
<Compile Include="Migrations\201402032322432_DBv12.Designer.cs">
|
<Compile Include="Migrations\201402032322432_DBv12.Designer.cs">
|
||||||
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Migrations\201404080227546_DBv13.cs" />
|
||||||
|
<Compile Include="Migrations\201404080227546_DBv13.Designer.cs">
|
||||||
|
<DependentUpon>201404080227546_DBv13.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Migrations\Configuration.cs" />
|
<Compile Include="Migrations\Configuration.cs" />
|
||||||
<Compile Include="Migrations\DiscoDataMigrator.cs" />
|
<Compile Include="Migrations\DiscoDataMigrator.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@@ -181,6 +187,9 @@
|
|||||||
<EmbeddedResource Include="Migrations\201402032322432_DBv12.resx">
|
<EmbeddedResource Include="Migrations\201402032322432_DBv12.resx">
|
||||||
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Migrations\201404080227546_DBv13.resx">
|
||||||
|
<DependentUpon>201404080227546_DBv13.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
using System.Data.Entity.Migrations.Infrastructure;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
public sealed partial class DBv13 : IMigrationMetadata
|
||||||
|
{
|
||||||
|
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv13));
|
||||||
|
|
||||||
|
string IMigrationMetadata.Id
|
||||||
|
{
|
||||||
|
get { return "201404080227546_DBv13"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Source
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Target
|
||||||
|
{
|
||||||
|
get { return Resources.GetString("Target"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
|
||||||
|
public partial class DBv13 : DbMigration
|
||||||
|
{
|
||||||
|
public override void Up()
|
||||||
|
{
|
||||||
|
AlterColumn("dbo.Devices", "ComputerName", c => c.String(maxLength: 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Down()
|
||||||
|
{
|
||||||
|
AlterColumn("dbo.Devices", "ComputerName", c => c.String(maxLength: 24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -3,6 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
|
||||||
namespace Disco.Data.Repository
|
namespace Disco.Data.Repository
|
||||||
{
|
{
|
||||||
@@ -15,6 +18,9 @@ namespace Disco.Data.Repository
|
|||||||
Database.SeedDeviceProfiles();
|
Database.SeedDeviceProfiles();
|
||||||
Database.SeedJobTypes();
|
Database.SeedJobTypes();
|
||||||
Database.SeedJobSubTypes();
|
Database.SeedJobSubTypes();
|
||||||
|
|
||||||
|
// Migration Maintenance
|
||||||
|
Database.MigratePreDomainObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SeedDeploymentId(this DiscoDataContext Database)
|
public static void SeedDeploymentId(this DiscoDataContext Database)
|
||||||
@@ -304,5 +310,128 @@ namespace Disco.Data.Repository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End Added: 2013-02-07 G#
|
// End Added: 2013-02-07 G#
|
||||||
|
|
||||||
|
#region Migrate Users SQL
|
||||||
|
private const string MigratePreDomainUsers_Sql = @"INSERT INTO [Users] SELECT @IdNew, u.DisplayName, u.Surname, u.GivenName, u.PhoneNumber, u.EmailAddress FROM [Users] u WHERE [Id]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobQueueJobs] SET [AddedUserId]=@IdNew WHERE [AddedUserId]=@IdExisting;
|
||||||
|
UPDATE [JobQueueJobs] SET [RemovedUserId]=@IdNew WHERE [RemovedUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [DeviceAttachments] SET [TechUserId]=@IdNew WHERE [TechUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [Devices] SET [AssignedUserId]=@IdNew WHERE [AssignedUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [DeviceUserAssignments] SET [AssignedUserId]=@IdNew WHERE [AssignedUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobAttachments] SET [TechUserId]=@IdNew WHERE [TechUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobComponents] SET [TechUserId]=@IdNew WHERE [TechUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobLogs] SET [TechUserId]=@IdNew WHERE [TechUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobMetaInsurances] SET [ClaimFormSentUserId]=@IdNew WHERE [ClaimFormSentUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [AccountingChargeAddedUserId]=@IdNew WHERE [AccountingChargeAddedUserId]=@IdExisting;
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [AccountingChargePaidUserId]=@IdNew WHERE [AccountingChargePaidUserId]=@IdExisting;
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [AccountingChargeRequiredUserId]=@IdNew WHERE [AccountingChargeRequiredUserId]=@IdExisting;
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [InvoiceReceivedUserId]=@IdNew WHERE [InvoiceReceivedUserId]=@IdExisting;
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [PurchaseOrderRaisedUserId]=@IdNew WHERE [PurchaseOrderRaisedUserId]=@IdExisting;
|
||||||
|
UPDATE [JobMetaNonWarranties] SET [PurchaseOrderSentUserId]=@IdNew WHERE [PurchaseOrderSentUserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [Jobs] SET [ClosedTechUserId]=@IdNew WHERE [ClosedTechUserId]=@IdExisting;
|
||||||
|
UPDATE [Jobs] SET [DeviceHeldTechUserId]=@IdNew WHERE [DeviceHeldTechUserId]=@IdExisting;
|
||||||
|
UPDATE [Jobs] SET [DeviceReadyForReturnTechUserId]=@IdNew WHERE [DeviceReadyForReturnTechUserId]=@IdExisting;
|
||||||
|
UPDATE [Jobs] SET [DeviceReturnedTechUserId]=@IdNew WHERE [DeviceReturnedTechUserId]=@IdExisting;
|
||||||
|
UPDATE [Jobs] SET [OpenedTechUserId]=@IdNew WHERE [OpenedTechUserId]=@IdExisting;
|
||||||
|
UPDATE [Jobs] SET [UserId]=@IdNew WHERE [UserId]=@IdExisting;
|
||||||
|
|
||||||
|
UPDATE [UserAttachments] SET [TechUserId]=@IdNew WHERE [TechUserId]=@IdExisting;
|
||||||
|
UPDATE [UserAttachments] SET [UserId]=@IdNew WHERE [UserId]=@IdExisting;
|
||||||
|
|
||||||
|
DELETE [Users] WHERE [Id]=@IdExisting;";
|
||||||
|
#endregion
|
||||||
|
public static void MigratePreDomainObjects(this DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
if (Database.Users.Count(u => !u.UserId.Contains(@"\")) > 0)
|
||||||
|
{
|
||||||
|
// Determine Computer Domain
|
||||||
|
string netBiosName = null;
|
||||||
|
string defaultNamingContext;
|
||||||
|
using (Domain d = Domain.GetComputerDomain())
|
||||||
|
{
|
||||||
|
string ldapPath = string.Format("LDAP://{0}/", d.Name);
|
||||||
|
string configurationNamingContext;
|
||||||
|
|
||||||
|
using (var adRootDSE = new DirectoryEntry(ldapPath + "RootDSE"))
|
||||||
|
{
|
||||||
|
defaultNamingContext = adRootDSE.Properties["defaultNamingContext"][0].ToString();
|
||||||
|
configurationNamingContext = adRootDSE.Properties["configurationNamingContext"][0].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var configSearchRoot = new DirectoryEntry(ldapPath + "CN=Partitions," + configurationNamingContext))
|
||||||
|
{
|
||||||
|
var configSearchFilter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", d.Name);
|
||||||
|
var configSearchLoadProperites = new string[] { "NetBIOSName" };
|
||||||
|
|
||||||
|
using (var configSearcher = new DirectorySearcher(configSearchRoot, configSearchFilter, configSearchLoadProperites, SearchScope.OneLevel))
|
||||||
|
{
|
||||||
|
SearchResult configResult = configSearcher.FindOne();
|
||||||
|
|
||||||
|
if (configResult != null)
|
||||||
|
netBiosName = configResult.Properties["NetBIOSName"][0].ToString();
|
||||||
|
else
|
||||||
|
netBiosName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(netBiosName))
|
||||||
|
throw new InvalidOperationException("Unable to determine the Domains NetBIOS Name");
|
||||||
|
|
||||||
|
// MIGRATE SETTINGS
|
||||||
|
|
||||||
|
// Authorization Roles
|
||||||
|
foreach (var authRole in Database.AuthorizationRoles.Where(ar => ar.SubjectIds != null).ToList())
|
||||||
|
{
|
||||||
|
var ids = string.Join(",", authRole.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : string.Format("{0}\\{1}", netBiosName, id)));
|
||||||
|
if (ids != authRole.SubjectIds)
|
||||||
|
authRole.SubjectIds = ids;
|
||||||
|
}
|
||||||
|
// Job Queues
|
||||||
|
foreach (var jobQueue in Database.JobQueues.Where(jq => jq.SubjectIds != null).ToList())
|
||||||
|
{
|
||||||
|
var ids = string.Join(",", jobQueue.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : string.Format("{0}\\{1}", netBiosName, id)));
|
||||||
|
if (ids != jobQueue.SubjectIds)
|
||||||
|
jobQueue.SubjectIds = ids;
|
||||||
|
}
|
||||||
|
// Device Profiles - OU
|
||||||
|
foreach (var deviceProfile in Database.DeviceProfiles.Where(dp => dp.OrganisationalUnit == null || !dp.OrganisationalUnit.Contains(@"DC=")).ToList())
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(deviceProfile.OrganisationalUnit))
|
||||||
|
deviceProfile.OrganisationalUnit = string.Format("CN=Computers,{0}", defaultNamingContext);
|
||||||
|
else
|
||||||
|
deviceProfile.OrganisationalUnit = string.Format("{0},{1}", deviceProfile.OrganisationalUnit, defaultNamingContext);
|
||||||
|
}
|
||||||
|
Database.SaveChanges();
|
||||||
|
|
||||||
|
// MIGRATE DEVICES
|
||||||
|
foreach (var device in Database.Devices.Where(d => d.DeviceDomainId != null && !d.DeviceDomainId.Contains(@"\")).ToList())
|
||||||
|
{
|
||||||
|
device.DeviceDomainId = string.Format("{0}\\{1}", netBiosName, device.DeviceDomainId);
|
||||||
|
}
|
||||||
|
Database.SaveChanges();
|
||||||
|
|
||||||
|
// MIGRATE USERS
|
||||||
|
foreach (var user in Database.Users.Where(u => !u.UserId.Contains(@"\")).ToList())
|
||||||
|
{
|
||||||
|
SqlParameter idExisting = new SqlParameter("@IdExisting", System.Data.SqlDbType.NVarChar, 50);
|
||||||
|
idExisting.Value = user.UserId;
|
||||||
|
|
||||||
|
SqlParameter idNew = new SqlParameter("@IdNew", System.Data.SqlDbType.NVarChar, 50);
|
||||||
|
idNew.Value = string.Format("{0}\\{1}", netBiosName, user.UserId);
|
||||||
|
|
||||||
|
Database.Database.ExecuteSqlCommand(MigratePreDomainUsers_Sql, idExisting, idNew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Disco.Models.ClientServices
|
|||||||
public string DeviceSerialNumber { get; set; }
|
public string DeviceSerialNumber { get; set; }
|
||||||
public string DeviceUUID { get; set; }
|
public string DeviceUUID { get; set; }
|
||||||
|
|
||||||
|
public string DeviceDNSDomainName { get; set; }
|
||||||
public string DeviceComputerName { get; set; }
|
public string DeviceComputerName { get; set; }
|
||||||
public bool DeviceIsPartOfDomain { get; set; }
|
public bool DeviceIsPartOfDomain { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data.Entity" />
|
<Reference Include="System.Data.Entity" />
|
||||||
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@@ -46,6 +47,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BI\Job\LocationModes.cs" />
|
<Compile Include="BI\Job\LocationModes.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\ActiveDirectoryDomain.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\ActiveDirectorySearchResult.cs" />
|
||||||
<Compile Include="Services\Authorization\IAuthorizationToken.cs" />
|
<Compile Include="Services\Authorization\IAuthorizationToken.cs" />
|
||||||
<Compile Include="Services\Authorization\IClaimNavigatorItem.cs" />
|
<Compile Include="Services\Authorization\IClaimNavigatorItem.cs" />
|
||||||
<Compile Include="Services\Authorization\IRoleToken.cs" />
|
<Compile Include="Services\Authorization\IRoleToken.cs" />
|
||||||
@@ -168,7 +172,7 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<UserProperties BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2011/7/1" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2011/7/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" />
|
||||||
</VisualStudio>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
|
{
|
||||||
|
public class ActiveDirectoryDomain
|
||||||
|
{
|
||||||
|
public string DnsName { get; private set; }
|
||||||
|
public string NetBiosName { get; private set; }
|
||||||
|
public string DistinguishedName { get; private set; }
|
||||||
|
|
||||||
|
public List<string> SearchContainers { get; private set; }
|
||||||
|
|
||||||
|
public ActiveDirectoryDomain(string DnsName, string NetBiosName, string DistinguishedName, List<string> SearchContainers)
|
||||||
|
{
|
||||||
|
this.DnsName = DnsName;
|
||||||
|
this.NetBiosName = NetBiosName;
|
||||||
|
this.DistinguishedName = DistinguishedName;
|
||||||
|
this.SearchContainers = SearchContainers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateSearchContainers(IEnumerable<string> Containers)
|
||||||
|
{
|
||||||
|
this.SearchContainers = Containers.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Models.Interop.ActiveDirectory
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
{
|
{
|
||||||
public class ActiveDirectoryGroup : IActiveDirectoryObject
|
public class ActiveDirectoryGroup : IActiveDirectoryObject
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Domain { get; set; }
|
||||||
public string DistinguishedName { get; set; }
|
|
||||||
public string SamAccountName { get; set; }
|
public string SamAccountName { get; set; }
|
||||||
|
|
||||||
|
public string DistinguishedName { get; set; }
|
||||||
public string SecurityIdentifier { get; set; }
|
public string SecurityIdentifier { get; set; }
|
||||||
public string CommonName { get; set; }
|
public string CommonName { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
public List<string> MemberOf { get; set; }
|
public List<string> MemberOf { get; set; }
|
||||||
|
|
||||||
|
public string NetBiosId { get { return string.Format(@"{0}\{1}", Domain, SamAccountName); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
using System;
|
using Disco.Models.Repository;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
|
|
||||||
namespace Disco.Models.Interop.ActiveDirectory
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
{
|
{
|
||||||
public class ActiveDirectoryMachineAccount : IActiveDirectoryObject
|
public class ActiveDirectoryMachineAccount : IActiveDirectoryObject
|
||||||
{
|
{
|
||||||
public string DistinguishedName { get; set; }
|
|
||||||
public string DnsName { get; set; }
|
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
public string Name { get; set; }
|
|
||||||
public Guid NetbootGUID { get; set; }
|
|
||||||
public string SecurityIdentifier { get; set; }
|
|
||||||
public string Path { get; set; }
|
|
||||||
public string SamAccountName { get; set; }
|
public string SamAccountName { get; set; }
|
||||||
|
|
||||||
|
public string SecurityIdentifier { get; set; }
|
||||||
|
public string DistinguishedName { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string DnsName { get; set; }
|
||||||
|
public Guid NetbootGUID { get; set; }
|
||||||
|
|
||||||
public bool IsCriticalSystemObject { get; set; }
|
public bool IsCriticalSystemObject { get; set; }
|
||||||
public Dictionary<string, object[]> LoadedProperties { get; set; }
|
public Dictionary<string, object[]> LoadedProperties { get; set; }
|
||||||
|
|
||||||
@@ -23,10 +25,11 @@ namespace Disco.Models.Interop.ActiveDirectory
|
|||||||
{
|
{
|
||||||
return new User
|
return new User
|
||||||
{
|
{
|
||||||
Id = this.SamAccountName,
|
UserId = this.Domain + "\\" + this.SamAccountName,
|
||||||
DisplayName = this.Name
|
DisplayName = this.Name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string NetBiosId { get { return string.Format(@"{0}\{1}", Domain, SamAccountName); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
|
{
|
||||||
|
public class ActiveDirectoryOrganisationalUnit
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Domain { get; set; }
|
||||||
|
public string DistinguishedName { get; set; }
|
||||||
|
public List<ActiveDirectoryOrganisationalUnit> Children { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
|
{
|
||||||
|
public class ActiveDirectorySearchResult
|
||||||
|
{
|
||||||
|
public ActiveDirectoryDomain Domain { get; set; }
|
||||||
|
public string SearchRoot { get; set; }
|
||||||
|
public SearchResult Result { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,25 +8,29 @@ namespace Disco.Models.Interop.ActiveDirectory
|
|||||||
{
|
{
|
||||||
public class ActiveDirectoryUserAccount : IActiveDirectoryObject
|
public class ActiveDirectoryUserAccount : IActiveDirectoryObject
|
||||||
{
|
{
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string DistinguishedName { get; set; }
|
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
public string Email { get; set; }
|
public string SamAccountName { get; set; }
|
||||||
public string GivenName { get; set; }
|
|
||||||
public List<string> Groups { get; set; }
|
public string DistinguishedName { get; set; }
|
||||||
public string Name { get; set; }
|
|
||||||
public string SecurityIdentifier { get; set; }
|
public string SecurityIdentifier { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public string Phone { get; set; }
|
|
||||||
public string SamAccountName { get; set; }
|
public string Name { get; set; }
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
public string Surname { get; set; }
|
public string Surname { get; set; }
|
||||||
|
public string GivenName { get; set; }
|
||||||
|
public string Phone { get; set; }
|
||||||
|
|
||||||
|
public List<string> Groups { get; set; }
|
||||||
|
|
||||||
public Dictionary<string, object[]> LoadedProperties { get; set; }
|
public Dictionary<string, object[]> LoadedProperties { get; set; }
|
||||||
|
|
||||||
public User ToRepositoryUser()
|
public User ToRepositoryUser()
|
||||||
{
|
{
|
||||||
return new User
|
return new User
|
||||||
{
|
{
|
||||||
Id = this.SamAccountName,
|
UserId = this.Domain + "\\" + this.SamAccountName,
|
||||||
DisplayName = this.DisplayName,
|
DisplayName = this.DisplayName,
|
||||||
Surname = this.Surname,
|
Surname = this.Surname,
|
||||||
GivenName = this.GivenName,
|
GivenName = this.GivenName,
|
||||||
@@ -35,5 +39,6 @@ namespace Disco.Models.Interop.ActiveDirectory
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string NetBiosId { get { return string.Format(@"{0}\{1}", Domain, SamAccountName); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Models.Interop.ActiveDirectory
|
namespace Disco.Models.Interop.ActiveDirectory
|
||||||
{
|
{
|
||||||
public interface IActiveDirectoryObject
|
public interface IActiveDirectoryObject
|
||||||
{
|
{
|
||||||
string DistinguishedName { get; set; }
|
string DistinguishedName { get; set; }
|
||||||
string SecurityIdentifier { get; set; }
|
string SecurityIdentifier { get; set; }
|
||||||
|
|
||||||
|
string Domain { get; set; }
|
||||||
string SamAccountName { get; set; }
|
string SamAccountName { get; set; }
|
||||||
|
string NetBiosId { get; }
|
||||||
|
|
||||||
string Name { get; set; }
|
string Name { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ namespace Disco.Models.Repository
|
|||||||
public int DeviceProfileId { get; set; }
|
public int DeviceProfileId { get; set; }
|
||||||
public int? DeviceBatchId { get; set; }
|
public int? DeviceBatchId { get; set; }
|
||||||
|
|
||||||
[StringLength(24)]
|
[StringLength(50), Column("ComputerName")]
|
||||||
public string ComputerName { get; set; }
|
public string DeviceDomainId { get; set; }
|
||||||
public string AssignedUserId { get; set; }
|
public string AssignedUserId { get; set; }
|
||||||
public DateTime? LastNetworkLogonDate { get; set; }
|
public DateTime? LastNetworkLogonDate { get; set; }
|
||||||
|
|
||||||
@@ -67,6 +67,26 @@ namespace Disco.Models.Repository
|
|||||||
return this.SerialNumber;
|
return this.SerialNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public string ComputerName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var index = DeviceDomainId.IndexOf('\\');
|
||||||
|
return index < 0 ? DeviceDomainId : DeviceDomainId.Substring(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public string ComputerDomainName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var index = DeviceDomainId.IndexOf('\\');
|
||||||
|
return index < 0 ? null : DeviceDomainId.Substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum DecommissionReasons
|
public enum DecommissionReasons
|
||||||
{
|
{
|
||||||
EndOfLife = 0,
|
EndOfLife = 0,
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace Disco.Models.Repository
|
|||||||
{
|
{
|
||||||
public class User
|
public class User
|
||||||
{
|
{
|
||||||
[StringLength(50), Key]
|
[StringLength(50), Key, Column("Id")]
|
||||||
public string Id { get; set; }
|
public string UserId { get; set; }
|
||||||
|
|
||||||
[StringLength(200)]
|
[StringLength(200)]
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
@@ -30,14 +30,34 @@ namespace Disco.Models.Repository
|
|||||||
[InverseProperty("UserId")]
|
[InverseProperty("UserId")]
|
||||||
public virtual IList<Job> Jobs { get; set; }
|
public virtual IList<Job> Jobs { get; set; }
|
||||||
|
|
||||||
|
[NotMapped, Obsolete("Should be using Combined Domain\\User format - UserId")]
|
||||||
|
public string Id
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var index = UserId.IndexOf('\\');
|
||||||
|
return index < 0 ? UserId : UserId.Substring(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public string Domain
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var index = UserId.IndexOf('\\');
|
||||||
|
return index < 0 ? null : UserId.Substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return string.Format("{0} ({1})", this.DisplayName, this.Id);
|
return string.Format("{0} ({1})", this.DisplayName, this.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSelf(User u)
|
public void UpdateSelf(User u)
|
||||||
{
|
{
|
||||||
if (!this.Id.Equals(u.Id, StringComparison.InvariantCultureIgnoreCase))
|
if (!this.UserId.Equals(u.UserId, StringComparison.InvariantCultureIgnoreCase))
|
||||||
throw new ArgumentException("User Id's do not match", "u");
|
throw new ArgumentException("User Id's do not match", "u");
|
||||||
|
|
||||||
if (this.Surname != u.Surname)
|
if (this.Surname != u.Surname)
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ namespace Disco.Models.Services.Jobs.JobLists
|
|||||||
public class JobTableItemModel : JobSearchResultItem
|
public class JobTableItemModel : JobSearchResultItem
|
||||||
{
|
{
|
||||||
public int JobId { get; set; }
|
public int JobId { get; set; }
|
||||||
|
|
||||||
|
#pragma warning disable 809
|
||||||
[Obsolete("Use [int] JobId instead")]
|
[Obsolete("Use [int] JobId instead")]
|
||||||
public override string Id
|
public override string Id
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,7 @@ namespace Disco.Models.Services.Jobs.JobLists
|
|||||||
this.JobId = int.Parse(value);
|
this.JobId = int.Parse(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore 618
|
||||||
public DateTime OpenedDate { get; set; }
|
public DateTime OpenedDate { get; set; }
|
||||||
public DateTime? ClosedDate { get; set; }
|
public DateTime? ClosedDate { get; set; }
|
||||||
public string JobTypeId { get; set; }
|
public string JobTypeId { get; set; }
|
||||||
@@ -30,6 +32,7 @@ namespace Disco.Models.Services.Jobs.JobLists
|
|||||||
public int? DeviceAddressId { get; set; }
|
public int? DeviceAddressId { get; set; }
|
||||||
public string DeviceAddress { get; set; }
|
public string DeviceAddress { get; set; }
|
||||||
public string OpenedTechUserId { get; set; }
|
public string OpenedTechUserId { get; set; }
|
||||||
|
public string OpenedTechUserFriendlyId { get; set; }
|
||||||
public string OpenedTechUserDisplayName { get; set; }
|
public string OpenedTechUserDisplayName { get; set; }
|
||||||
public string StatusDescription { get; set; }
|
public string StatusDescription { get; set; }
|
||||||
public string StatusId { get; set; }
|
public string StatusId { get; set; }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Disco.Models.Services.Searching
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string Type { get { return type; } }
|
public string Type { get { return type; } }
|
||||||
public string Description { get { return string.Format("{0} ({1})", this.Id, this.ComputerName); } }
|
public string Description { get { return string.Format("{0} ({1})", this.Id, this.ComputerName); } }
|
||||||
public string ScoreValue { get { return string.Format("{0} {1} {2} {3}", this.Id, this.AssignedUserId, this.AssignedUserDisplayName, this.AssetNumber); } }
|
public string ScoreValue { get { return string.Format("{0} {1} {2} {3} {4}", this.Id, this.AssignedUserId.Substring(0, this.AssignedUserId.IndexOf('\\')), this.AssignedUserId, this.AssignedUserDisplayName, this.AssetNumber); } }
|
||||||
|
|
||||||
public string AssetNumber { get; set; }
|
public string AssetNumber { get; set; }
|
||||||
public string AssignedUserDescription
|
public string AssignedUserDescription
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ namespace Disco.Models.Services.Searching
|
|||||||
public virtual string Id { get; set; }
|
public virtual string Id { get; set; }
|
||||||
public string Type { get { return type; } }
|
public string Type { get { return type; } }
|
||||||
public string Description { get { return string.Format("{0} ({1}; {2})", this.Id, this.UserId, this.DeviceSerialNumber); } }
|
public string Description { get { return string.Format("{0} ({1}; {2})", this.Id, this.UserId, this.DeviceSerialNumber); } }
|
||||||
public string ScoreValue { get { return string.Format("{0} {1} {2} {3}", this.Id, this.UserId, this.DeviceSerialNumber, this.UserDisplayName); } }
|
public string ScoreValue { get { return string.Format("{0} {1} {2} {3} {4}", this.Id, this.UserId.Substring(0, this.UserId.IndexOf('\\')), this.UserId, this.DeviceSerialNumber, this.UserDisplayName); } }
|
||||||
|
|
||||||
public string DeviceSerialNumber { get; set; }
|
public string DeviceSerialNumber { get; set; }
|
||||||
|
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
|
public string UserFriendlyId { get; set; }
|
||||||
public string UserDisplayName { get; set; }
|
public string UserDisplayName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Disco.Models.Services.Searching
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string Type { get { return type; } }
|
public string Type { get { return type; } }
|
||||||
public string Description { get { return string.Format("{0} ({1})", this.DisplayName, this.Id); } }
|
public string Description { get { return string.Format("{0} ({1})", this.DisplayName, this.Id); } }
|
||||||
public string ScoreValue { get { return string.Format("{0} {1}", this.Id, this.DisplayName); } }
|
public string ScoreValue { get { return string.Format("{0} {1} {2}", this.Id.Substring(0, this.Id.IndexOf('\\')), this.Id, this.DisplayName); } }
|
||||||
|
|
||||||
public int AssignedDevicesCount { get; set; }
|
public int AssignedDevicesCount { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ namespace Disco.Services.Authorization
|
|||||||
{ "Config.Plugin.Install", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Install, (c, v) => c.Config.Plugin.Install = v, "Install/Update Plugins", "Can install and update plugins", false) },
|
{ "Config.Plugin.Install", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Install, (c, v) => c.Config.Plugin.Install = v, "Install/Update Plugins", "Can install and update plugins", false) },
|
||||||
{ "Config.Plugin.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Show, (c, v) => c.Config.Plugin.Show = v, "Show Plugins", "Can show plugins", false) },
|
{ "Config.Plugin.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Show, (c, v) => c.Config.Plugin.Show = v, "Show Plugins", "Can show plugins", false) },
|
||||||
{ "Config.Plugin.Uninstall", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Uninstall, (c, v) => c.Config.Plugin.Uninstall = v, "Uninstall Plugins", "Can uninstall plugins", false) },
|
{ "Config.Plugin.Uninstall", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Plugin.Uninstall, (c, v) => c.Config.Plugin.Uninstall = v, "Uninstall Plugins", "Can uninstall plugins", false) },
|
||||||
|
{ "Config.System.ConfigureActiveDirectory", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.System.ConfigureActiveDirectory, (c, v) => c.Config.System.ConfigureActiveDirectory = v, "Configure Active Directory Settings", "Can configure the Active Directory interoperability settings", false) },
|
||||||
{ "Config.System.ConfigureProxy", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.System.ConfigureProxy, (c, v) => c.Config.System.ConfigureProxy = v, "Configure Proxy Settings", "Can configure the proxy settings", false) },
|
{ "Config.System.ConfigureProxy", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.System.ConfigureProxy, (c, v) => c.Config.System.ConfigureProxy = v, "Configure Proxy Settings", "Can configure the proxy settings", false) },
|
||||||
{ "Config.System.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.System.Show, (c, v) => c.Config.System.Show = v, "Show System Configuration", "Can show the system configuration", false) },
|
{ "Config.System.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.System.Show, (c, v) => c.Config.System.Show = v, "Show System Configuration", "Can show the system configuration", false) },
|
||||||
{ "Config.Organisation.ConfigureAddresses", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Organisation.ConfigureAddresses, (c, v) => c.Config.Organisation.ConfigureAddresses = v, "Configure Addresses", "Can configure organisation addresses", false) },
|
{ "Config.Organisation.ConfigureAddresses", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Organisation.ConfigureAddresses, (c, v) => c.Config.Organisation.ConfigureAddresses = v, "Configure Addresses", "Can configure organisation addresses", false) },
|
||||||
@@ -286,6 +287,7 @@ namespace Disco.Services.Authorization
|
|||||||
new ClaimNavigatorItem("Config.Plugin.Uninstall", false)
|
new ClaimNavigatorItem("Config.Plugin.Uninstall", false)
|
||||||
}),
|
}),
|
||||||
new ClaimNavigatorItem("Config.System", "System", "Permissions related to System Configuration", false, new List<IClaimNavigatorItem>() {
|
new ClaimNavigatorItem("Config.System", "System", "Permissions related to System Configuration", false, new List<IClaimNavigatorItem>() {
|
||||||
|
new ClaimNavigatorItem("Config.System.ConfigureActiveDirectory", false),
|
||||||
new ClaimNavigatorItem("Config.System.ConfigureProxy", false),
|
new ClaimNavigatorItem("Config.System.ConfigureProxy", false),
|
||||||
new ClaimNavigatorItem("Config.System.Show", false)
|
new ClaimNavigatorItem("Config.System.Show", false)
|
||||||
}),
|
}),
|
||||||
@@ -551,6 +553,7 @@ namespace Disco.Services.Authorization
|
|||||||
c.Config.Plugin.Install = true;
|
c.Config.Plugin.Install = true;
|
||||||
c.Config.Plugin.Show = true;
|
c.Config.Plugin.Show = true;
|
||||||
c.Config.Plugin.Uninstall = true;
|
c.Config.Plugin.Uninstall = true;
|
||||||
|
c.Config.System.ConfigureActiveDirectory = true;
|
||||||
c.Config.System.ConfigureProxy = true;
|
c.Config.System.ConfigureProxy = true;
|
||||||
c.Config.System.Show = true;
|
c.Config.System.Show = true;
|
||||||
c.Config.Organisation.ConfigureAddresses = true;
|
c.Config.Organisation.ConfigureAddresses = true;
|
||||||
@@ -956,6 +959,11 @@ namespace Disco.Services.Authorization
|
|||||||
public static class System
|
public static class System
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>Configure Active Directory Settings
|
||||||
|
/// <para>Can configure the Active Directory interoperability settings</para>
|
||||||
|
/// </summary>
|
||||||
|
public const string ConfigureActiveDirectory = "Config.System.ConfigureActiveDirectory";
|
||||||
|
|
||||||
/// <summary>Configure Proxy Settings
|
/// <summary>Configure Proxy Settings
|
||||||
/// <para>Can configure the proxy settings</para>
|
/// <para>Can configure the proxy settings</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Disco.Services.Authorization
|
|||||||
|
|
||||||
// Log Access Denied
|
// Log Access Denied
|
||||||
if (Token != null) // Don't log anonymous
|
if (Token != null) // Don't log anonymous
|
||||||
AuthorizationLog.LogAccessDenied(Token.User.Id, resultResource, resultMessage);
|
AuthorizationLog.LogAccessDenied(Token.User.UserId, resultResource, resultMessage);
|
||||||
|
|
||||||
// Build Response View
|
// Build Response View
|
||||||
var ex = new AccessDeniedException(resultMessage, resultResource);
|
var ex = new AccessDeniedException(resultMessage, resultResource);
|
||||||
|
|||||||
@@ -14,5 +14,8 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.System
|
|||||||
|
|
||||||
[ClaimDetails("Configure Proxy Settings", "Can configure the proxy settings")]
|
[ClaimDetails("Configure Proxy Settings", "Can configure the proxy settings")]
|
||||||
public bool ConfigureProxy { get; set; }
|
public bool ConfigureProxy { get; set; }
|
||||||
|
|
||||||
|
[ClaimDetails("Configure Active Directory Settings", "Can configure the Active Directory interoperability settings")]
|
||||||
|
public bool ConfigureActiveDirectory { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace Disco.Services.Authorization.Roles
|
|||||||
}
|
}
|
||||||
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup, User User)
|
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup, User User)
|
||||||
{
|
{
|
||||||
var subjectIds = (new string[] { User.Id }).Concat(SecurityGroup).Select(sg => sg.ToLower());
|
var subjectIds = (new string[] { User.UserId }).Concat(SecurityGroup).Select(sg => sg.ToLower());
|
||||||
|
|
||||||
return _Cache.Where(t => subjectIds.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
|
return _Cache.Where(t => subjectIds.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,6 +174,12 @@
|
|||||||
<Compile Include="Authorization\Roles\RoleToken.cs" />
|
<Compile Include="Authorization\Roles\RoleToken.cs" />
|
||||||
<Compile Include="Extensions\DateTimeExtensions.cs" />
|
<Compile Include="Extensions\DateTimeExtensions.cs" />
|
||||||
<Compile Include="Extensions\StringExtensions.cs" />
|
<Compile Include="Extensions\StringExtensions.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\ActiveDirectory.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\ActiveDirectoryExtensions.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\Internal\ADDiscoverForestServers.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\Internal\ADGroupCache.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\Internal\ADInterop.cs" />
|
||||||
|
<Compile Include="Interop\ActiveDirectory\Internal\ADUpdateLastNetworkLogonDateJob.cs" />
|
||||||
<Compile Include="Jobs\JobExtensions.cs" />
|
<Compile Include="Jobs\JobExtensions.cs" />
|
||||||
<Compile Include="Jobs\JobLists\JobTableExtensions.cs" />
|
<Compile Include="Jobs\JobLists\JobTableExtensions.cs" />
|
||||||
<Compile Include="Jobs\JobQueues\Cache.cs" />
|
<Compile Include="Jobs\JobQueues\Cache.cs" />
|
||||||
@@ -240,7 +246,7 @@
|
|||||||
<Compile Include="Plugins\Features\UIExtension\UIExtensions.cs" />
|
<Compile Include="Plugins\Features\UIExtension\UIExtensions.cs" />
|
||||||
<Compile Include="Users\Cache.cs" />
|
<Compile Include="Users\Cache.cs" />
|
||||||
<Compile Include="Users\CacheCleanTask.cs" />
|
<Compile Include="Users\CacheCleanTask.cs" />
|
||||||
<Compile Include="Users\Searching.cs" />
|
<Compile Include="Users\UserExtensions.cs" />
|
||||||
<Compile Include="Users\UserService.cs" />
|
<Compile Include="Users\UserService.cs" />
|
||||||
<Compile Include="Web\AuthorizedController.cs" />
|
<Compile Include="Web\AuthorizedController.cs" />
|
||||||
<Compile Include="Web\AuthorizedDatabaseController.cs" />
|
<Compile Include="Web\AuthorizedDatabaseController.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,531 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Services.Interop.ActiveDirectory
|
||||||
|
{
|
||||||
|
public static class ActiveDirectory
|
||||||
|
{
|
||||||
|
private const int SingleSearchResult = 1;
|
||||||
|
public const int MaxForestServerSearch = 30;
|
||||||
|
|
||||||
|
public static void Initialize(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
ADInterop.Initialize(Database);
|
||||||
|
}
|
||||||
|
public static void UpdateSearchContainers(DiscoDataContext Database, List<string> Containers)
|
||||||
|
{
|
||||||
|
ADInterop.UpdateSearchContainers(Database, Containers);
|
||||||
|
}
|
||||||
|
public static bool UpdateSearchEntireForest(DiscoDataContext Database, bool SearchEntireForest)
|
||||||
|
{
|
||||||
|
return ADInterop.UpdateSearchEntireForest(Database, SearchEntireForest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain PrimaryDomain
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ADInterop.PrimaryDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectoryDomain> Domains
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ADInterop.Domains.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectorySite Site
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ADInterop.Site;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain GetDomainByDistinguishedName(string DistinguishedName)
|
||||||
|
{
|
||||||
|
return ADInterop.GetDomainByDistinguishedName(DistinguishedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain GetDomainByNetBiosName(string NetBiosName)
|
||||||
|
{
|
||||||
|
return ADInterop.GetDomainByNetBiosName(NetBiosName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain GetDomainByDnsName(string DnsName)
|
||||||
|
{
|
||||||
|
return ADInterop.GetDomainByDnsName(DnsName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain GetDomainFromId(string Id)
|
||||||
|
{
|
||||||
|
return ADInterop.GetDomainFromId(Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> LoadForestServers()
|
||||||
|
{
|
||||||
|
return ADInterop.LoadForestServers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<List<string>> LoadForestServersAsync()
|
||||||
|
{
|
||||||
|
return ADInterop.LoadForestServersAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool SearchEntireForest
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ADInterop.SearchEntireForest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Machine Account
|
||||||
|
private static readonly string[] MachineLoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "dNSHostName", "netbootGUID", "isCriticalSystemObject" };
|
||||||
|
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(DomainController DomainController, string Id, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
return RetrieveMachineAccount(DomainController, Id, (System.Guid?)null, (System.Guid?)null, AdditionalProperties);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(string Id, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
return RetrieveMachineAccount(Id, (System.Guid?)null, (System.Guid?)null, AdditionalProperties);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(DomainController DomainController, string Id, System.Guid? UUIDNetbootGUID, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
return RetrieveMachineAccount(DomainController, Id, UUIDNetbootGUID, (System.Guid?)null, AdditionalProperties);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(string Id, System.Guid? UUIDNetbootGUID, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
return RetrieveMachineAccount(Id, UUIDNetbootGUID, (System.Guid?)null, AdditionalProperties);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(string Id, System.Guid? UUIDNetbootGUID, System.Guid? MacAddressNetbootGUID, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
return RetrieveMachineAccount(null, Id, UUIDNetbootGUID, MacAddressNetbootGUID, AdditionalProperties);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryMachineAccount RetrieveMachineAccount(DomainController DomainController, string Id, System.Guid? UUIDNetbootGUID, System.Guid? MacAddressNetbootGUID, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Id))
|
||||||
|
throw new ArgumentNullException("Id");
|
||||||
|
|
||||||
|
// Add $ identifier for machine accounts
|
||||||
|
if (!Id.EndsWith("$"))
|
||||||
|
Id += "$";
|
||||||
|
|
||||||
|
const string ldapFilterTemplate = "(&(objectCategory=computer)(sAMAccountName={0}))";
|
||||||
|
const string ldapNetbootGuidFilterTemplate = "(&(objectCategory=computer)(netbootGUID={0}))";
|
||||||
|
|
||||||
|
string[] loadProperites = (AdditionalProperties != null && AdditionalProperties.Length > 0)
|
||||||
|
? MachineLoadProperties.Concat(AdditionalProperties).ToArray()
|
||||||
|
: MachineLoadProperties;
|
||||||
|
|
||||||
|
ActiveDirectorySearchResult adResult;
|
||||||
|
|
||||||
|
var splitId = UserExtensions.SplitUserId(Id);
|
||||||
|
var ldapSamAccountFilter = string.Format(ldapFilterTemplate, splitId.Item2);
|
||||||
|
var domain = ADInterop.GetDomainFromId(Id);
|
||||||
|
|
||||||
|
adResult = ADInterop.SearchAll(domain, DomainController, ldapSamAccountFilter, SingleSearchResult, loadProperites).FirstOrDefault();
|
||||||
|
if (adResult == null && (UUIDNetbootGUID.HasValue || MacAddressNetbootGUID.HasValue))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (UUIDNetbootGUID.HasValue)
|
||||||
|
{
|
||||||
|
var ldapFilter = string.Format(ldapNetbootGuidFilterTemplate, ADInterop.FormatGuidForLdapQuery(UUIDNetbootGUID.Value));
|
||||||
|
adResult = ADInterop.SearchAll(domain, DomainController, ldapFilter, SingleSearchResult, loadProperites).FirstOrDefault();
|
||||||
|
}
|
||||||
|
if (adResult == null && MacAddressNetbootGUID.HasValue)
|
||||||
|
{
|
||||||
|
var ldapFilter = string.Format(ldapNetbootGuidFilterTemplate, ADInterop.FormatGuidForLdapQuery(MacAddressNetbootGUID.Value));
|
||||||
|
adResult = ADInterop.SearchAll(domain, DomainController, ldapFilter, SingleSearchResult, loadProperites).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adResult != null)
|
||||||
|
return adResult.AsMachineAccount(AdditionalProperties);
|
||||||
|
else
|
||||||
|
return null; // Not Found
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActiveDirectoryMachineAccount AsMachineAccount(this ActiveDirectorySearchResult item, string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
string name = item.Result.Properties["name"][0].ToString();
|
||||||
|
string sAMAccountName = item.Result.Properties["sAMAccountName"][0].ToString();
|
||||||
|
string distinguishedName = item.Result.Properties["distinguishedName"][0].ToString();
|
||||||
|
string objectSid = ADInterop.ConvertBytesToSDDLString((byte[])item.Result.Properties["objectSid"][0]);
|
||||||
|
|
||||||
|
var dNSNameProperty = item.Result.Properties["dNSHostName"];
|
||||||
|
string dNSName = null;
|
||||||
|
if (dNSNameProperty.Count > 0)
|
||||||
|
dNSName = dNSNameProperty[0].ToString();
|
||||||
|
else
|
||||||
|
dNSName = string.Format("{0}.{1}", sAMAccountName.TrimEnd('$'), item.Domain.DnsName);
|
||||||
|
|
||||||
|
bool isCriticalSystemObject = (bool)item.Result.Properties["isCriticalSystemObject"][0];
|
||||||
|
|
||||||
|
System.Guid netbootGUIDResult = default(System.Guid);
|
||||||
|
ResultPropertyValueCollection netbootGUIDProp = item.Result.Properties["netbootGUID"];
|
||||||
|
if (netbootGUIDProp.Count > 0)
|
||||||
|
{
|
||||||
|
netbootGUIDResult = new System.Guid((byte[])netbootGUIDProp[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Properties
|
||||||
|
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
|
||||||
|
if (AdditionalProperties != null)
|
||||||
|
foreach (string propertyName in AdditionalProperties)
|
||||||
|
{
|
||||||
|
var property = item.Result.Properties[propertyName];
|
||||||
|
var propertyValues = new List<object>();
|
||||||
|
for (int index = 0; index < property.Count; index++)
|
||||||
|
propertyValues.Add(property[index]);
|
||||||
|
additionalProperties.Add(propertyName, propertyValues.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ActiveDirectoryMachineAccount
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
DistinguishedName = distinguishedName,
|
||||||
|
SamAccountName = sAMAccountName,
|
||||||
|
SecurityIdentifier = objectSid,
|
||||||
|
NetbootGUID = netbootGUIDResult,
|
||||||
|
Path = item.Result.Path,
|
||||||
|
Domain = item.Domain.NetBiosName,
|
||||||
|
DnsName = dNSName,
|
||||||
|
IsCriticalSystemObject = isCriticalSystemObject,
|
||||||
|
LoadedProperties = additionalProperties
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string OfflineDomainJoinProvision(ActiveDirectoryDomain Domain, DomainController DomainController, string ComputerName, string OrganisationalUnit, ref ActiveDirectoryMachineAccount MachineAccount, out string DiagnosticInformation)
|
||||||
|
{
|
||||||
|
const string ldapFilterTemplate = "(&(objectCategory=computer)(sAMAccountName={0}))";
|
||||||
|
|
||||||
|
if (MachineAccount != null && MachineAccount.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", MachineAccount.DistinguishedName));
|
||||||
|
|
||||||
|
if (MachineAccount != null)
|
||||||
|
MachineAccount.DeleteAccount(DomainController);
|
||||||
|
|
||||||
|
var computerId = UserExtensions.SplitUserId(ComputerName);
|
||||||
|
|
||||||
|
var offlineJoinResult = ADInterop.OfflineDomainJoinProvision(Domain, DomainController, computerId.Item2, OrganisationalUnit, out DiagnosticInformation);
|
||||||
|
|
||||||
|
// Reload newly created Account
|
||||||
|
string[] loadAdditionalProperties = (MachineAccount != null && MachineAccount.LoadedProperties != null && MachineAccount.LoadedProperties.Count > 0)
|
||||||
|
? MachineAccount.LoadedProperties.Keys.ToArray()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
MachineAccount = null;
|
||||||
|
|
||||||
|
string[] loadProperites = (loadAdditionalProperties != null)
|
||||||
|
? MachineLoadProperties.Concat(loadAdditionalProperties).ToArray()
|
||||||
|
: MachineLoadProperties;
|
||||||
|
|
||||||
|
var ldapSamAccountName = computerId.Item2.EndsWith("$") ? computerId.Item2 : computerId.Item2 + "$";
|
||||||
|
var ldapFilter = string.Format(ldapFilterTemplate, ldapSamAccountName);
|
||||||
|
var ldapResult = ADInterop.SearchDomain(Domain, DomainController, Domain.DistinguishedName, ldapFilter, 1, loadProperites).FirstOrDefault();
|
||||||
|
|
||||||
|
if (ldapResult != null)
|
||||||
|
MachineAccount = ldapResult.AsMachineAccount(loadAdditionalProperties);
|
||||||
|
|
||||||
|
return offlineJoinResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region User Account
|
||||||
|
private static readonly string[] UserLoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "displayName", "sn", "givenName", "memberOf", "primaryGroupID", "mail", "telephoneNumber" };
|
||||||
|
|
||||||
|
public static ActiveDirectoryUserAccount RetrieveUserAccount(string Id, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
const string ldapFilter = "(&(objectCategory=Person)(sAMAccountName={0}))";
|
||||||
|
|
||||||
|
string[] loadProperites = (AdditionalProperties != null && AdditionalProperties.Length > 0)
|
||||||
|
? UserLoadProperties.Concat(AdditionalProperties).ToArray()
|
||||||
|
: UserLoadProperties;
|
||||||
|
|
||||||
|
return SearchBySamAccountName(Id, ldapFilter, loadProperites).Select(result => result.AsUserAccount(AdditionalProperties)).FirstOrDefault();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectoryUserAccount> SearchUserAccounts(string Term, params string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
const int resultLimit = 30; // Default Search Limit
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Term))
|
||||||
|
throw new ArgumentNullException("Term");
|
||||||
|
|
||||||
|
string ldapFilter = string.Format("(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName=*{0}*)(displayName=*{0}*)))", ADInterop.EscapeLdapQuery(Term));
|
||||||
|
|
||||||
|
string[] loadProperites = (AdditionalProperties != null && AdditionalProperties.Length > 0)
|
||||||
|
? UserLoadProperties.Concat(AdditionalProperties).ToArray()
|
||||||
|
: UserLoadProperties;
|
||||||
|
|
||||||
|
return ADInterop.SearchScope(ldapFilter, resultLimit, loadProperites).Select(result => result.AsUserAccount(AdditionalProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActiveDirectoryUserAccount AsUserAccount(this ActiveDirectorySearchResult item, string[] AdditionalProperties)
|
||||||
|
{
|
||||||
|
string name = item.Result.Properties["name"][0].ToString();
|
||||||
|
string username = item.Result.Properties["sAMAccountName"][0].ToString();
|
||||||
|
string distinguishedName = item.Result.Properties["distinguishedName"][0].ToString();
|
||||||
|
byte[] objectSid = (byte[])item.Result.Properties["objectSid"][0];
|
||||||
|
string objectSidSDDL = ADInterop.ConvertBytesToSDDLString(objectSid);
|
||||||
|
|
||||||
|
ResultPropertyValueCollection displayNameProp = item.Result.Properties["displayName"];
|
||||||
|
string displayName = username;
|
||||||
|
if (displayNameProp.Count > 0)
|
||||||
|
displayName = displayNameProp[0].ToString();
|
||||||
|
string surname = null;
|
||||||
|
ResultPropertyValueCollection surnameProp = item.Result.Properties["sn"];
|
||||||
|
if (surnameProp.Count > 0)
|
||||||
|
surname = surnameProp[0].ToString();
|
||||||
|
string givenName = null;
|
||||||
|
ResultPropertyValueCollection givenNameProp = item.Result.Properties["givenName"];
|
||||||
|
if (givenNameProp.Count > 0)
|
||||||
|
givenName = givenNameProp[0].ToString();
|
||||||
|
string email = null;
|
||||||
|
ResultPropertyValueCollection emailProp = item.Result.Properties["mail"];
|
||||||
|
if (emailProp.Count > 0)
|
||||||
|
email = emailProp[0].ToString();
|
||||||
|
string phone = null;
|
||||||
|
ResultPropertyValueCollection phoneProp = item.Result.Properties["telephoneNumber"];
|
||||||
|
if (phoneProp.Count > 0)
|
||||||
|
phone = phoneProp[0].ToString();
|
||||||
|
|
||||||
|
int primaryGroupID = (int)item.Result.Properties["primaryGroupID"][0];
|
||||||
|
string primaryGroupSid = ADInterop.ConvertBytesToSDDLString(ADInterop.BuildPrimaryGroupSid(objectSid, primaryGroupID));
|
||||||
|
var groupDistinguishedNames = item.Result.Properties["memberOf"].Cast<string>().ToList();
|
||||||
|
groupDistinguishedNames.Add(ADGroupCache.GetGroupsDistinguishedNameForSecurityIdentifier(primaryGroupSid));
|
||||||
|
List<string> groups = ADGroupCache.GetGroups(groupDistinguishedNames).ToList();
|
||||||
|
|
||||||
|
// Additional Properties
|
||||||
|
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
|
||||||
|
if (AdditionalProperties != null)
|
||||||
|
foreach (string propertyName in AdditionalProperties)
|
||||||
|
{
|
||||||
|
var property = item.Result.Properties[propertyName];
|
||||||
|
var propertyValues = new List<object>();
|
||||||
|
for (int index = 0; index < property.Count; index++)
|
||||||
|
propertyValues.Add(property[index]);
|
||||||
|
additionalProperties.Add(propertyName, propertyValues.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ActiveDirectoryUserAccount
|
||||||
|
{
|
||||||
|
Domain = item.Domain.NetBiosName,
|
||||||
|
Name = name,
|
||||||
|
Surname = surname,
|
||||||
|
GivenName = givenName,
|
||||||
|
Email = email,
|
||||||
|
Phone = phone,
|
||||||
|
DistinguishedName = distinguishedName,
|
||||||
|
SamAccountName = username,
|
||||||
|
DisplayName = displayName,
|
||||||
|
SecurityIdentifier = objectSidSDDL,
|
||||||
|
Groups = groups,
|
||||||
|
Path = item.Result.Path,
|
||||||
|
LoadedProperties = additionalProperties
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Groups
|
||||||
|
private static readonly string[] GroupLoadProperties = { "name", "distinguishedName", "cn", "sAMAccountName", "objectSid", "memberOf" };
|
||||||
|
|
||||||
|
public static ActiveDirectoryGroup RetrieveGroup(string Id)
|
||||||
|
{
|
||||||
|
const string ldapFilter = "(&(objectCategory=Group)(objectSid={0}))";
|
||||||
|
|
||||||
|
return SearchBySamAccountName(Id, ldapFilter, GroupLoadProperties).Select(result => result.AsGroup()).FirstOrDefault();
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryGroup RetrieveGroupWithDistinguishedName(string DistinguishedName)
|
||||||
|
{
|
||||||
|
ActiveDirectoryDomain domain;
|
||||||
|
|
||||||
|
using (var groupEntry = ADInterop.RetrieveDirectoryEntry(DistinguishedName, out domain))
|
||||||
|
{
|
||||||
|
if (groupEntry == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return groupEntry.AsGroup(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryGroup RetrieveGroupWithSecurityIdentifier(string SecurityIdentifier)
|
||||||
|
{
|
||||||
|
const int resultLimit = 1;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(SecurityIdentifier))
|
||||||
|
throw new ArgumentNullException("SecurityIdentifier");
|
||||||
|
|
||||||
|
var sidBytes = ADInterop.ConvertSDDLStringToBytes(SecurityIdentifier);
|
||||||
|
var sidBinaryString = ADInterop.ConvertBytesToBinarySidString(sidBytes);
|
||||||
|
|
||||||
|
string ldapFilter = string.Format("(&(objectCategory=Group)(objectSid={0}))", sidBinaryString);
|
||||||
|
|
||||||
|
return ADInterop.SearchAll(ldapFilter, resultLimit, null).Select(result => result.AsGroup()).FirstOrDefault();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectoryGroup> SearchGroups(string Term)
|
||||||
|
{
|
||||||
|
const int resultLimit = 30; // Default Search Limit
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Term))
|
||||||
|
throw new ArgumentNullException("Term");
|
||||||
|
|
||||||
|
string ldapFilter = string.Format("(&(objectCategory=Group)(|(sAMAccountName=*{0}*)(name=*{0}*)(cn=*{0}*)))", ADInterop.EscapeLdapQuery(Term));
|
||||||
|
|
||||||
|
return ADInterop.SearchScope(ldapFilter, resultLimit, GroupLoadProperties).Select(result => result.AsGroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActiveDirectoryGroup AsGroup(this ActiveDirectorySearchResult item)
|
||||||
|
{
|
||||||
|
var name = (string)item.Result.Properties["name"][0];
|
||||||
|
var distinguishedName = (string)item.Result.Properties["distinguishedName"][0];
|
||||||
|
var cn = (string)item.Result.Properties["cn"][0];
|
||||||
|
var sAMAccountName = (string)item.Result.Properties["sAMAccountName"][0];
|
||||||
|
var objectSid = ADInterop.ConvertBytesToSDDLString((byte[])item.Result.Properties["objectSid"][0]);
|
||||||
|
var memberOf = item.Result.Properties["memberOf"].Cast<string>().ToList();
|
||||||
|
|
||||||
|
return new ActiveDirectoryGroup()
|
||||||
|
{
|
||||||
|
Domain = item.Domain.DnsName,
|
||||||
|
Name = name,
|
||||||
|
DistinguishedName = distinguishedName,
|
||||||
|
CommonName = cn,
|
||||||
|
SamAccountName = sAMAccountName,
|
||||||
|
SecurityIdentifier = objectSid,
|
||||||
|
MemberOf = memberOf
|
||||||
|
};
|
||||||
|
}
|
||||||
|
private static ActiveDirectoryGroup AsGroup(this DirectoryEntry item, ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
var name = (string)item.Properties["name"][0];
|
||||||
|
var distinguishedName = (string)item.Properties["distinguishedName"][0];
|
||||||
|
var cn = (string)item.Properties["cn"][0];
|
||||||
|
var sAMAccountName = (string)item.Properties["sAMAccountName"][0];
|
||||||
|
var objectSid = ADInterop.ConvertBytesToSDDLString((byte[])item.Properties["objectSid"][0]);
|
||||||
|
var memberOf = item.Properties["memberOf"].Cast<string>().ToList();
|
||||||
|
|
||||||
|
return new ActiveDirectoryGroup()
|
||||||
|
{
|
||||||
|
Domain = Domain.DnsName,
|
||||||
|
Name = name,
|
||||||
|
DistinguishedName = distinguishedName,
|
||||||
|
CommonName = cn,
|
||||||
|
SamAccountName = sAMAccountName,
|
||||||
|
SecurityIdentifier = objectSid,
|
||||||
|
MemberOf = memberOf
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Object
|
||||||
|
private static readonly string[] ObjectLoadProperties = { "objectCategory" };
|
||||||
|
private static readonly string[] ObjectLoadPropertiesAll = ObjectLoadProperties.Concat(UserLoadProperties).Concat(MachineLoadProperties).Concat(GroupLoadProperties).Distinct().ToArray();
|
||||||
|
|
||||||
|
public static IActiveDirectoryObject RetrieveObject(string Id)
|
||||||
|
{
|
||||||
|
const string ldapFilter = "(&(|(objectCategory=Person)(objectCategory=Computer)(objectCategory=Group))(sAMAccountName={0}))";
|
||||||
|
|
||||||
|
return SearchBySamAccountName(Id, ldapFilter, ObjectLoadPropertiesAll)
|
||||||
|
.Select<ActiveDirectorySearchResult, IActiveDirectoryObject>(result =>
|
||||||
|
{
|
||||||
|
var objectCategory = (string)result.Result.Properties["objectCategory"][0];
|
||||||
|
objectCategory = objectCategory.Substring(0, objectCategory.IndexOf(',')).ToLower();
|
||||||
|
switch (objectCategory)
|
||||||
|
{
|
||||||
|
case "cn=person":
|
||||||
|
return result.AsUserAccount(null);
|
||||||
|
case "cn=computer":
|
||||||
|
return result.AsMachineAccount(null);
|
||||||
|
case "cn=group":
|
||||||
|
return result.AsGroup();
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException("Unexpected objectCategory");
|
||||||
|
}
|
||||||
|
}).FirstOrDefault();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Organisation Units
|
||||||
|
|
||||||
|
public static List<ActiveDirectoryOrganisationalUnit> RetrieveOrganisationalUnitStructure(ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
using (DirectoryEntry domainRoot = ADInterop.RetrieveDirectoryEntry(Domain.DistinguishedName, out Domain))
|
||||||
|
{
|
||||||
|
return ActiveDirectory.RetrieveOrganisationalUnitStructureInternal(Domain, domainRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static List<ActiveDirectoryOrganisationalUnit> RetrieveOrganisationalUnitStructureInternal(ActiveDirectoryDomain Domain, DirectoryEntry Container)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<ActiveDirectoryOrganisationalUnit>> resultTree = new Dictionary<string, List<ActiveDirectoryOrganisationalUnit>>();
|
||||||
|
|
||||||
|
using (DirectorySearcher adSearcher = new DirectorySearcher(Container, "(objectCategory=organizationalUnit)", new string[]
|
||||||
|
{
|
||||||
|
"name",
|
||||||
|
"distinguishedName"
|
||||||
|
}, SearchScope.Subtree))
|
||||||
|
{
|
||||||
|
adSearcher.PageSize = 500;
|
||||||
|
|
||||||
|
using (SearchResultCollection adResults = adSearcher.FindAll())
|
||||||
|
{
|
||||||
|
resultTree = adResults.Cast<SearchResult>().Select(adResult =>
|
||||||
|
{
|
||||||
|
string i = adResult.Properties["name"][0].ToString();
|
||||||
|
string dn = adResult.Properties["distinguishedName"][0].ToString();
|
||||||
|
return new ActiveDirectoryOrganisationalUnit
|
||||||
|
{
|
||||||
|
Domain = Domain.NetBiosName,
|
||||||
|
Name = i,
|
||||||
|
DistinguishedName = dn,
|
||||||
|
};
|
||||||
|
}).GroupBy(ou => ou.DistinguishedName.Substring(ou.DistinguishedName.IndexOf(',') + 1)).ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build Tree
|
||||||
|
var results = resultTree[Domain.DistinguishedName];
|
||||||
|
foreach (var child in results)
|
||||||
|
RetrieveOrganisationalUnitStructureChildrenInternal(child, resultTree);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
private static void RetrieveOrganisationalUnitStructureChildrenInternal(ActiveDirectoryOrganisationalUnit OrganisationalUnit, Dictionary<string, List<ActiveDirectoryOrganisationalUnit>> ResultTree)
|
||||||
|
{
|
||||||
|
List<ActiveDirectoryOrganisationalUnit> children;
|
||||||
|
|
||||||
|
if (ResultTree.TryGetValue(OrganisationalUnit.DistinguishedName, out children))
|
||||||
|
{
|
||||||
|
foreach (var child in children)
|
||||||
|
RetrieveOrganisationalUnitStructureChildrenInternal(child, ResultTree);
|
||||||
|
|
||||||
|
OrganisationalUnit.Children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
private static IEnumerable<ActiveDirectorySearchResult> SearchBySamAccountName(string Id, string LdapFilterTemplate, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var splitId = UserExtensions.SplitUserId(Id);
|
||||||
|
var ldapFilter = string.Format(LdapFilterTemplate, splitId.Item2);
|
||||||
|
var domains = ADInterop.GetDomainFromId(Id);
|
||||||
|
|
||||||
|
return ADInterop.SearchAll(domains, ldapFilter, SingleSearchResult, LoadProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,391 @@
|
|||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Services.Interop.ActiveDirectory
|
||||||
|
{
|
||||||
|
public static class ActiveDirectoryExtensions
|
||||||
|
{
|
||||||
|
#region Domain/Directory Extensions
|
||||||
|
|
||||||
|
public static DomainController RetrieveWritableDomainController(this ActiveDirectoryDomain domain)
|
||||||
|
{
|
||||||
|
return ADInterop.RetrieveWritableDomainController(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<DomainController> RetrieveReachableDomainControllers(this ActiveDirectorySite site, ActiveDirectoryDomain domain)
|
||||||
|
{
|
||||||
|
return site.Servers.OfType<DomainController>().Where(dc => dc.Reachable() && dc.Domain.Name.Equals(domain.DnsName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<DomainController> RetrieveReachableDomainControllers(this ActiveDirectoryDomain domain)
|
||||||
|
{
|
||||||
|
var d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, domain.DnsName));
|
||||||
|
return d.FindAllDomainControllers().OfType<DomainController>().Where(dc => dc.Reachable());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Reachable(this DirectoryServer ds)
|
||||||
|
{
|
||||||
|
using (Ping p = new Ping())
|
||||||
|
{
|
||||||
|
var pr = p.Send(ds.Name, 500);
|
||||||
|
return (pr.Status == IPStatus.Success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFriendlyOrganisationalUnitName(this ActiveDirectoryDomain domain, string DistinguishedName)
|
||||||
|
{
|
||||||
|
if (!DistinguishedName.EndsWith(domain.DistinguishedName, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
throw new ArgumentException(string.Format("The Distinguished Name [{0}] doesn't exist within this domain [{1}]", DistinguishedName, domain.DistinguishedName));
|
||||||
|
|
||||||
|
StringBuilder name = new StringBuilder();
|
||||||
|
|
||||||
|
name.Append('[').Append(domain.NetBiosName).Append(']');
|
||||||
|
|
||||||
|
var subDN = DistinguishedName.Substring(0, DistinguishedName.Length - domain.DistinguishedName.Length);
|
||||||
|
var subDNComponents = subDN.Split(',');
|
||||||
|
|
||||||
|
subDNComponents
|
||||||
|
.Where(c => !string.IsNullOrWhiteSpace(c))
|
||||||
|
.Reverse()
|
||||||
|
.Select(c => c.Substring(c.IndexOf('=') + 1))
|
||||||
|
.ToList()
|
||||||
|
.ForEach(c => name.Append(" > ").Append(c));
|
||||||
|
|
||||||
|
return name.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDefaultComputerContainer(this ActiveDirectoryDomain domain)
|
||||||
|
{
|
||||||
|
return string.Format("CN=Computers,{0}", domain.DistinguishedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region User Account Extensions
|
||||||
|
public static object GetPropertyValue(this ActiveDirectoryUserAccount account, string PropertyName, int Index = 0)
|
||||||
|
{
|
||||||
|
switch (PropertyName.ToLower())
|
||||||
|
{
|
||||||
|
case "name":
|
||||||
|
return account.Name;
|
||||||
|
case "samaccountname":
|
||||||
|
return account.SamAccountName;
|
||||||
|
case "distinguishedname":
|
||||||
|
return account.DistinguishedName;
|
||||||
|
case "objectsid":
|
||||||
|
return account.SecurityIdentifier;
|
||||||
|
case "sn":
|
||||||
|
return account.Surname;
|
||||||
|
case "givenname":
|
||||||
|
return account.GivenName;
|
||||||
|
case "mail":
|
||||||
|
return account.Email;
|
||||||
|
case "telephonenumber":
|
||||||
|
return account.Phone;
|
||||||
|
default:
|
||||||
|
object[] adProperty;
|
||||||
|
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
||||||
|
return adProperty[Index];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Machine Account Extensions
|
||||||
|
|
||||||
|
public static void DeleteAccount(this ActiveDirectoryMachineAccount account, DomainController DomainController)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
using (DirectoryEntry deAccount = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
deAccount.DeleteObjectRecursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void DeleteAccount(this ActiveDirectoryMachineAccount account)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
account.DeleteAccount(domainController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetNetbootGUID(this ActiveDirectoryMachineAccount account, DomainController DomainController, System.Guid updatedNetbootGUID)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
using (DirectoryEntry deAccount = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
PropertyValueCollection netbootGUIDProp = deAccount.Properties["netbootGUID"];
|
||||||
|
bool flag = netbootGUIDProp.Count > 0;
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
netbootGUIDProp.Clear();
|
||||||
|
}
|
||||||
|
netbootGUIDProp.Add(updatedNetbootGUID.ToByteArray());
|
||||||
|
deAccount.CommitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void SetDescription(this ActiveDirectoryMachineAccount account, DomainController DomainController, string Description)
|
||||||
|
{
|
||||||
|
using (DirectoryEntry deAccount = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
PropertyValueCollection descriptionProp = deAccount.Properties["description"];
|
||||||
|
if (descriptionProp.Count > 0)
|
||||||
|
{
|
||||||
|
descriptionProp.Clear();
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Description))
|
||||||
|
{
|
||||||
|
descriptionProp.Add(Description);
|
||||||
|
}
|
||||||
|
deAccount.CommitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void SetDescription(this ActiveDirectoryMachineAccount account, string Description)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
account.SetDescription(domainController, Description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetDescription(this ActiveDirectoryMachineAccount account, DomainController DomainController, Device Device)
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
if (Device.AssignedUserId != null)
|
||||||
|
{
|
||||||
|
descriptionBuilder.Append(Device.AssignedUser.UserId).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Device.DeviceModelId.HasValue)
|
||||||
|
{
|
||||||
|
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
|
||||||
|
|
||||||
|
string description = descriptionBuilder.ToString().Trim();
|
||||||
|
if (description.Length > 1024)
|
||||||
|
description = description.Substring(0, 1024);
|
||||||
|
|
||||||
|
account.SetDescription(DomainController, description);
|
||||||
|
}
|
||||||
|
public static void SetDescription(this ActiveDirectoryMachineAccount account, Device Device)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
account.SetDescription(domainController, Device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DisableAccount(this ActiveDirectoryMachineAccount account, DomainController DomainController)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
using (DirectoryEntry deAccount = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
int accountControl = (int)deAccount.Properties["userAccountControl"][0];
|
||||||
|
int updatedAccountControl = (accountControl | 2);
|
||||||
|
if (accountControl != updatedAccountControl)
|
||||||
|
{
|
||||||
|
deAccount.Properties["userAccountControl"][0] = updatedAccountControl;
|
||||||
|
deAccount.CommitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void DisableAccount(this ActiveDirectoryMachineAccount account)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
account.DisableAccount(domainController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void EnableAccount(this ActiveDirectoryMachineAccount account, DomainController DomainController)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
using (DirectoryEntry deAccount = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
int accountControl = (int)deAccount.Properties["userAccountControl"][0];
|
||||||
|
if ((accountControl & 2) == 2)
|
||||||
|
{
|
||||||
|
int updatedAccountControl = (accountControl ^ 2);
|
||||||
|
deAccount.Properties["userAccountControl"][0] = updatedAccountControl;
|
||||||
|
deAccount.CommitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void EnableAccount(this ActiveDirectoryMachineAccount account)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
account.EnableAccount(domainController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool UpdateNetbootGUID(this ActiveDirectoryMachineAccount account, DomainController DomainController, string UUID, string MACAddress)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
Guid netbootGUID = Guid.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(UUID))
|
||||||
|
{
|
||||||
|
netbootGUID = ActiveDirectoryExtensions.NetbootGUIDFromUUID(UUID);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(MACAddress))
|
||||||
|
{
|
||||||
|
netbootGUID = ActiveDirectoryExtensions.NetbootGUIDFromMACAddress(MACAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netbootGUID != System.Guid.Empty && netbootGUID != account.NetbootGUID)
|
||||||
|
{
|
||||||
|
account.SetNetbootGUID(DomainController, netbootGUID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool UpdateNetbootGUID(this ActiveDirectoryMachineAccount account, string UUID, string MACAddress)
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
using (var domainController = domain.RetrieveWritableDomainController())
|
||||||
|
{
|
||||||
|
return account.UpdateNetbootGUID(domainController, UUID, MACAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static System.Guid NetbootGUIDFromMACAddress(string MACAddress)
|
||||||
|
{
|
||||||
|
string strippedMACAddress = MACAddress.Trim().Replace(":", string.Empty).Replace("-", string.Empty);
|
||||||
|
bool flag = strippedMACAddress.Length == 12;
|
||||||
|
System.Guid NetbootGUIDFromMACAddress;
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
System.Guid guid = new System.Guid(string.Format("00000000-0000-0000-0000-{0}", strippedMACAddress));
|
||||||
|
NetbootGUIDFromMACAddress = guid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NetbootGUIDFromMACAddress = System.Guid.Empty;
|
||||||
|
}
|
||||||
|
return NetbootGUIDFromMACAddress;
|
||||||
|
}
|
||||||
|
public static System.Guid NetbootGUIDFromUUID(string UUID)
|
||||||
|
{
|
||||||
|
System.Guid result = new System.Guid(UUID);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetPropertyValue(this ActiveDirectoryMachineAccount account, string PropertyName, int Index = 0)
|
||||||
|
{
|
||||||
|
switch (PropertyName.ToLower())
|
||||||
|
{
|
||||||
|
case "name":
|
||||||
|
return account.Name;
|
||||||
|
case "samaccountname":
|
||||||
|
return account.SamAccountName;
|
||||||
|
case "distinguishedname":
|
||||||
|
return account.DistinguishedName;
|
||||||
|
case "objectsid":
|
||||||
|
return account.SecurityIdentifier;
|
||||||
|
case "netbootguid":
|
||||||
|
return account.NetbootGUID;
|
||||||
|
default:
|
||||||
|
object[] adProperty;
|
||||||
|
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
||||||
|
return adProperty[Index];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPStatus PingComputer(this ActiveDirectoryMachineAccount account, int Timeout = 2000)
|
||||||
|
{
|
||||||
|
using (var p = new Ping())
|
||||||
|
{
|
||||||
|
PingReply reply = p.Send(account.DnsName, Timeout);
|
||||||
|
return reply.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MoveOrganisationalUnit(this ActiveDirectoryMachineAccount account, DomainController DomainController, string NewOrganisationUnit)
|
||||||
|
{
|
||||||
|
if (account.IsCriticalSystemObject)
|
||||||
|
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
||||||
|
|
||||||
|
var parentDistinguishedName = account.ParentDistinguishedName();
|
||||||
|
|
||||||
|
if (parentDistinguishedName != null && !parentDistinguishedName.Equals(NewOrganisationUnit, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
var domain = account.GetDomain();
|
||||||
|
|
||||||
|
// If no OU provided, place in default Computers container
|
||||||
|
if (string.IsNullOrWhiteSpace(NewOrganisationUnit))
|
||||||
|
NewOrganisationUnit = domain.GetDefaultComputerContainer();
|
||||||
|
|
||||||
|
if (!NewOrganisationUnit.EndsWith(domain.DistinguishedName, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
throw new InvalidOperationException(string.Format("Unable to move AD Account from one domain [{0}] to another [{1}].", account.DistinguishedName, NewOrganisationUnit));
|
||||||
|
|
||||||
|
using (DirectoryEntry ou = DomainController.RetrieveDirectoryEntry(NewOrganisationUnit))
|
||||||
|
{
|
||||||
|
using (DirectoryEntry i = DomainController.RetrieveDirectoryEntry(account.DistinguishedName))
|
||||||
|
{
|
||||||
|
i.UsePropertyCache = false;
|
||||||
|
i.MoveTo(ou);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ParentDistinguishedName(this ActiveDirectoryMachineAccount account)
|
||||||
|
{
|
||||||
|
// Determine Parent
|
||||||
|
if (!string.IsNullOrWhiteSpace(account.DistinguishedName))
|
||||||
|
return account.DistinguishedName.Substring(account.DistinguishedName.IndexOf(",") + 1);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActiveDirectoryDomain GetDomain(this ActiveDirectoryMachineAccount account)
|
||||||
|
{
|
||||||
|
var domain = ActiveDirectory.GetDomainByNetBiosName(account.Domain);
|
||||||
|
|
||||||
|
if (domain == null)
|
||||||
|
throw new InvalidOperationException(string.Format("Unable to find Domain [{0}] for account [{1}]", account.Domain, account.Name));
|
||||||
|
else
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Services.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Services.Interop.ActiveDirectory.Internal
|
||||||
|
{
|
||||||
|
public class ADDiscoverForestServers : ScheduledTask
|
||||||
|
{
|
||||||
|
public override string TaskName { get { return "Active Directory - Discover Forest Servers"; } }
|
||||||
|
public override bool SingleInstanceTask { get { return true; } }
|
||||||
|
public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
|
||||||
|
protected override void ExecuteTask()
|
||||||
|
{
|
||||||
|
var forestServers = DiscoverForestServers();
|
||||||
|
ADInterop._ForestServers = forestServers;
|
||||||
|
|
||||||
|
// Restrict Searching Entire Forest if to many servers
|
||||||
|
using (DiscoDataContext Database = new DiscoDataContext())
|
||||||
|
{
|
||||||
|
var searchEntireForest = Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest;
|
||||||
|
|
||||||
|
// Check explicitly configured: No
|
||||||
|
if (!searchEntireForest.HasValue || searchEntireForest.Value)
|
||||||
|
{
|
||||||
|
// Not Configured, or explicitly configured: Yes
|
||||||
|
if (forestServers.Count > ActiveDirectory.MaxForestServerSearch)
|
||||||
|
{
|
||||||
|
// Update Database
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ScheduledTaskStatus ScheduleNow()
|
||||||
|
{
|
||||||
|
var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(ADDiscoverForestServers)).Where(ts => ts.IsRunning).FirstOrDefault();
|
||||||
|
if (taskStatus != null)
|
||||||
|
return taskStatus;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var t = new ADDiscoverForestServers();
|
||||||
|
return t.ScheduleTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<string> DiscoverForestServers()
|
||||||
|
{
|
||||||
|
using (var computerDomain = Domain.GetComputerDomain())
|
||||||
|
{
|
||||||
|
return computerDomain.Forest.Domains.Cast<Domain>().SelectMany(d => d.FindAllDomainControllers().Cast<DomainController>()).Select(dc => dc.Name).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-13
@@ -1,18 +1,15 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Concurrent;
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Services.Tasks;
|
using Disco.Services.Tasks;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
namespace Disco.Services.Interop.ActiveDirectory.Internal
|
||||||
{
|
{
|
||||||
public class ActiveDirectoryCachedGroups : ScheduledTask
|
public class ADGroupCache : ScheduledTask
|
||||||
{
|
{
|
||||||
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _SecurityIdentifierCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _SecurityIdentifierCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
||||||
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _DistinguishedNameCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _DistinguishedNameCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
||||||
@@ -72,7 +69,7 @@ namespace Disco.BI.Interop.ActiveDirectory
|
|||||||
if (groupRecord == null)
|
if (groupRecord == null)
|
||||||
{
|
{
|
||||||
// Load from AD
|
// Load from AD
|
||||||
var group = ActiveDirectory.GetGroupFromDistinguishedName(DistinguishedName);
|
var group = ActiveDirectory.RetrieveGroupWithDistinguishedName(DistinguishedName);
|
||||||
SetValue(group);
|
SetValue(group);
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
@@ -91,7 +88,7 @@ namespace Disco.BI.Interop.ActiveDirectory
|
|||||||
if (groupRecord == null)
|
if (groupRecord == null)
|
||||||
{
|
{
|
||||||
// Load from AD
|
// Load from AD
|
||||||
var group = ActiveDirectory.GetGroupFromSecurityIdentifier(SecurityIdentifier);
|
var group = ActiveDirectory.RetrieveGroupWithSecurityIdentifier(SecurityIdentifier);
|
||||||
SetValue(group);
|
SetValue(group);
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
@@ -0,0 +1,617 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Services.Interop.ActiveDirectory.Internal
|
||||||
|
{
|
||||||
|
internal static class ADInterop
|
||||||
|
{
|
||||||
|
public static List<ActiveDirectoryDomain> Domains { get; private set; }
|
||||||
|
public static ActiveDirectoryDomain PrimaryDomain { get; private set; }
|
||||||
|
public static ActiveDirectorySite Site { get; private set; }
|
||||||
|
internal static List<string> _ForestServers { get; set; }
|
||||||
|
private static bool _SearchEntireForest { get; set; }
|
||||||
|
private static bool _Initialized = false;
|
||||||
|
private static object _InitializeLock = new object();
|
||||||
|
|
||||||
|
#region Initialization
|
||||||
|
|
||||||
|
public static void Initialize(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
if (!_Initialized)
|
||||||
|
{
|
||||||
|
lock (_InitializeLock)
|
||||||
|
{
|
||||||
|
if (!_Initialized)
|
||||||
|
{
|
||||||
|
_SearchEntireForest = Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest ?? true; // Default True
|
||||||
|
|
||||||
|
using (var computerDomain = Domain.GetComputerDomain())
|
||||||
|
{
|
||||||
|
PrimaryDomain = GetDomainInternal(computerDomain, Database);
|
||||||
|
|
||||||
|
Domains = computerDomain.Forest.Domains.Cast<Domain>().Select(d =>
|
||||||
|
{
|
||||||
|
if (d.Name == PrimaryDomain.DnsName)
|
||||||
|
return PrimaryDomain;
|
||||||
|
else
|
||||||
|
return GetDomainInternal(d, Database);
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Site = ActiveDirectorySite.GetComputerSite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActiveDirectoryDomain GetDomainInternal(Domain d, DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
string ldapPath = string.Format("LDAP://{0}/", d.Name);
|
||||||
|
string defaultNamingContext;
|
||||||
|
string configurationNamingContext;
|
||||||
|
string netBiosName;
|
||||||
|
|
||||||
|
using (var adRootDSE = new DirectoryEntry(ldapPath + "RootDSE"))
|
||||||
|
{
|
||||||
|
defaultNamingContext = adRootDSE.Properties["defaultNamingContext"][0].ToString();
|
||||||
|
configurationNamingContext = adRootDSE.Properties["configurationNamingContext"][0].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var configSearchRoot = new DirectoryEntry(ldapPath + "CN=Partitions," + configurationNamingContext))
|
||||||
|
{
|
||||||
|
var configSearchFilter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", d.Name);
|
||||||
|
var configSearchLoadProperites = new string[] { "NetBIOSName" };
|
||||||
|
|
||||||
|
using (var configSearcher = new DirectorySearcher(configSearchRoot, configSearchFilter, configSearchLoadProperites, System.DirectoryServices.SearchScope.OneLevel))
|
||||||
|
{
|
||||||
|
SearchResult configResult = configSearcher.FindOne();
|
||||||
|
|
||||||
|
if (configResult != null)
|
||||||
|
netBiosName = configResult.Properties["NetBIOSName"][0].ToString();
|
||||||
|
else
|
||||||
|
netBiosName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Containers
|
||||||
|
List<string> searchContainersAll = Database.DiscoConfiguration.ActiveDirectory.SearchContainers;
|
||||||
|
List<string> searchContainers = null;
|
||||||
|
|
||||||
|
if (searchContainersAll != null && searchContainersAll.Count > 0)
|
||||||
|
searchContainers = Database.DiscoConfiguration.ActiveDirectory.SearchContainers.Where(c => c.EndsWith(defaultNamingContext, StringComparison.InvariantCultureIgnoreCase)).ToList();
|
||||||
|
else
|
||||||
|
searchContainers = new List<string>() { defaultNamingContext }; // No search constraints set - search entire tree
|
||||||
|
|
||||||
|
return new ActiveDirectoryDomain(d.Name, netBiosName, defaultNamingContext, searchContainers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateSearchContainers(DiscoDataContext Database, IEnumerable<string> Containers)
|
||||||
|
{
|
||||||
|
if (Containers != null)
|
||||||
|
{
|
||||||
|
var distinctContainers = Containers
|
||||||
|
.Where(c => !string.IsNullOrWhiteSpace(c))
|
||||||
|
.Distinct().ToList();
|
||||||
|
|
||||||
|
Containers = distinctContainers.Where(c => !distinctContainers.Any(s => (c != s) && (c.EndsWith(s))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Containers == null || Containers.Count() == 0)
|
||||||
|
{
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchContainers = null;
|
||||||
|
|
||||||
|
// No search constraints set - search entire tree
|
||||||
|
Domains.ForEach(d => d.UpdateSearchContainers(new string[] { d.DistinguishedName }));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchContainers = Containers.ToList();
|
||||||
|
|
||||||
|
Domains.ForEach(d => { d.UpdateSearchContainers(Containers.Where(c => c.EndsWith(d.DistinguishedName, StringComparison.InvariantCultureIgnoreCase))); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool UpdateSearchEntireForest(DiscoDataContext Database, bool SearchEntireForest)
|
||||||
|
{
|
||||||
|
if (SearchEntireForest == false)
|
||||||
|
{
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest = false;
|
||||||
|
ADInterop._SearchEntireForest = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var forestServers = LoadForestServers();
|
||||||
|
if (forestServers.Count <= ActiveDirectory.MaxForestServerSearch)
|
||||||
|
{
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest = true;
|
||||||
|
ADInterop._SearchEntireForest = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Database.DiscoConfiguration.ActiveDirectory.SearchEntireForest = false;
|
||||||
|
ADInterop._SearchEntireForest = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Domain Getters
|
||||||
|
|
||||||
|
public static bool TryGetDomainByDistinguishedName(string DistinguishedName, out ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
// Find closest match
|
||||||
|
Domain = ADInterop.Domains.Where(d => DistinguishedName.EndsWith(d.DistinguishedName, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
.OrderByDescending(d => d.DistinguishedName.Length).FirstOrDefault();
|
||||||
|
|
||||||
|
return (Domain != null);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryDomain GetDomainByDistinguishedName(string DistinguishedName)
|
||||||
|
{
|
||||||
|
ActiveDirectoryDomain domain;
|
||||||
|
if (!TryGetDomainByDistinguishedName(DistinguishedName, out domain))
|
||||||
|
throw new ArgumentException(string.Format("The domain is unknown distinguished name: [{0}]", DistinguishedName), "Id");
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetDomainByNetBiosName(string NetBiosName, out ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
Domain = ADInterop.Domains.FirstOrDefault(d => d.NetBiosName.Equals(NetBiosName, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
return (Domain != null);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryDomain GetDomainByNetBiosName(string NetBiosName)
|
||||||
|
{
|
||||||
|
ActiveDirectoryDomain domain;
|
||||||
|
if (!TryGetDomainByNetBiosName(NetBiosName, out domain))
|
||||||
|
throw new ArgumentException(string.Format("The specified domain is unknown [{0}]", NetBiosName), "Id");
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetDomainByDnsName(string DnsName, out ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
Domain = ADInterop.Domains.FirstOrDefault(d => d.DnsName.Equals(DnsName, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
return (Domain != null);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryDomain GetDomainByDnsName(string DnsName)
|
||||||
|
{
|
||||||
|
ActiveDirectoryDomain domain;
|
||||||
|
if (!TryGetDomainByDnsName(DnsName, out domain))
|
||||||
|
throw new ArgumentException(string.Format("The specified domain is unknown [{0}]", DnsName), "Id");
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetDomainFromId(string Id, out ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Id))
|
||||||
|
throw new ArgumentNullException("Id");
|
||||||
|
|
||||||
|
var idSplit = UserExtensions.SplitUserId(Id);
|
||||||
|
|
||||||
|
if (idSplit.Item1 == null)
|
||||||
|
throw new ArgumentException(string.Format("The Id must include the Domain [{0}]", Id), "Id");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(idSplit.Item1))
|
||||||
|
throw new ArgumentException(string.Format("The Id Domain was empty [{0}]", Id), "Id");
|
||||||
|
if (string.IsNullOrWhiteSpace(idSplit.Item2))
|
||||||
|
throw new ArgumentException(string.Format("The Id Name was empty [{0}]", Id), "Id");
|
||||||
|
|
||||||
|
return TryGetDomainByNetBiosName(idSplit.Item1, out Domain);
|
||||||
|
}
|
||||||
|
public static ActiveDirectoryDomain GetDomainFromId(string Id)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Id))
|
||||||
|
throw new ArgumentNullException("Id");
|
||||||
|
|
||||||
|
var idSplit = UserExtensions.SplitUserId(Id);
|
||||||
|
|
||||||
|
if (idSplit.Item1 == null)
|
||||||
|
throw new ArgumentException(string.Format("The Id must include the Domain [{0}]", Id), "Id");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(idSplit.Item1))
|
||||||
|
throw new ArgumentException(string.Format("The Id Domain was empty [{0}]", Id), "Id");
|
||||||
|
if (string.IsNullOrWhiteSpace(idSplit.Item2))
|
||||||
|
throw new ArgumentException(string.Format("The Id Name was empty [{0}]", Id), "Id");
|
||||||
|
|
||||||
|
return GetDomainByNetBiosName(idSplit.Item1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> LoadForestServers()
|
||||||
|
{
|
||||||
|
if (_ForestServers == null)
|
||||||
|
{
|
||||||
|
lock (_InitializeLock)
|
||||||
|
{
|
||||||
|
if (_ForestServers == null)
|
||||||
|
{
|
||||||
|
var status = ADDiscoverForestServers.ScheduleNow();
|
||||||
|
status.CompletionTask.Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _ForestServers;
|
||||||
|
}
|
||||||
|
public static Task<List<string>> LoadForestServersAsync()
|
||||||
|
{
|
||||||
|
if (_ForestServers != null)
|
||||||
|
return Task.FromResult(_ForestServers);
|
||||||
|
|
||||||
|
lock (_InitializeLock)
|
||||||
|
{
|
||||||
|
if (_ForestServers != null)
|
||||||
|
return Task.FromResult(_ForestServers);
|
||||||
|
|
||||||
|
// Invoke Scheduled Task
|
||||||
|
var status = ADDiscoverForestServers.ScheduleNow();
|
||||||
|
|
||||||
|
return status.CompletionTask.ContinueWith(t =>
|
||||||
|
{
|
||||||
|
return ADInterop._ForestServers.ToList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool SearchEntireForest
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_ForestServers != null && _ForestServers.Count > ActiveDirectory.MaxForestServerSearch)
|
||||||
|
return false; // Never
|
||||||
|
|
||||||
|
return _SearchEntireForest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Searching
|
||||||
|
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domains, LdapFilter, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(string LdapFilter, int ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domains, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(DomainsWithController, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domains, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domain, DomainController, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domain, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var query = DomainsWithController
|
||||||
|
.SelectMany(d => SearchAll(d.Item1, d.Item2, LdapFilter, ResultLimit, LoadProperties));
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
query = query.Take(ResultLimit.Value);
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var query = Domains
|
||||||
|
.SelectMany(domain => SearchAll(domain, LdapFilter, ResultLimit, LoadProperties));
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
query = query.Take(ResultLimit.Value);
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchDomain(Domain, DomainController, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchDomain(Domain, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domains, LdapFilter, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(string LdapFilter, int ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domains, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domains, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(DomainsWithController, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domain, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domain, DomainController, LdapFilter, null, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var query = DomainsWithController
|
||||||
|
.SelectMany(d => SearchScope(d.Item1, d.Item2, LdapFilter, ResultLimit, LoadProperties));
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
query = query.Take(ResultLimit.Value);
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var query = Domains
|
||||||
|
.SelectMany(domain => SearchScope(domain, LdapFilter, ResultLimit, LoadProperties));
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
query = query.Take(ResultLimit.Value);
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchScope(Domain, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
if (Domain.SearchContainers == null)
|
||||||
|
return Enumerable.Empty<ActiveDirectorySearchResult>();
|
||||||
|
|
||||||
|
var query = Domain.SearchContainers
|
||||||
|
.SelectMany(container => SearchDomain(Domain, DomainController, container, LdapFilter, ResultLimit, LoadProperties));
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
query = query.Take(ResultLimit.Value);
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchDomain(ActiveDirectoryDomain Domain, string SearchRoot, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchDomain(Domain, null, SearchRoot, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchDomain(ActiveDirectoryDomain Domain, DomainController DomainController, string SearchRoot, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
string ldapServer = DomainController == null ? Domain.DnsName : DomainController.Name;
|
||||||
|
string searchRoot = SearchRoot ?? Domain.DistinguishedName;
|
||||||
|
string ldapPath = string.Format(@"LDAP://{0}/{1}", ldapServer, searchRoot);
|
||||||
|
|
||||||
|
using (DirectoryEntry rootEntry = new DirectoryEntry(ldapPath))
|
||||||
|
{
|
||||||
|
using (DirectorySearcher searcher = new DirectorySearcher(rootEntry, LdapFilter, LoadProperties, System.DirectoryServices.SearchScope.Subtree))
|
||||||
|
{
|
||||||
|
searcher.PageSize = 500;
|
||||||
|
|
||||||
|
if (ResultLimit.HasValue)
|
||||||
|
searcher.SizeLimit = ResultLimit.Value;
|
||||||
|
return searcher.FindAll().Cast<SearchResult>().Select(result => new ActiveDirectorySearchResult()
|
||||||
|
{
|
||||||
|
Domain = Domain,
|
||||||
|
SearchRoot = searchRoot,
|
||||||
|
Result = result,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static string OfflineDomainJoinProvision(ActiveDirectoryDomain Domain, DomainController DomainController, string ComputerSamAccountName, string OrganisationalUnit, out string DiagnosticInformation)
|
||||||
|
{
|
||||||
|
StringBuilder diagnosticInfo = new StringBuilder();
|
||||||
|
string DJoinResult = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(ComputerSamAccountName))
|
||||||
|
ComputerSamAccountName = ComputerSamAccountName.TrimEnd('$');
|
||||||
|
if (string.IsNullOrWhiteSpace(ComputerSamAccountName) || ComputerSamAccountName.Length > 24)
|
||||||
|
throw new System.ArgumentException("Invalid Computer Name; > 0 and <= 24", "ComputerName");
|
||||||
|
|
||||||
|
// Ensure Specified OU Exists
|
||||||
|
if (!string.IsNullOrEmpty(OrganisationalUnit))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var deOU = DomainController.RetrieveDirectoryEntry(OrganisationalUnit))
|
||||||
|
{
|
||||||
|
if (deOU == null)
|
||||||
|
throw new Exception(string.Format("OU's Directory Entry couldn't be found at [{0}]", OrganisationalUnit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("An error occurred while trying to locate the specified OU: {0}", OrganisationalUnit), "OrganisationalUnit", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string tempFileName = System.IO.Path.GetTempFileName();
|
||||||
|
string argumentOU = (!string.IsNullOrWhiteSpace(OrganisationalUnit)) ? string.Format(" /MACHINEOU \"{0}\"", OrganisationalUnit) : string.Empty;
|
||||||
|
string arguments = string.Format("/PROVISION /DOMAIN \"{0}\" /DCNAME \"{1}\" /MACHINE \"{2}\"{3} /REUSE /SAVEFILE \"{4}\"",
|
||||||
|
Domain.DnsName,
|
||||||
|
DomainController.Name,
|
||||||
|
ComputerSamAccountName,
|
||||||
|
argumentOU,
|
||||||
|
tempFileName
|
||||||
|
);
|
||||||
|
ProcessStartInfo commandStarter = new ProcessStartInfo("DJOIN.EXE", arguments)
|
||||||
|
{
|
||||||
|
CreateNoWindow = true,
|
||||||
|
ErrorDialog = false,
|
||||||
|
LoadUserProfile = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
diagnosticInfo.AppendFormat("{0} {1}", "DJOIN.EXE", arguments);
|
||||||
|
diagnosticInfo.AppendLine();
|
||||||
|
|
||||||
|
string stdOutput;
|
||||||
|
string stdError;
|
||||||
|
using (Process commandProc = Process.Start(commandStarter))
|
||||||
|
{
|
||||||
|
commandProc.WaitForExit(20000);
|
||||||
|
stdOutput = commandProc.StandardOutput.ReadToEnd();
|
||||||
|
stdError = commandProc.StandardError.ReadToEnd();
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(stdOutput))
|
||||||
|
diagnosticInfo.AppendLine(stdOutput);
|
||||||
|
if (!string.IsNullOrWhiteSpace(stdError))
|
||||||
|
diagnosticInfo.AppendLine(stdError);
|
||||||
|
|
||||||
|
if (System.IO.File.Exists(tempFileName))
|
||||||
|
{
|
||||||
|
DJoinResult = System.Convert.ToBase64String(System.IO.File.ReadAllBytes(tempFileName));
|
||||||
|
System.IO.File.Delete(tempFileName);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(DJoinResult))
|
||||||
|
throw new System.InvalidOperationException(string.Format("Domain Join Unsuccessful{0}Error: {1}{0}Output: {2}", System.Environment.NewLine, stdError, stdOutput));
|
||||||
|
|
||||||
|
DiagnosticInformation = diagnosticInfo.ToString();
|
||||||
|
|
||||||
|
return DJoinResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectoryEntry RetrieveDirectoryEntry(string DistinguishedName, out ActiveDirectoryDomain Domain)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(DistinguishedName))
|
||||||
|
throw new ArgumentNullException("DistinguishedName");
|
||||||
|
|
||||||
|
// Find Domain
|
||||||
|
var domain = GetDomainByDistinguishedName(DistinguishedName);
|
||||||
|
|
||||||
|
Domain = domain;
|
||||||
|
|
||||||
|
return new DirectoryEntry(string.Format(@"LDAP://{0}/{1}", domain.DnsName, DistinguishedName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DomainController RetrieveWritableDomainController(this ActiveDirectoryDomain domain)
|
||||||
|
{
|
||||||
|
var adContext = new DirectoryContext(DirectoryContextType.Domain, domain.DnsName);
|
||||||
|
using (var adDomain = Domain.GetDomain(adContext))
|
||||||
|
{
|
||||||
|
return adDomain.FindDomainController(LocatorOptions.WriteableRequired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectoryEntry RetrieveDirectoryEntry(this DomainController domainController, string DistinguishedName)
|
||||||
|
{
|
||||||
|
return new DirectoryEntry(string.Format(@"LDAP://{0}/{1}", domainController.Name, DistinguishedName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteObjectRecursive(this DirectoryEntry directoryEntry)
|
||||||
|
{
|
||||||
|
DeleteObjectRecursiveInternal(directoryEntry);
|
||||||
|
|
||||||
|
using (var deParent = directoryEntry.Parent)
|
||||||
|
{
|
||||||
|
deParent.Children.Remove(directoryEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void DeleteObjectRecursiveInternal(DirectoryEntry directoryEntry)
|
||||||
|
{
|
||||||
|
List<DirectoryEntry> children = directoryEntry.Children.Cast<DirectoryEntry>().ToList();
|
||||||
|
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
DeleteObjectRecursive(child);
|
||||||
|
directoryEntry.Children.Remove(child);
|
||||||
|
child.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
internal static string ConvertBytesToSDDLString(byte[] SID)
|
||||||
|
{
|
||||||
|
SecurityIdentifier sID = new SecurityIdentifier(SID, 0);
|
||||||
|
|
||||||
|
return sID.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] ConvertSDDLStringToBytes(string SidSsdlString)
|
||||||
|
{
|
||||||
|
SecurityIdentifier sID = new SecurityIdentifier(SidSsdlString);
|
||||||
|
|
||||||
|
var sidBytes = new byte[sID.BinaryLength];
|
||||||
|
|
||||||
|
sID.GetBinaryForm(sidBytes, 0);
|
||||||
|
|
||||||
|
return sidBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] BuildPrimaryGroupSid(byte[] UserSID, int PrimaryGroupId)
|
||||||
|
{
|
||||||
|
var groupSid = (byte[])UserSID.Clone();
|
||||||
|
|
||||||
|
int ridOffset = groupSid.Length - 4;
|
||||||
|
int groupId = PrimaryGroupId;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
groupSid[ridOffset + i] = (byte)(groupId & 0xFF);
|
||||||
|
groupId >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupSid;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ConvertBytesToBinarySidString(byte[] SID)
|
||||||
|
{
|
||||||
|
StringBuilder escapedSid = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (var sidByte in SID)
|
||||||
|
{
|
||||||
|
escapedSid.Append('\\');
|
||||||
|
escapedSid.Append(sidByte.ToString("x2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return escapedSid.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string EscapeLdapQuery(string query)
|
||||||
|
{
|
||||||
|
return query.Replace("*", "\\2a").Replace("(", "\\28").Replace(")", "\\29").Replace("\\", "\\5c").Replace("NUL", "\\00").Replace("/", "\\2f");
|
||||||
|
}
|
||||||
|
internal static string FormatGuidForLdapQuery(System.Guid g)
|
||||||
|
{
|
||||||
|
checked
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
byte[] array = g.ToByteArray();
|
||||||
|
for (int i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
byte b = array[i];
|
||||||
|
sb.Append("\\");
|
||||||
|
sb.Append(b.ToString("X2"));
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Logging;
|
||||||
|
using Disco.Services.Tasks;
|
||||||
|
using Quartz;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Disco.Services.Interop.ActiveDirectory.Internal
|
||||||
|
{
|
||||||
|
public class ADUpdateLastNetworkLogonDateJob : ScheduledTask
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string TaskName { get { return "Active Directory - Update Last Network Logon Dates Task"; } }
|
||||||
|
public override bool SingleInstanceTask { get { return true; } }
|
||||||
|
public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
|
||||||
|
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
|
||||||
|
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
|
||||||
|
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 30));
|
||||||
|
|
||||||
|
this.ScheduleTask(triggerBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteTask()
|
||||||
|
{
|
||||||
|
int changeCount;
|
||||||
|
|
||||||
|
this.Status.UpdateStatus(1, "Starting", "Connecting to the Database and initializing the environment");
|
||||||
|
using (DiscoDataContext database = new DiscoDataContext())
|
||||||
|
{
|
||||||
|
UpdateLastNetworkLogonDates(database, this.Status);
|
||||||
|
this.Status.UpdateStatus(95, "Updating Database", "Writing last network logon dates to the Database");
|
||||||
|
changeCount = database.SaveChanges();
|
||||||
|
this.Status.Finished(string.Format("{0} Device last network logon dates updated", changeCount), "/Config/SystemConfig");
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLog.LogInformation(new string[]
|
||||||
|
{
|
||||||
|
"Updated LastNetworkLogon Device Property for Device/s",
|
||||||
|
changeCount.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScheduledTaskStatus ScheduleImmediately()
|
||||||
|
{
|
||||||
|
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ADUpdateLastNetworkLogonDateJob)).Where(s => s.IsRunning).FirstOrDefault();
|
||||||
|
if (existingTask != null)
|
||||||
|
return existingTask;
|
||||||
|
|
||||||
|
var instance = new ADUpdateLastNetworkLogonDateJob();
|
||||||
|
return instance.ScheduleTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool UpdateLastNetworkLogonDate(Device Device)
|
||||||
|
{
|
||||||
|
const string ldapFilterTemplate = "(&(objectCategory=Computer)(sAMAccountName={0}))";
|
||||||
|
string[] ldapProperties = new string[] { "lastLogon", "lastLogonTimestamp" };
|
||||||
|
|
||||||
|
System.DateTime? lastLogon = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Device.DeviceDomainId))
|
||||||
|
{
|
||||||
|
var deviceSamAccountName = UserExtensions.SplitUserId(Device.DeviceDomainId).Item2 + "$";
|
||||||
|
var ldapFilter = string.Format(ldapFilterTemplate, ADInterop.EscapeLdapQuery(deviceSamAccountName));
|
||||||
|
|
||||||
|
var domain = ADInterop.GetDomainFromId(Device.DeviceDomainId);
|
||||||
|
IEnumerable<DomainController> domainControllers;
|
||||||
|
|
||||||
|
if (ADInterop.SearchEntireForest)
|
||||||
|
domainControllers = domain.RetrieveReachableDomainControllers();
|
||||||
|
else
|
||||||
|
domainControllers = ADInterop.Site.RetrieveReachableDomainControllers(domain);
|
||||||
|
|
||||||
|
lastLogon = domainControllers.Select(dc =>
|
||||||
|
{
|
||||||
|
using (var directoryRoot = dc.RetrieveDirectoryEntry(domain.DistinguishedName))
|
||||||
|
{
|
||||||
|
using (var directorySearcher = new DirectorySearcher(directoryRoot, ldapFilter, ldapProperties, SearchScope.Subtree))
|
||||||
|
{
|
||||||
|
var directoryResult = directorySearcher.FindOne();
|
||||||
|
|
||||||
|
if (directoryResult != null)
|
||||||
|
{
|
||||||
|
long lastLogonValue = default(long);
|
||||||
|
long lastLogonTimestampValue = default(long);
|
||||||
|
|
||||||
|
var lastLogonProperty = directoryResult.Properties["lastLogon"];
|
||||||
|
if (lastLogonProperty != null && lastLogonProperty.Count > 0)
|
||||||
|
lastLogonValue = (long)lastLogonProperty[0];
|
||||||
|
var lastLogonTimestampProperty = directoryResult.Properties["lastLogonTimestamp"];
|
||||||
|
if (lastLogonTimestampProperty != null && lastLogonTimestampProperty.Count > 0)
|
||||||
|
lastLogonTimestampValue = (long)lastLogonTimestampProperty[0];
|
||||||
|
|
||||||
|
long highedValue = Math.Max(lastLogonValue, lastLogonTimestampValue);
|
||||||
|
|
||||||
|
if (highedValue > 0)
|
||||||
|
return (DateTime?)new DateTime((DateTime.FromFileTime(highedValue).Ticks / 10000000L) * 10000000L);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}).Where(dt => dt.HasValue).Max();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLogon.HasValue &&
|
||||||
|
(
|
||||||
|
!Device.LastNetworkLogonDate.HasValue
|
||||||
|
|| Device.LastNetworkLogonDate.Value < lastLogon
|
||||||
|
))
|
||||||
|
{
|
||||||
|
Device.LastNetworkLogonDate = lastLogon;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateLastNetworkLogonDates(DiscoDataContext Database, ScheduledTaskStatus status)
|
||||||
|
{
|
||||||
|
const string ldapFilter = "(objectCategory=Computer)";
|
||||||
|
string[] ldapProperties = new string[] { "sAMAccountName", "lastLogon" };
|
||||||
|
|
||||||
|
status.UpdateStatus(2, "Initializing", "Determining Domains and Available Domain Controllers");
|
||||||
|
|
||||||
|
// Determine Domain Controllers to Query
|
||||||
|
IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> domainControllers;
|
||||||
|
if (ADInterop.SearchEntireForest)
|
||||||
|
domainControllers = ADInterop.Domains.SelectMany(d => d.RetrieveReachableDomainControllers(), (d, dc) => Tuple.Create(d, dc));
|
||||||
|
else
|
||||||
|
domainControllers = ADInterop.Domains.SelectMany(d => ADInterop.Site.RetrieveReachableDomainControllers(d), (d, dc) => Tuple.Create(d, dc));
|
||||||
|
|
||||||
|
// Determine Queries
|
||||||
|
var requiredRueries = domainControllers
|
||||||
|
.Where(s => s.Item1.SearchContainers != null && s.Item1.SearchContainers.Count > 0)
|
||||||
|
.SelectMany(s => s.Item1.SearchContainers, (s, c) => Tuple.Create(s.Item1, s.Item2, c)).ToList();
|
||||||
|
|
||||||
|
var queries = Enumerable.Range(0, requiredRueries.Count).Select(i =>
|
||||||
|
{
|
||||||
|
var q = requiredRueries[i];
|
||||||
|
return Tuple.Create(i, q.Item1, q.Item2, q.Item3);
|
||||||
|
});
|
||||||
|
|
||||||
|
var queryResults = queries.SelectMany(q =>
|
||||||
|
{
|
||||||
|
var queryIndex = q.Item1;
|
||||||
|
var domain = q.Item2;
|
||||||
|
var domainController = q.Item3;
|
||||||
|
var searchRoot = q.Item4;
|
||||||
|
|
||||||
|
// Update Status
|
||||||
|
double progress = 5 + (queryIndex * (90 / requiredRueries.Count));
|
||||||
|
status.UpdateStatus(progress, string.Format("Querying Domain [{0}] using controller [{1}]", domain.NetBiosName, domainController.Name), string.Format("Searching: {0}", searchRoot));
|
||||||
|
|
||||||
|
// Perform Query
|
||||||
|
using (var directoryRoot = domainController.RetrieveDirectoryEntry(searchRoot))
|
||||||
|
{
|
||||||
|
using (var directorySearcher = new DirectorySearcher(directoryRoot, ldapFilter, ldapProperties, SearchScope.Subtree))
|
||||||
|
{
|
||||||
|
directorySearcher.PageSize = 500;
|
||||||
|
|
||||||
|
var directoryResults = directorySearcher.FindAll();
|
||||||
|
|
||||||
|
if (directoryResults != null)
|
||||||
|
{
|
||||||
|
return directoryResults.Cast<SearchResult>().Select(result =>
|
||||||
|
{
|
||||||
|
var samAccountProperity = result.Properties["sAMAccountName"];
|
||||||
|
|
||||||
|
|
||||||
|
long lastLogonValue = default(long);
|
||||||
|
long lastLogonTimestampValue = default(long);
|
||||||
|
|
||||||
|
var lastLogonProperty = result.Properties["lastLogon"];
|
||||||
|
if (lastLogonProperty != null && lastLogonProperty.Count > 0)
|
||||||
|
lastLogonValue = (long)lastLogonProperty[0];
|
||||||
|
var lastLogonTimestampProperty = result.Properties["lastLogonTimestamp"];
|
||||||
|
if (lastLogonTimestampProperty != null && lastLogonTimestampProperty.Count > 0)
|
||||||
|
lastLogonTimestampValue = (long)lastLogonTimestampProperty[0];
|
||||||
|
|
||||||
|
long highedValue = Math.Max(lastLogonValue, lastLogonTimestampValue);
|
||||||
|
|
||||||
|
if (highedValue > 0)
|
||||||
|
{
|
||||||
|
var computerName = string.Format(@"{0}\{1}", domain.NetBiosName, samAccountProperity[0].ToString().TrimEnd('$'));
|
||||||
|
var lastLogon = new DateTime((DateTime.FromFileTime(highedValue).Ticks / 10000000L) * 10000000L);
|
||||||
|
return Tuple.Create(computerName, lastLogon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}).Where(i => i != null).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<Tuple<string, DateTime>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).GroupBy(r => r.Item1, StringComparer.InvariantCultureIgnoreCase).ToDictionary(g => g.Key.ToUpper(), g => g.Max(i => i.Item2));
|
||||||
|
|
||||||
|
status.UpdateStatus(90, "Processing Results", "Processing last network logon dates and looking for updates");
|
||||||
|
|
||||||
|
foreach (Device device in Database.Devices.Where(device => device.DeviceDomainId != null))
|
||||||
|
{
|
||||||
|
DateTime lastLogonDate;
|
||||||
|
if (queryResults.TryGetValue(device.DeviceDomainId.ToUpper(), out lastLogonDate))
|
||||||
|
{
|
||||||
|
if (!device.LastNetworkLogonDate.HasValue)
|
||||||
|
device.LastNetworkLogonDate = lastLogonDate;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Change accuracy to the second
|
||||||
|
lastLogonDate = new DateTime((lastLogonDate.Ticks / 10000000L) * 10000000L);
|
||||||
|
|
||||||
|
if (device.LastNetworkLogonDate.Value < lastLogonDate)
|
||||||
|
device.LastNetworkLogonDate = lastLogonDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Models.Services.Jobs.JobLists;
|
using Disco.Models.Services.Jobs.JobLists;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -61,10 +62,13 @@ namespace Disco.Services
|
|||||||
{
|
{
|
||||||
i.UserId = j.UserId;
|
i.UserId = j.UserId;
|
||||||
i.UserDisplayName = j.User.DisplayName;
|
i.UserDisplayName = j.User.DisplayName;
|
||||||
|
|
||||||
|
i.UserFriendlyId = UserExtensions.FriendlyUserId(j.UserId);
|
||||||
}
|
}
|
||||||
if (j.OpenedTechUser != null)
|
if (j.OpenedTechUser != null)
|
||||||
{
|
{
|
||||||
i.OpenedTechUserId = j.OpenedTechUserId;
|
i.OpenedTechUserId = j.OpenedTechUserId;
|
||||||
|
i.OpenedTechUserFriendlyId = UserExtensions.FriendlyUserId(j.OpenedTechUserId);
|
||||||
i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName;
|
i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,8 +232,13 @@ namespace Disco.Services
|
|||||||
model.ShowDeviceAddress = Database.DiscoConfiguration.MultiSiteMode;
|
model.ShowDeviceAddress = Database.DiscoConfiguration.MultiSiteMode;
|
||||||
|
|
||||||
foreach (var j in items)
|
foreach (var j in items)
|
||||||
|
{
|
||||||
|
j.UserFriendlyId =j.UserId == null ? null : UserExtensions.FriendlyUserId(j.UserId);
|
||||||
|
j.OpenedTechUserFriendlyId = UserExtensions.FriendlyUserId(j.OpenedTechUserId);
|
||||||
|
|
||||||
if (j.DeviceAddressId.HasValue)
|
if (j.DeviceAddressId.HasValue)
|
||||||
j.DeviceAddress = Database.DiscoConfiguration.OrganisationAddresses.GetAddress(j.DeviceAddressId.Value).Name;
|
j.DeviceAddress = Database.DiscoConfiguration.OrganisationAddresses.GetAddress(j.DeviceAddressId.Value).Name;
|
||||||
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace Disco.Services.Jobs.JobQueues
|
|||||||
|
|
||||||
public static ReadOnlyCollection<JobQueueToken> UsersQueues(User User)
|
public static ReadOnlyCollection<JobQueueToken> UsersQueues(User User)
|
||||||
{
|
{
|
||||||
return UsersQueues(User.Id);
|
return UsersQueues(User.UserId);
|
||||||
}
|
}
|
||||||
public static ReadOnlyCollection<JobQueueToken> UsersQueues(string UserId)
|
public static ReadOnlyCollection<JobQueueToken> UsersQueues(string UserId)
|
||||||
{
|
{
|
||||||
@@ -141,7 +141,7 @@ namespace Disco.Services.Jobs.JobQueues
|
|||||||
}
|
}
|
||||||
public static ReadOnlyCollection<JobQueueToken> UsersQueues(AuthorizationToken UserAuthorization)
|
public static ReadOnlyCollection<JobQueueToken> UsersQueues(AuthorizationToken UserAuthorization)
|
||||||
{
|
{
|
||||||
string cacheKey = string.Format(_cacheHttpRequestKey, UserAuthorization.User.Id);
|
string cacheKey = string.Format(_cacheHttpRequestKey, UserAuthorization.User.UserId);
|
||||||
ReadOnlyCollection<JobQueueToken> tokens = null;
|
ReadOnlyCollection<JobQueueToken> tokens = null;
|
||||||
|
|
||||||
// Check for ASP.NET
|
// Check for ASP.NET
|
||||||
@@ -152,7 +152,7 @@ namespace Disco.Services.Jobs.JobQueues
|
|||||||
|
|
||||||
if (tokens == null)
|
if (tokens == null)
|
||||||
{
|
{
|
||||||
var subjectIds = (new string[] { UserAuthorization.User.Id }).Concat(UserAuthorization.GroupMembership);
|
var subjectIds = (new string[] { UserAuthorization.User.UserId }).Concat(UserAuthorization.GroupMembership);
|
||||||
tokens = _cache.GetQueuesForSubject(subjectIds);
|
tokens = _cache.GetQueuesForSubject(subjectIds);
|
||||||
|
|
||||||
HttpContext.Current.Items[_cacheHttpRequestKey] = tokens;
|
HttpContext.Current.Items[_cacheHttpRequestKey] = tokens;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Disco.Services.Plugins
|
|||||||
var resource = string.Format("{0} [{1}]", attributeDenied.AuthorizeResource, HostController.Request.RawUrl);
|
var resource = string.Format("{0} [{1}]", attributeDenied.AuthorizeResource, HostController.Request.RawUrl);
|
||||||
|
|
||||||
if (CurrentUser != null)
|
if (CurrentUser != null)
|
||||||
AuthorizationLog.LogAccessDenied(CurrentUser.Id, resource, message);
|
AuthorizationLog.LogAccessDenied(CurrentUser.UserId, resource, message);
|
||||||
|
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Disco.Models.Interop.ActiveDirectory;
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Models.Services.Jobs.JobLists;
|
using Disco.Models.Services.Jobs.JobLists;
|
||||||
using Disco.Models.Services.Searching;
|
using Disco.Models.Services.Searching;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -29,7 +30,7 @@ namespace Disco.Services.Searching
|
|||||||
j.Id == termInt ||
|
j.Id == termInt ||
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.DisplayName.Contains(Term));
|
j.User.DisplayName.Contains(Term));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -37,7 +38,7 @@ namespace Disco.Services.Searching
|
|||||||
query = Database.Jobs.Where(j =>
|
query = Database.Jobs.Where(j =>
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.DisplayName.Contains(Term));
|
j.User.DisplayName.Contains(Term));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ namespace Disco.Services.Searching
|
|||||||
j.DeviceHeldLocation.Contains(Term) ||
|
j.DeviceHeldLocation.Contains(Term) ||
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.Surname.Contains(Term) ||
|
j.User.Surname.Contains(Term) ||
|
||||||
j.User.GivenName.Contains(Term) ||
|
j.User.GivenName.Contains(Term) ||
|
||||||
j.User.DisplayName.Contains(Term) ||
|
j.User.DisplayName.Contains(Term) ||
|
||||||
@@ -89,7 +90,7 @@ namespace Disco.Services.Searching
|
|||||||
j.DeviceHeldLocation.Contains(Term) ||
|
j.DeviceHeldLocation.Contains(Term) ||
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.Surname.Contains(Term) ||
|
j.User.Surname.Contains(Term) ||
|
||||||
j.User.GivenName.Contains(Term) ||
|
j.User.GivenName.Contains(Term) ||
|
||||||
j.User.DisplayName.Contains(Term));
|
j.User.DisplayName.Contains(Term));
|
||||||
@@ -103,7 +104,7 @@ namespace Disco.Services.Searching
|
|||||||
j.DeviceHeldLocation.Contains(Term) ||
|
j.DeviceHeldLocation.Contains(Term) ||
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.Surname.Contains(Term) ||
|
j.User.Surname.Contains(Term) ||
|
||||||
j.User.GivenName.Contains(Term) ||
|
j.User.GivenName.Contains(Term) ||
|
||||||
j.User.DisplayName.Contains(Term) ||
|
j.User.DisplayName.Contains(Term) ||
|
||||||
@@ -116,7 +117,7 @@ namespace Disco.Services.Searching
|
|||||||
j.DeviceHeldLocation.Contains(Term) ||
|
j.DeviceHeldLocation.Contains(Term) ||
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
j.Device.SerialNumber.Contains(Term) ||
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
j.Device.AssetNumber.Contains(Term) ||
|
||||||
j.User.Id == Term ||
|
j.User.UserId == Term ||
|
||||||
j.User.Surname.Contains(Term) ||
|
j.User.Surname.Contains(Term) ||
|
||||||
j.User.GivenName.Contains(Term) ||
|
j.User.GivenName.Contains(Term) ||
|
||||||
j.User.DisplayName.Contains(Term));
|
j.User.DisplayName.Contains(Term));
|
||||||
@@ -148,7 +149,7 @@ namespace Disco.Services.Searching
|
|||||||
UserService.SearchUsers(Database, Term);
|
UserService.SearchUsers(Database, Term);
|
||||||
|
|
||||||
var matches = Database.Users.Where(u =>
|
var matches = Database.Users.Where(u =>
|
||||||
u.Id.Contains(Term) ||
|
u.UserId.Contains(Term) ||
|
||||||
u.Surname.Contains(Term) ||
|
u.Surname.Contains(Term) ||
|
||||||
u.GivenName.Contains(Term) ||
|
u.GivenName.Contains(Term) ||
|
||||||
u.DisplayName.Contains(Term)
|
u.DisplayName.Contains(Term)
|
||||||
@@ -159,7 +160,7 @@ namespace Disco.Services.Searching
|
|||||||
|
|
||||||
return matches.Select(u => new UserSearchResultItem()
|
return matches.Select(u => new UserSearchResultItem()
|
||||||
{
|
{
|
||||||
Id = u.Id,
|
Id = u.UserId,
|
||||||
Surname = u.Surname,
|
Surname = u.Surname,
|
||||||
GivenName = u.GivenName,
|
GivenName = u.GivenName,
|
||||||
DisplayName = u.DisplayName,
|
DisplayName = u.DisplayName,
|
||||||
@@ -170,7 +171,7 @@ namespace Disco.Services.Searching
|
|||||||
|
|
||||||
public static List<User> SearchUsersUpstream(string Term, int? LimitCount = null)
|
public static List<User> SearchUsersUpstream(string Term, int? LimitCount = null)
|
||||||
{
|
{
|
||||||
IEnumerable<ActiveDirectoryUserAccount> matches = UserService.SearchUsers(Term);
|
IEnumerable<ActiveDirectoryUserAccount> matches = ActiveDirectory.SearchUserAccounts(Term);
|
||||||
|
|
||||||
if (LimitCount.HasValue)
|
if (LimitCount.HasValue)
|
||||||
matches = matches.Take(LimitCount.Value);
|
matches = matches.Take(LimitCount.Value);
|
||||||
@@ -190,7 +191,7 @@ namespace Disco.Services.Searching
|
|||||||
{
|
{
|
||||||
query = Database.Devices.Where(d =>
|
query = Database.Devices.Where(d =>
|
||||||
d.AssetNumber.Contains(Term) ||
|
d.AssetNumber.Contains(Term) ||
|
||||||
d.ComputerName.Contains(Term) ||
|
d.DeviceDomainId.Contains(Term) ||
|
||||||
d.SerialNumber.Contains(Term) ||
|
d.SerialNumber.Contains(Term) ||
|
||||||
d.Location.Contains(Term) ||
|
d.Location.Contains(Term) ||
|
||||||
Term.Contains(d.SerialNumber) ||
|
Term.Contains(d.SerialNumber) ||
|
||||||
@@ -201,7 +202,7 @@ namespace Disco.Services.Searching
|
|||||||
{
|
{
|
||||||
query = Database.Devices.Where(d =>
|
query = Database.Devices.Where(d =>
|
||||||
d.AssetNumber.Contains(Term) ||
|
d.AssetNumber.Contains(Term) ||
|
||||||
d.ComputerName.Contains(Term) ||
|
d.DeviceDomainId.Contains(Term) ||
|
||||||
d.SerialNumber.Contains(Term) ||
|
d.SerialNumber.Contains(Term) ||
|
||||||
d.Location.Contains(Term) ||
|
d.Location.Contains(Term) ||
|
||||||
Term.Contains(d.SerialNumber));
|
Term.Contains(d.SerialNumber));
|
||||||
@@ -232,7 +233,7 @@ namespace Disco.Services.Searching
|
|||||||
{
|
{
|
||||||
Id = d.SerialNumber,
|
Id = d.SerialNumber,
|
||||||
AssetNumber = d.AssetNumber,
|
AssetNumber = d.AssetNumber,
|
||||||
ComputerName = d.ComputerName,
|
ComputerName = d.DeviceDomainId,
|
||||||
DeviceModelDescription = d.DeviceModel.Description,
|
DeviceModelDescription = d.DeviceModel.Description,
|
||||||
DeviceProfileDescription = d.DeviceProfile.Description,
|
DeviceProfileDescription = d.DeviceProfile.Description,
|
||||||
DecommissionedDate = d.DecommissionedDate,
|
DecommissionedDate = d.DecommissionedDate,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using Quartz;
|
using Quartz;
|
||||||
using System.Web.Script.Serialization;
|
using System.Web.Script.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Disco.Services.Tasks
|
namespace Disco.Services.Tasks
|
||||||
{
|
{
|
||||||
@@ -16,7 +17,7 @@ namespace Disco.Services.Tasks
|
|||||||
private string _triggerKey;
|
private string _triggerKey;
|
||||||
private string _taskName;
|
private string _taskName;
|
||||||
private Type _taskType;
|
private Type _taskType;
|
||||||
private EventWaitHandle _waitHandle;
|
private TaskCompletionSource<ScheduledTaskStatus> _tcs;
|
||||||
private bool _isSilent;
|
private bool _isSilent;
|
||||||
|
|
||||||
private byte _progress;
|
private byte _progress;
|
||||||
@@ -72,6 +73,14 @@ namespace Disco.Services.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task CompletionTask
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _tcs.Task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
@@ -87,7 +96,7 @@ namespace Disco.Services.Tasks
|
|||||||
{
|
{
|
||||||
this._taskName = Task.TaskName;
|
this._taskName = Task.TaskName;
|
||||||
this._taskType = Task.GetType();
|
this._taskType = Task.GetType();
|
||||||
this._waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
|
this._tcs = new TaskCompletionSource<ScheduledTaskStatus>();
|
||||||
|
|
||||||
this._sessionId = SessionId;
|
this._sessionId = SessionId;
|
||||||
this._triggerKey = TriggerKey;
|
this._triggerKey = TriggerKey;
|
||||||
@@ -294,11 +303,13 @@ namespace Disco.Services.Tasks
|
|||||||
}
|
}
|
||||||
internal void Finally()
|
internal void Finally()
|
||||||
{
|
{
|
||||||
this._waitHandle.Set();
|
this._tcs.SetResult(this);
|
||||||
}
|
}
|
||||||
public void Reset(DateTime? NextScheduledTimestamp)
|
public void Reset(DateTime? NextScheduledTimestamp)
|
||||||
{
|
{
|
||||||
this._waitHandle.Reset();
|
if (this._tcs != null)
|
||||||
|
this._tcs.Task.Dispose();
|
||||||
|
this._tcs = new TaskCompletionSource<ScheduledTaskStatus>();
|
||||||
|
|
||||||
List<string> changedProperties = new List<string>();
|
List<string> changedProperties = new List<string>();
|
||||||
|
|
||||||
@@ -352,7 +363,7 @@ namespace Disco.Services.Tasks
|
|||||||
}
|
}
|
||||||
public bool WaitUntilFinished(TimeSpan Timeout)
|
public bool WaitUntilFinished(TimeSpan Timeout)
|
||||||
{
|
{
|
||||||
return this._waitHandle.WaitOne(Timeout);
|
return this._tcs.Task.Wait(Timeout);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Services.Users
|
|
||||||
{
|
|
||||||
public static class Searching
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Disco.Services
|
||||||
|
{
|
||||||
|
public static class UserExtensions
|
||||||
|
{
|
||||||
|
public static bool IsInPrimaryDomain(this User u)
|
||||||
|
{
|
||||||
|
return u.Domain.Equals(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.PrimaryDomain.NetBiosName, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FriendlyId(this User u)
|
||||||
|
{
|
||||||
|
return FriendlyUserId(u.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FriendlyUserId(string UserId)
|
||||||
|
{
|
||||||
|
var splitUserId = SplitUserId(UserId);
|
||||||
|
|
||||||
|
if (splitUserId.Item1 != null && splitUserId.Item1.Equals(ActiveDirectory.PrimaryDomain.NetBiosName, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return splitUserId.Item2;
|
||||||
|
else
|
||||||
|
return UserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tuple<string, string> SplitUserId(string UserId)
|
||||||
|
{
|
||||||
|
var slashIndex = UserId.IndexOf('\\');
|
||||||
|
if (slashIndex < 0)
|
||||||
|
return Tuple.Create<string, string>(null, UserId);
|
||||||
|
else
|
||||||
|
return Tuple.Create(UserId.Substring(0, slashIndex), UserId.Substring(slashIndex + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Disco.Models.Interop.ActiveDirectory;
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Authorization.Roles;
|
using Disco.Services.Authorization.Roles;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Logging;
|
using Disco.Services.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
@@ -20,19 +21,9 @@ namespace Disco.Services.Users
|
|||||||
public static class UserService
|
public static class UserService
|
||||||
{
|
{
|
||||||
private const string _cacheHttpRequestKey = "Disco_CurrentUserToken";
|
private const string _cacheHttpRequestKey = "Disco_CurrentUserToken";
|
||||||
private static Func<string, string[], ActiveDirectoryUserAccount> _GetActiveDirectoryUserAccount;
|
|
||||||
private static Func<string, string[], ActiveDirectoryMachineAccount> _GetActiveDirectoryMachineAccount;
|
|
||||||
private static Func<string, List<ActiveDirectoryUserAccount>> _SearchActiveDirectoryUsers;
|
|
||||||
|
|
||||||
public static void Initialize(DiscoDataContext Database,
|
public static void Initialize(DiscoDataContext Database)
|
||||||
Func<string, string[], ActiveDirectoryUserAccount> GetActiveDirectoryUserAccount,
|
|
||||||
Func<string, string[], ActiveDirectoryMachineAccount> GetActiveDirectoryMachineAccount,
|
|
||||||
Func<string, List<ActiveDirectoryUserAccount>> SearchActiveDirectoryUsers)
|
|
||||||
{
|
{
|
||||||
_GetActiveDirectoryUserAccount = GetActiveDirectoryUserAccount;
|
|
||||||
_GetActiveDirectoryMachineAccount = GetActiveDirectoryMachineAccount;
|
|
||||||
_SearchActiveDirectoryUsers = SearchActiveDirectoryUsers;
|
|
||||||
|
|
||||||
Authorization.Roles.RoleCache.Initialize(Database);
|
Authorization.Roles.RoleCache.Initialize(Database);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,10 +47,7 @@ namespace Disco.Services.Users
|
|||||||
userId = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
|
userId = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId.Contains("\\"))
|
return userId;
|
||||||
return userId.Substring(checked(userId.IndexOf("\\") + 1));
|
|
||||||
else
|
|
||||||
return userId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,38 +192,31 @@ namespace Disco.Services.Users
|
|||||||
Cache.FlushCache();
|
Cache.FlushCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<ActiveDirectoryUserAccount> SearchUsers(string Term)
|
internal static IEnumerable<ActiveDirectoryUserAccount> SearchUsers(DiscoDataContext Database, string Term)
|
||||||
{
|
{
|
||||||
return _SearchActiveDirectoryUsers(Term);
|
var adImportedUsers = ActiveDirectory.SearchUserAccounts(Term);
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<ActiveDirectoryUserAccount> SearchUsers(DiscoDataContext Database, string Term)
|
|
||||||
{
|
|
||||||
var adImportedUsers = SearchUsers(Term);
|
|
||||||
foreach (var adU in adImportedUsers.Select(adU => adU.ToRepositoryUser()))
|
foreach (var adU in adImportedUsers.Select(adU => adU.ToRepositoryUser()))
|
||||||
{
|
{
|
||||||
var existingUser = Database.Users.Find(adU.Id);
|
var existingUser = Database.Users.Find(adU.UserId);
|
||||||
if (existingUser != null)
|
if (existingUser != null)
|
||||||
existingUser.UpdateSelf(adU);
|
existingUser.UpdateSelf(adU);
|
||||||
else
|
else
|
||||||
Database.Users.Add(adU);
|
Database.Users.Add(adU);
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
UserService.InvalidateCachedUser(adU.Id);
|
UserService.InvalidateCachedUser(adU.UserId);
|
||||||
}
|
}
|
||||||
return adImportedUsers;
|
return adImportedUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Tuple<User, AuthorizationToken> ImportUser(DiscoDataContext Database, string UserId)
|
internal static Tuple<User, AuthorizationToken> ImportUser(DiscoDataContext Database, string UserId)
|
||||||
{
|
{
|
||||||
if (_GetActiveDirectoryUserAccount == null)
|
|
||||||
throw new InvalidOperationException("UserServer has not been Initialized");
|
|
||||||
if (string.IsNullOrEmpty(UserId))
|
if (string.IsNullOrEmpty(UserId))
|
||||||
throw new ArgumentNullException("UserId is required", "UserId");
|
throw new ArgumentNullException("UserId is required", "UserId");
|
||||||
|
|
||||||
if (UserId.EndsWith("$"))
|
if (UserId.EndsWith("$"))
|
||||||
{
|
{
|
||||||
// Machine Account
|
// Machine Account
|
||||||
var adAccount = _GetActiveDirectoryMachineAccount(UserId, null);
|
var adAccount = ActiveDirectory.RetrieveMachineAccount(UserId);
|
||||||
|
|
||||||
if (adAccount == null)
|
if (adAccount == null)
|
||||||
return null;
|
return null;
|
||||||
@@ -252,7 +233,7 @@ namespace Disco.Services.Users
|
|||||||
ActiveDirectoryUserAccount adAccount;
|
ActiveDirectoryUserAccount adAccount;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
adAccount = _GetActiveDirectoryUserAccount(UserId, null);
|
adAccount = ActiveDirectory.RetrieveUserAccount(UserId);
|
||||||
|
|
||||||
if (adAccount == null)
|
if (adAccount == null)
|
||||||
throw new ArgumentException(string.Format("Invalid Username: '{0}'; User not found in Active Directory", UserId), "Username");
|
throw new ArgumentException(string.Format("Invalid Username: '{0}'; User not found in Active Directory", UserId), "Username");
|
||||||
@@ -275,7 +256,7 @@ namespace Disco.Services.Users
|
|||||||
var user = adAccount.ToRepositoryUser();
|
var user = adAccount.ToRepositoryUser();
|
||||||
|
|
||||||
// Update Repository
|
// Update Repository
|
||||||
User existingUser = Database.Users.Find(user.Id);
|
User existingUser = Database.Users.Find(user.UserId);
|
||||||
if (existingUser == null)
|
if (existingUser == null)
|
||||||
Database.Users.Add(user);
|
Database.Users.Add(user);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
@using Disco;
|
@using Disco;
|
||||||
@using Disco.BI.Extensions;
|
@using Disco.BI.Extensions;
|
||||||
@using Disco.Models.Repository;
|
@using Disco.Models.Repository;
|
||||||
|
@using Disco.Services;
|
||||||
|
@using Disco.Services.Web;
|
||||||
@using Disco.Web;
|
@using Disco.Web;
|
||||||
@using System.Web.Mvc
|
@using System.Web.Mvc
|
||||||
@using System.Web.Mvc.Html;
|
@using System.Web.Mvc.Html;
|
||||||
@using Disco.Services.Web;
|
|
||||||
|
|
||||||
|
|
||||||
@helper FriendlyDate(DateTime d, string ElementId = null, bool WithoutSuffix = false)
|
@helper FriendlyDate(DateTime d, string ElementId = null, bool WithoutSuffix = false)
|
||||||
{<span @(ElementId == null ? null : new HtmlString(string.Format("id=\"{0}\" ", ElementId)))title="@d.ToFullDateTime()" data-livestamp="@d.ToUnixEpoc()" data-isodate="@d.ToISO8601()" class="date nowrap@(WithoutSuffix ? " noMomentSuffix" : null)">@d.ToFullDateTime()</span>}
|
{<span @(ElementId == null ? null : new HtmlString(string.Format("id=\"{0}\" ", ElementId)))title="@d.ToFullDateTime()" data-livestamp="@d.ToUnixEpoc()" data-isodate="@d.ToISO8601()" class="date nowrap@(WithoutSuffix ? " noMomentSuffix" : null)">@d.ToFullDateTime()</span>}
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
{
|
{
|
||||||
if (u != null)
|
if (u != null)
|
||||||
{
|
{
|
||||||
@prepend <span title="@u">@u.Id</span>
|
@prepend <span title="@u">@u.FriendlyId()</span>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -20,13 +20,13 @@ namespace Disco.Web
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Helpers;
|
using System.Web.Helpers;
|
||||||
|
|
||||||
#line 6 "..\..\App_Code\CommonHelpers.cshtml"
|
#line 8 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 7 "..\..\App_Code\CommonHelpers.cshtml"
|
#line 9 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
using System.Web.Mvc.Html;
|
using System.Web.Mvc.Html;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
@@ -54,13 +54,19 @@ namespace Disco.Web
|
|||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 8 "..\..\App_Code\CommonHelpers.cshtml"
|
#line 5 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
|
using Disco.Services;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
#line 6 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 5 "..\..\App_Code\CommonHelpers.cshtml"
|
#line 7 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
@@ -509,7 +515,7 @@ WriteLiteralTo(@__razor_helper_writer, "\">");
|
|||||||
|
|
||||||
|
|
||||||
#line 37 "..\..\App_Code\CommonHelpers.cshtml"
|
#line 37 "..\..\App_Code\CommonHelpers.cshtml"
|
||||||
WriteTo(@__razor_helper_writer, u.Id);
|
WriteTo(@__razor_helper_writer, u.FriendlyId());
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Disco.Data.Repository;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Disco.Web
|
namespace Disco.Web
|
||||||
{
|
{
|
||||||
@@ -32,6 +29,9 @@ namespace Disco.Web
|
|||||||
// Initialize Logging
|
// Initialize Logging
|
||||||
Disco.Services.Logging.LogContext.Initalize(Database, DiscoApplication.SchedulerFactory);
|
Disco.Services.Logging.LogContext.Initalize(Database, DiscoApplication.SchedulerFactory);
|
||||||
|
|
||||||
|
// Initialize Active Directory Interop
|
||||||
|
Disco.Services.Interop.ActiveDirectory.ActiveDirectory.Initialize(Database);
|
||||||
|
|
||||||
// Load Organisation Name
|
// Load Organisation Name
|
||||||
DiscoApplication.OrganisationName = Database.DiscoConfiguration.OrganisationName;
|
DiscoApplication.OrganisationName = Database.DiscoConfiguration.OrganisationName;
|
||||||
DiscoApplication.MultiSiteMode = Database.DiscoConfiguration.MultiSiteMode;
|
DiscoApplication.MultiSiteMode = Database.DiscoConfiguration.MultiSiteMode;
|
||||||
@@ -43,11 +43,7 @@ namespace Disco.Web
|
|||||||
Database.DiscoConfiguration.ProxyPassword);
|
Database.DiscoConfiguration.ProxyPassword);
|
||||||
|
|
||||||
// Initialize User Service Interop
|
// Initialize User Service Interop
|
||||||
Disco.Services.Users.UserService.Initialize(Database,
|
Disco.Services.Users.UserService.Initialize(Database);
|
||||||
(UserId, AdditionalProperties) => Disco.BI.Interop.ActiveDirectory.ActiveDirectory.GetUserAccount(UserId, AdditionalProperties),
|
|
||||||
(UserId, AdditionalProperties) => Disco.BI.Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(UserId, null, null, AdditionalProperties),
|
|
||||||
(Term) => Disco.BI.Interop.ActiveDirectory.ActiveDirectory.SearchUsers(Term));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InitalizeNormalEnvironment(DiscoDataContext Database)
|
public static void InitalizeNormalEnvironment(DiscoDataContext Database)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Authorization.Roles;
|
using Disco.Services.Authorization.Roles;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using System;
|
using System;
|
||||||
@@ -75,7 +75,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var oldRoleName = AuthorizationRole.Name;
|
var oldRoleName = AuthorizationRole.Name;
|
||||||
AuthorizationRole.Name = Name;
|
AuthorizationRole.Name = Name;
|
||||||
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
||||||
AuthorizationLog.LogRoleConfiguredRenamed(AuthorizationRole, CurrentUser.Id, oldRoleName);
|
AuthorizationLog.LogRoleConfiguredRenamed(AuthorizationRole, CurrentUser.UserId, oldRoleName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,9 +93,9 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
||||||
|
|
||||||
if (removedClaims.Length > 0)
|
if (removedClaims.Length > 0)
|
||||||
AuthorizationLog.LogRoleConfiguredClaimsRemoved(AuthorizationRole, CurrentUser.Id, removedClaims);
|
AuthorizationLog.LogRoleConfiguredClaimsRemoved(AuthorizationRole, CurrentUser.UserId, removedClaims);
|
||||||
if (addedClaims.Length > 0)
|
if (addedClaims.Length > 0)
|
||||||
AuthorizationLog.LogRoleConfiguredClaimsAdded(AuthorizationRole, CurrentUser.Id, addedClaims);
|
AuthorizationLog.LogRoleConfiguredClaimsAdded(AuthorizationRole, CurrentUser.UserId, addedClaims);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSubjects(AuthorizationRole AuthorizationRole, string[] Subjects)
|
private void UpdateSubjects(AuthorizationRole AuthorizationRole, string[] Subjects)
|
||||||
@@ -107,7 +107,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
// Validate Subjects
|
// Validate Subjects
|
||||||
if (Subjects != null && Subjects.Length > 0)
|
if (Subjects != null && Subjects.Length > 0)
|
||||||
{
|
{
|
||||||
var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple<string, IActiveDirectoryObject>(s, ActiveDirectory.GetObject(s))).ToList();
|
var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple<string, IActiveDirectoryObject>(s, ActiveDirectory.RetrieveObject(s))).ToList();
|
||||||
var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList();
|
var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList();
|
||||||
|
|
||||||
if (invalidSubjects.Count > 0)
|
if (invalidSubjects.Count > 0)
|
||||||
@@ -130,9 +130,9 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
||||||
|
|
||||||
if (removedSubjects != null && removedSubjects.Length > 0)
|
if (removedSubjects != null && removedSubjects.Length > 0)
|
||||||
AuthorizationLog.LogRoleConfiguredSubjectsRemoved(AuthorizationRole, CurrentUser.Id, removedSubjects);
|
AuthorizationLog.LogRoleConfiguredSubjectsRemoved(AuthorizationRole, CurrentUser.UserId, removedSubjects);
|
||||||
if (addedSubjects != null && addedSubjects.Length > 0)
|
if (addedSubjects != null && addedSubjects.Length > 0)
|
||||||
AuthorizationLog.LogRoleConfiguredSubjectsAdded(AuthorizationRole, CurrentUser.Id, addedSubjects);
|
AuthorizationLog.LogRoleConfiguredSubjectsAdded(AuthorizationRole, CurrentUser.UserId, addedSubjects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,8 +234,8 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
|
|
||||||
public virtual ActionResult SearchSubjects(string term)
|
public virtual ActionResult SearchSubjects(string term)
|
||||||
{
|
{
|
||||||
var groupResults = BI.Interop.ActiveDirectory.ActiveDirectory.SearchGroups(term).Cast<IActiveDirectoryObject>();
|
var groupResults = ActiveDirectory.SearchGroups(term).Cast<IActiveDirectoryObject>();
|
||||||
var userResults = BI.Interop.ActiveDirectory.ActiveDirectory.SearchUsers(term).Cast<IActiveDirectoryObject>();
|
var userResults = ActiveDirectory.SearchUserAccounts(term).Cast<IActiveDirectoryObject>();
|
||||||
|
|
||||||
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName)
|
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName)
|
||||||
.Select(r => Models.AuthorizationRole.SubjectItem.FromActiveDirectoryObject(r)).ToList();
|
.Select(r => Models.AuthorizationRole.SubjectItem.FromActiveDirectoryObject(r)).ToList();
|
||||||
@@ -245,7 +245,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
|
|
||||||
public virtual ActionResult Subject(string Id)
|
public virtual ActionResult Subject(string Id)
|
||||||
{
|
{
|
||||||
var subject = ActiveDirectory.GetObject(Id);
|
var subject = ActiveDirectory.RetrieveObject(Id);
|
||||||
|
|
||||||
if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup))
|
if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup))
|
||||||
return Json(null, JsonRequestBehavior.AllowGet);
|
return Json(null, JsonRequestBehavior.AllowGet);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using System;
|
using System;
|
||||||
@@ -148,9 +148,9 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
device.DeviceProfile = p;
|
device.DeviceProfile = p;
|
||||||
|
|
||||||
// Update AD Account
|
// Update AD Account
|
||||||
if (!string.IsNullOrEmpty(device.ComputerName) && device.ComputerName.Length <= 24)
|
if (!string.IsNullOrEmpty(device.DeviceDomainId) && device.DeviceDomainId.Length <= 24)
|
||||||
{
|
{
|
||||||
var adMachineAccount = ActiveDirectory.GetMachineAccount(device.ComputerName);
|
var adMachineAccount = ActiveDirectory.RetrieveMachineAccount(device.DeviceDomainId);
|
||||||
if (adMachineAccount != null)
|
if (adMachineAccount != null)
|
||||||
adMachineAccount.SetDescription(device);
|
adMachineAccount.SetDescription(device);
|
||||||
}
|
}
|
||||||
@@ -501,7 +501,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var da = Database.DeviceAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
var da = Database.DeviceAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
||||||
if (da != null)
|
if (da != null)
|
||||||
{
|
{
|
||||||
if (da.TechUserId.Equals(CurrentUser.Id, StringComparison.InvariantCultureIgnoreCase))
|
if (da.TechUserId.Equals(CurrentUser.UserId, StringComparison.InvariantCultureIgnoreCase))
|
||||||
Authorization.RequireAny(Claims.Device.Actions.RemoveAnyAttachments, Claims.Device.Actions.RemoveOwnAttachments);
|
Authorization.RequireAny(Claims.Device.Actions.RemoveAnyAttachments, Claims.Device.Actions.RemoveOwnAttachments);
|
||||||
else
|
else
|
||||||
Authorization.Require(Claims.Device.Actions.RemoveAnyAttachments);
|
Authorization.Require(Claims.Device.Actions.RemoveAnyAttachments);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -90,7 +91,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Device Profile Number");
|
throw new Exception("Invalid Device Profile Number");
|
||||||
}
|
}
|
||||||
if (redirect.HasValue && redirect.Value)
|
if (redirect.HasValue && redirect.Value)
|
||||||
return RedirectToAction(MVC.Config.DeviceModel.Index(deviceProfile.Id));
|
return RedirectToAction(MVC.Config.DeviceProfile.Index(deviceProfile.Id));
|
||||||
else
|
else
|
||||||
return Json("OK", JsonRequestBehavior.AllowGet);
|
return Json("OK", JsonRequestBehavior.AllowGet);
|
||||||
}
|
}
|
||||||
@@ -245,11 +246,13 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
private void UpdateOrganisationalUnit(Disco.Models.Repository.DeviceProfile deviceProfile, string OrganisationalUnit)
|
private void UpdateOrganisationalUnit(Disco.Models.Repository.DeviceProfile deviceProfile, string OrganisationalUnit)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(OrganisationalUnit))
|
if (string.IsNullOrWhiteSpace(OrganisationalUnit))
|
||||||
OrganisationalUnit = null;
|
OrganisationalUnit = ActiveDirectory.PrimaryDomain.GetDefaultComputerContainer();
|
||||||
|
|
||||||
deviceProfile.OrganisationalUnit = OrganisationalUnit;
|
if (OrganisationalUnit != deviceProfile.OrganisationalUnit)
|
||||||
|
{
|
||||||
Database.SaveChanges();
|
deviceProfile.OrganisationalUnit = OrganisationalUnit;
|
||||||
|
Database.SaveChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateComputerNameTemplate(Disco.Models.Repository.DeviceProfile deviceProfile, string ComputerNameTemplate)
|
private void UpdateComputerNameTemplate(Disco.Models.Repository.DeviceProfile deviceProfile, string ComputerNameTemplate)
|
||||||
@@ -364,13 +367,6 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[DiscoAuthorize(Claims.Config.DeviceProfile.Configure)]
|
|
||||||
public virtual ActionResult OrganisationalUnits()
|
|
||||||
{
|
|
||||||
var OUs = BI.Interop.ActiveDirectory.ActiveDirectory.GetOrganisationalUnitStructure();
|
|
||||||
return Json(OUs, JsonRequestBehavior.AllowGet);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Actions
|
#region Actions
|
||||||
|
|
||||||
[DiscoAuthorize(Claims.Config.DeviceProfile.Delete)]
|
[DiscoAuthorize(Claims.Config.DeviceProfile.Delete)]
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.AccountingChargeRequiredUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.AccountingChargeRequiredUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -697,7 +697,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.AccountingChargeAddedUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.AccountingChargeAddedUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -731,7 +731,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.AccountingChargePaidUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.AccountingChargePaidUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -765,7 +765,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.PurchaseOrderRaisedUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.PurchaseOrderRaisedUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -808,7 +808,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.PurchaseOrderSentUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.PurchaseOrderSentUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -842,7 +842,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
throw new Exception("Invalid Date Format");
|
throw new Exception("Invalid Date Format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaNonWarranty.InvoiceReceivedUserId = CurrentUser.Id;
|
job.JobMetaNonWarranty.InvoiceReceivedUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -991,7 +991,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.JobMetaInsurance.ClaimFormSentUserId = CurrentUser.Id;
|
job.JobMetaInsurance.ClaimFormSentUserId = CurrentUser.UserId;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return new Models.Job._DateChangeModel()
|
return new Models.Job._DateChangeModel()
|
||||||
{
|
{
|
||||||
@@ -1508,7 +1508,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = job.Id,
|
JobId = job.Id,
|
||||||
TechUserId = CurrentUser.Id,
|
TechUserId = CurrentUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Added Flag: {0}{1}Reason: {2}", flagStatus.Item1, Environment.NewLine, Reason)
|
Comments = string.Format("Added Flag: {0}{1}Reason: {2}", flagStatus.Item1, Environment.NewLine, Reason)
|
||||||
};
|
};
|
||||||
@@ -1857,7 +1857,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var jl = new Disco.Models.Repository.JobLog()
|
var jl = new Disco.Models.Repository.JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = CurrentUser.Id,
|
TechUserId = CurrentUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = comment
|
Comments = comment
|
||||||
};
|
};
|
||||||
@@ -1876,7 +1876,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var jl = Database.JobLogs.Find(id);
|
var jl = Database.JobLogs.Find(id);
|
||||||
if (jl != null)
|
if (jl != null)
|
||||||
{
|
{
|
||||||
if (jl.TechUserId.Equals(CurrentUser.Id, StringComparison.InvariantCultureIgnoreCase))
|
if (jl.TechUserId.Equals(CurrentUser.UserId, StringComparison.InvariantCultureIgnoreCase))
|
||||||
Authorization.RequireAny(Claims.Job.Actions.RemoveAnyLogs, Claims.Job.Actions.RemoveOwnLogs);
|
Authorization.RequireAny(Claims.Job.Actions.RemoveAnyLogs, Claims.Job.Actions.RemoveOwnLogs);
|
||||||
else
|
else
|
||||||
Authorization.Require(Claims.Job.Actions.RemoveAnyLogs);
|
Authorization.Require(Claims.Job.Actions.RemoveAnyLogs);
|
||||||
@@ -1950,7 +1950,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var ja = new Disco.Models.Repository.JobAttachment()
|
var ja = new Disco.Models.Repository.JobAttachment()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = CurrentUser.Id,
|
TechUserId = CurrentUser.UserId,
|
||||||
Filename = file.FileName,
|
Filename = file.FileName,
|
||||||
MimeType = contentType,
|
MimeType = contentType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -2012,7 +2012,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var ja = Database.JobAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
var ja = Database.JobAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
||||||
if (ja != null)
|
if (ja != null)
|
||||||
{
|
{
|
||||||
if (ja.TechUserId.Equals(CurrentUser.Id, StringComparison.InvariantCultureIgnoreCase))
|
if (ja.TechUserId.Equals(CurrentUser.UserId, StringComparison.InvariantCultureIgnoreCase))
|
||||||
Authorization.RequireAny(Claims.Job.Actions.RemoveAnyAttachments, Claims.Job.Actions.RemoveOwnAttachments);
|
Authorization.RequireAny(Claims.Job.Actions.RemoveAnyAttachments, Claims.Job.Actions.RemoveOwnAttachments);
|
||||||
else
|
else
|
||||||
Authorization.Require(Claims.Job.Actions.RemoveAnyAttachments);
|
Authorization.Require(Claims.Job.Actions.RemoveAnyAttachments);
|
||||||
@@ -2046,7 +2046,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
Cost = cost,
|
Cost = cost,
|
||||||
TechUserId = CurrentUser.Id
|
TechUserId = CurrentUser.UserId
|
||||||
};
|
};
|
||||||
Database.JobComponents.Add(jc);
|
Database.JobComponents.Add(jc);
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Disco.BI.Interop.ActiveDirectory;
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Jobs.JobQueues;
|
using Disco.Services.Jobs.JobQueues;
|
||||||
@@ -9,6 +8,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
|
||||||
namespace Disco.Web.Areas.API.Controllers
|
namespace Disco.Web.Areas.API.Controllers
|
||||||
{
|
{
|
||||||
@@ -288,7 +288,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
// Validate Subjects
|
// Validate Subjects
|
||||||
if (Subjects != null && Subjects.Length > 0)
|
if (Subjects != null && Subjects.Length > 0)
|
||||||
{
|
{
|
||||||
var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple<string, IActiveDirectoryObject>(s, ActiveDirectory.GetObject(s))).ToList();
|
var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple<string, IActiveDirectoryObject>(s, ActiveDirectory.RetrieveObject(s))).ToList();
|
||||||
var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList();
|
var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList();
|
||||||
|
|
||||||
if (invalidSubjects.Count > 0)
|
if (invalidSubjects.Count > 0)
|
||||||
@@ -370,8 +370,8 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
[DiscoAuthorize(Claims.Config.JobQueue.Configure)]
|
[DiscoAuthorize(Claims.Config.JobQueue.Configure)]
|
||||||
public virtual ActionResult SearchSubjects(string term)
|
public virtual ActionResult SearchSubjects(string term)
|
||||||
{
|
{
|
||||||
var groupResults = BI.Interop.ActiveDirectory.ActiveDirectory.SearchGroups(term).Cast<IActiveDirectoryObject>();
|
var groupResults = ActiveDirectory.SearchGroups(term).Cast<IActiveDirectoryObject>();
|
||||||
var userResults = BI.Interop.ActiveDirectory.ActiveDirectory.SearchUsers(term).Cast<IActiveDirectoryObject>();
|
var userResults = ActiveDirectory.SearchUserAccounts(term).Cast<IActiveDirectoryObject>();
|
||||||
|
|
||||||
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName)
|
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName)
|
||||||
.Select(r => Models.JobQueue.SubjectItem.FromActiveDirectoryObject(r)).ToList();
|
.Select(r => Models.JobQueue.SubjectItem.FromActiveDirectoryObject(r)).ToList();
|
||||||
@@ -382,7 +382,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
[DiscoAuthorize(Claims.Config.JobQueue.Configure)]
|
[DiscoAuthorize(Claims.Config.JobQueue.Configure)]
|
||||||
public virtual ActionResult Subject(string Id)
|
public virtual ActionResult Subject(string Id)
|
||||||
{
|
{
|
||||||
var subject = ActiveDirectory.GetObject(Id);
|
var subject = ActiveDirectory.RetrieveObject(Id);
|
||||||
|
|
||||||
if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup))
|
if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup))
|
||||||
return Json(null, JsonRequestBehavior.AllowGet);
|
return Json(null, JsonRequestBehavior.AllowGet);
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
using Disco.Data.Configuration;
|
||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -17,7 +20,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
[DiscoAuthorize(Claims.Config.System.Show)]
|
[DiscoAuthorize(Claims.Config.System.Show)]
|
||||||
public virtual ActionResult UpdateLastNetworkLogonDates()
|
public virtual ActionResult UpdateLastNetworkLogonDates()
|
||||||
{
|
{
|
||||||
var taskStatus = ActiveDirectoryUpdateLastNetworkLogonDateJob.ScheduleImmediately();
|
var taskStatus = Disco.Services.Interop.ActiveDirectory.Internal.ADUpdateLastNetworkLogonDateJob.ScheduleImmediately();
|
||||||
|
|
||||||
return RedirectToAction(MVC.Config.Logging.TaskStatus(taskStatus.SessionId));
|
return RedirectToAction(MVC.Config.Logging.TaskStatus(taskStatus.SessionId));
|
||||||
}
|
}
|
||||||
@@ -219,5 +222,97 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Active Directory
|
||||||
|
|
||||||
|
[DiscoAuthorize(Claims.Config.System.ConfigureActiveDirectory)]
|
||||||
|
public virtual ActionResult UpdateActiveDirectorySearchScope(List<string> Containers, bool redirect = false)
|
||||||
|
{
|
||||||
|
ActiveDirectory.UpdateSearchContainers(Database, Containers);
|
||||||
|
Database.SaveChanges();
|
||||||
|
|
||||||
|
if (redirect)
|
||||||
|
return RedirectToAction(MVC.Config.SystemConfig.Index());
|
||||||
|
else
|
||||||
|
return Json("OK", JsonRequestBehavior.AllowGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DiscoAuthorize(Claims.Config.System.ConfigureActiveDirectory)]
|
||||||
|
public virtual ActionResult UpdateActiveDirectorySearchEntireForest(bool SearchEntireForest, bool redirect = false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = ActiveDirectory.UpdateSearchEntireForest(Database, SearchEntireForest);
|
||||||
|
|
||||||
|
Database.SaveChanges();
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
var forestServers = ActiveDirectory.LoadForestServers();
|
||||||
|
if (forestServers.Count > ActiveDirectory.MaxForestServerSearch)
|
||||||
|
throw new InvalidOperationException(string.Format("This forest contains more than the Max Forest Server Search restriction ({0})", ActiveDirectory.MaxForestServerSearch));
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException("Unable to change the 'SearchEntireForest' property for an unknown reason, please report this bug");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirect)
|
||||||
|
return RedirectToAction(MVC.Config.SystemConfig.Index());
|
||||||
|
else
|
||||||
|
return Json("OK", JsonRequestBehavior.AllowGet);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (redirect)
|
||||||
|
throw;
|
||||||
|
else
|
||||||
|
return Json(string.Format("Error: {0}", ex.Message), JsonRequestBehavior.AllowGet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DiscoAuthorizeAny(Claims.Config.System.ConfigureActiveDirectory, Claims.Config.DeviceProfile.Configure)]
|
||||||
|
public virtual ActionResult DomainOrganisationalUnits()
|
||||||
|
{
|
||||||
|
var domainOUs = ActiveDirectory.Domains
|
||||||
|
.Select(d => new Models.System.DomainOrganisationalUnitsModel() { Domain = d, OrganisationalUnits = ActiveDirectory.RetrieveOrganisationalUnitStructure(d) })
|
||||||
|
.Select(ous => ous.ToFancyTreeNode()).ToList();
|
||||||
|
|
||||||
|
return Json(domainOUs, JsonRequestBehavior.AllowGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Proxy Settings
|
||||||
|
|
||||||
|
[DiscoAuthorize(Claims.Config.System.ConfigureProxy)]
|
||||||
|
public virtual ActionResult UpdateProxySettings(string ProxyAddress, int? ProxyPort, string ProxyUsername, string ProxyPassword, bool redirect = false)
|
||||||
|
{
|
||||||
|
// Default Proxy Port
|
||||||
|
if (!ProxyPort.HasValue)
|
||||||
|
ProxyPort = 8080;
|
||||||
|
|
||||||
|
SystemConfiguration config = Database.DiscoConfiguration;
|
||||||
|
//config.DataStoreLocation = DataStoreLocation;
|
||||||
|
config.ProxyAddress = ProxyAddress;
|
||||||
|
config.ProxyPort = ProxyPort.Value;
|
||||||
|
config.ProxyUsername = ProxyUsername;
|
||||||
|
config.ProxyPassword = ProxyPassword;
|
||||||
|
DiscoApplication.SetGlobalProxy(ProxyAddress, ProxyPort.Value, ProxyUsername, ProxyPassword);
|
||||||
|
|
||||||
|
Database.SaveChanges();
|
||||||
|
|
||||||
|
// Try and check for updates if needed - After Proxy Changed
|
||||||
|
if (Database.DiscoConfiguration.UpdateLastCheck == null
|
||||||
|
|| Database.DiscoConfiguration.UpdateLastCheck.ResponseTimestamp < DateTime.Now.AddDays(-1))
|
||||||
|
{
|
||||||
|
Disco.BI.Interop.Community.UpdateCheckTask.ScheduleNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirect)
|
||||||
|
return RedirectToAction(MVC.Config.SystemConfig.Index());
|
||||||
|
else
|
||||||
|
return Json("OK", JsonRequestBehavior.AllowGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using System;
|
using System;
|
||||||
@@ -61,8 +62,13 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DiscoAuthorize(Claims.User.Actions.AddAttachments)]
|
[DiscoAuthorize(Claims.User.Actions.AddAttachments)]
|
||||||
public virtual ActionResult AttachmentUpload(string id, string Comments)
|
public virtual ActionResult AttachmentUpload(string id, string Domain, string Comments)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(Domain))
|
||||||
|
id = ActiveDirectory.PrimaryDomain.NetBiosName + @"\" + id;
|
||||||
|
else
|
||||||
|
id = Domain + @"\" + id;
|
||||||
|
|
||||||
var u = Database.Users.Find(id);
|
var u = Database.Users.Find(id);
|
||||||
if (u != null)
|
if (u != null)
|
||||||
{
|
{
|
||||||
@@ -77,7 +83,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
|
|
||||||
var ua = new Disco.Models.Repository.UserAttachment()
|
var ua = new Disco.Models.Repository.UserAttachment()
|
||||||
{
|
{
|
||||||
UserId = u.Id,
|
UserId = u.UserId,
|
||||||
TechUserId = UserService.CurrentUserId,
|
TechUserId = UserService.CurrentUserId,
|
||||||
Filename = file.FileName,
|
Filename = file.FileName,
|
||||||
MimeType = contentType,
|
MimeType = contentType,
|
||||||
@@ -118,9 +124,14 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DiscoAuthorize(Claims.User.ShowAttachments)]
|
[DiscoAuthorize(Claims.User.ShowAttachments)]
|
||||||
public virtual ActionResult Attachments(string id)
|
public virtual ActionResult Attachments(string id, string Domain)
|
||||||
{
|
{
|
||||||
var u = Database.Users.Include("UserAttachments.TechUser").Where(m => m.Id == id).FirstOrDefault();
|
if (string.IsNullOrEmpty(Domain))
|
||||||
|
id = ActiveDirectory.PrimaryDomain.NetBiosName + @"\" + id;
|
||||||
|
else
|
||||||
|
id = Domain + @"\" + id;
|
||||||
|
|
||||||
|
var u = Database.Users.Include("UserAttachments.TechUser").Where(m => m.UserId == id).FirstOrDefault();
|
||||||
if (u != null)
|
if (u != null)
|
||||||
{
|
{
|
||||||
var m = new Models.Attachment.AttachmentsModel()
|
var m = new Models.Attachment.AttachmentsModel()
|
||||||
@@ -140,7 +151,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
var ua = Database.UserAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
var ua = Database.UserAttachments.Include("TechUser").Where(m => m.Id == id).FirstOrDefault();
|
||||||
if (ua != null)
|
if (ua != null)
|
||||||
{
|
{
|
||||||
if (ua.TechUserId.Equals(CurrentUser.Id, StringComparison.InvariantCultureIgnoreCase))
|
if (ua.TechUserId.Equals(CurrentUser.UserId, StringComparison.InvariantCultureIgnoreCase))
|
||||||
Authorization.RequireAny(Claims.User.Actions.RemoveAnyAttachments, Claims.User.Actions.RemoveOwnAttachments);
|
Authorization.RequireAny(Claims.User.Actions.RemoveAnyAttachments, Claims.User.Actions.RemoveOwnAttachments);
|
||||||
else
|
else
|
||||||
Authorization.Require(Claims.User.Actions.RemoveAnyAttachments);
|
Authorization.Require(Claims.User.Actions.RemoveAnyAttachments);
|
||||||
@@ -155,12 +166,18 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[DiscoAuthorize(Claims.User.Actions.GenerateDocuments)]
|
[DiscoAuthorize(Claims.User.Actions.GenerateDocuments)]
|
||||||
public virtual ActionResult GeneratePdf(string id, string DocumentTemplateId)
|
public virtual ActionResult GeneratePdf(string id, string Domain, string DocumentTemplateId)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(id))
|
if (string.IsNullOrEmpty(id))
|
||||||
throw new ArgumentNullException("id");
|
throw new ArgumentNullException("id");
|
||||||
if (string.IsNullOrEmpty(DocumentTemplateId))
|
if (string.IsNullOrEmpty(DocumentTemplateId))
|
||||||
throw new ArgumentNullException("AttachmentTypeId");
|
throw new ArgumentNullException("AttachmentTypeId");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Domain))
|
||||||
|
id = ActiveDirectory.PrimaryDomain.NetBiosName + @"\" + id;
|
||||||
|
else
|
||||||
|
id = Domain + @"\" + id;
|
||||||
|
|
||||||
var user = Database.Users.Find(id);
|
var user = Database.Users.Find(id);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
@@ -174,7 +191,7 @@ namespace Disco.Web.Areas.API.Controllers
|
|||||||
pdf = documentTemplate.GeneratePdf(Database, user, UserService.CurrentUser, timeStamp, generationState);
|
pdf = documentTemplate.GeneratePdf(Database, user, UserService.CurrentUser, timeStamp, generationState);
|
||||||
}
|
}
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
return File(pdf, "application/pdf", string.Format("{0}_{1}_{2:yyyyMMdd-HHmmss}.pdf", documentTemplate.Id, user.Id, timeStamp));
|
return File(pdf, "application/pdf", string.Format("{0}_{1}_{2:yyyyMMdd-HHmmss}.pdf", documentTemplate.Id, user.UserId, timeStamp));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using Disco.Web.Models.Shared;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Disco.Web.Areas.API.Models.System
|
||||||
|
{
|
||||||
|
public class DomainOrganisationalUnitsModel
|
||||||
|
{
|
||||||
|
public ActiveDirectoryDomain Domain { get; set; }
|
||||||
|
public List<ActiveDirectoryOrganisationalUnit> OrganisationalUnits { get; set; }
|
||||||
|
|
||||||
|
public FancyTreeNode ToFancyTreeNode()
|
||||||
|
{
|
||||||
|
FancyTreeNode[] children = OrganisationalUnits.Select(ou => OrganisationalUnitToFancyTreeNode(ou)).ToArray();
|
||||||
|
|
||||||
|
return new FancyTreeNode()
|
||||||
|
{
|
||||||
|
key = Domain.DistinguishedName,
|
||||||
|
title = Domain.NetBiosName,
|
||||||
|
folder = true,
|
||||||
|
tooltip = Domain.DnsName,
|
||||||
|
children = children,
|
||||||
|
unselectable = false,
|
||||||
|
expanded = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
private FancyTreeNode OrganisationalUnitToFancyTreeNode(ActiveDirectoryOrganisationalUnit OrganisationalUnit)
|
||||||
|
{
|
||||||
|
FancyTreeNode[] children = OrganisationalUnit.Children == null
|
||||||
|
? null
|
||||||
|
: OrganisationalUnit.Children.Select(ou => OrganisationalUnitToFancyTreeNode(ou)).ToArray();
|
||||||
|
|
||||||
|
return new FancyTreeNode()
|
||||||
|
{
|
||||||
|
key = OrganisationalUnit.DistinguishedName,
|
||||||
|
title = OrganisationalUnit.Name,
|
||||||
|
folder = true,
|
||||||
|
tooltip = OrganisationalUnit.DistinguishedName,
|
||||||
|
children = children,
|
||||||
|
unselectable = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using Disco.Models.UI.Config.AuthorizationRole;
|
using Disco.Models.UI.Config.AuthorizationRole;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Authorization.Roles;
|
using Disco.Services.Authorization.Roles;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Plugins.Features.UIExtension;
|
using Disco.Services.Plugins.Features.UIExtension;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
@@ -27,7 +28,7 @@ namespace Disco.Web.Areas.Config.Controllers
|
|||||||
|
|
||||||
var token = RoleToken.FromAuthorizationRole(ar);
|
var token = RoleToken.FromAuthorizationRole(ar);
|
||||||
var subjects = token.SubjectIds == null ? new List<Models.AuthorizationRole.ShowModel.SubjectDescriptor>() :
|
var subjects = token.SubjectIds == null ? new List<Models.AuthorizationRole.ShowModel.SubjectDescriptor>() :
|
||||||
token.SubjectIds.Select(subjectId => Disco.BI.Interop.ActiveDirectory.ActiveDirectory.GetObject(subjectId))
|
token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId))
|
||||||
.Where(item => item != null)
|
.Where(item => item != null)
|
||||||
.Select(item => Models.AuthorizationRole.ShowModel.SubjectDescriptor.FromActiveDirectoryObject(item))
|
.Select(item => Models.AuthorizationRole.ShowModel.SubjectDescriptor.FromActiveDirectoryObject(item))
|
||||||
.OrderBy(item => item.Name).ToList();
|
.OrderBy(item => item.Name).ToList();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Models.UI.Config.DeviceProfile;
|
using Disco.Models.UI.Config.DeviceProfile;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Plugins;
|
using Disco.Services.Plugins;
|
||||||
using Disco.Services.Plugins.Features.CertificateProvider;
|
using Disco.Services.Plugins.Features.CertificateProvider;
|
||||||
using Disco.Services.Plugins.Features.UIExtension;
|
using Disco.Services.Plugins.Features.UIExtension;
|
||||||
@@ -75,7 +76,8 @@ namespace Disco.Web.Areas.Config.Controllers
|
|||||||
{
|
{
|
||||||
ComputerNameTemplate = DeviceProfile.DefaultComputerNameTemplate,
|
ComputerNameTemplate = DeviceProfile.DefaultComputerNameTemplate,
|
||||||
ProvisionADAccount = true,
|
ProvisionADAccount = true,
|
||||||
DistributionType = DeviceProfile.DistributionTypes.OneToMany
|
DistributionType = DeviceProfile.DistributionTypes.OneToMany,
|
||||||
|
OrganisationalUnit = ActiveDirectory.PrimaryDomain.GetDefaultComputerContainer()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Disco.Models.Services.Jobs.JobQueues;
|
using Disco.Models.Services.Jobs.JobQueues;
|
||||||
using Disco.Models.UI.Config.JobQueue;
|
using Disco.Models.UI.Config.JobQueue;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Jobs.JobQueues;
|
using Disco.Services.Jobs.JobQueues;
|
||||||
using Disco.Services.Plugins.Features.UIExtension;
|
using Disco.Services.Plugins.Features.UIExtension;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
@@ -28,7 +29,7 @@ namespace Disco.Web.Areas.Config.Controllers
|
|||||||
|
|
||||||
var token = JobQueueToken.FromJobQueue(jq);
|
var token = JobQueueToken.FromJobQueue(jq);
|
||||||
var subjects = token.SubjectIds == null ? new List<Models.JobQueue.ShowModel.SubjectDescriptor>() :
|
var subjects = token.SubjectIds == null ? new List<Models.JobQueue.ShowModel.SubjectDescriptor>() :
|
||||||
token.SubjectIds.Select(subjectId => Disco.BI.Interop.ActiveDirectory.ActiveDirectory.GetObject(subjectId))
|
token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId))
|
||||||
.Where(item => item != null)
|
.Where(item => item != null)
|
||||||
.Select(item => Models.JobQueue.ShowModel.SubjectDescriptor.FromActiveDirectoryObject(item))
|
.Select(item => Models.JobQueue.ShowModel.SubjectDescriptor.FromActiveDirectoryObject(item))
|
||||||
.OrderBy(item => item.Name).ToList();
|
.OrderBy(item => item.Name).ToList();
|
||||||
|
|||||||
@@ -12,20 +12,5 @@ namespace Disco.Web.Areas.Config.Controllers
|
|||||||
var m = Models.SystemConfig.IndexModel.FromConfiguration(Database.DiscoConfiguration);
|
var m = Models.SystemConfig.IndexModel.FromConfiguration(Database.DiscoConfiguration);
|
||||||
return View(m);
|
return View(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DiscoAuthorizeAll(Claims.Config.System.Show, Claims.Config.System.ConfigureProxy), HttpPost]
|
|
||||||
public virtual ActionResult Index(Models.SystemConfig.IndexModel config)
|
|
||||||
{
|
|
||||||
if (ModelState.IsValid)
|
|
||||||
{
|
|
||||||
config.ToConfiguration(Database);
|
|
||||||
return RedirectToAction(MVC.Config.Config.Index());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Disco.Web.Areas.Config.Models.AuthorizationRole
|
|||||||
{
|
{
|
||||||
var item = new SubjectDescriptor()
|
var item = new SubjectDescriptor()
|
||||||
{
|
{
|
||||||
Id = ADObject.SamAccountName,
|
Id = ADObject.NetBiosId,
|
||||||
Name = ADObject.Name
|
Name = ADObject.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ using System.Data.SqlClient;
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.BI.Interop.Community;
|
using Disco.Models.BI.Interop.Community;
|
||||||
using Disco.Services.Tasks;
|
using Disco.Services.Tasks;
|
||||||
|
using Disco.Models.Interop.ActiveDirectory;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
|
||||||
namespace Disco.Web.Areas.Config.Models.SystemConfig
|
namespace Disco.Web.Areas.Config.Models.SystemConfig
|
||||||
{
|
{
|
||||||
@@ -72,6 +75,20 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Active Directory
|
||||||
|
|
||||||
|
[Display(Name="Search Entire Forest")]
|
||||||
|
public bool ADSearchEntireForest { get; set; }
|
||||||
|
|
||||||
|
public ActiveDirectoryDomain ADPrimaryDomain { get; set; }
|
||||||
|
public List<ActiveDirectoryDomain> ADAdditionalDomains { get; set; }
|
||||||
|
public ActiveDirectorySite ADSite { get; set; }
|
||||||
|
public List<Tuple<DirectoryServer, bool>> ADSiteServers { get; set; }
|
||||||
|
public List<Tuple<string, ActiveDirectoryDomain, string>> ADSearchContainers { get; set; }
|
||||||
|
public List<string> ADForestServers { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Proxy
|
#region Proxy
|
||||||
public string ProxyAddress { get; set; }
|
public string ProxyAddress { get; set; }
|
||||||
public int ProxyPort { get; set; }
|
public int ProxyPort { get; set; }
|
||||||
@@ -87,7 +104,7 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig
|
|||||||
|
|
||||||
public static IndexModel FromConfiguration(SystemConfiguration config)
|
public static IndexModel FromConfiguration(SystemConfiguration config)
|
||||||
{
|
{
|
||||||
return new IndexModel()
|
var m = new IndexModel()
|
||||||
{
|
{
|
||||||
DiscoVersion = typeof(DiscoApplication).Assembly.GetName().Version,
|
DiscoVersion = typeof(DiscoApplication).Assembly.GetName().Version,
|
||||||
DataStoreLocation = config.DataStoreLocation,
|
DataStoreLocation = config.DataStoreLocation,
|
||||||
@@ -100,27 +117,33 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig
|
|||||||
UpdateNextScheduled = Disco.BI.Interop.Community.UpdateCheckTask.NextScheduled,
|
UpdateNextScheduled = Disco.BI.Interop.Community.UpdateCheckTask.NextScheduled,
|
||||||
UpdateBetaDeployment = config.UpdateBetaDeployment
|
UpdateBetaDeployment = config.UpdateBetaDeployment
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
public void ToConfiguration(DiscoDataContext Database)
|
// AD
|
||||||
{
|
m.ADPrimaryDomain = ActiveDirectory.PrimaryDomain;
|
||||||
SystemConfiguration config = Database.DiscoConfiguration;
|
m.ADAdditionalDomains = ActiveDirectory.Domains.Where(d => d != m.ADPrimaryDomain).ToList();
|
||||||
//config.DataStoreLocation = DataStoreLocation;
|
m.ADSite = ActiveDirectory.Site;
|
||||||
config.ProxyAddress = ProxyAddress;
|
m.ADSiteServers = m.ADSite.Servers.Cast<DirectoryServer>().Select(s => Tuple.Create(s, s.Reachable())).ToList();
|
||||||
config.ProxyPort = ProxyPort;
|
var configSearchContainers = config.ActiveDirectory.SearchContainers;
|
||||||
config.ProxyUsername = ProxyUsername;
|
m.ADSearchContainers = configSearchContainers == null ? null : configSearchContainers.Select(c =>
|
||||||
config.ProxyPassword = ProxyPassword;
|
|
||||||
DiscoApplication.SetGlobalProxy(ProxyAddress, ProxyPort, ProxyUsername, ProxyPassword);
|
|
||||||
|
|
||||||
Database.SaveChanges();
|
|
||||||
|
|
||||||
// Try and check for updates if needed - After Proxy Changed
|
|
||||||
if (Database.DiscoConfiguration.UpdateLastCheck == null
|
|
||||||
|| Database.DiscoConfiguration.UpdateLastCheck.ResponseTimestamp < DateTime.Now.AddDays(-1))
|
|
||||||
{
|
{
|
||||||
Disco.BI.Interop.Community.UpdateCheckTask.ScheduleNow();
|
var d = ActiveDirectory.GetDomainByDistinguishedName(c);
|
||||||
}
|
return Tuple.Create(c, d, d.GetFriendlyOrganisationalUnitName(c));
|
||||||
}
|
}).ToList();
|
||||||
|
|
||||||
|
var loadForestServersTask = ActiveDirectory.LoadForestServersAsync();
|
||||||
|
if (loadForestServersTask.Wait(TimeSpan.FromSeconds(3)))
|
||||||
|
{
|
||||||
|
m.ADForestServers = loadForestServersTask.Result;
|
||||||
|
var configValue = config.ActiveDirectory.SearchEntireForest ?? true;
|
||||||
|
m.ADSearchEntireForest = configValue && m.ADForestServers.Count <= ActiveDirectory.MaxForestServerSearch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m.ADForestServers = null;
|
||||||
|
m.ADSearchEntireForest = config.ActiveDirectory.SearchEntireForest ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.AuthorizationRole
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.AuthorizationRole
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -35,6 +35,7 @@ namespace Disco.Web.Areas.Config.Views.AuthorizationRole
|
|||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.Config
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceBatch
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceBatch
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceBatch
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceBatch
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceModel
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceModel
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceModel
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceModel
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
@Html.HiddenFor(model => model.DeviceProfile.ComputerNameTemplate)
|
@Html.HiddenFor(model => model.DeviceProfile.ComputerNameTemplate)
|
||||||
@Html.HiddenFor(model => model.DeviceProfile.ProvisionADAccount)
|
@Html.HiddenFor(model => model.DeviceProfile.ProvisionADAccount)
|
||||||
@Html.HiddenFor(model => model.DeviceProfile.DistributionType)
|
@Html.HiddenFor(model => model.DeviceProfile.DistributionType)
|
||||||
|
@Html.HiddenFor(model => model.DeviceProfile.OrganisationalUnit)
|
||||||
<p class="actions">
|
<p class="actions">
|
||||||
<input type="submit" class="button" value="Create" />
|
<input type="submit" class="button" value="Create" />
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceProfile
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
@@ -174,6 +175,17 @@ WriteLiteral(" ");
|
|||||||
Write(Html.HiddenFor(model => model.DeviceProfile.DistributionType));
|
Write(Html.HiddenFor(model => model.DeviceProfile.DistributionType));
|
||||||
|
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
WriteLiteral("\r\n");
|
||||||
|
|
||||||
|
WriteLiteral(" ");
|
||||||
|
|
||||||
|
|
||||||
|
#line 38 "..\..\Areas\Config\Views\DeviceProfile\Create.cshtml"
|
||||||
|
Write(Html.HiddenFor(model => model.DeviceProfile.OrganisationalUnit));
|
||||||
|
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("\r\n <p");
|
WriteLiteral("\r\n <p");
|
||||||
@@ -198,7 +210,7 @@ WriteLiteral(">\r\n $(function () {\r\n $(\'#Name\').focus().s
|
|||||||
"\r\n </script>\r\n");
|
"\r\n </script>\r\n");
|
||||||
|
|
||||||
|
|
||||||
#line 47 "..\..\Areas\Config\Views\DeviceProfile\Create.cshtml"
|
#line 48 "..\..\Areas\Config\Views\DeviceProfile\Create.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.34003
|
// Runtime Version:4.0.30319.34011
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DeviceProfile
|
|||||||
using Disco;
|
using Disco;
|
||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
using Disco.Services.Web;
|
using Disco.Services.Web;
|
||||||
using Disco.Web;
|
using Disco.Web;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user