From 90cd0a2828cd5802077b305b2ad206abf06f7686 Mon Sep 17 00:00:00 2001 From: max Date: Wed, 8 Jan 2025 15:55:00 +0100 Subject: [PATCH] [CHANGE] Removed generics and using base classes --- .../AuthorityProviderExtensions.cs | 17 ++--- .../Managers/AuthorityGroupManager.cs | 2 +- .../Managers/AuthorityRoleManager.cs | 2 +- .../Managers/AuthorityUserManager.cs | 66 ++++++++----------- .../Models/Authority/AuthorityUser.cs | 14 ++-- .../Repositories/IAttributeRepository.cs | 2 +- .../Repositories/IGroupRepository.cs | 2 +- .../Repositories/IRoleRepository.cs | 2 +- .../Repositories/IUserRepository.cs | 26 ++++---- .../Validators/IPasswordValidator.cs | 5 +- .../Validators/IUserValidator.cs | 5 +- .../Validators/PasswordEqualsValidator.cs | 11 +--- .../Validators/PasswordOptionsValidator.cs | 5 +- .../Validators/UserValidator.cs | 23 +++---- 14 files changed, 77 insertions(+), 105 deletions(-) diff --git a/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs b/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs index ab2b8fc..88c02f2 100644 --- a/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs +++ b/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs @@ -1,6 +1,5 @@ using DotBased.AspNet.Authority.Crypto; using DotBased.AspNet.Authority.Managers; -using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Models.Options; using DotBased.AspNet.Authority.Validators; using Microsoft.Extensions.DependencyInjection; @@ -11,10 +10,6 @@ namespace DotBased.AspNet.Authority; public static class AuthorityProviderExtensions { public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action? optionsAction = null) - => services.AddAuthority(optionsAction); - - public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action? optionsAction = null) - where TUser : class where TGroup : class where TRole : class { if (optionsAction != null) { @@ -24,16 +19,16 @@ public static class AuthorityProviderExtensions services.TryAddScoped(); services.TryAddScoped(); - services.TryAddScoped, PasswordOptionsValidator>(); - services.TryAddScoped, PasswordEqualsValidator>(); - services.TryAddScoped, UserValidator>(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); /*services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped();*/ services.TryAddScoped(); - services.TryAddScoped>(); - services.TryAddScoped>(); - services.TryAddScoped>(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); return new AuthorityBuilder(services); } diff --git a/DotBased.AspNet.Authority/Managers/AuthorityGroupManager.cs b/DotBased.AspNet.Authority/Managers/AuthorityGroupManager.cs index a4dffbe..7da7e73 100644 --- a/DotBased.AspNet.Authority/Managers/AuthorityGroupManager.cs +++ b/DotBased.AspNet.Authority/Managers/AuthorityGroupManager.cs @@ -1,6 +1,6 @@ namespace DotBased.AspNet.Authority.Managers; -public class AuthorityGroupManager +public class AuthorityGroupManager { } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs b/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs index c41b6d2..420b639 100644 --- a/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs +++ b/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs @@ -1,6 +1,6 @@ namespace DotBased.AspNet.Authority.Managers; -public class AuthorityRoleManager +public class AuthorityRoleManager { } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs b/DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs index f72af18..6cc0974 100644 --- a/DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs +++ b/DotBased.AspNet.Authority/Managers/AuthorityUserManager.cs @@ -8,16 +8,16 @@ using DotBased.Logging; namespace DotBased.AspNet.Authority.Managers; -public class AuthorityUserManager where TUser : class +public class AuthorityUserManager { public AuthorityUserManager( AuthorityManager manager, - IUserRepository userRepository, + IUserRepository userRepository, IPasswordHasher passwordHasher, - IEnumerable>? passwordValidators, - IEnumerable>? userValidators) + IEnumerable? passwordValidators, + IEnumerable? userValidators) { - _logger = LogService.RegisterLogger>(); + _logger = LogService.RegisterLogger(); AuthorityManager = manager; UserRepository = userRepository; PasswordHasher = passwordHasher; @@ -29,14 +29,14 @@ public class AuthorityUserManager where TUser : class private readonly ILogger _logger; public AuthorityManager AuthorityManager { get; } - public IUserRepository UserRepository { get; } + public IUserRepository UserRepository { get; } public IPasswordHasher PasswordHasher { get; } - public IEnumerable> PasswordValidators { get; } = []; - public IEnumerable> UserValidators { get; } = []; + public IEnumerable PasswordValidators { get; } = []; + public IEnumerable UserValidators { get; } = []; - public async Task ValidatePasswordAsync(TUser user, string password) + public async Task ValidatePasswordAsync(AuthorityUser user, string password) { List errors = []; foreach (var validator in PasswordValidators) @@ -50,7 +50,7 @@ public class AuthorityUserManager where TUser : class return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok(); } - public async Task ValidateUserAsync(TUser user) + public async Task ValidateUserAsync(AuthorityUser user) { List errors = []; foreach (var userValidator in UserValidators) @@ -64,41 +64,31 @@ public class AuthorityUserManager where TUser : class return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok(); } - public async Task> SearchUsersAsync(string query, int maxResults = 20, int offset = 0) + public async Task> SearchUsersAsync(string query, int maxResults = 20, int offset = 0) { - var searchResult = await UserRepository.GetUsersAsync(query, maxResults, offset); - return searchResult.Item1 == null ? ListResult.Failed("No results!") : ListResult.Ok(searchResult.Item1, searchResult.Item2); + var searchResult = await UserRepository.GetAuthorityUsersAsync(query, maxResults, offset); + return searchResult.Item1 == null ? ListResult.Failed("No results!") : ListResult.Ok(searchResult.Item1, searchResult.Item2); } - public async Task> UpdatePasswordAsync(TUser user, string password) + public async Task> UpdatePasswordAsync(AuthorityUser user, string password) { - if (user is not AuthorityUserBase userBase) - { - return AuthorityResult.Error($"Given user is not of base type {nameof(AuthorityUserBase)}!"); - } - var passwordValidation = await ValidatePasswordAsync(user, password); if (!passwordValidation.Success) { List errors = []; errors.AddRange(passwordValidation.Errors); - return AuthorityResult.Failed(errors, ResultFailReason.Validation); + return AuthorityResult.Failed(errors, ResultFailReason.Validation); } - userBase.PasswordHash = await PasswordHasher.HashPasswordAsync(password); - userBase.SecurityVersion = AuthorityManager.GenerateVersion(); + user.PasswordHash = await PasswordHasher.HashPasswordAsync(password); + user.SecurityVersion = AuthorityManager.GenerateVersion(); var updateResult = await UserRepository.UpdateUserAsync(user); - return updateResult == null ? AuthorityResult.Error("Failed to save updates!") : AuthorityResult.Ok(updateResult); + return updateResult == null ? AuthorityResult.Error("Failed to save updates!") : AuthorityResult.Ok(updateResult); } - public async Task> CreateUserAsync(TUser userModel, string password) + public async Task> CreateUserAsync(AuthorityUser userModel, string password) { - if (userModel is not AuthorityUserBase userBase) - { - return AuthorityResult.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) @@ -106,28 +96,28 @@ public class AuthorityUserManager where TUser : class List errors = []; errors.AddRange(userValidation.Errors); errors.AddRange(passwordValidation.Errors); - return AuthorityResult.Failed(errors, ResultFailReason.Validation); + return AuthorityResult.Failed(errors, ResultFailReason.Validation); } - userBase.Version = AuthorityManager.GenerateVersion(); - userBase.SecurityVersion = AuthorityManager.GenerateVersion(); + userModel.Version = AuthorityManager.GenerateVersion(); + userModel.SecurityVersion = AuthorityManager.GenerateVersion(); var hashedPassword = await PasswordHasher.HashPasswordAsync(password); - userBase.PasswordHash = hashedPassword; + userModel.PasswordHash = hashedPassword; var userCreationResult = await UserRepository.CreateUserAsync(userModel); return userCreationResult != null - ? AuthorityResult.Ok(userCreationResult) - : AuthorityResult.Error("Failed to create user in repository!"); + ? AuthorityResult.Ok(userCreationResult) + : AuthorityResult.Error("Failed to create user in repository!"); } - public async Task> UpdateUserAsync(TUser model) + public async Task> UpdateUserAsync(AuthorityUser model) { var updateResult = await UserRepository.UpdateUserAsync(model); - return updateResult != null ? Result.Ok(updateResult) : Result.Failed("Failed to update user in repository!"); + return updateResult != null ? Result.Ok(updateResult) : Result.Failed("Failed to update user in repository!"); } - public async Task DeleteUserAsync(TUser model) + public async Task DeleteUserAsync(AuthorityUser model) { var deleteResult = await UserRepository.DeleteUserAsync(model); return deleteResult; diff --git a/DotBased.AspNet.Authority/Models/Authority/AuthorityUser.cs b/DotBased.AspNet.Authority/Models/Authority/AuthorityUser.cs index 7f7f87a..9f52b58 100644 --- a/DotBased.AspNet.Authority/Models/Authority/AuthorityUser.cs +++ b/DotBased.AspNet.Authority/Models/Authority/AuthorityUser.cs @@ -2,7 +2,7 @@ using DotBased.AspNet.Authority.Attributes; namespace DotBased.AspNet.Authority.Models.Authority; -public class AuthorityUser : AuthorityUser +public class AuthorityUser { public AuthorityUser(string userName) : this() { @@ -14,15 +14,9 @@ public class AuthorityUser : AuthorityUser Id = Guid.NewGuid(); CreatedDate = DateTime.Now; } -} - -public abstract class AuthorityUser : AuthorityUserBase where TKey : IEquatable -{ - public TKey Id { get; set; } -} - -public abstract class AuthorityUserBase -{ + + public Guid Id { get; set; } + public bool Enabled { get; set; } public bool Confirmed { get; set; } diff --git a/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs b/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs index 92272f3..7e22f88 100644 --- a/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs +++ b/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs @@ -1,6 +1,6 @@ namespace DotBased.AspNet.Authority.Repositories; -public interface IAttributeRepository where TAttribute : class where TId : IEquatable +public interface IAttributeRepository { } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs b/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs index e3c6369..f16b7d2 100644 --- a/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs +++ b/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs @@ -1,6 +1,6 @@ namespace DotBased.AspNet.Authority.Repositories; -public interface IGroupRepository where TGroup : class +public interface IGroupRepository { } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs index e3c9b4c..436076b 100644 --- a/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs +++ b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs @@ -1,6 +1,6 @@ namespace DotBased.AspNet.Authority.Repositories; -public interface IRoleRepository where TRole : class where TId : IEquatable +public interface IRoleRepository { } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Repositories/IUserRepository.cs b/DotBased.AspNet.Authority/Repositories/IUserRepository.cs index 46e833a..f86cdb5 100644 --- a/DotBased.AspNet.Authority/Repositories/IUserRepository.cs +++ b/DotBased.AspNet.Authority/Repositories/IUserRepository.cs @@ -1,16 +1,18 @@ +using DotBased.AspNet.Authority.Models.Authority; + namespace DotBased.AspNet.Authority.Repositories; -public interface IUserRepository where TUser : class +public interface IUserRepository { - public Task GetUserByIdAsync(string id, CancellationToken? cancellationToken = null); - public Task GetUserIdAsync(TUser user, CancellationToken? cancellationToken = null); - public Task?, int>> GetUsersAsync(string query, int maxResults = 20, int offset = 0, CancellationToken? cancellationToken = null); - public Task GetUserByEmailAsync(string email, CancellationToken? cancellationToken = null); - public Task SetVersionAsync(TUser user, long version, CancellationToken? cancellationToken = null); - public Task GetVersionAsync(TUser user, CancellationToken? cancellationToken = null); - public Task SetSecurityVersionAsync(TUser user, long version, CancellationToken? cancellationToken = null); - public Task GetSecurityVersionAsync(TUser user, CancellationToken? cancellationToken = null); - public Task CreateUserAsync(TUser user, CancellationToken? cancellationToken = null); - public Task UpdateUserAsync(TUser user, CancellationToken? cancellationToken = null); - public Task DeleteUserAsync(TUser user, CancellationToken? cancellationToken = null); + public Task GetAuthorityUserByIdAsync(string id, CancellationToken? cancellationToken = null); + public Task GetAuthorityUserIdAsync(AuthorityUser user, CancellationToken? cancellationToken = null); + public Task?, int>> GetAuthorityUsersAsync(string query, int maxResults = 20, int offset = 0, CancellationToken? cancellationToken = null); + public Task GetAuthorityUserByEmailAsync(string email, CancellationToken? cancellationToken = null); + public Task SetVersionAsync(AuthorityUser user, long version, CancellationToken? cancellationToken = null); + public Task GetVersionAsync(AuthorityUser user, CancellationToken? cancellationToken = null); + public Task SetSecurityVersionAsync(AuthorityUser user, long version, CancellationToken? cancellationToken = null); + public Task GetSecurityVersionAsync(AuthorityUser user, CancellationToken? cancellationToken = null); + public Task CreateUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null); + public Task UpdateUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null); + public Task DeleteUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null); } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs b/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs index 1f6304f..ff7c770 100644 --- a/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs +++ b/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs @@ -1,9 +1,10 @@ using DotBased.AspNet.Authority.Managers; +using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Models.Validation; namespace DotBased.AspNet.Authority.Validators; -public interface IPasswordValidator where TUser : class +public interface IPasswordValidator { - public Task ValidatePasswordAsync(AuthorityUserManager userManager, TUser user, string password); + public Task ValidatePasswordAsync(AuthorityUserManager userManager, AuthorityUser user, string password); } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Validators/IUserValidator.cs b/DotBased.AspNet.Authority/Validators/IUserValidator.cs index a2b3f69..da07405 100644 --- a/DotBased.AspNet.Authority/Validators/IUserValidator.cs +++ b/DotBased.AspNet.Authority/Validators/IUserValidator.cs @@ -1,9 +1,10 @@ using DotBased.AspNet.Authority.Managers; +using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Models.Validation; namespace DotBased.AspNet.Authority.Validators; -public interface IUserValidator where TUser : class +public interface IUserValidator { - public Task ValidateUserAsync(AuthorityUserManager manager, TUser user); + public Task ValidateUserAsync(AuthorityUserManager manager, AuthorityUser user); } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Validators/PasswordEqualsValidator.cs b/DotBased.AspNet.Authority/Validators/PasswordEqualsValidator.cs index b91de4a..a95c55d 100644 --- a/DotBased.AspNet.Authority/Validators/PasswordEqualsValidator.cs +++ b/DotBased.AspNet.Authority/Validators/PasswordEqualsValidator.cs @@ -4,20 +4,15 @@ using DotBased.AspNet.Authority.Models.Validation; namespace DotBased.AspNet.Authority.Validators; -public class PasswordEqualsValidator : IPasswordValidator where TUser : class +public class PasswordEqualsValidator : IPasswordValidator { private const string ValidatorId = "Authority.Validator.Password.Equals"; private const string ValidationBase = "Authority.Validation.Password"; - public async Task ValidatePasswordAsync(AuthorityUserManager userManager, TUser user, string password) + public async Task ValidatePasswordAsync(AuthorityUserManager userManager, AuthorityUser user, string password) { - if (user is not AuthorityUserBase authorityUser) - { - throw new ArgumentException($"User is not type of {nameof(AuthorityUserBase)}!", nameof(user)); - } - List errors = []; var hashedPassword = await userManager.PasswordHasher.HashPasswordAsync(password); - if (authorityUser.PasswordHash != null && authorityUser.PasswordHash.Equals(hashedPassword, StringComparison.Ordinal)) + if (user.PasswordHash != null && user.PasswordHash.Equals(hashedPassword, StringComparison.Ordinal)) { errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.InUse", "User uses this password already!")); } diff --git a/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs b/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs index 65de9b2..bd38b25 100644 --- a/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs +++ b/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs @@ -1,4 +1,5 @@ using DotBased.AspNet.Authority.Managers; +using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Models.Validation; using DotBased.Extensions; @@ -8,12 +9,12 @@ namespace DotBased.AspNet.Authority.Validators; /// Validates the password against the options that is configured. /// /// The user model used. -public class PasswordOptionsValidator : IPasswordValidator where TUser : class +public class PasswordOptionsValidator : IPasswordValidator { private const string ValidatorId = "Authority.Validator.Password.Options"; private const string ValidationBase = "Authority.Validation.Password"; - public async Task ValidatePasswordAsync(AuthorityUserManager userManager, TUser user, string password) + public async Task ValidatePasswordAsync(AuthorityUserManager userManager, AuthorityUser user, string password) { if (userManager == null) { diff --git a/DotBased.AspNet.Authority/Validators/UserValidator.cs b/DotBased.AspNet.Authority/Validators/UserValidator.cs index e23183b..317327f 100644 --- a/DotBased.AspNet.Authority/Validators/UserValidator.cs +++ b/DotBased.AspNet.Authority/Validators/UserValidator.cs @@ -5,34 +5,27 @@ using DotBased.AspNet.Authority.Models.Validation; namespace DotBased.AspNet.Authority.Validators; -public class UserValidator : IUserValidator where TUser : class +public class UserValidator : IUserValidator { private const string ValidatorId = "Authority.Validator.User"; private const string ValidationBase = "Authority.Validation.User"; - public async Task ValidateUserAsync(AuthorityUserManager manager, TUser user) + public async Task ValidateUserAsync(AuthorityUserManager manager, AuthorityUser user) { List errors = []; var userOptions = manager.AuthorityManager.Options.User; - if (user is not AuthorityUserBase userBase) - { - errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.NotAuthorityUser", - $"Given user model is not an type of {nameof(AuthorityUserBase)}")); - return ValidationResult.Failed(errors); - } - if (userOptions.RequireUniqueEmail) { - if (string.IsNullOrWhiteSpace(userBase.EmailAddress)) + if (string.IsNullOrWhiteSpace(user.EmailAddress)) { errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.NoEmail", $"Option {nameof(UserOptions.RequireUniqueEmail)} is set to true but given user does not have an email address!")); } else { - var userEmailResult = await manager.UserRepository.GetUserByEmailAsync(userBase.EmailAddress); + var userEmailResult = await manager.UserRepository.GetAuthorityUserByEmailAsync(user.EmailAddress); if (userEmailResult != null) { errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.EmailExists", @@ -41,9 +34,9 @@ public class UserValidator : IUserValidator where TUser : class } } - if (!string.IsNullOrWhiteSpace(userBase.UserName)) + if (!string.IsNullOrWhiteSpace(user.UserName)) { - if (userOptions.UserNameBlackList.Count != 0 && userOptions.UserNameBlackList.Contains(userBase.UserName, userOptions.UserNameBlackListComparer)) + if (userOptions.UserNameBlackList.Count != 0 && userOptions.UserNameBlackList.Contains(user.UserName, userOptions.UserNameBlackListComparer)) { errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Blacklisted", "Given username is not allowed (blacklisted)")); } @@ -53,11 +46,11 @@ public class UserValidator : IUserValidator where TUser : class List chars = []; if (userOptions.UserNameCharacterListType == ListOption.Whitelist) { - chars.AddRange(userBase.UserName.Where(userNameChar => !userOptions.UserNameCharacters.Contains(userNameChar))); + chars.AddRange(user.UserName.Where(userNameChar => !userOptions.UserNameCharacters.Contains(userNameChar))); } if (userOptions.UserNameCharacterListType == ListOption.Blacklist) { - chars.AddRange(userBase.UserName.Where(userNameChar => userOptions.UserNameCharacters.Contains(userNameChar))); + chars.AddRange(user.UserName.Where(userNameChar => userOptions.UserNameCharacters.Contains(userNameChar))); } if (chars.Count <= 0) return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok();