initial commit
This commit is contained in:
129
DigitalData.Core.Authentication/Services/ADService.cs
Normal file
129
DigitalData.Core.Authentication/Services/ADService.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using DigitalData.Core.Attributes;
|
||||
using DigitalData.Core.Contracts.Authentication.Services;
|
||||
using System.Collections;
|
||||
using System.DirectoryServices;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DigitalData.Core.Authentication.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for interacting with Active Directory to perform searches and read data into objects of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type into which Active Directory search results will be mapped.</typeparam>
|
||||
public class ADService<T> : IADService<T> where T : new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DirectorySearcher"/> used for performing Active Directory searches.
|
||||
/// </summary>
|
||||
public DirectorySearcher Searcher { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ADService{T}"/> class.
|
||||
/// Sets up the directory searcher with the appropriate search scope and size limit,
|
||||
/// and applies a custom filter if defined on the type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <exception cref="PlatformNotSupportedException">Thrown when not running on Windows.</exception>
|
||||
public ADService() {
|
||||
if (!OperatingSystem.IsWindows())
|
||||
throw new PlatformNotSupportedException("The ListGroups method is only supported on the windows platform.");
|
||||
|
||||
Searcher = new()
|
||||
{
|
||||
SearchScope = SearchScope.Subtree,
|
||||
SizeLimit = 50000
|
||||
};
|
||||
|
||||
if (AttrHelper.GetFilterAttrOf<T>()?.Query is string filter)
|
||||
Searcher.Filter = filter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a search in Active Directory using the current filter and returns all matching entries.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="SearchResultCollection"/> containing all search results.</returns>
|
||||
/// <exception cref="PlatformNotSupportedException">Thrown when not running on Windows.</exception>
|
||||
public SearchResultCollection SearchAll()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
throw new PlatformNotSupportedException("The ListGroups method is only supported on the windows platform.");
|
||||
|
||||
return Searcher.FindAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all search results into a list of objects of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <returns>A list of objects of type <typeparamref name="T"/> that represents all found Active Directory entries.</returns>
|
||||
/// <exception cref="PlatformNotSupportedException">Thrown when not running on Windows.</exception>
|
||||
public IEnumerable<T> ReadAll()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
throw new PlatformNotSupportedException("The ListGroups method is only supported on the windows platform.");
|
||||
|
||||
List<T> list = new();
|
||||
foreach (SearchResult result in SearchAll())
|
||||
{
|
||||
ResultPropertyCollection rpc = result.Properties;
|
||||
T obj = MapResultProperty<T>(rpc);
|
||||
list.Add(obj);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps properties from a <see cref="ResultPropertyCollection"/> to a new instance of type <typeparamref name="TDest"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDest">The destination type for the properties to be mapped to.</typeparam>
|
||||
/// <param name="rpc">The collection of result properties from an Active Directory search result.</param>
|
||||
/// <returns>A new instance of <typeparamref name="TDest"/> with properties set based on the search result.</returns>
|
||||
/// <exception cref="PlatformNotSupportedException">Thrown when not running on Windows.</exception>
|
||||
public static TDest MapResultProperty<TDest>(ResultPropertyCollection rpc) where TDest : new()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
throw new PlatformNotSupportedException("The method is only supported on the Windows platform.");
|
||||
|
||||
TDest resultObject = new();
|
||||
foreach (string propertyName in rpc.PropertyNames ?? throw new ArgumentNullException("PropertyNames are null"))
|
||||
{
|
||||
var propertyValue = rpc[propertyName][0];
|
||||
PropertyInfo? pi = typeof(TDest).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (pi != null && propertyValue != null)
|
||||
{
|
||||
Type propertyType = pi.PropertyType;
|
||||
Type underlyingType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
|
||||
|
||||
if (propertyType != underlyingType)
|
||||
{
|
||||
propertyValue = Convert.ChangeType(propertyValue, underlyingType);
|
||||
pi.SetValue(resultObject, propertyValue);
|
||||
}
|
||||
else if (typeof(IEnumerable).IsAssignableFrom(propertyType) && propertyType != typeof(string))
|
||||
{
|
||||
var itemType = propertyType.GetGenericArguments()[0];
|
||||
IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType));
|
||||
list.Add(Convert.ChangeType(propertyValue, itemType));
|
||||
pi.SetValue(resultObject, list);
|
||||
}
|
||||
else if (propertyValue is byte[] && propertyType == typeof(string))
|
||||
{
|
||||
pi.SetValue(resultObject, Convert.ToBase64String((byte[])propertyValue));
|
||||
}
|
||||
else if (propertyValue is byte[] stBytes && propertyType == typeof(string))
|
||||
{
|
||||
pi.SetValue(resultObject, BitConverter.ToString(stBytes).Replace("-", ""));
|
||||
}
|
||||
else if (propertyValue is byte[] guiBytes && propertyType == typeof(Guid))
|
||||
{
|
||||
pi.SetValue(resultObject, new Guid(guiBytes));
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyValue = Convert.ChangeType(propertyValue, propertyType);
|
||||
pi.SetValue(resultObject, propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user