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 TangoWebClientV2 : IDisposable where TLoginRequest : WebRequestMessage where TLoginResponse : WebTokenResponse { private WebTransportClient _client; private bool _disposed; private TLoginRequest _lastLoginRequest; 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 TimeSpan RequestTimeout { get { return _client.RequestTimeout; } set { _client.RequestTimeout = value; } } public TangoWebClientV2(String address, String controller) { _client = new WebTransportClient(); Controller = controller; Address = address; } public TangoWebClientV2(String address, String controller, String token) : this(address, controller) { Token = token; } public TangoWebClientV2(TangoWebClientV2 cloned) { _client = new WebTransportClient(); Address = cloned.Address; Controller = cloned.Controller; IsAuthenticated = cloned.IsAuthenticated; RequestTimeout = cloned.RequestTimeout; WebToken = cloned.WebToken; _lastLoginRequest = cloned._lastLoginRequest; Token = cloned.Token; } public T Clone() where T : TangoWebClientV2 { return Activator.CreateInstance(typeof(T), new object[] { this }) as T; } 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 ex) { try { await Login(_lastLoginRequest); var response = await _client.PostJson(GetActionAddress(action), request); return response; } catch { throw; } } catch (Exception ex) { throw; } } private String GetActionAddress(String action) { return GetServiceAddress() + action; } protected virtual String GetServiceAddress() { return Address + $"/api/{Controller}/"; } public virtual void Dispose() { if (!_disposed) { _disposed = true; _client.Dispose(); } } } }