155 lines
7.9 KiB
C#
155 lines
7.9 KiB
C#
using PostFundManagement.Domain.Abstractions;
|
|
using PostFundManagement.Domain.Errors;
|
|
using PostFundManagement.Domain.Models.Security;
|
|
using static PostFundManagement.Domain.Extensions.Constants;
|
|
|
|
namespace PostFundManagement.Infrastructure.Security;
|
|
|
|
public class SkorubaUserService([FromKeyedServices(SkorubaHttpClient)] IHttpClientFactory httpClientFactory) : ISkorubaUserService
|
|
{
|
|
public async Task<Result<string>> CreateUserAsync(CreateUserRequest request, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result<string>>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var response = await httpClient.PostAsJsonAsync("api/users", request, cancellationToken);
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
return Result.Fail(CreateError.Create("Failed to create user."));
|
|
|
|
var created = await response.Content.ReadFromJsonAsync<UserResponse>(cancellationToken: cancellationToken);
|
|
|
|
return Result.FailIf(created is null, CreateError.Create("User ID missing from creation response."))
|
|
.ToResult(created?.Id!);
|
|
}));
|
|
|
|
public async Task<Result<UserResponse>> GetUserAsync(Guid userId, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result<UserResponse>>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var result = await httpClient.GetFromJsonAsync<UserResponse>($"api/users/{userId}", cancellationToken);
|
|
|
|
return Result.FailIf(result is null, NotFoundError.Create($"User {userId} not found."))
|
|
.ToResult(result!);
|
|
}));
|
|
|
|
public async Task<Result> UpdateUserAsync(UpdateUserRequest request, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var response = await httpClient.PutAsJsonAsync("api/users", request, cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, UpdateError.Create("Failed to update user."));
|
|
}));
|
|
|
|
public async Task<Result> SetUserLockoutAsync(Guid userId, bool disabled, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var user = await httpClient.GetFromJsonAsync<UpdateUserRequest>($"api/users/{userId}", cancellationToken);
|
|
|
|
if (user is null)
|
|
return Result.Fail(NotFoundError.Create($"User {userId} not found."));
|
|
|
|
var updated = user with
|
|
{
|
|
LockoutEnabled = true,
|
|
LockoutEnd = disabled ? DateTimeOffset.UtcNow.AddYears(100) : null
|
|
};
|
|
|
|
var response = await httpClient.PutAsJsonAsync("api/users", updated, cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, UpdateError.Create("Failed to update user lockout status."));
|
|
}));
|
|
|
|
public async Task<Result> AddClaimAsync(Guid userId, string claimType, string claimValue, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var payload = new { UserId = userId, ClaimType = claimType, ClaimValue = claimValue };
|
|
|
|
var response = await httpClient.PostAsJsonAsync($"api/users/{userId}/claims", payload, cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, CreateError.Create("Failed to add user claim."));
|
|
}));
|
|
|
|
public async Task<Result> RemoveClaimAsync(Guid userId, int claimId, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var response = await httpClient.DeleteAsync($"api/users/{userId}/claims/{claimId}", cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, CreateError.Create("Failed to remove user claim."));
|
|
}));
|
|
|
|
public async Task<Result<Claim[]>> GetUserClaimsAsync(string userId, int page = 1, int pageSize = 50, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result<Claim[]>>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
|
|
var result = await httpClient.GetFromJsonAsync<ClaimsResponse>($"api/users/{userId}/claims?page={page}&pageSize={pageSize}", cancellationToken);
|
|
|
|
return Result.FailIf(result is null, NotFoundError.Create($"Claims for user {userId} could not be retrieved."))
|
|
.ToResult(result?.Claims.ToArray() ?? []);
|
|
}));
|
|
|
|
public async Task<Result> AddRoleAsync(Guid userId, string roleId, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var payload = new { UserId = userId, RoleId = roleId };
|
|
|
|
var response = await httpClient.PostAsJsonAsync($"api/users/{userId}/roles", payload, cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, CreateError.Create("Failed to add user role."));
|
|
}));
|
|
|
|
public async Task<Result> RemoveRoleAsync(Guid userId, string roleId, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var response = await httpClient.DeleteAsync($"api/users/{userId}/roles/{roleId}", cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, CreateError.Create("Failed to remove user role."));
|
|
}));
|
|
|
|
public async Task<Result<Role[]>> GetUserRolesAsync(string userId, int page = 1, int pageSize = 50, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result<Role[]>>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
|
|
var result = await httpClient.GetFromJsonAsync<RolesResponse>($"api/users/{userId}/roles?page={page}&pageSize={pageSize}", cancellationToken);
|
|
|
|
return Result.FailIf(result is null, NotFoundError.Create($"Roles for user {userId} could not be retrieved."))
|
|
.ToResult(result?.Roles?.ToArray() ?? []);
|
|
}));
|
|
|
|
public async Task<Result> InvalidateUserSessionAsync(Guid userId, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
var user = await httpClient.GetFromJsonAsync<UserResponse>($"api/users/{userId}", cancellationToken);
|
|
|
|
if (user is null)
|
|
return Result.Fail(NotFoundError.Create($"User {userId} not found."));
|
|
|
|
var response = await httpClient.PutAsJsonAsync("api/users", user, cancellationToken);
|
|
|
|
return Result.OkIf(response.IsSuccessStatusCode, UpdateError.Create("Failed to invalidate user session."));
|
|
}));
|
|
|
|
public async Task<Result<Role[]>> GetAvailableRolesAsync(string? searchText = null, int page = 1, int pageSize = 50, CancellationToken cancellationToken = default) =>
|
|
await Result.Try((Func<Task<Result<Role[]>>>)(async () =>
|
|
{
|
|
var httpClient = httpClientFactory.CreateClient();
|
|
|
|
var query = $"api/roles?page={page}&pageSize={pageSize}";
|
|
|
|
if (!string.IsNullOrWhiteSpace(searchText))
|
|
query += $"&searchText={Uri.EscapeDataString(searchText)}";
|
|
|
|
var result = await httpClient.GetFromJsonAsync<RolesResponse>(query, cancellationToken);
|
|
|
|
return Result.FailIf(result is null, NotFoundError.Create("Available roles could not be retrieved."))
|
|
.ToResult(result?.Roles?.ToArray() ?? []);
|
|
}));
|
|
} |