2024-07-11 09:11:01 -07:00

208 lines
8.3 KiB
C#

using System.Security.Claims;
using System.Text.Json;
using MesaFabApproval.Shared.Models;
using Microsoft.Extensions.Caching.Memory;
namespace MesaFabApproval.Client.Services;
public interface IUserService {
ClaimsPrincipal GetClaimsPrincipalFromUser(User user);
string GetLoginIdFromClaimsPrincipal(ClaimsPrincipal claimsPrincipal);
Task<User> GetUserFromClaimsPrincipal(ClaimsPrincipal claimsPrincipal);
Task<User> GetUserByUserId(int userId);
Task<User> GetUserByLoginId(string loginId);
Task<IEnumerable<User>> GetAllActiveUsers();
Task<IEnumerable<int>> GetApproverUserIdsBySubRoleCategoryItem(string item);
}
public class UserService : IUserService {
private readonly IMemoryCache _cache;
private readonly IHttpClientFactory _httpClientFactory;
public UserService(IMemoryCache cache, IHttpClientFactory httpClientFactory) {
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException("IHttpClientFactory not injected");
}
public ClaimsPrincipal GetClaimsPrincipalFromUser(User user) {
if (user is null) throw new ArgumentNullException("user cannot be null");
List<Claim> claims = new() {
new Claim(nameof(user.LoginID), user.LoginID)
};
if (user.IsManager) claims.Add(new Claim(ClaimTypes.Role, "manager"));
if (user.IsAdmin) claims.Add(new Claim(ClaimTypes.Role, "admin"));
ClaimsIdentity identity = new ClaimsIdentity(claims, "MesaFabApprovalWasm");
return new ClaimsPrincipal(identity);
}
public async Task<User> GetUserByUserId(int userId) {
if (userId <= 0) throw new ArgumentException($"{userId} is not a valid user ID");
User? user = _cache.Get<User>($"user{userId}");
if (user is null)
user = _cache.Get<IEnumerable<User>>("allActiveUsers")?.FirstOrDefault(u => u.UserID == userId);
if (user is null) {
HttpClient httpClient = _httpClientFactory.CreateClient("API");
HttpRequestMessage requestMessage = new(HttpMethod.Get, $"user/userId?userId={userId}");
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
if (responseMessage.IsSuccessStatusCode) {
string responseContent = await responseMessage.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
user = JsonSerializer.Deserialize<User>(responseContent, jsonSerializerOptions) ??
throw new Exception("Unable to parse user from API response");
_cache.Set($"user{userId}", user, DateTimeOffset.Now.AddDays(1));
} else {
throw new Exception($"GetUserByUserId failed for user {userId}, because {responseMessage.ReasonPhrase}");
}
}
if (user is null) throw new Exception($"User for userId {userId} not found");
return user;
}
public async Task<User> GetUserByLoginId(string loginId) {
if (string.IsNullOrWhiteSpace(loginId))
throw new ArgumentNullException("loginId cannot be null or empty");
User? user = _cache.Get<User>($"user{loginId}");
if (user is null)
user = _cache.Get<IEnumerable<User>>("allActiveUsers")?.FirstOrDefault(u => u.LoginID == loginId);
if (user is null) {
HttpClient httpClient = _httpClientFactory.CreateClient("API");
HttpRequestMessage requestMessage = new(HttpMethod.Get, $"user/loginId?loginId={loginId}");
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
if (responseMessage.IsSuccessStatusCode) {
string responseContent = await responseMessage.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
user = JsonSerializer.Deserialize<User>(responseContent, jsonSerializerOptions) ??
throw new Exception("Unable to parse user from API response");
_cache.Set($"user{loginId}", user, DateTimeOffset.Now.AddDays(1));
} else {
throw new Exception($"GetUserByLoginId failed for {loginId}, because {responseMessage.ReasonPhrase}");
}
}
if (user is null) throw new Exception($"User for loginId {loginId} not found");
return user;
}
public async Task<IEnumerable<User>> GetAllActiveUsers() {
IEnumerable<User>? activeUsers = _cache.Get<IEnumerable<User>>("allActiveUsers");
if (activeUsers is null) {
HttpClient httpClient = _httpClientFactory.CreateClient("API");
HttpRequestMessage requestMessage = new(HttpMethod.Get, $"users/active");
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
if (responseMessage.IsSuccessStatusCode) {
string responseContent = await responseMessage.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
activeUsers = JsonSerializer.Deserialize<IEnumerable<User>>(responseContent, jsonSerializerOptions) ??
throw new Exception("Unable to parse user from API response");
_cache.Set("allActiveUsers", activeUsers, DateTimeOffset.Now.AddHours(1));
} else {
throw new Exception($"Cannot get all active users, because {responseMessage.ReasonPhrase}");
}
}
if (activeUsers is null)
activeUsers = new List<User>();
return activeUsers;
}
public string GetLoginIdFromClaimsPrincipal(ClaimsPrincipal principal) {
if (principal is null) throw new ArgumentNullException("Principal cannot be null");
Claim loginIdClaim = principal.FindFirst("LoginID") ??
throw new Exception("LoginID claim not found in principal");
string loginId = loginIdClaim.Value;
return loginId;
}
public async Task<User> GetUserFromClaimsPrincipal(ClaimsPrincipal claimsPrincipal) {
if (claimsPrincipal is null) throw new ArgumentNullException("ClaimsPrincipal cannot be null");
Claim loginIdClaim = claimsPrincipal.FindFirst("LoginID") ??
throw new Exception("LoginID claim not found in principal");
string loginId = loginIdClaim.Value ??
throw new Exception("LoginID claim value is null");
User user = await GetUserByLoginId(loginId) ??
throw new Exception($"User for loginId {loginId} not found");
return user;
}
public async Task<IEnumerable<int>> GetApproverUserIdsBySubRoleCategoryItem(string item) {
if (string.IsNullOrWhiteSpace(item)) throw new ArgumentException("SubRoleCategoryItem cannot be null or empty");
IEnumerable<int>? approverUserIds = _cache.Get<IEnumerable<int>>($"approvers{item}");
if (approverUserIds is null) {
HttpClient httpClient = _httpClientFactory.CreateClient("API");
HttpRequestMessage requestMessage = new(HttpMethod.Get, $"approver?subRoleCategoryItem={item}");
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
if (responseMessage.IsSuccessStatusCode) {
string responseContent = await responseMessage.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
approverUserIds = JsonSerializer.Deserialize<IEnumerable<int>>(responseContent, jsonSerializerOptions) ??
throw new Exception("Unable to parse user from API response");
_cache.Set($"approvers{item}", approverUserIds, DateTimeOffset.Now.AddDays(1));
} else {
throw new Exception($"Unable to get approvers for SubRoleCategoryItem {item}, because {responseMessage.ReasonPhrase}");
}
}
if (approverUserIds is null) throw new Exception($"Approvers for SubRoleCategoryItem {item} not found");
return approverUserIds;
}
}