using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Flawless.Client.Remote; using ReactiveUI; using Refit; namespace Flawless.Client.Service; public class Api : BaseService { class ApiAuthenticationHandler : DelegatingHandler { public ApiAuthenticationHandler(HttpMessageHandler innerHandler) : base(innerHandler) { } protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var tk = Api.C._token.Value; if (tk != null) request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tk.Token); return base.SendAsync(request, cancellationToken); } } public IObservable IsLoggedIn => _isLoggedIn; public IObservable ServerUrl => _serverUrl; public IReactiveProperty Status => _status; public IObservable Token => _token; public IReactiveProperty Username => _username; private readonly ReactiveProperty _isLoggedIn = new(false); private readonly ReactiveProperty _serverUrl = new(string.Empty); private readonly ReactiveProperty _status = new(null); private readonly ReactiveProperty _token = new(null); private readonly ReactiveProperty _username = new(string.Empty); #region GatewayConfig private IFlawlessServer? _gateway; public bool IsGatewayReady => _gateway != null; public IFlawlessServer Gateway => _gateway ?? throw new InvalidProgramException("Not set gateway yet!"); public void ClearGateway() { _gateway = null; _username.Value = null; _isLoggedIn.Value = false; _status.Value = null; _serverUrl.Value = null; _token.Value = null; } public async ValueTask SetGatewayAsync(string host) { var setting = new RefitSettings() { HttpMessageHandlerFactory = () => new ApiAuthenticationHandler(new HttpClientHandler()) }; var tempGateway = RestService.For(host, setting); _status.Value = await tempGateway.Status(); _serverUrl.Value = host; _gateway = tempGateway; } public async ValueTask LoginAsync(string username, string password) { _token.Value = await _gateway.Login(new LoginRequest { Username = username, Password = password }); _username.Value = username; _isLoggedIn.Value = true; await UserService.C.DownloadUserInfoAsync(username); } #endregion #region TokenOperations public bool RequireRefreshToken() { if (_token.Value == null) return true; if (DateTime.UtcNow > _token.Value.Expiration!.Value.UtcDateTime.AddMinutes(-2)) return true; return false; } public async ValueTask TryRefreshTokenAsync() { if (_token.Value == null) return false; try { _token.Value = await Gateway.Refresh(_token.Value); } catch (Exception e) { await Console.Error.WriteLineAsync(e.ToString()); return false; } return true; } #endregion }