Files
pfm/PostFundManagement.Application/Services/Users/UserService.cs
T
hermes ea71e55e2d Refactored UI
Added Role filed to user table and endpoint implementation
2026-09-28 10:25:00 +02:00

117 lines
5.3 KiB
C#

using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Services.Users;
public sealed class UserService(IDbContextFactory<ApplicationDbContext> contextFactory, ITenantContextService tenantContext) : IUserService
{
public async Task<Result> SyncUserAsync(Guid userId, string email, string role, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (string.IsNullOrWhiteSpace(role))
return Result.Fail(ValidationError.Create("Failed to sync, user role not present, contact support"));
var tenantUser = await context.TenantUsers
.Include(i => i.User)
.FirstOrDefaultAsync(u => u.UserId == userId, cancellationToken);
if (tenantUser is null)
{
context.Users.Add(new Domain.Entities.User
{
Id = userId,
Email = email,
Status = ActivityStatus.Active,
LastLoginAt = DateTime.UtcNow,
Role = role
});
context.TenantUsers.Add(new Domain.Entities.TenantUser
{
CreatedAt = DateTime.UtcNow,
CreatedBy = userId,
Status = ActivityStatus.Active,
TenantId = tenantContext.TenantId,
UserId = userId
});
}
else
{
tenantUser.User!.Email = email;
tenantUser.User.LastLoginAt = DateTime.UtcNow;
tenantUser.User.Role = role;
context.Users.Update(tenantUser.User);
}
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.Create("Failed to sync user, contact support"));
}));
public async Task<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<User[]>>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var query = context.TenantUsers.Include(i => i.User).AsNoTracking();
if (request.Status.HasValue)
query = query.Where(u => u.Status == request.Status.Value);
if (!string.IsNullOrWhiteSpace(request.Email))
query = query.Where(u => u.User!.Email != null && u.User!.Email.Contains(request.Email));
if (!string.IsNullOrWhiteSpace(request.SortBy))
query = request.SortBy.ToLowerInvariant() switch
{
"email" => request.SortDescending ? query.OrderByDescending(u => u.User!.Email) : query.OrderBy(u => u.User!.Email),
"lastloginat" => request.SortDescending ? query.OrderByDescending(u => u.User!.LastLoginAt) : query.OrderBy(u => u.User!.LastLoginAt),
"status" => request.SortDescending ? query.OrderByDescending(u => u.Status) : query.OrderBy(u => u.Status),
_ => request.SortDescending ? query.OrderByDescending(u => u.Id) : query.OrderBy(u => u.Id)
};
else
query = query.OrderBy(u => u.Id);
var users = await query.Skip((pagination.Page - 1) * pagination.PageSize)
.Take(pagination.PageSize).ToListAsync(cancellationToken);
return Result.Ok(users.Select(u => u.User!.Map()).ToArray());
}));
public async Task<Result> UpdateUserStatusAsync(Guid userId, ActivityStatus status, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var changedTotal = await context.TenantUsers
.Include(i => i.User)
.Where(f => f.UserId == userId)
.ExecuteUpdateAsync(f => f
.SetProperty(u => u.Status, status), cancellationToken);
changedTotal += await context.Users.Where(f => f.Id == userId)
.ExecuteUpdateAsync(f => f.SetProperty(u => u.Status, status), cancellationToken);
return Result.OkIf(changedTotal > 0, UpdateError.New);
}));
public async Task<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken) =>
await Result.Try((Func<Task<Result<User>>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var tenantUser = await context.TenantUsers.AsNoTracking()
.Include(i => i.User)
.FirstOrDefaultAsync(f => f.UserId == userId, cancellationToken);
return Result.FailIf(tenantUser == null, NotFoundError.New)
.ToResult(tenantUser!.User?.Map()!);
}));
}