using System; using System.Collections.Generic; using System.Linq; using System.Security.Authentication; using System.Text; using System.Threading.Tasks; using Tango.Transport.Web; using Tango.Web.Security; namespace Tango.Web { public abstract class TangoWebClient : IDisposable where TLoginRequest : WebRequestMessage where TLoginResponse : WebTokenResponse { private WebTransportClient _client; private bool _disposed; private TLoginRequest _lastLoginRequest; private DeploymentSlot? _environment; public DeploymentSlot? Environment { get { return _environment; } set { if (_environment != value) { _lastLoginRequest = null; IsAuthenticated = false; } _environment = value; } } public String Address { get; set; } public String Controller { get; private set; } public String Token { get; private set; } public WebToken WebToken { get; private set; } public bool IsAuthenticated { get; private set; } public TangoWebClient(DeploymentSlot environment, String controller) { _client = new WebTransportClient(); Controller = controller; Environment = environment; } public TangoWebClient(DeploymentSlot environment, String controller, String token) : this(environment, controller) { Token = token; } public TangoWebClient(String address, String controller, String token) { _client = new WebTransportClient(); Address = address; Controller = controller; Token = token; } public async Task Login(TLoginRequest request) { var response = await _client.PostJson(GetActionAddress("Login"), request); Token = response.AccessToken; _client.AuthenticationToken = Token; WebToken = WebToken.FromToken(Token); _lastLoginRequest = request; IsAuthenticated = true; return response; } protected virtual async Task Post(String action, TRequest request) where TRequest : class, IWebRequestMessage where TResponse : class, IWebResponseMessage { if (IsAuthenticated) { if (DateTime.UtcNow >= WebToken.Expiration) { await Login(_lastLoginRequest); } } try { var response = await _client.PostJson(GetActionAddress(action), request); return response; } catch (TokenExpiredException) { try { await Login(_lastLoginRequest); var response = await _client.PostJson(GetActionAddress(action), request); return response; } catch { throw; } } catch { throw; } } private String GetActionAddress(String action) { return GetServiceAddress() + action; } protected virtual String GetServiceAddress() { if (Environment != null) { return Environment.Value.ToAddress() + $"/api/{Controller}/"; } else { return Address + $"/api/{Controller}/"; } } public virtual void Dispose() { if (!_disposed) { _disposed = true; _client.Dispose(); } } } }