diff --git a/src/Console/Program.cs b/src/Console/Program.cs index ccf88a3b..9cc94b55 100644 --- a/src/Console/Program.cs +++ b/src/Console/Program.cs @@ -665,17 +665,17 @@ namespace Bit.Console foreach(var group in result.Groups) { Con.WriteLine(" {0} - {1}", group.Name, group.Id); + foreach(var user in group.Users) + { + Con.WriteLine(" {0}", user); + } } Con.WriteLine(); Con.WriteLine("Users:"); foreach(var user in result.Users) { - Con.WriteLine(" {0}", user.Email); - foreach(var group in user.Groups) - { - Con.WriteLine(" {0}", group); - } + Con.WriteLine(" {0}{1}", user.Email, user.Disabled ? " (disabled)" : null); } } else diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 034dbabd..fa40fdbc 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -64,6 +64,7 @@ + diff --git a/src/Core/Enums/UserAccountControl.cs b/src/Core/Enums/UserAccountControl.cs new file mode 100644 index 00000000..2cf9d36f --- /dev/null +++ b/src/Core/Enums/UserAccountControl.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bit.Core.Enums +{ + [Flags] + public enum UserAccountControl : int + { + AccountDisabled = 0x00000002, + LockOut = 0x00000010, + } +} diff --git a/src/Core/Models/Entry.cs b/src/Core/Models/Entry.cs index df412cce..bdcc5d3a 100644 --- a/src/Core/Models/Entry.cs +++ b/src/Core/Models/Entry.cs @@ -17,11 +17,12 @@ namespace Bit.Core.Models { public string Name { get; set; } public HashSet Members { get; set; } = new HashSet(); + public HashSet Users { get; set; } = new HashSet(); } public class UserEntry : Entry { public string Email { get; set; } - public HashSet Groups { get; set; } = new HashSet(); + public bool Disabled { get; set; } } } diff --git a/src/Core/Models/ImportRequest.cs b/src/Core/Models/ImportRequest.cs index 77d91b7c..295e30b4 100644 --- a/src/Core/Models/ImportRequest.cs +++ b/src/Core/Models/ImportRequest.cs @@ -20,10 +20,12 @@ namespace Bit.Core.Models { Name = entry.Name; ExternalId = entry.Id; + Users = entry.Users; } public string Name { get; set; } public string ExternalId { get; set; } + public IEnumerable Users { get; set; } } public class User @@ -31,11 +33,11 @@ namespace Bit.Core.Models public User(UserEntry entry) { Email = entry.Email; - ExternalGroupIds = entry.Groups; + Disabled = entry.Disabled; } public string Email { get; set; } - public IEnumerable ExternalGroupIds { get; set; } + public bool Disabled { get; set; } } } diff --git a/src/Core/Models/SyncResult.cs b/src/Core/Models/SyncResult.cs index afa99723..dced4d3b 100644 --- a/src/Core/Models/SyncResult.cs +++ b/src/Core/Models/SyncResult.cs @@ -10,7 +10,7 @@ namespace Bit.Core.Models { public bool Success { get; set; } public string ErrorMessage { get; set; } - public List Groups { get; set; } - public List Users { get; set; } + public List Groups { get; set; } = new List(); + public List Users { get; set; } = new List(); } } diff --git a/src/Core/Services/AzureDirectoryService.cs b/src/Core/Services/AzureDirectoryService.cs index 09fab5fe..6a99a8dd 100644 --- a/src/Core/Services/AzureDirectoryService.cs +++ b/src/Core/Services/AzureDirectoryService.cs @@ -134,13 +134,14 @@ namespace Bit.Core.Services var entries = new List(); - var users = await _graphClient.Users.Request().Select("id,mail,userPrincipalName").GetAsync(); + var users = await _graphClient.Users.Request().Select("id,mail,userPrincipalName,accountEnabled").GetAsync(); foreach(var user in users) { var entry = new UserEntry { Id = user.Id, - Email = user.Mail ?? user.UserPrincipalName + Email = user.Mail ?? user.UserPrincipalName, + Disabled = !user.AccountEnabled.GetValueOrDefault(true) }; if(entry.Email.Contains("#")) diff --git a/src/Core/Services/LdapDirectoryService.cs b/src/Core/Services/LdapDirectoryService.cs index b3eb72c4..6063e39a 100644 --- a/src/Core/Services/LdapDirectoryService.cs +++ b/src/Core/Services/LdapDirectoryService.cs @@ -1,4 +1,5 @@ -using Bit.Core.Models; +using Bit.Core.Enums; +using Bit.Core.Models; using Bit.Core.Utilities; using System; using System.Collections.Generic; @@ -226,10 +227,26 @@ namespace Bit.Core.Services user.CreationDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.CreationDateAttribute); user.RevisionDate = item.Properties.ParseDateTime(SettingsService.Instance.Sync.RevisionDateAttribute); - users.Add(user); + user.Disabled = EntryDisabled(item); } return Task.FromResult(users); } + + private static bool EntryDisabled(SearchResult item) + { + if(!item.Properties.Contains("userAccountControl")) + { + return false; + } + + UserAccountControl control; + if(!Enum.TryParse(item.Properties["userAccountControl"].ToString(), out control)) + { + return false; + } + + return (control & UserAccountControl.AccountDisabled) == UserAccountControl.AccountDisabled; + } } } diff --git a/src/Core/Utilities/Sync.cs b/src/Core/Utilities/Sync.cs index ec3e5fea..6f3f884f 100644 --- a/src/Core/Utilities/Sync.cs +++ b/src/Core/Utilities/Sync.cs @@ -18,7 +18,7 @@ namespace Bit.Core.Utilities var groups = entriesResult.Item1; var users = entriesResult.Item2; - FlattenGroupsToUsers(groups, null, groups, users); + FlattenUsersToGroups(groups, null, groups, users); if(!sendToServer) { @@ -81,7 +81,7 @@ namespace Bit.Core.Utilities } } - private static void FlattenGroupsToUsers(List currentGroups, List currentGroupsUsers, + private static void FlattenUsersToGroups(List currentGroups, List currentGroupsUsers, List allGroups, List allUsers) { foreach(var group in currentGroups) @@ -91,9 +91,9 @@ namespace Bit.Core.Utilities foreach(var user in usersInThisGroup) { - if(!user.Groups.Contains(group.Id)) + if(!group.Users.Contains(user.Email)) { - user.Groups.Add(group.Id); + group.Users.Add(user.Email); } } @@ -101,9 +101,9 @@ namespace Bit.Core.Utilities { foreach(var user in currentGroupsUsers) { - if(!user.Groups.Contains(group.Id)) + if(!group.Users.Contains(user.Email)) { - user.Groups.Add(group.Id); + group.Users.Add(user.Email); } } @@ -111,7 +111,7 @@ namespace Bit.Core.Utilities } // Recurse it - FlattenGroupsToUsers(groupsInThisGroup, usersInThisGroup, allGroups, allUsers); + FlattenUsersToGroups(groupsInThisGroup, usersInThisGroup, allGroups, allUsers); } } }