Saving
This commit is contained in:
6
Services/AppStatusService.cs
Normal file
6
Services/AppStatusService.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace decePubClient.Services;
|
||||
|
||||
public class AppStatusService
|
||||
{
|
||||
|
||||
}
|
196
Services/IHttpService.cs
Normal file
196
Services/IHttpService.cs
Normal file
@ -0,0 +1,196 @@
|
||||
using Blazored.LocalStorage;
|
||||
using System.Globalization;
|
||||
using System.Net.Http.Json;
|
||||
using System.Net;
|
||||
using decePubClient.Models;
|
||||
|
||||
namespace decePubClient.Services
|
||||
{
|
||||
public interface IHttpService
|
||||
{
|
||||
Task<HttpResponseMessage> Get(string uri, object payload = default, string?[] queryParams = default);
|
||||
|
||||
Task<HttpResponseMessage> GetAnon(string uri, object payload = default, string?[] queryParams = default);
|
||||
|
||||
Task<HttpResponseMessage> Post(string uri, object payload = default);
|
||||
|
||||
Task<HttpResponseMessage> PostAnon(string uri, object payload = default);
|
||||
|
||||
Task<HttpResponseMessage> Delete(string uri, string?[] queryParams = default, object payload = default);
|
||||
}
|
||||
|
||||
public class HttpService : IHttpService
|
||||
{
|
||||
readonly IHttpClientFactory HttpClientFactory;
|
||||
readonly TokenAuthStateProvider AuthStateProvider;
|
||||
readonly ILogger<HttpService> Logger;
|
||||
readonly ILocalStorageService Storage;
|
||||
readonly IStorage DbStorage;
|
||||
|
||||
public HttpService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
TokenAuthStateProvider authStateProvider,
|
||||
ILogger<HttpService> logger,
|
||||
ILocalStorageService storage,
|
||||
IStorage dbStorage)
|
||||
{
|
||||
HttpClientFactory = httpClientFactory;
|
||||
AuthStateProvider = authStateProvider;
|
||||
Logger = logger;
|
||||
Storage = storage;
|
||||
DbStorage = dbStorage;
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Get(string uri, object payload = default, string?[] queryParams = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}";
|
||||
var request = default(HttpRequestMessage);
|
||||
if (queryParams != null)
|
||||
request = new(HttpMethod.Get, string.Join('?', uri, string.Join('&', queryParams)));
|
||||
else
|
||||
request = new(HttpMethod.Get, uri);
|
||||
if (payload != null)
|
||||
request.Content = JsonContent.Create(payload);
|
||||
return await SendRequest(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(Get)}:{uri}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(Get)}:{uri}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Post(string uri, object payload = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}";
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, uri)
|
||||
{
|
||||
Content = JsonContent.Create(payload)
|
||||
};
|
||||
return await SendRequest(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(Post)}:{uri}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(Post)}:{uri}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> GetAnon(string uri, object payload = default, string?[] queryParams = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}";
|
||||
var request = default(HttpRequestMessage);
|
||||
if (queryParams != null)
|
||||
request = new(HttpMethod.Get, string.Join('?', uri, string.Join('&', queryParams)));
|
||||
else
|
||||
request = new(HttpMethod.Get, uri);
|
||||
if (payload != null)
|
||||
request.Content = JsonContent.Create(payload);
|
||||
return await SendAnonRequest(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(GetAnon)}:{uri}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(GetAnon)}:{uri}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> PostAnon(string uri, object payload = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}";
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, uri)
|
||||
{
|
||||
Content = JsonContent.Create(payload)
|
||||
};
|
||||
return await SendAnonRequest(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(PostAnon)}:{uri}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(PostAnon)}:{uri}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Delete(string uri, string?[] queryParams = default, object payload = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}";
|
||||
var request = default(HttpRequestMessage);
|
||||
if (queryParams != null)
|
||||
request = new(HttpMethod.Delete, string.Join('?', uri, string.Join('&', queryParams)));
|
||||
else
|
||||
request = new(HttpMethod.Delete, uri);
|
||||
if (payload != null)
|
||||
request.Content = JsonContent.Create(payload);
|
||||
return await SendRequest(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(Delete)}:{uri}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(Delete)}:{uri}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
// helper methods
|
||||
async Task<HttpResponseMessage> SendRequest(HttpRequestMessage request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var authData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
|
||||
var isApiUrl = !request.RequestUri?.IsAbsoluteUri;
|
||||
if (isApiUrl.HasValue && isApiUrl.Value)
|
||||
request.Headers.Authorization = new("Bearer", authData.Token);
|
||||
|
||||
var response = await HttpClientFactory.CreateClient().SendAsync(request);
|
||||
if (response.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)
|
||||
{
|
||||
Logger.LogWarning($"{nameof(SendRequest)}:401/403:{request.RequestUri?.OriginalString}:{await response.Content.ReadAsStringAsync()}");
|
||||
await DbStorage.AddLog($"{nameof(SendRequest)}:401/403:{request.RequestUri?.OriginalString}:{await response.Content.ReadAsStringAsync()}", $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}");
|
||||
await AuthStateProvider.LogoutAsync();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<HttpResponseMessage> SendAnonRequest(HttpRequestMessage request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var authData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
|
||||
if (!string.IsNullOrEmpty(authData?.Token))
|
||||
request.Headers.Authorization = new("Bearer", authData.Token);
|
||||
|
||||
var response = await HttpClientFactory.CreateClient().SendAsync(request);
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(SendAnonRequest)}:{request.RequestUri?.OriginalString}");
|
||||
await DbStorage.AddLog(ex, $"{nameof(SendAnonRequest)}:{request.RequestUri?.OriginalString}");
|
||||
return new(HttpStatusCode.ServiceUnavailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
Services/MessagesService.cs
Normal file
10
Services/MessagesService.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace decePubClient.Services
|
||||
{
|
||||
public class MessagesService
|
||||
{
|
||||
public MessagesService()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
89
Services/TokenAuthStateProvider.cs
Normal file
89
Services/TokenAuthStateProvider.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Blazored.LocalStorage;
|
||||
using decePubClient.Models;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace decePubClient.Services
|
||||
{
|
||||
public class TokenAuthStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
readonly ILocalStorageService Storage;
|
||||
readonly IStorage DbStorage;
|
||||
readonly ILogger<TokenAuthStateProvider> Logger;
|
||||
AuthData AuthData { get; set; }
|
||||
|
||||
public TokenAuthStateProvider(ILocalStorageService storage,
|
||||
IStorage dbStorage,
|
||||
ILogger<TokenAuthStateProvider> logger)
|
||||
{
|
||||
Storage = storage;
|
||||
DbStorage = dbStorage;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public void SetToken(/*string token, long expirationTicks = default*/)
|
||||
{
|
||||
//AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
|
||||
//if (string.IsNullOrEmpty(token))
|
||||
//{
|
||||
// Logger.LogInformation($"set null({nameof(SetToken)})");
|
||||
// AuthData.Token = null;
|
||||
// AuthData.TokenExpiration = null;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// AuthData.Token = token;
|
||||
// AuthData.TokenExpiration = expirationTicks;
|
||||
//}
|
||||
//await Storage.SetItemAsync(nameof(AuthData), AuthData);
|
||||
|
||||
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
|
||||
}
|
||||
|
||||
public async ValueTask<bool> IsAuthenticatedAsync()
|
||||
{
|
||||
AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
|
||||
if (AuthData is null)
|
||||
{
|
||||
AuthData = new();
|
||||
await Storage.SetItemAsync(nameof(AuthData), AuthData);
|
||||
}
|
||||
return AuthData.Token != null &&
|
||||
AuthData.TokenExpiration.HasValue &&
|
||||
AuthData.TokenExpiration.Value > DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
public async Task LogoutAsync(bool deleteDb = false)
|
||||
{
|
||||
Logger.LogInformation($"set null({nameof(LogoutAsync)})");
|
||||
//await Storage.RemoveItemAsync(nameof(PrivateCacheData));
|
||||
await Storage.RemoveItemAsync(nameof(AuthData));
|
||||
if (deleteDb)
|
||||
await DbStorage.RemoveAll(includeClientLogs: true);
|
||||
|
||||
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
|
||||
if (string.IsNullOrEmpty(AuthData?.Token))
|
||||
{
|
||||
Logger.LogInformation($"set null({nameof(GetAuthenticationStateAsync)})");
|
||||
return new(new());
|
||||
}
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.UserData, JsonSerializer.Serialize(AuthData.User))
|
||||
};
|
||||
|
||||
//claims.Add(new(Policies.IsUser, (AuthData.User.Policies.Contains(Policies.IsUser)).ToString().ToLower()));
|
||||
//claims.Add(new(Policies.UserPlus, (AuthData.User.Policies.Contains(Policies.UserPlus)).ToString().ToLower()));
|
||||
//claims.Add(new(Policies.IsAdmin, (AuthData.User.Policies.Contains(Policies.IsAdmin)).ToString().ToLower()));
|
||||
|
||||
var identity = new ClaimsIdentity(claims, "jwt");
|
||||
return new(new(identity));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user