DotBased/DotBased.AspNet.Authority/Managers/AuthorityManager.cs

105 lines
3.8 KiB
C#
Raw Normal View History

2024-12-25 22:50:04 +01:00
using System.Reflection;
using DotBased.AspNet.Authority.Attributes;
using DotBased.AspNet.Authority.Crypto;
using DotBased.AspNet.Authority.Models.Options;
using DotBased.AspNet.Authority.Repositories;
using DotBased.AspNet.Authority.Validators;
2024-12-25 22:50:04 +01:00
using DotBased.Logging;
using Microsoft.Extensions.Options;
namespace DotBased.AspNet.Authority.Managers;
2024-12-21 15:30:17 +01:00
public partial class AuthorityManager
2024-12-21 15:30:17 +01:00
{
2024-12-25 22:50:04 +01:00
public AuthorityManager(
IOptions<AuthorityOptions> options,
IServiceProvider services,
ICryptographer cryptographer,
IUserRepository userRepository,
IPasswordHasher passwordHasher)
2024-12-25 22:50:04 +01:00
{
_logger = LogService.RegisterLogger<AuthorityManager>();
Options = options.Value;
2024-12-25 22:50:04 +01:00
Services = services;
Cryptographer = cryptographer;
UserRepository = userRepository;
PasswordHasher = passwordHasher;
2024-12-25 22:50:04 +01:00
}
private readonly ILogger _logger;
public IServiceProvider Services { get; }
public AuthorityOptions Options { get; }
public ICryptographer Cryptographer { get; }
public IUserRepository UserRepository { get; }
public IPasswordHasher PasswordHasher { get; }
public IEnumerable<IPasswordValidator> PasswordValidators { get; } = [];
public IEnumerable<IUserValidator> UserValidators { get; } = [];
2024-12-25 22:50:04 +01:00
public long GenerateVersion() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
2024-12-26 20:01:57 +01:00
2024-12-25 22:50:04 +01:00
/// <summary>
/// Protect or unprotect the properties with the <see cref="ProtectAttribute"/>
/// </summary>
/// <param name="data">The data model</param>
/// <param name="protection">True for protect false for unprotect.</param>
2024-12-25 22:50:04 +01:00
/// <typeparam name="TModel">The class with the properties to protect.</typeparam>
public async Task HandlePropertyProtection<TModel>(TModel data, bool protection)
{
var props = GetProtectedPropertiesValues(data);
2024-12-25 22:50:04 +01:00
if (props.Count == 0)
{
return;
}
var handledProperties = 0;
foreach (var property in props)
{
if (property.PropertyType != typeof(string))
{
_logger.Warning("Property({PropName}) with type: {PropType} detected, encrypting only supports strings! Skipping property!", property.Name, property.PropertyType);
continue;
}
string? cryptString;
if (protection)
{
cryptString = await Cryptographer.EncryptAsync(property.GetValue(data)?.ToString() ?? string.Empty);
}
else
{
cryptString = await Cryptographer.DecryptAsync(property.GetValue(data)?.ToString() ?? string.Empty);
}
if (cryptString == null)
{
_logger.Warning("{Protection} failed for property {PropName}", protection ? "Encryption" : "Decryption", property.Name);
2024-12-25 22:50:04 +01:00
continue;
}
property.SetValue(data, cryptString);
handledProperties++;
}
_logger.Debug("{HandledPropCount}/{TotalPropCount} protection properties handled!", handledProperties, props.Count);
}
2024-12-30 15:40:52 +01:00
public bool IsPropertyProtected<TModel>(string propertyName)
2024-12-25 22:50:04 +01:00
{
var protectedProperties = GetProtectedProperties<TModel>();
2024-12-30 15:40:52 +01:00
var propertyFound = protectedProperties.Where(propInfo => propInfo.Name == propertyName);
return propertyFound.Any();
2024-12-25 22:50:04 +01:00
}
public List<PropertyInfo> GetProtectedPropertiesValues<TModel>(TModel model)
{
var protectedProperties = GetProtectedProperties<TModel>();
return protectedProperties.Count != 0 ? protectedProperties : [];
}
public List<PropertyInfo> GetProtectedProperties<TModel>()
=> typeof(TModel).GetProperties().Where(p => Attribute.IsDefined(p, typeof(ProtectAttribute))).ToList();
2024-12-21 15:30:17 +01:00
}