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:
Gary Sharp
2014-04-10 17:58:04 +10:00
parent b841c6b2c0
commit db73cc1a12
218 changed files with 6383 additions and 2535 deletions
@@ -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.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
this.moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
}
#region Configuration Modules
@@ -29,6 +30,7 @@ namespace Disco.Data.Configuration
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
private Lazy<Modules.ActiveDirectoryConfiguration> moduleActiveDirectoryConfiguration;
public Modules.BootstrapperConfiguration Bootstrapper
{
@@ -58,6 +60,13 @@ namespace Disco.Data.Configuration
return moduleJobPreferencesConfiguration.Value;
}
}
public Modules.ActiveDirectoryConfiguration ActiveDirectory
{
get
{
return moduleActiveDirectoryConfiguration.Value;
}
}
#endregion
+9
View File
@@ -48,6 +48,7 @@
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Reactive.Core">
<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\ConfigurationBase.cs" />
<Compile Include="Configuration\ConfigurationCache.cs" />
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
<Compile Include="Configuration\SystemConfiguration.cs" />
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
@@ -130,6 +132,10 @@
<Compile Include="Migrations\201402032322432_DBv12.Designer.cs">
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
</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\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -181,6 +187,9 @@
<EmbeddedResource Include="Migrations\201402032322432_DBv12.resx">
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\201404080227546_DBv13.resx">
<DependentUpon>201404080227546_DBv13.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
+27
View File
@@ -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
+129
View File
@@ -3,6 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.Repository;
using System.Data.SqlClient;
using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices;
namespace Disco.Data.Repository
{
@@ -15,6 +18,9 @@ namespace Disco.Data.Repository
Database.SeedDeviceProfiles();
Database.SeedJobTypes();
Database.SeedJobSubTypes();
// Migration Maintenance
Database.MigratePreDomainObjects();
}
public static void SeedDeploymentId(this DiscoDataContext Database)
@@ -304,5 +310,128 @@ namespace Disco.Data.Repository
}
}
// 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);
}
}
}
}
}