diff --git a/Disco.Services/Interop/ActiveDirectory/ActiveDirectory.cs b/Disco.Services/Interop/ActiveDirectory/ActiveDirectory.cs index f8d36d1f..9e083bc9 100644 --- a/Disco.Services/Interop/ActiveDirectory/ActiveDirectory.cs +++ b/Disco.Services/Interop/ActiveDirectory/ActiveDirectory.cs @@ -245,6 +245,7 @@ namespace Disco.Services.Interop.ActiveDirectory #region User Account private static readonly string[] UserLoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "displayName", "sn", "givenName", "memberOf", "primaryGroupID", "mail", "telephoneNumber" }; + private static readonly string[] UserQuickLoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "displayName", "sn", "givenName", "mail", "telephoneNumber" }; public static ActiveDirectoryUserAccount RetrieveUserAccount(string Id, params string[] AdditionalProperties) { @@ -254,9 +255,13 @@ namespace Disco.Services.Interop.ActiveDirectory ? UserLoadProperties.Concat(AdditionalProperties).ToArray() : UserLoadProperties; - return SearchBySamAccountName(Id, ldapFilter, loadProperites).Select(result => result.AsUserAccount(AdditionalProperties)).FirstOrDefault(); + return SearchBySamAccountName(Id, ldapFilter, loadProperites).Select(result => result.AsUserAccount(false, AdditionalProperties)).FirstOrDefault(); } public static IEnumerable SearchUserAccounts(string Term, params string[] AdditionalProperties) + { + return SearchUserAccounts(Term, false, AdditionalProperties); + } + public static IEnumerable SearchUserAccounts(string Term, bool Quick, params string[] AdditionalProperties) { const int resultLimit = 30; // Default Search Limit @@ -272,26 +277,30 @@ namespace Disco.Services.Interop.ActiveDirectory 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() + string[] loadProperites = Quick + ? UserQuickLoadProperties : UserLoadProperties; + if (AdditionalProperties != null && AdditionalProperties.Length > 0) + loadProperites.Concat(AdditionalProperties).ToArray(); + IEnumerable searchResults; if (searchDomain == null) searchResults = ADInterop.SearchScope(ldapFilter, resultLimit, loadProperites); else searchResults = ADInterop.SearchScope(searchDomain, ldapFilter, resultLimit, loadProperites); - return searchResults.Select(result => result.AsUserAccount(AdditionalProperties)); + return searchResults.Select(result => result.AsUserAccount(Quick, AdditionalProperties)); } - private static ActiveDirectoryUserAccount AsUserAccount(this ActiveDirectorySearchResult item, string[] AdditionalProperties) + private static ActiveDirectoryUserAccount AsUserAccount(this ActiveDirectorySearchResult item, bool Quick, 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); + List groups = null; ResultPropertyValueCollection displayNameProp = item.Result.Properties["displayName"]; string displayName = username; @@ -314,15 +323,19 @@ namespace Disco.Services.Interop.ActiveDirectory 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().ToList(); - groupDistinguishedNames.Add(ADGroupCache.GetGroupsDistinguishedNameForSecurityIdentifier(primaryGroupSid)); - List groups = ADGroupCache.GetGroups(groupDistinguishedNames).ToList(); + // Don't load Groups when doing a quick search + if (!Quick) + { + int primaryGroupID = (int)item.Result.Properties["primaryGroupID"][0]; + string primaryGroupSid = ADInterop.ConvertBytesToSDDLString(ADInterop.BuildPrimaryGroupSid(objectSid, primaryGroupID)); + var groupDistinguishedNames = item.Result.Properties["memberOf"].Cast().ToList(); + groupDistinguishedNames.Add(ADGroupCache.GetGroupsDistinguishedNameForSecurityIdentifier(primaryGroupSid)); + groups = ADGroupCache.GetGroups(groupDistinguishedNames).ToList(); + } // Additional Properties Dictionary additionalProperties = new Dictionary(); - if (AdditionalProperties != null) + if (AdditionalProperties != null && AdditionalProperties.Length > 0) foreach (string propertyName in AdditionalProperties) { var property = item.Result.Properties[propertyName]; @@ -457,7 +470,7 @@ namespace Disco.Services.Interop.ActiveDirectory 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) + public static IActiveDirectoryObject RetrieveObject(string Id, bool Quick) { const string ldapFilter = "(&(|(objectCategory=Person)(objectCategory=Computer)(objectCategory=Group))(sAMAccountName={0}))"; @@ -469,7 +482,7 @@ namespace Disco.Services.Interop.ActiveDirectory switch (objectCategory) { case "cn=person": - return result.AsUserAccount(null); + return result.AsUserAccount(Quick, null); case "cn=computer": return result.AsMachineAccount(null); case "cn=group": diff --git a/Disco.Services/Searching/Search.cs b/Disco.Services/Searching/Search.cs index f88a02be..8c286597 100644 --- a/Disco.Services/Searching/Search.cs +++ b/Disco.Services/Searching/Search.cs @@ -171,7 +171,7 @@ namespace Disco.Services.Searching public static List SearchUsersUpstream(string Term, int? LimitCount = null) { - IEnumerable matches = ActiveDirectory.SearchUserAccounts(Term); + IEnumerable matches = ActiveDirectory.SearchUserAccounts(Term, Quick: true); if (LimitCount.HasValue) matches = matches.Take(LimitCount.Value); diff --git a/Disco.Services/Users/UserService.cs b/Disco.Services/Users/UserService.cs index 0d58d712..87b7dea8 100644 --- a/Disco.Services/Users/UserService.cs +++ b/Disco.Services/Users/UserService.cs @@ -208,7 +208,7 @@ namespace Disco.Services.Users internal static IEnumerable SearchUsers(DiscoDataContext Database, string Term) { - var adImportedUsers = ActiveDirectory.SearchUserAccounts(Term); + var adImportedUsers = ActiveDirectory.SearchUserAccounts(Term, Quick: true); foreach (var adU in adImportedUsers.Select(adU => adU.ToRepositoryUser())) { var existingUser = Database.Users.Find(adU.UserId); diff --git a/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs b/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs index e968971f..0e02e32b 100644 --- a/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs +++ b/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs @@ -108,7 +108,11 @@ namespace Disco.Web.Areas.API.Controllers // Validate Subjects if (Subjects != null && Subjects.Length > 0) { - var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple(s, ActiveDirectory.RetrieveObject(s))).ToList(); + var subjects = Subjects + .Where(s => !string.IsNullOrWhiteSpace(s)) + .Select(s => s.Trim()) + .Select(s => Tuple.Create(s, ActiveDirectory.RetrieveObject(s, Quick: true))) + .ToList(); var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList(); if (invalidSubjects.Count > 0) @@ -242,7 +246,11 @@ namespace Disco.Web.Areas.API.Controllers if (Subjects == null || Subjects.Length == 0) throw new ArgumentNullException("Subjects", "At least one Id must be supplied"); - var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple(s, ActiveDirectory.RetrieveObject(s))).ToList(); + var subjects = Subjects + .Where(s => !string.IsNullOrWhiteSpace(s)) + .Select(s => s.Trim()) + .Select(s => Tuple.Create(s, ActiveDirectory.RetrieveObject(s, Quick: true))) + .ToList(); var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList(); if (invalidSubjects.Count > 0) @@ -286,7 +294,7 @@ namespace Disco.Web.Areas.API.Controllers else if (!Id.Contains(@"\")) Id = string.Format(@"{0}\{1}", ActiveDirectory.PrimaryDomain.NetBiosName, Id); - var subject = ActiveDirectory.RetrieveObject(Id); + var subject = ActiveDirectory.RetrieveObject(Id, Quick: true); if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup)) return Json(null, JsonRequestBehavior.AllowGet); diff --git a/Disco.Web/Areas/API/Controllers/JobQueueController.cs b/Disco.Web/Areas/API/Controllers/JobQueueController.cs index b20a07d4..f0e67ef7 100644 --- a/Disco.Web/Areas/API/Controllers/JobQueueController.cs +++ b/Disco.Web/Areas/API/Controllers/JobQueueController.cs @@ -288,7 +288,11 @@ namespace Disco.Web.Areas.API.Controllers // Validate Subjects if (Subjects != null && Subjects.Length > 0) { - var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple(s, ActiveDirectory.RetrieveObject(s))).ToList(); + var subjects = Subjects + .Where(s => !string.IsNullOrWhiteSpace(s)) + .Select(s => s.Trim()) + .Select(s => Tuple.Create(s, ActiveDirectory.RetrieveObject(s, Quick: true))) + .ToList(); var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList(); if (invalidSubjects.Count > 0) @@ -382,7 +386,7 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.Config.JobQueue.Configure)] public virtual ActionResult Subject(string Id) { - var subject = ActiveDirectory.RetrieveObject(Id); + var subject = ActiveDirectory.RetrieveObject(Id, Quick: true); if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup)) return Json(null, JsonRequestBehavior.AllowGet); diff --git a/Disco.Web/Areas/Config/Controllers/AuthorizationRoleController.cs b/Disco.Web/Areas/Config/Controllers/AuthorizationRoleController.cs index b4b6cf96..4434e96e 100644 --- a/Disco.Web/Areas/Config/Controllers/AuthorizationRoleController.cs +++ b/Disco.Web/Areas/Config/Controllers/AuthorizationRoleController.cs @@ -28,7 +28,7 @@ namespace Disco.Web.Areas.Config.Controllers var token = RoleToken.FromAuthorizationRole(ar); var subjects = token.SubjectIds == null ? new List() : - token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId)) + token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId, Quick: true)) .Where(item => item != null) .Select(item => Models.AuthorizationRole.SubjectDescriptorModel.FromActiveDirectoryObject(item)) .OrderBy(item => item.Name).ToList(); @@ -53,7 +53,7 @@ namespace Disco.Web.Areas.Config.Controllers .Select(ar => RoleToken.FromAuthorizationRole(ar)).Cast().ToList(); var administratorSubjects = UserService.AdministratorSubjectIds - .Select(subjectId => ActiveDirectory.RetrieveObject(subjectId)) + .Select(subjectId => ActiveDirectory.RetrieveObject(subjectId, Quick: true)) .Where(item => item != null) .Select(item => Models.AuthorizationRole.SubjectDescriptorModel.FromActiveDirectoryObject(item)) .OrderBy(item => item.Name).ToList(); diff --git a/Disco.Web/Areas/Config/Controllers/JobQueueController.cs b/Disco.Web/Areas/Config/Controllers/JobQueueController.cs index 4be01521..f5d8ebd4 100644 --- a/Disco.Web/Areas/Config/Controllers/JobQueueController.cs +++ b/Disco.Web/Areas/Config/Controllers/JobQueueController.cs @@ -29,7 +29,7 @@ namespace Disco.Web.Areas.Config.Controllers var token = JobQueueToken.FromJobQueue(jq); var subjects = token.SubjectIds == null ? new List() : - token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId)) + token.SubjectIds.Select(subjectId => ActiveDirectory.RetrieveObject(subjectId, Quick: true)) .Where(item => item != null) .Select(item => Models.JobQueue.ShowModel.SubjectDescriptor.FromActiveDirectoryObject(item)) .OrderBy(item => item.Name).ToList(); diff --git a/Disco.Web/Controllers/InitialConfigController.cs b/Disco.Web/Controllers/InitialConfigController.cs index 689d7eac..1da37b5b 100644 --- a/Disco.Web/Controllers/InitialConfigController.cs +++ b/Disco.Web/Controllers/InitialConfigController.cs @@ -255,7 +255,7 @@ namespace Disco.Web.Controllers public virtual ActionResult Administrators() { var administratorSubjects = UserService.AdministratorSubjectIds - .Select(subjectId => ActiveDirectory.RetrieveObject(subjectId)) + .Select(subjectId => ActiveDirectory.RetrieveObject(subjectId, Quick: true)) .Where(item => item != null) .Select(item => Disco.Web.Areas.Config.Models.AuthorizationRole.SubjectDescriptorModel.FromActiveDirectoryObject(item)) .OrderBy(item => item.Name).ToList(); @@ -284,7 +284,7 @@ namespace Disco.Web.Controllers else if (!Id.Contains(@"\")) Id = string.Format(@"{0}\{1}", ActiveDirectory.PrimaryDomain.NetBiosName, Id); - var subject = ActiveDirectory.RetrieveObject(Id); + var subject = ActiveDirectory.RetrieveObject(Id, Quick: true); if (subject == null || !(subject is ActiveDirectoryUserAccount || subject is ActiveDirectoryGroup)) return Json(null, JsonRequestBehavior.AllowGet); @@ -302,7 +302,11 @@ namespace Disco.Web.Controllers if (Subjects != null || Subjects.Length > 0) { - var subjects = Subjects.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).Select(s => new Tuple(s, ActiveDirectory.RetrieveObject(s))).ToList(); + var subjects = Subjects + .Where(s => !string.IsNullOrWhiteSpace(s)) + .Select(s => s.Trim()) + .Select(s => Tuple.Create(s, ActiveDirectory.RetrieveObject(s, Quick: true))) + .ToList(); var invalidSubjects = subjects.Where(s => s.Item2 == null).ToList(); if (invalidSubjects.Count > 0)