diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2019-02-19 01:50:58 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2019-02-19 01:50:58 +0200 |
| commit | 9736b8c8ede6a0d121dea8381f0abb561fad5631 (patch) | |
| tree | 1c38f3f5be82b923ffae40fae00a25487179ab54 /Software/Visual_Studio/Tango.Web | |
| parent | be3343cc0268179c7a6f628fa5e68f323a3335e5 (diff) | |
| download | Tango-9736b8c8ede6a0d121dea8381f0abb561fad5631.tar.gz Tango-9736b8c8ede6a0d121dea8381f0abb561fad5631.zip | |
Implemented auto generated web clients for PPC and machine studio.
Improved interactions with web clients across solutions.
Diffstat (limited to 'Software/Visual_Studio/Tango.Web')
5 files changed, 196 insertions, 29 deletions
diff --git a/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs b/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs index 8e0eb4288..890d69d53 100644 --- a/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs +++ b/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Security.Authentication; using System.Text; using System.Threading.Tasks; +using Tango.Transport.Web; namespace Tango.Web.Authentication { @@ -13,7 +14,7 @@ namespace Tango.Web.Authentication private class TokenWrapper : IEquatable<TokenWrapper> { - public DateTime Date { get; set; } + public WebToken WebToken { get; set; } public T Value { get; set; } @@ -31,61 +32,51 @@ namespace Tango.Web.Authentication public TimeSpan ExpirationTime { get; set; } - public String GetOrCreate(T tokenObject) + public WebToken GetOrCreate(T tokenObject) { var existing_token = _tokens.FirstOrDefault(x => x.Value.Value.Equals(tokenObject)); if (existing_token.Key != null) { - return existing_token.Key; + return existing_token.Value.WebToken; } else { String token = Guid.NewGuid().ToString(); - _tokens.Add(token, new TokenWrapper() + TokenWrapper wrapper = new TokenWrapper() { Value = tokenObject, - Date = DateTime.Now, - }); - return token; + WebToken = new WebToken() + { + AccessToken = token, + Expiration = DateTime.UtcNow.Add(ExpirationTime) + }, + }; + + _tokens.Add(token, wrapper); + return wrapper.WebToken; } } - public bool Exists(String token) + public void Validate(String token) { - RemoveOrRenewExpired(token); - - return _tokens.ContainsKey(token); + GetTokenObject(token); } public T GetTokenObject(String token) { - RemoveOrRenewExpired(token); - if (!_tokens.ContainsKey(token)) { throw new AuthenticationException("Invalid token."); } - return _tokens[token].Value; - } - - private void RemoveOrRenewExpired(String token) - { - DateTime now = DateTime.Now; - - if (_tokens.ContainsKey(token)) + if (DateTime.UtcNow > _tokens[token].WebToken.Expiration) { - _tokens[token].Date = now; + _tokens.Remove(token); + throw new SessionExpiredException("Session Expired."); } - foreach (var t in _tokens.ToList()) - { - if (now > t.Value.Date.Add(ExpirationTime)) - { - _tokens.Remove(t.Key); - } - } + return _tokens[token].Value; } } } diff --git a/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs b/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs new file mode 100644 index 000000000..71ec6eb0b --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Web.Authentication +{ + public class WebToken + { + public DateTime Expiration { get; set; } + public String AccessToken { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs b/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs new file mode 100644 index 000000000..17ac6636f --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.Web.Authentication +{ + public class WebTokenResponse : WebResponseMessage + { + public WebToken WebToken { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Web/Tango.Web.csproj b/Software/Visual_Studio/Tango.Web/Tango.Web.csproj index 98352e131..56711df28 100644 --- a/Software/Visual_Studio/Tango.Web/Tango.Web.csproj +++ b/Software/Visual_Studio/Tango.Web/Tango.Web.csproj @@ -244,7 +244,9 @@ <Link>GlobalVersionInfo.cs</Link> </Compile> <Compile Include="ActiveDirectory\ActiveDirectoryManager.cs" /> + <Compile Include="Authentication\WebTokenResponse.cs" /> <Compile Include="Authentication\TokensManager.cs" /> + <Compile Include="Authentication\WebToken.cs" /> <Compile Include="DeploymentSlot.cs" /> <Compile Include="DeploymentSlotAddressAttribute.cs" /> <Compile Include="ExtensionMethods\DeploymentSlotExtensions.cs" /> @@ -253,6 +255,7 @@ <Compile Include="Storage\ExtensionMethods.cs" /> <Compile Include="Storage\StorageManager.cs" /> <Compile Include="TangoWebApplication.cs" /> + <Compile Include="TangoWebClient.cs" /> <Compile Include="WebConfig.cs" /> <Compile Include="Controllers\JsonController.cs" /> <Compile Include="Formatters\JsonNetFormatter.cs" /> @@ -289,6 +292,10 @@ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> <Name>Tango.Settings</Name> </ProjectReference> + <ProjectReference Include="..\Tango.Transport\Tango.Transport.csproj"> + <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> + <Name>Tango.Transport</Name> + </ProjectReference> </ItemGroup> <ItemGroup /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/Software/Visual_Studio/Tango.Web/TangoWebClient.cs b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs new file mode 100644 index 000000000..bb943533a --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs @@ -0,0 +1,141 @@ +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.Authentication; + +namespace Tango.Web +{ + public abstract class TangoWebClient<TLoginRequest, TLoginResponse> : 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 Controller { get; private set; } + public WebToken WebToken { get; private set; } + public bool IsAuthenticated { get; private set; } + + public TangoWebClient(DeploymentSlot environment, String controller) + { + Controller = controller; + Environment = environment; + _client = new WebTransportClient(); + } + + public TangoWebClient(DeploymentSlot environment, String controller, WebToken token) : this(environment, controller) + { + WebToken = token; + } + + public async Task<TLoginResponse> Login(TLoginRequest request) + { + var response = await _client.PostJson<TLoginRequest, TLoginResponse>(GetActionAddress("Login"), request); + WebToken = response.WebToken; + _lastLoginRequest = request; + IsAuthenticated = true; + return response; + } + + protected virtual async Task<TResponse> Post<TRequest, TResponse>(String action, TRequest request) where TRequest : class, IWebRequestMessage where TResponse : class, IWebResponseMessage + { + bool has_own_token = false; + + if (request is WebRequestSecureMessage) + { + has_own_token = (request as WebRequestSecureMessage).AccessToken != null; + + if (!has_own_token) + { + if (IsAuthenticated) + { + if (DateTime.UtcNow >= WebToken.Expiration) + { + await Login(_lastLoginRequest); + } + } + else + { + throw new AuthenticationException("This tango web client has not been authenticated with the service. Please use the login method to authenticate."); + } + + (request as WebRequestSecureMessage).AccessToken = WebToken.AccessToken; + } + } + + try + { + var response = await _client.PostJson<TRequest, TResponse>(GetActionAddress(action), request); + return response; + } + catch (SessionExpiredException) + { + if (!has_own_token) + { + try + { + await Login(_lastLoginRequest); + + if (request is WebRequestSecureMessage) + { + (request as WebRequestSecureMessage).AccessToken = WebToken.AccessToken; + } + + var response = await _client.PostJson<TRequest, TResponse>(GetActionAddress(action), request); + return response; + } + catch + { + throw; + } + } + else + { + throw; + } + } + catch + { + throw; + } + } + + private String GetActionAddress(String action) + { + return GetServiceAddress() + action; + } + + protected virtual String GetServiceAddress() + { + return Environment.ToAddress() + $"/api/{Controller}/"; + } + + public virtual void Dispose() + { + if (!_disposed) + { + _disposed = true; + _client.Dispose(); + } + } + } +} |
