From f0cb7218ac0f10c449ac6f845faefd174a7387e4 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 11 Apr 2025 19:57:20 +0200 Subject: [PATCH] [CHANGE] Updated role repository tasks --- .../Repositories/RoleRepository.cs | 239 ++++++------------ .../Managers/AuthorityRoleManager.cs | 126 +++++---- .../Repositories/IRoleRepository.cs | 19 +- 3 files changed, 151 insertions(+), 233 deletions(-) diff --git a/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs b/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs index 4d2a459..9da3084 100644 --- a/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs +++ b/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs @@ -2,207 +2,132 @@ using DotBased.AspNet.Authority.EFCore.Models; using DotBased.AspNet.Authority.Models; using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Repositories; -using DotBased.Monads; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace DotBased.AspNet.Authority.EFCore.Repositories; -public class RoleRepository(IDbContextFactory contextFactory) : RepositoryBase, IRoleRepository +public class RoleRepository(IDbContextFactory contextFactory, ILogger logger) : RepositoryBase, IRoleRepository { - public async Task>> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default) + public async Task> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var query = context.Roles.AsQueryable(); + if (!string.IsNullOrWhiteSpace(search)) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var query = context.Roles.AsQueryable(); - if (!string.IsNullOrWhiteSpace(search)) - { - query = query.Where(r => - $"{r.Name} {r.Id}".Contains(search, StringComparison.CurrentCultureIgnoreCase)); - } + query = query.Where(r => + $"{r.Name} {r.Id}".Contains(search, StringComparison.CurrentCultureIgnoreCase)); + } - var total = await query.CountAsync(cancellationToken); - var select = await query.OrderBy(r => r.Name).Skip(offset).Take(limit).Select(r => new AuthorityRoleItem() - { - Id = r.Id, - Name = r.Name - }).ToListAsync(cancellationToken: cancellationToken); - return QueryItems.Create(select, total, limit, offset); - } - catch (Exception e) + var total = await query.CountAsync(cancellationToken); + var select = await query.OrderBy(r => r.Name).Skip(offset).Take(limit).Select(r => new AuthorityRoleItem() { - return e; - } + Id = r.Id, + Name = r.Name + }).ToListAsync(cancellationToken: cancellationToken); + return QueryItems.Create(select, total, limit, offset); } - public async Task> GetRoleByIdAsync(Guid id, CancellationToken cancellationToken = default) + public async Task GetRoleByIdAsync(Guid id, CancellationToken cancellationToken = default) { - try - { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var role = await context.Roles.Where(r => r.Id == id).Include(r => r.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); - if (role != null) - { - return role; - } - return ResultError.Fail("Role not found!"); - } - catch (Exception e) - { - return e; - } + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var role = await context.Roles.Where(r => r.Id == id).Include(r => r.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); + return role; } - public async Task> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) + public async Task CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (role.Id == Guid.Empty) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - if (role.Id == Guid.Empty) - { - return ResultError.Fail("Id cannot be empty!"); - } - var entity = context.Roles.Add(role); - var saveResult = await context.SaveChangesAsync(cancellationToken); - return saveResult <= 0 ? ResultError.Fail("Failed to create role!") : entity.Entity; - } - catch (Exception e) - { - return e; + throw new Exception("Role id is required!"); } + var entity = context.Roles.Add(role); + var saveResult = await context.SaveChangesAsync(cancellationToken); + + return saveResult != 0 ? entity.Entity : null; } - public async Task> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) + public async Task UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var currentRole = await context.Roles.FirstOrDefaultAsync(r => r.Id == role.Id, cancellationToken: cancellationToken); + if (currentRole == null) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var currentRole = await context.Roles.FirstOrDefaultAsync(r => r.Id == role.Id, cancellationToken: cancellationToken); - if (currentRole == null) - { - return ResultError.Fail("Role not found!"); - } + throw new Exception($"Role with id {role.Id} not found!"); + } - if (role.Version != currentRole.Version) - { - return ResultError.Fail("Role version does not match, version validation failed!"); - } + if (role.Version != currentRole.Version) + { + throw new Exception("Role version does not match!"); + } - var entity = context.Roles.Update(role); - var saveResult = await context.SaveChangesAsync(cancellationToken); - return saveResult <= 0 ? ResultError.Fail("Failed to update role!") : entity.Entity; - } - catch (Exception e) - { - return e; - } + var entity = context.Roles.Update(role); + var saveResult = await context.SaveChangesAsync(cancellationToken); + return saveResult != 0 ? entity.Entity : null; } - public async Task DeleteRolesAsync(List roles, CancellationToken cancellationToken = default) + public async Task DeleteRolesAsync(List roles, CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var roleIds = roles.Select(r => r.Id).ToList(); + + context.Roles.RemoveRange(roles); + context.RoleLinks.RemoveRange(context.RoleLinks.Where(rl => roleIds.Contains(rl.RoleId))); + + var removedRoles = await context.SaveChangesAsync(cancellationToken); + if (removedRoles == roles.Count) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var roleIds = roles.Select(r => r.Id).ToList(); - - context.Roles.RemoveRange(roles); - context.RoleLinks.RemoveRange(context.RoleLinks.Where(rg => roleIds.Contains(rg.RoleId))); - - var removeResult = await context.SaveChangesAsync(cancellationToken); - return removeResult == roles.Count? Result.Success() : ResultError.Fail($"Not all roles have been removed! {removeResult} of {roles.Count} roles removed!"); - } - catch (Exception e) - { - return e; + return true; } + logger.LogError("Failed to remove all roles, {removedRoles}/{totalRoles} roles removed!", removedRoles, roles.Count); + return false; } - public async Task> GetUserRolesAsync(AuthorityUser user, int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default) + public async Task AddRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + foreach (var role in roles) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var roleIds = await context.RoleLinks.Where(r => r.LinkId == user.Id).Select(i => i.RoleId).ToListAsync(cancellationToken: cancellationToken); - var rolesQuery = context.Roles.Where(r => roleIds.Contains(r.Id)); - if (!string.IsNullOrEmpty(search)) - { - rolesQuery = rolesQuery.Where(r => r.Name.Contains(search)); - } + context.RoleLinks.Add(new RoleLink { LinkId = linkId, RoleId = role.Id }); + } + var linkedRoles = await context.SaveChangesAsync(cancellationToken); + if (linkedRoles == roles.Count) + { + return true; + } - var roles = rolesQuery.Where(r => roleIds.Contains(r.Id)).Skip(offset).Take(limit).Select(r => new AuthorityRoleItem() - { - Id = r.Id, - Name = r.Name - }); - return ListResultOld.Ok(roles, limit, offset); - } - catch (Exception e) - { - return HandleExceptionListResult("Failed to get user roles.", e); - } + logger.LogError("Failed to link all given roles, {linkedRoles}/{totalRoles} roles linked!", linkedRoles, roles.Count); + return false; } - public async Task AddRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default) + public async Task> GetLinkedRolesAsync(List linkIds, CancellationToken cancellationToken = default) { - try - { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - foreach (var role in roles) - { - context.RoleLinks.Add(new RoleLink() { LinkId = linkId, RoleId = role.Id }); - } - var saveResult = await context.SaveChangesAsync(cancellationToken); - return saveResult == roles.Count ? Result.Success() : ResultError.Fail($"Not all roles have been linked! {saveResult} of {roles.Count} roles linked!"); - } - catch (Exception e) - { - return e; - } + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var linkedRoles = context.RoleLinks.Where(r => linkIds.Contains(r.LinkId)).Select(r => r.RoleId); + var roleList = await context.Roles.Where(r => linkedRoles.Contains(r.Id)).ToListAsync(cancellationToken); + return roleList.DistinctBy(r => r.Id).ToList(); } - public async Task>> GetLinkedRolesAsync(List linkIds, CancellationToken cancellationToken = default) + public async Task UnlinkRolesAsync(List roles, Guid linkId, CancellationToken cancellationToken = default) { - try + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + var roleIds = roles.Select(r => r.Id).ToList(); + context.RoleLinks.RemoveRange(context.RoleLinks.Where(rg => rg.LinkId == linkId && roleIds.Contains(rg.RoleId))); + var unlinkedRoles = await context.SaveChangesAsync(cancellationToken); + if (unlinkedRoles == roles.Count) { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var linkedRoles = context.RoleLinks.Where(r => linkIds.Contains(r.LinkId)).Select(r => r.RoleId); - var roleList = await context.Roles.Where(r => linkedRoles.Contains(r.Id)).ToListAsync(cancellationToken); - return roleList.DistinctBy(r => r.Id).ToList(); - } - catch (Exception e) - { - return e; + return true; } + + logger.LogError("Failed to remove all linked roles, {unlinkedRoles}/{totalRoles} roles unlinked!", unlinkedRoles, roles.Count); + return false; } - public async Task DeleteRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default) + public async Task> GetRolesFromLinkAsync(Guid linkId, List roles, CancellationToken cancellationToken = default) { - try - { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var roleIds = roles.Select(r => r.Id).ToList(); - context.RoleLinks.RemoveRange(context.RoleLinks.Where(rg => rg.LinkId == linkId && roleIds.Contains(rg.RoleId))); - var saveResult = await context.SaveChangesAsync(cancellationToken); - return saveResult == roles.Count ? Result.Success() : ResultError.Fail($"Not all roles have been unlinked! {saveResult} of {roles.Count} roles unlinked!"); - } - catch (Exception e) - { - return e; - } - } - - public async Task>> HasRolesAsync(Guid linkId, List roles, CancellationToken cancellationToken = default) - { - try - { - await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var hasRoles = await context.RoleLinks.Where(r => r.LinkId == linkId && roles.Any(ar => ar.Id == r.RoleId)).Select(r => r.RoleId).ToListAsync(cancellationToken); - return hasRoles; - } - catch (Exception e) - { - return e; - } + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + return await context.RoleLinks.Where(r => r.LinkId == linkId && roles.Any(ar => ar.Id == r.RoleId)).Select(r => r.RoleId).ToListAsync(cancellationToken); } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs b/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs index beda419..adb54b1 100755 --- a/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs +++ b/DotBased.AspNet.Authority/Managers/AuthorityRoleManager.cs @@ -10,18 +10,28 @@ public partial class AuthorityManager { role.Version = GenerateVersion(); var createResult = await RoleRepository.CreateRoleAsync(role, cancellationToken); + if (createResult == null) + { + return ResultError.Fail("Failed to create new role."); + } + return createResult; } public async Task DeleteRolesAsync(List roles, CancellationToken cancellationToken = default) { - var result = await RoleRepository.DeleteRolesAsync(roles, cancellationToken); - return result; + var success = await RoleRepository.DeleteRolesAsync(roles, cancellationToken); + return success ? Result.Success() : ResultError.Fail("Failed to delete roles."); } public async Task> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { var result = await RoleRepository.UpdateRoleAsync(role, cancellationToken); + if (result == null) + { + return ResultError.Fail("Failed to update role."); + } + return result; } @@ -31,81 +41,59 @@ public partial class AuthorityManager return searchResult; } - public async Task AddRolesToUserAsync(List roles, AuthorityUser user, CancellationToken cancellationToken = default) + public async Task AddRolesToUserAsync(List roles, AuthorityUser user, CancellationToken cancellationToken = default) { var usrValidation = await IsValidUserAsync(user, cancellationToken); if (!usrValidation.Success) { - _logger.Error(usrValidation.Exception ?? new Exception("Validation for user failed!"), "Invalid user!"); - return; + return ResultError.Fail("Validation for user failed!"); } - var checkResult = await RoleRepository.HasRolesAsync(user.Id, roles, cancellationToken); - var hasRolesList = checkResult.Match>(success: v => v, (_) => []); + var linkedRoles = await RoleRepository.GetRolesFromLinkAsync(user.Id, roles, cancellationToken); var rolesToAdd = roles; - if (hasRolesList.Count != 0) + if (linkedRoles.Count != 0) { - rolesToAdd = roles.Where(r => !hasRolesList.Contains(r.Id)).ToList(); + rolesToAdd = roles.Where(r => !linkedRoles.Contains(r.Id)).ToList(); } - var addResult = await RoleRepository.AddRolesLinkAsync(rolesToAdd, user.Id, cancellationToken); - addResult.Match(() => - { - _logger.Debug("Role links successfully added!"); - }, e => - { - _logger.Error(e.Exception ?? new Exception("Match failed!"), e.Description); - }); + var addSuccess = await RoleRepository.AddRolesLinkAsync(rolesToAdd, user.Id, cancellationToken); + + return addSuccess ? Result.Success() : ResultError.Fail("Failed to add roles."); } - public async Task RemoveRolesFromUserAsync(List roles, AuthorityUser user, CancellationToken cancellationToken = default) + public async Task RemoveRolesFromUserAsync(List roles, AuthorityUser user, CancellationToken cancellationToken = default) { var usrValidation = await IsValidUserAsync(user, cancellationToken); if (!usrValidation.Success) { - _logger.Error(usrValidation.Exception ?? new Exception("Validation for user failed!"), "Invalid user!"); - return; + return ResultError.Fail("Validation for user failed!"); } - var checkResult = await RoleRepository.HasRolesAsync(user.Id, roles, cancellationToken); - var hasRolesList = checkResult.Match>(success: v => v, (_) => []); + var linkedRoles = await RoleRepository.GetRolesFromLinkAsync(user.Id, roles, cancellationToken); var rolesToRemove = roles; - if (hasRolesList.Count != 0) + if (linkedRoles.Count != 0) { - rolesToRemove = roles.Where(r => !hasRolesList.Contains(r.Id)).ToList(); + rolesToRemove = roles.Where(r => !linkedRoles.Contains(r.Id)).ToList(); } - var removeResult = await RoleRepository.DeleteRolesLinkAsync(rolesToRemove, user.Id, cancellationToken); - removeResult.Match(() => - { - _logger.Debug("Removed roles from user!"); - }, e => - { - _logger.Error(e.Exception ?? new Exception("Removing roles from user failed!"), e.Description); - }); + var removeResult = await RoleRepository.UnlinkRolesAsync(rolesToRemove, user.Id, cancellationToken); + return removeResult ? Result.Success() : ResultError.Fail("Failed to remove roles."); } - public async Task AddRolesToGroupAsync(List roles, AuthorityGroup group, CancellationToken cancellationToken = default) + public async Task AddRolesToGroupAsync(List roles, AuthorityGroup group, CancellationToken cancellationToken = default) { - var checkResult = await RoleRepository.HasRolesAsync(group.Id, roles, cancellationToken); - var hasRolesList = checkResult.Match>(success: v => v, (_) => []); + var linkedRoles = await RoleRepository.GetRolesFromLinkAsync(group.Id, roles, cancellationToken); var rolesToAdd = roles; - if (hasRolesList.Count != 0) + if (linkedRoles.Count != 0) { - rolesToAdd = roles.Where(r => !hasRolesList.Contains(r.Id)).ToList(); + rolesToAdd = roles.Where(r => !linkedRoles.Contains(r.Id)).ToList(); } - var addResult = await RoleRepository.AddRolesLinkAsync(rolesToAdd, group.Id, cancellationToken); - addResult.Match(() => - { - _logger.Debug("Added roles to group."); - }, e => - { - _logger.Error(e.Exception ?? new Exception("Adding roles to group failed!"), e.Description); - }); + var linkResult = await RoleRepository.AddRolesLinkAsync(rolesToAdd, group.Id, cancellationToken); + return linkResult ? Result.Success() : ResultError.Fail("Failed to add roles."); } /// @@ -115,35 +103,41 @@ public partial class AuthorityManager /// public async Task>> GetUserRolesAsync(AuthorityUser user, CancellationToken cancellationToken = default) { - var usrValidation = await IsValidUserAsync(user, cancellationToken); - if (!usrValidation.Success) + try { - return ResultError.Fail("Invalid user"); + var usrValidation = await IsValidUserAsync(user, cancellationToken); + if (!usrValidation.Success) + { + return ResultError.Fail("Invalid user"); + } + + var searchIds = new List { user.Id }; + + var usrGroups = await GetUserGroupsAsync(user, cancellationToken); + if (usrGroups.Success) + { + searchIds.AddRange(usrGroups.Items.Select(g => g.Id).ToList()); + } + + var linkedRolesResult = await RoleRepository.GetLinkedRolesAsync(searchIds, cancellationToken); + return linkedRolesResult; } - - var searchIds = new List { user.Id }; - - var usrGroups = await GetUserGroupsAsync(user, cancellationToken); - if (usrGroups.Success) + catch (Exception e) { - searchIds.AddRange(usrGroups.Items.Select(g => g.Id).ToList()); + return e; } - - var linkedRolesResult = await RoleRepository.GetLinkedRolesAsync(searchIds, cancellationToken); - return linkedRolesResult.Match>(roles => roles, e => - { - _logger.Error(e.Exception ?? new Exception("Failed to get user roles!"), e.Description); - return []; - }); } public async Task>> GetGroupRolesAsync(List groupIds, CancellationToken cancellationToken = default) { - var linkedRolesResult = await RoleRepository.GetLinkedRolesAsync(groupIds, cancellationToken); - return linkedRolesResult.Match>(roles => roles, e => + try { - _logger.Error(e.Exception ?? new Exception("Failed to get group roles!"), e.Description); - return []; - }); + var linkedRolesResult = await RoleRepository.GetLinkedRolesAsync(groupIds, cancellationToken); + return linkedRolesResult; + } + catch (Exception e) + { + return e; + } } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs index ba68d4a..24ee00a 100755 --- a/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs +++ b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs @@ -1,19 +1,18 @@ using DotBased.AspNet.Authority.Models; using DotBased.AspNet.Authority.Models.Authority; -using DotBased.Monads; namespace DotBased.AspNet.Authority.Repositories; public interface IRoleRepository { - public Task>> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default); - public Task> GetRoleByIdAsync(Guid id, CancellationToken cancellationToken = default); - public Task> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default); - public Task> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default); - public Task DeleteRolesAsync(List roles, CancellationToken cancellationToken = default); - public Task AddRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default); - public Task>> GetLinkedRolesAsync(List linkIds, CancellationToken cancellationToken = default); - public Task DeleteRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default); + public Task> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default); + public Task GetRoleByIdAsync(Guid id, CancellationToken cancellationToken = default); + public Task CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default); + public Task UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default); + public Task DeleteRolesAsync(List roles, CancellationToken cancellationToken = default); + public Task AddRolesLinkAsync(List roles, Guid linkId, CancellationToken cancellationToken = default); + public Task> GetLinkedRolesAsync(List linkIds, CancellationToken cancellationToken = default); + public Task UnlinkRolesAsync(List roles, Guid linkId, CancellationToken cancellationToken = default); /// /// Return the role ids the linkId has. @@ -22,5 +21,5 @@ public interface IRoleRepository /// /// /// - public Task>> HasRolesAsync(Guid linkId, List roles, CancellationToken cancellationToken = default); + public Task> GetRolesFromLinkAsync(Guid linkId, List roles, CancellationToken cancellationToken = default); } \ No newline at end of file