mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-15 15:53:41 +00:00
revision date filter. allow clearing config values
This commit is contained in:
@@ -313,8 +313,8 @@ namespace Bit.Console
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Con.Write("Type [{0}]: ", currentType);
|
Con.Write("Type [{0}]: ", currentType);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
switch(input)
|
switch(input)
|
||||||
{
|
{
|
||||||
@@ -330,32 +330,32 @@ namespace Bit.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
Con.Write("Address [{0}]: ", config.Address);
|
Con.Write("Address [{0}]: ", config.Address);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.Address = input;
|
config.Address = input;
|
||||||
}
|
}
|
||||||
Con.Write("Port [{0}]: ", config.Port);
|
Con.Write("Port [{0}]: ", config.Port);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.Port = input;
|
config.Port = input;
|
||||||
}
|
}
|
||||||
Con.Write("Path [{0}]: ", config.Path);
|
Con.Write("Path [{0}]: ", config.Path);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.Path = input;
|
config.Path = input;
|
||||||
}
|
}
|
||||||
Con.Write("Username [{0}]: ", config.Username);
|
Con.Write("Username [{0}]: ", config.Username);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.Username = input;
|
config.Username = input;
|
||||||
}
|
}
|
||||||
Con.Write("Password: ");
|
Con.Write("Password: ");
|
||||||
input = ReadSecureLine();
|
input = ReadSecureLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.Password = new EncryptedData(input);
|
config.Password = new EncryptedData(input);
|
||||||
input = null;
|
input = null;
|
||||||
@@ -385,7 +385,8 @@ namespace Bit.Console
|
|||||||
|
|
||||||
private static Task ConfigSyncAsync()
|
private static Task ConfigSyncAsync()
|
||||||
{
|
{
|
||||||
var config = Core.Services.SettingsService.Instance.Sync ?? new SyncConfiguration();
|
var config = Core.Services.SettingsService.Instance.Sync ??
|
||||||
|
new SyncConfiguration(Core.Services.SettingsService.Instance.Server.Type);
|
||||||
|
|
||||||
if(_usingArgs)
|
if(_usingArgs)
|
||||||
{
|
{
|
||||||
@@ -443,57 +444,63 @@ namespace Bit.Console
|
|||||||
string input;
|
string input;
|
||||||
|
|
||||||
Con.Write("Sync groups? [{0}]: ", config.SyncGroups ? "y" : "n");
|
Con.Write("Sync groups? [{0}]: ", config.SyncGroups ? "y" : "n");
|
||||||
input = Con.ReadLine().Trim().ToLower();
|
input = Con.ReadLine().ToLower();
|
||||||
config.SyncGroups = input == "y" || input == "yes" || string.IsNullOrWhiteSpace(input);
|
if(!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
config.SyncGroups = input == "y" || input == "yes";
|
||||||
|
}
|
||||||
if(config.SyncGroups)
|
if(config.SyncGroups)
|
||||||
{
|
{
|
||||||
Con.Write("Group filter [{0}]: ", config.GroupFilter);
|
Con.Write("Group filter [{0}]: ", config.GroupFilter);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.GroupFilter = input;
|
config.GroupFilter = input;
|
||||||
}
|
}
|
||||||
Con.Write("Group name attribute [{0}]: ", config.GroupNameAttribute);
|
Con.Write("Group name attribute [{0}]: ", config.GroupNameAttribute);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.GroupNameAttribute = input;
|
config.GroupNameAttribute = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Con.Write("Sync users? [{0}]: ", config.SyncUsers ? "y" : "n");
|
Con.Write("Sync users? [{0}]: ", config.SyncUsers ? "y" : "n");
|
||||||
input = Con.ReadLine().Trim().ToLower();
|
input = Con.ReadLine().ToLower();
|
||||||
config.SyncUsers = input == "y" || input == "yes" || string.IsNullOrWhiteSpace(input);
|
if(!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
config.SyncUsers = input == "y" || input == "yes";
|
||||||
|
}
|
||||||
if(config.SyncUsers)
|
if(config.SyncUsers)
|
||||||
{
|
{
|
||||||
Con.Write("User filter [{0}]: ", config.UserFilter);
|
Con.Write("User filter [{0}]: ", config.UserFilter);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.UserFilter = input;
|
config.UserFilter = input;
|
||||||
}
|
}
|
||||||
Con.Write("User email attribute [{0}]: ", config.UserEmailAttribute);
|
Con.Write("User email attribute [{0}]: ", config.UserEmailAttribute);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.GroupNameAttribute = input;
|
config.GroupNameAttribute = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Con.Write("Member Of Attribute [{0}]: ", config.MemberAttribute);
|
Con.Write("Member Of Attribute [{0}]: ", config.MemberAttribute);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.MemberAttribute = input;
|
config.MemberAttribute = input;
|
||||||
}
|
}
|
||||||
Con.Write("Creation Attribute [{0}]: ", config.CreationDateAttribute);
|
Con.Write("Creation Attribute [{0}]: ", config.CreationDateAttribute);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.CreationDateAttribute = input;
|
config.CreationDateAttribute = input;
|
||||||
}
|
}
|
||||||
Con.Write("Changed Attribute [{0}]: ", config.RevisionDateAttribute);
|
Con.Write("Changed Attribute [{0}]: ", config.RevisionDateAttribute);
|
||||||
input = Con.ReadLine().Trim();
|
input = Con.ReadLine();
|
||||||
if(!string.IsNullOrWhiteSpace(input))
|
if(!string.IsNullOrEmpty(input))
|
||||||
{
|
{
|
||||||
config.RevisionDateAttribute = input;
|
config.RevisionDateAttribute = input;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
<Compile Include="Services\TokenService.cs" />
|
<Compile Include="Services\TokenService.cs" />
|
||||||
<Compile Include="Services\AuthService.cs" />
|
<Compile Include="Services\AuthService.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Utilities\Extensions.cs" />
|
||||||
<Compile Include="Utilities\Sync.cs" />
|
<Compile Include="Utilities\Sync.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Bit.Core.Enums
|
|||||||
public enum DirectoryType : byte
|
public enum DirectoryType : byte
|
||||||
{
|
{
|
||||||
ActiveDirectory = 0,
|
ActiveDirectory = 0,
|
||||||
AzureActiveCirectory = 1,
|
AzureActiveDirectory = 1,
|
||||||
Other = 2
|
Other = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Bit.Core.Enums;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.DirectoryServices;
|
using System.DirectoryServices;
|
||||||
@@ -10,17 +11,38 @@ namespace Bit.Core.Models
|
|||||||
{
|
{
|
||||||
public class SyncConfiguration
|
public class SyncConfiguration
|
||||||
{
|
{
|
||||||
|
public SyncConfiguration() { }
|
||||||
|
|
||||||
|
public SyncConfiguration(DirectoryType type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case DirectoryType.ActiveDirectory:
|
||||||
|
MemberAttribute = "memberOf";
|
||||||
|
CreationDateAttribute = "whenCreated";
|
||||||
|
RevisionDateAttribute = "whenChanged";
|
||||||
|
UserEmailPrefixAttribute = "sAMAccountName";
|
||||||
|
break;
|
||||||
|
case DirectoryType.AzureActiveDirectory:
|
||||||
|
break;
|
||||||
|
case DirectoryType.Other:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string GroupFilter { get; set; } = "(&(objectClass=group))";
|
public string GroupFilter { get; set; } = "(&(objectClass=group))";
|
||||||
public string UserFilter { get; set; } = "(&(objectClass=person))";
|
public string UserFilter { get; set; } = "(&(objectClass=person))";
|
||||||
public bool SyncGroups { get; set; } = true;
|
public bool SyncGroups { get; set; } = true;
|
||||||
public bool SyncUsers { get; set; } = true;
|
public bool SyncUsers { get; set; } = true;
|
||||||
public string MemberAttribute { get; set; } = "memberOf";
|
public string MemberAttribute { get; set; } = "member";
|
||||||
public string GroupNameAttribute { get; set; } = "name";
|
public string GroupNameAttribute { get; set; } = "name";
|
||||||
public string UserEmailAttribute { get; set; } = "mail";
|
public string UserEmailAttribute { get; set; } = "mail";
|
||||||
public bool EmailPrefixSuffix { get; set; } = false;
|
public bool EmailPrefixSuffix { get; set; } = false;
|
||||||
public string UserEmailPrefixAttribute { get; set; } = "sAMAccountName";
|
public string UserEmailPrefixAttribute { get; set; } = "cn";
|
||||||
public string UserEmailSuffix { get; set; } = "@companyname.com";
|
public string UserEmailSuffix { get; set; } = "@companyname.com";
|
||||||
public string CreationDateAttribute { get; set; } = "whenCreated";
|
public string CreationDateAttribute { get; set; }
|
||||||
public string RevisionDateAttribute { get; set; } = "whenChanged";
|
public string RevisionDateAttribute { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,32 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DateTime? LastGroupSyncDate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Settings.LastGroupSyncDate;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Settings.LastGroupSyncDate = value;
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime? LastUserSyncDate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Settings.LastUserSyncDate;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Settings.LastUserSyncDate = value;
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class SettingsModel
|
public class SettingsModel
|
||||||
{
|
{
|
||||||
public string ApiBaseUrl { get; set; }
|
public string ApiBaseUrl { get; set; }
|
||||||
@@ -175,6 +201,8 @@ namespace Bit.Core.Services
|
|||||||
public ServerConfiguration Server { get; set; }
|
public ServerConfiguration Server { get; set; }
|
||||||
public SyncConfiguration Sync { get; set; }
|
public SyncConfiguration Sync { get; set; }
|
||||||
public Organization Organization { get; set; }
|
public Organization Organization { get; set; }
|
||||||
|
public DateTime? LastGroupSyncDate { get; set; }
|
||||||
|
public DateTime? LastUserSyncDate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/Core/Utilities/Extensions.cs
Normal file
24
src/Core/Utilities/Extensions.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Core.Utilities
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
private const string GeneralizedTimeFormat = "yyyyMMddHHmmss.f'Z'";
|
||||||
|
|
||||||
|
public static DateTime ToDateTime(this string generalizedTimeString)
|
||||||
|
{
|
||||||
|
return DateTime.ParseExact(generalizedTimeString, GeneralizedTimeFormat, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToGeneralizedTimeUTC(this DateTime date)
|
||||||
|
{
|
||||||
|
return date.ToString("yyyyMMddHHmmss.f'Z'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,6 +40,8 @@ namespace Bit.Core.Utilities
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
List<GroupEntry> groups = null;
|
List<GroupEntry> groups = null;
|
||||||
if(SettingsService.Instance.Sync.SyncGroups)
|
if(SettingsService.Instance.Sync.SyncGroups)
|
||||||
{
|
{
|
||||||
@@ -58,6 +60,16 @@ namespace Bit.Core.Utilities
|
|||||||
var response = await ApiService.Instance.PostImportAsync(request);
|
var response = await ApiService.Instance.PostImportAsync(request);
|
||||||
if(response.Succeeded)
|
if(response.Succeeded)
|
||||||
{
|
{
|
||||||
|
if(SettingsService.Instance.Sync.SyncGroups)
|
||||||
|
{
|
||||||
|
SettingsService.Instance.LastGroupSyncDate = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SettingsService.Instance.Sync.SyncUsers)
|
||||||
|
{
|
||||||
|
SettingsService.Instance.LastUserSyncDate = now;
|
||||||
|
}
|
||||||
|
|
||||||
return new SyncResult
|
return new SyncResult
|
||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
@@ -100,6 +112,16 @@ namespace Bit.Core.Utilities
|
|||||||
var entry = SettingsService.Instance.Server.GetDirectoryEntry();
|
var entry = SettingsService.Instance.Server.GetDirectoryEntry();
|
||||||
var filter = string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.GroupFilter) ? null :
|
var filter = string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.GroupFilter) ? null :
|
||||||
SettingsService.Instance.Sync.GroupFilter;
|
SettingsService.Instance.Sync.GroupFilter;
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.RevisionDateAttribute) &&
|
||||||
|
SettingsService.Instance.LastGroupSyncDate.HasValue)
|
||||||
|
{
|
||||||
|
filter = string.Format("(&{0}({1}>{2}))",
|
||||||
|
filter != null ? string.Format("({0})", filter) : string.Empty,
|
||||||
|
SettingsService.Instance.Sync.RevisionDateAttribute,
|
||||||
|
SettingsService.Instance.LastGroupSyncDate.Value.ToGeneralizedTimeUTC());
|
||||||
|
}
|
||||||
|
|
||||||
var searcher = new DirectorySearcher(entry, filter);
|
var searcher = new DirectorySearcher(entry, filter);
|
||||||
var result = searcher.FindAll();
|
var result = searcher.FindAll();
|
||||||
|
|
||||||
@@ -180,6 +202,16 @@ namespace Bit.Core.Utilities
|
|||||||
var entry = SettingsService.Instance.Server.GetDirectoryEntry();
|
var entry = SettingsService.Instance.Server.GetDirectoryEntry();
|
||||||
var filter = string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.UserFilter) ? null :
|
var filter = string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.UserFilter) ? null :
|
||||||
SettingsService.Instance.Sync.UserFilter;
|
SettingsService.Instance.Sync.UserFilter;
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(SettingsService.Instance.Sync.RevisionDateAttribute) &&
|
||||||
|
SettingsService.Instance.LastUserSyncDate.HasValue)
|
||||||
|
{
|
||||||
|
filter = string.Format("(&{0}({1}>{2}))",
|
||||||
|
filter != null ? string.Format("({0})", filter) : string.Empty,
|
||||||
|
SettingsService.Instance.Sync.RevisionDateAttribute,
|
||||||
|
SettingsService.Instance.LastUserSyncDate.Value.ToGeneralizedTimeUTC());
|
||||||
|
}
|
||||||
|
|
||||||
var searcher = new DirectorySearcher(entry, filter);
|
var searcher = new DirectorySearcher(entry, filter);
|
||||||
var result = searcher.FindAll();
|
var result = searcher.FindAll();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user