103 lines
4.8 KiB
C#
103 lines
4.8 KiB
C#
using DigitalData.Core.Contracts.Application;
|
|
using Microsoft.Extensions.Logging;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.DirectoryServices;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Microsoft.Extensions.Configuration;
|
|
using System.DirectoryServices.AccountManagement;
|
|
using Microsoft.Extensions.Localization;
|
|
|
|
namespace DigitalData.Core.Application
|
|
{
|
|
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
|
public class DirectorySearchService : ServiceBase, IDirectorySearchService
|
|
{
|
|
private readonly IMemoryCache _memoryCache;
|
|
public string ServerName { get; }
|
|
public string Root { get; }
|
|
public string SearchRootPath { get; }
|
|
private readonly DateTimeOffset _userCacheExpiration;
|
|
public Dictionary<string, string> CustomSearchFilters { get; }
|
|
|
|
public DirectorySearchService(IConfiguration configuration, ILogger<DirectorySearchService> logger, IMemoryCache memoryCache, IStringLocalizer defaultLocalizer) : base(defaultLocalizer)
|
|
{
|
|
_memoryCache = memoryCache;
|
|
|
|
ServerName = configuration["DirectorySearch:ServerName"] ?? throw new InvalidOperationException("The server name for directory search is not configured. Please specify the 'DirectorySearch:ServerName' in the configuration.");
|
|
|
|
Root = configuration["DirectorySearch:Root"] ?? throw new InvalidOperationException("The root for directory search is not configured. Please specify the 'DirectorySearch:Root' in the configuration.");
|
|
|
|
SearchRootPath = $"LDAP://{ServerName}/{Root}";
|
|
|
|
var customSearchFiltersSection = configuration.GetSection("DirectorySearch:CustomSearchFilters");
|
|
CustomSearchFilters = customSearchFiltersSection.Get<Dictionary<string, string>>() ?? new();
|
|
|
|
var dayCounts = configuration.GetValue<int>("DirectorySearch:UserCacheExpirationDays");
|
|
if (dayCounts == default)
|
|
_userCacheExpiration = default;
|
|
else
|
|
_userCacheExpiration = DateTimeOffset.Now.Date.AddDays(dayCounts);
|
|
}
|
|
|
|
public bool ValidateCredentials(string dirEntryUsername, string dirEntryPassword)
|
|
{
|
|
using var context = new PrincipalContext(ContextType.Domain, ServerName, Root);
|
|
return context.ValidateCredentials(dirEntryUsername, dirEntryPassword);
|
|
}
|
|
|
|
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
|
|
{
|
|
List<ResultPropertyCollection> list = new();
|
|
|
|
var searcher = new DirectorySearcher()
|
|
{
|
|
Filter = filter,
|
|
SearchScope = searchScope,
|
|
SizeLimit = sizeLimit,
|
|
SearchRoot = searchRoot
|
|
};
|
|
|
|
if (properties.Length > 0)
|
|
{
|
|
searcher.PropertiesToLoad.Clear();
|
|
foreach (var property in properties)
|
|
if(property is not null)
|
|
searcher.PropertiesToLoad.Add(property);
|
|
}
|
|
|
|
foreach (SearchResult result in searcher.FindAll())
|
|
{
|
|
ResultPropertyCollection rpc = result.Properties;
|
|
list.Add(rpc);
|
|
}
|
|
|
|
return Successful<IEnumerable<ResultPropertyCollection>>(list);
|
|
}
|
|
|
|
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
|
|
{
|
|
List<ResultPropertyCollection> list = new();
|
|
|
|
_memoryCache.TryGetValue(username, out DirectoryEntry? searchRoot);
|
|
|
|
if (searchRoot is null)
|
|
return Failed<IEnumerable<ResultPropertyCollection>>(MessageKey.DirSearcherDisconnected.ToString());
|
|
|
|
return FindAll(searchRoot, filter, searchScope, sizeLimit, properties);
|
|
}
|
|
|
|
public void SetSearchRootCache(string dirEntryUsername, string dirEntryPassword)
|
|
{
|
|
if (_userCacheExpiration == default)
|
|
_memoryCache.Set(key: dirEntryUsername, new DirectoryEntry(path: SearchRootPath, username: dirEntryUsername, password: dirEntryPassword));
|
|
else
|
|
_memoryCache.Set(key: dirEntryUsername, new DirectoryEntry(path: SearchRootPath, username: dirEntryUsername, password: dirEntryPassword), absoluteExpiration: _userCacheExpiration);
|
|
}
|
|
|
|
public DirectoryEntry? GetSearchRootCache(string dirEntryUsername)
|
|
{
|
|
_memoryCache.TryGetValue(dirEntryUsername, out DirectoryEntry? root);
|
|
return root;
|
|
}
|
|
}
|
|
} |