[CHANGE] Implementing managers. repositories
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace DotBased.AspNet.Authority.Managers;
|
||||
|
||||
public class AuthorityGroupManager<TGroup>
|
||||
{
|
||||
|
||||
}
|
97
DotBased.AspNet.Authority/Managers/AuthorityManager.cs
Normal file
97
DotBased.AspNet.Authority/Managers/AuthorityManager.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System.Reflection;
|
||||
using DotBased.AspNet.Authority.Attributes;
|
||||
using DotBased.AspNet.Authority.Crypto;
|
||||
using DotBased.AspNet.Authority.Models.Options;
|
||||
using DotBased.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace DotBased.AspNet.Authority.Managers;
|
||||
|
||||
public class AuthorityManager
|
||||
{
|
||||
public AuthorityManager(
|
||||
IOptions<AuthorityOptions> options,
|
||||
IServiceProvider services,
|
||||
ICryptographer cryptographer)
|
||||
{
|
||||
_logger = LogService.RegisterLogger<AuthorityManager>();
|
||||
Options = options.Value ?? new AuthorityOptions();
|
||||
Services = services;
|
||||
Cryptographer = cryptographer;
|
||||
}
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public IServiceProvider Services { get; }
|
||||
public AuthorityOptions Options { get; }
|
||||
public ICryptographer Cryptographer { get; }
|
||||
|
||||
|
||||
public long GenerateVersion() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
|
||||
/// <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>
|
||||
/// <typeparam name="TModel">The class with the properties to protect.</typeparam>
|
||||
public async Task HandlePropertyProtection<TModel>(TModel data, bool protection)
|
||||
{
|
||||
var props = GetProtectedPropertiesValues<TModel>(data);
|
||||
if (Cryptographer == null)
|
||||
{
|
||||
_logger.Warning("No cryptographer specified! Cannot encrypt/decrypt properties.");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
property.SetValue(data, cryptString);
|
||||
handledProperties++;
|
||||
}
|
||||
_logger.Debug("{HandledPropCount}/{TotalPropCount} protection properties handled!", handledProperties, props.Count);
|
||||
}
|
||||
|
||||
public bool IsPropertyProtected<TModel>(string propertyName)
|
||||
{
|
||||
var protectedProperties = GetProtectedProperties<TModel>();
|
||||
var propertyFound = protectedProperties.Where(propInfo => propInfo.Name == propertyName);
|
||||
return propertyFound.Any();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
namespace DotBased.AspNet.Authority.Managers;
|
||||
|
||||
public class AuthorityRoleManager<TRole>
|
||||
{
|
||||
|
||||
}
|
97
DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs
Normal file
97
DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using DotBased.AspNet.Authority.Crypto;
|
||||
using DotBased.AspNet.Authority.Models;
|
||||
using DotBased.AspNet.Authority.Models.Authority;
|
||||
using DotBased.AspNet.Authority.Models.Validation;
|
||||
using DotBased.AspNet.Authority.Repositories;
|
||||
using DotBased.AspNet.Authority.Validators;
|
||||
using DotBased.Logging;
|
||||
|
||||
namespace DotBased.AspNet.Authority.Managers;
|
||||
|
||||
public class AuthorityUserManager<TUser> where TUser : class
|
||||
{
|
||||
public AuthorityUserManager(
|
||||
AuthorityManager manager,
|
||||
IUserRepository<TUser> userRepository,
|
||||
IPasswordHasher passwordHasher,
|
||||
IEnumerable<IPasswordValidator<TUser>>? passwordValidators,
|
||||
IEnumerable<IUserValidator<TUser>>? userValidators)
|
||||
{
|
||||
_logger = LogService.RegisterLogger<AuthorityUserManager<TUser>>();
|
||||
AuthorityManager = manager;
|
||||
UserRepository = userRepository;
|
||||
PasswordHasher = passwordHasher;
|
||||
if (passwordValidators != null)
|
||||
PasswordValidators = passwordValidators;
|
||||
if (userValidators != null)
|
||||
UserValidators = userValidators;
|
||||
}
|
||||
|
||||
private readonly ILogger _logger;
|
||||
public AuthorityManager AuthorityManager { get; }
|
||||
public IUserRepository<TUser> UserRepository { get; }
|
||||
|
||||
public IPasswordHasher PasswordHasher { get; }
|
||||
|
||||
public IEnumerable<IPasswordValidator<TUser>> PasswordValidators { get; } = [];
|
||||
public IEnumerable<IUserValidator<TUser>> UserValidators { get; } = [];
|
||||
|
||||
public async Task<ValidationResult> ValidatePasswordAsync(TUser user, string password)
|
||||
{
|
||||
List<ValidationError> errors = [];
|
||||
foreach (var validator in PasswordValidators)
|
||||
{
|
||||
var validatorResult = await validator.ValidatePasswordAsync(this, user, password);
|
||||
if (!validatorResult.Success)
|
||||
{
|
||||
errors.AddRange(validatorResult.Errors);
|
||||
}
|
||||
}
|
||||
return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok();
|
||||
}
|
||||
|
||||
public async Task<ValidationResult> ValidateUserAsync(TUser user)
|
||||
{
|
||||
List<ValidationError> errors = [];
|
||||
foreach (var userValidator in UserValidators)
|
||||
{
|
||||
var validationResult = await userValidator.ValidateUserAsync(this, user);
|
||||
if (!validationResult.Success)
|
||||
{
|
||||
errors.AddRange(validationResult.Errors);
|
||||
}
|
||||
}
|
||||
return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok();
|
||||
}
|
||||
|
||||
public async Task<AuthorityResult<TUser>> CreateUserAsync(TUser userModel, string password)
|
||||
{
|
||||
if (userModel is not AuthorityUserBase userBase)
|
||||
{
|
||||
return AuthorityResult<TUser>.Error($"Given user is not of base type {nameof(AuthorityUserBase)}!");
|
||||
}
|
||||
|
||||
var userValidation = await ValidateUserAsync(userModel);
|
||||
var passwordValidation = await ValidatePasswordAsync(userModel, password);
|
||||
if (!userValidation.Success || !passwordValidation.Success)
|
||||
{
|
||||
List<ValidationError> errors = [];
|
||||
errors.AddRange(userValidation.Errors);
|
||||
errors.AddRange(passwordValidation.Errors);
|
||||
return AuthorityResult<TUser>.Failed(errors, ResultFailReason.Validation);
|
||||
}
|
||||
|
||||
var version = AuthorityManager.GenerateVersion();
|
||||
userBase.Version = version;
|
||||
var securityVersion = AuthorityManager.GenerateVersion();
|
||||
userBase.SecurityVersion = securityVersion;
|
||||
var hashedPassword = await PasswordHasher.HashPasswordAsync(password);
|
||||
userBase.PasswordHash = hashedPassword;
|
||||
|
||||
var userCreationResult = await UserRepository.CreateUserAsync(userModel);
|
||||
|
||||
return userCreationResult != null
|
||||
? AuthorityResult<TUser>.Ok(userCreationResult)
|
||||
: AuthorityResult<TUser>.Error("Failed to create user in repository!");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user