using DotBased.AspNet.Authority.Models; using DotBased.AspNet.Authority.Models.Authority; using DotBased.AspNet.Authority.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace DotBased.AspNet.Authority.EFCore.Repositories; public class UserRepository(IDbContextFactory contextFactory, ILogger logger) : RepositoryBase, IUserRepository { public async Task> GetAuthorityUsersAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var query = context.Users.AsQueryable(); if (!string.IsNullOrWhiteSpace(search)) { query = query.Where(u => $"{u.Id} {u.Name} {u.UserName} {u.EmailAddress} {u.PhoneNumber}".Contains(search, StringComparison.CurrentCultureIgnoreCase)); } var totalCount = query.Count(); 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 QueryItems.Create(selected, totalCount, limit, offset); } public async Task GetAuthorityUserByIdAsync(Guid id, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); if (id == Guid.Empty) { throw new Exception("Id is required!"); } return await context.Users.Where(u => u.Id == id).Include(u => u.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); } public async Task CreateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); if (user.Id == Guid.Empty) { throw new Exception("User id is required!"); } var entity = context.Users.Add(user); var saveResult = await context.SaveChangesAsync(cancellationToken); return saveResult != 0 ? entity.Entity : null; } public async Task UpdateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken: cancellationToken); if (usr == null) { throw new Exception("User not found!"); } if (usr.Version != user.Version || usr.SecurityVersion != user.SecurityVersion) { throw new Exception("User does not have the correct security version!"); } var entity = context.Users.Update(user); var saveResult = await context.SaveChangesAsync(cancellationToken); return saveResult != 0 ? entity.Entity : null; } public async Task DeleteUsersAsync(List users, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usrIds = users.Select(u => u.Id); context.Users.RemoveRange(users); context.RoleLinks.RemoveRange(context.RoleLinks.Where(rl => usrIds.Contains(rl.LinkId))); var removedResult = await context.SaveChangesAsync(cancellationToken); if (removedResult != 0) return true; logger.LogError("Failed to delete users"); return false; } public async Task GetUserByEmailAsync(string email, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); return await context.Users.Where(u => u.EmailAddress == email).Include(u => u.Attributes).FirstOrDefaultAsync(cancellationToken: cancellationToken); } public async Task SetVersionAsync(AuthorityUser user, long version, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken); if (usr == null) { throw new Exception("User not found!"); } if (usr.Version != user.Version) { throw new Exception("User does not have the correct security version!"); } usr.Version = version; context.Users.Update(usr); var saveResult = await context.SaveChangesAsync(cancellationToken); return saveResult != 0; } public async Task GetVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usrVersion = await context.Users.Where(u => u.Id == user.Id).Select(u => u.Version).FirstOrDefaultAsync(cancellationToken); return usrVersion; } public async Task SetSecurityVersionAsync(AuthorityUser user, long securityVersion, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken); if (usr == null) { throw new Exception("User not found!"); } if (usr.SecurityVersion != user.SecurityVersion) { throw new Exception("User does not have the correct security version!"); } usr.SecurityVersion = securityVersion; context.Users.Update(usr); var saveResult = await context.SaveChangesAsync(cancellationToken); return saveResult != 0; } public async Task GetSecurityVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var usrVersion = await context.Users.Where(u => u.Id == user.Id).Select(u => u.SecurityVersion).FirstOrDefaultAsync(cancellationToken); return usrVersion; } }