diff --git a/src/Core/Models/Entry.cs b/src/Core/Models/Entry.cs index f5e5e030..2f70b0a9 100644 --- a/src/Core/Models/Entry.cs +++ b/src/Core/Models/Entry.cs @@ -25,5 +25,6 @@ namespace Bit.Core.Models { public string Email { get; set; } public bool Disabled { get; set; } + public bool Deleted { get; set; } } } diff --git a/src/Core/Models/ImportRequest.cs b/src/Core/Models/ImportRequest.cs index 9fac3595..13e48bea 100644 --- a/src/Core/Models/ImportRequest.cs +++ b/src/Core/Models/ImportRequest.cs @@ -33,13 +33,13 @@ namespace Bit.Core.Models public User(UserEntry entry) { Email = entry.Email; - Disabled = entry.Disabled; + Deleted = entry.Disabled || entry.Deleted; ExternalId = entry.ExternalId; } public string ExternalId { get; set; } public string Email { get; set; } - public bool Disabled { get; set; } + public bool Deleted { get; set; } } } diff --git a/src/Core/Services/AzureDirectoryService.cs b/src/Core/Services/AzureDirectoryService.cs index f9592592..d3bdcba1 100644 --- a/src/Core/Services/AzureDirectoryService.cs +++ b/src/Core/Services/AzureDirectoryService.cs @@ -214,7 +214,7 @@ namespace Bit.Core.Services object deleted; if(user.AdditionalData.TryGetValue("@removed", out deleted) && deleted.ToString().Contains("changed")) { - entry.Disabled = true; + entry.Deleted = true; } else if(!entry.Disabled && (entry?.Email?.Contains("#") ?? true)) { diff --git a/src/Core/Services/LdapDirectoryService.cs b/src/Core/Services/LdapDirectoryService.cs index 69294068..0d30d89d 100644 --- a/src/Core/Services/LdapDirectoryService.cs +++ b/src/Core/Services/LdapDirectoryService.cs @@ -201,58 +201,93 @@ namespace Bit.Core.Services var users = new List(); foreach(SearchResult item in result) { - var user = new UserEntry - { - ReferenceId = new Uri(item.Path).Segments?.LastOrDefault() - }; - - if(user.ReferenceId == null) + var user = BuildUser(item, false); + if(user == null) { continue; } - // External Id - if(item.Properties.Contains("objectGUID") && item.Properties["objectGUID"].Count > 0) - { - user.ExternalId = item.Properties["objectGUID"][0].ToString(); - } - else - { - user.ExternalId = user.ReferenceId; - } + users.Add(user); + } - user.Disabled = EntryDisabled(item); + // Deleted users + if(SettingsService.Instance.Server.Type == DirectoryType.ActiveDirectory) + { + filter = string.Format("(&{0}(isDeleted=TRUE))", + filter != null ? string.Format("({0})", filter) : string.Empty); - // Email - if(SettingsService.Instance.Sync.EmailPrefixSuffix && - item.Properties.Contains(SettingsService.Instance.Sync.UserEmailPrefixAttribute) && - item.Properties[SettingsService.Instance.Sync.UserEmailPrefixAttribute].Count > 0 && - !string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.UserEmailSuffix)) + searcher = new DirectorySearcher(entry, filter); + searcher.Tombstone = true; + result = searcher.FindAll(); + foreach(SearchResult item in result) { - user.Email = string.Concat( - item.Properties[SettingsService.Instance.Sync.UserEmailPrefixAttribute][0].ToString(), - SettingsService.Instance.Sync.UserEmailSuffix).ToLowerInvariant(); - } - else if(item.Properties.Contains(SettingsService.Instance.Sync.UserEmailAttribute) && - item.Properties[SettingsService.Instance.Sync.UserEmailAttribute].Count > 0) - { - user.Email = item.Properties[SettingsService.Instance.Sync.UserEmailAttribute][0] - .ToString() - .ToLowerInvariant(); - } - else if(!user.Disabled) - { - continue; - } + var user = BuildUser(item, true); + if(user == null) + { + continue; + } - // Dates - user.CreationDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.CreationDateAttribute); - user.RevisionDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.RevisionDateAttribute); + users.Add(user); + } } return Task.FromResult(users); } + private static UserEntry BuildUser(SearchResult item, bool deleted) + { + var user = new UserEntry + { + ReferenceId = new Uri(item.Path).Segments?.LastOrDefault(), + Deleted = deleted + }; + + if(user.ReferenceId == null) + { + return null; + } + + // External Id + if(item.Properties.Contains("objectGUID") && item.Properties["objectGUID"].Count > 0) + { + user.ExternalId = item.Properties["objectGUID"][0].ToString(); + } + else + { + user.ExternalId = user.ReferenceId; + } + + user.Disabled = EntryDisabled(item); + + // Email + if(SettingsService.Instance.Sync.EmailPrefixSuffix && + item.Properties.Contains(SettingsService.Instance.Sync.UserEmailPrefixAttribute) && + item.Properties[SettingsService.Instance.Sync.UserEmailPrefixAttribute].Count > 0 && + !string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.UserEmailSuffix)) + { + user.Email = string.Concat( + item.Properties[SettingsService.Instance.Sync.UserEmailPrefixAttribute][0].ToString(), + SettingsService.Instance.Sync.UserEmailSuffix).ToLowerInvariant(); + } + else if(item.Properties.Contains(SettingsService.Instance.Sync.UserEmailAttribute) && + item.Properties[SettingsService.Instance.Sync.UserEmailAttribute].Count > 0) + { + user.Email = item.Properties[SettingsService.Instance.Sync.UserEmailAttribute][0] + .ToString() + .ToLowerInvariant(); + } + else if(!user.Disabled && !user.Deleted) + { + return null; + } + + // Dates + user.CreationDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.CreationDateAttribute); + user.RevisionDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.RevisionDateAttribute); + + return user; + } + private static bool EntryDisabled(SearchResult item) { if(!item.Properties.Contains("userAccountControl"))