diff --git a/DotBased.AspNet.Authority.EFCore/Repositories/RepositoryBase.cs b/DotBased.AspNet.Authority.EFCore/Repositories/RepositoryBase.cs new file mode 100644 index 0000000..1be6d12 --- /dev/null +++ b/DotBased.AspNet.Authority.EFCore/Repositories/RepositoryBase.cs @@ -0,0 +1,19 @@ +namespace DotBased.AspNet.Authority.EFCore.Repositories; + +public abstract class RepositoryBase +{ + protected Result HandleExceptionResult(string message, Exception ex) => new(HandleException(message, ex)); + + protected ListResult HandleExceptionListResult(string message, Exception ex) => + new(HandleException(message, ex)); + + protected Result HandleException(string message, Exception ex) + { + if (ex is OperationCanceledException oce) + { + return Result.Failed("Operation cancelled.", oce); + } + + return Result.Failed(message, ex); + } +} \ No newline at end of file diff --git a/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs b/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs index bd15ed7..491080e 100644 --- a/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs +++ b/DotBased.AspNet.Authority.EFCore/Repositories/RoleRepository.cs @@ -1,32 +1,117 @@ using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Repositories; +using Microsoft.EntityFrameworkCore; namespace DotBased.AspNet.Authority.EFCore.Repositories; -public class RoleRepository : IRoleRepository +public class RoleRepository(IDbContextFactory contextFactory) : RepositoryBase, IRoleRepository { - public 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) { - throw new NotImplementedException(); + try + { + 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)); + } + + 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 ListResult.Ok(select, total, limit, offset); + } + catch (Exception e) + { + return HandleExceptionListResult("Failed to get roles.", e); + } } - public Task> GetRoleByIdAsync(string id, CancellationToken cancellationToken = default) + public async Task> GetRoleByIdAsync(string id, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + try + { + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (!Guid.TryParse(id, out var guid)) + { + return Result.Failed("Invalid id!"); + } + var role = await context.Roles.Where(r => r.Id == guid).Include(r => r.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); + return Result.HandleResult(role, "Role not found!"); + } + catch (Exception e) + { + return HandleExceptionResult("Failed to get role!", e); + } } - public Task> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) + public async Task> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + try + { + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (role.Id == Guid.Empty) + { + return Result.Failed("Id cannot be empty!"); + } + var entity = context.Roles.Add(role); + var saveResult = await context.SaveChangesAsync(cancellationToken); + return saveResult <= 0 ? Result.Failed("Failed to create role!") : Result.Ok(entity.Entity); + } + catch (Exception e) + { + return HandleExceptionResult("Failed to create role!", e); + } } - public Task> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) + public async Task> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + 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) + { + return Result.Failed("Role not found!"); + } + + if (role.Version != currentRole.Version) + { + return Result.Failed("Role version does not match, version validation failed!"); + } + + var entity = context.Roles.Update(role); + var saveResult = await context.SaveChangesAsync(cancellationToken); + return saveResult <= 0 ? Result.Failed("Failed to update role!") : Result.Ok(entity.Entity); + } + catch (Exception e) + { + return HandleExceptionResult("Failed to update role!", e); + } } - public Task DeleteRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) + public async Task DeleteRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + 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) + { + return Result.Failed("Role not found, could not delete!"); + } + context.Roles.Remove(currentRole); + var saveResult = await context.SaveChangesAsync(cancellationToken); + return saveResult <= 0 ? Result.Failed("Failed to delete role!") : Result.Ok(); + } + catch (Exception e) + { + return HandleException("Failed to delete role!", e); + } } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs b/DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs index 599f5d0..efcc004 100644 --- a/DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs +++ b/DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace DotBased.AspNet.Authority.EFCore.Repositories; -public class UserRepository(IDbContextFactory contextFactory) : IUserRepository +public class UserRepository(IDbContextFactory contextFactory) : RepositoryBase, IUserRepository { public async Task> GetAuthorityUsersAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default) { @@ -18,20 +18,19 @@ public class UserRepository(IDbContextFactory contextFactory) $"{u.Id} {u.Name} {u.UserName} {u.EmailAddress} {u.PhoneNumber}".Contains(search, StringComparison.CurrentCultureIgnoreCase)); } - var totalCount = query.Count(); - var selected = query.Skip(offset).Take(limit).Select(u => new AuthorityUserItem() + var selected = await query.OrderBy(u => u.UserName).Skip(offset).Take(limit).Select(u => new AuthorityUserItem() { Id = u.Id, UserName = u.UserName, EmailAddress = u.EmailAddress, PhoneNumber = u.PhoneNumber - }); + }).ToListAsync(cancellationToken: cancellationToken); return ListResult.Ok(selected, totalCount, limit, offset); } catch (Exception e) { - return ListResult.Failed("Failed to get users.", e); + return HandleExceptionListResult("Failed to get users.", e); } } @@ -45,12 +44,12 @@ public class UserRepository(IDbContextFactory contextFactory) return Result.Failed("Invalid id!"); } - var user = await context.Users.FirstOrDefaultAsync(u => u.Id == guid, cancellationToken: cancellationToken); + var user = await context.Users.Where(u => u.Id == guid).Include(u => u.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); return Result.HandleResult(user, "User not found."); } catch (Exception e) { - return Result.Failed("Failed to get user.", e); + return HandleExceptionResult("Failed to get user.", e); } } @@ -69,7 +68,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("Failed to create user.", e); + return HandleExceptionResult("Failed to create user.", e); } } @@ -95,7 +94,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("Failed to update user!", e); + return HandleExceptionResult("Failed to update user!", e); } } @@ -115,7 +114,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("Failed to delete user!", e); + return HandleException("Failed to delete user!", e); } } @@ -124,12 +123,12 @@ public class UserRepository(IDbContextFactory contextFactory) try { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var usr = await context.Users.FirstOrDefaultAsync(u => u.EmailAddress == email, cancellationToken: cancellationToken); + var usr = await context.Users.Where(u => u.EmailAddress == email).Include(u => u.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); return Result.HandleResult(usr, "User not found by given email address."); } catch (Exception e) { - return Result.Failed("An error occured while getting the user.", e); + return HandleExceptionResult("An error occured while getting the user.", e); } } @@ -156,7 +155,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("An error occured while updating the version.", e); + return HandleException("An error occured while updating the version.", e); } } @@ -170,7 +169,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("An error occured while getting the user version.", e); + return HandleExceptionResult("An error occured while getting the user version.", e); } } @@ -197,7 +196,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("An error occured while updating the security version.", e); + return HandleException("An error occured while updating the security version.", e); } } @@ -211,7 +210,7 @@ public class UserRepository(IDbContextFactory contextFactory) } catch (Exception e) { - return Result.Failed("An error occured while getting the user security version.", e); + return HandleExceptionResult("An error occured while getting the user security version.", e); } } } \ No newline at end of file diff --git a/DotBased.AspNet.Authority/Models/Authority/AuthorityRoleItem.cs b/DotBased.AspNet.Authority/Models/Authority/AuthorityRoleItem.cs index e285d5a..b8273d8 100644 --- a/DotBased.AspNet.Authority/Models/Authority/AuthorityRoleItem.cs +++ b/DotBased.AspNet.Authority/Models/Authority/AuthorityRoleItem.cs @@ -2,5 +2,7 @@ namespace DotBased.AspNet.Authority.Models.Authority; public class AuthorityRoleItem { - + public Guid Id { get; set; } = Guid.NewGuid(); + + public string? Name { get; set; } } \ No newline at end of file