From 7516dc061ccbbd8ef638b85a4b06c70f4cbb1d73 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 10 May 2022 13:35:23 +0200 Subject: [PATCH 01/25] Started better API Class --- FabAccessAPI/API.cs | 65 ++++++++++++++ FabAccessAPI/ConnectionData.cs | 15 ++++ FabAccessAPI/ConnectionInfo.cs | 13 +++ FabAccessAPI/ConnectionStatusChange.cs | 23 +++++ .../Exceptions/APIIncompatibleException.cs | 22 +++++ .../Exceptions/ConnectingFailedException.cs | 22 +++++ .../Exceptions/ReconnectingFailedException.cs | 22 +++++ FabAccessAPI/IAPI.cs | 56 ++++++++++++ FabAccessAPI/Mechanism.cs | 7 ++ FabAccessAPI_Test/API_Test.cs | 88 +++++++++++++++++++ FabAccessAPI_Test/TestEnv.cs | 10 +++ 11 files changed, 343 insertions(+) create mode 100644 FabAccessAPI/API.cs create mode 100644 FabAccessAPI/ConnectionData.cs create mode 100644 FabAccessAPI/ConnectionInfo.cs create mode 100644 FabAccessAPI/ConnectionStatusChange.cs create mode 100644 FabAccessAPI/Exceptions/APIIncompatibleException.cs create mode 100644 FabAccessAPI/Exceptions/ConnectingFailedException.cs create mode 100644 FabAccessAPI/Exceptions/ReconnectingFailedException.cs create mode 100644 FabAccessAPI/IAPI.cs create mode 100644 FabAccessAPI/Mechanism.cs create mode 100644 FabAccessAPI_Test/API_Test.cs create mode 100644 FabAccessAPI_Test/TestEnv.cs diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs new file mode 100644 index 0000000..e66e960 --- /dev/null +++ b/FabAccessAPI/API.cs @@ -0,0 +1,65 @@ +using FabAccessAPI.Schema; +using System; + +namespace FabAccessAPI +{ + public class API : IAPI + { + #region Private Members + #endregion + + #region Constructors + public API() + { + + } + #endregion + #region Events + public event EventHandler ConnectionStatusChanged; + #endregion + + #region Members + public ConnectionData ConnectionData { get; private set; } + + public ConnectionInfo ConnectionInfo { get; private set; } + + public bool IsConnected + { + get + { + throw new NotImplementedException(); + } + } + + public Session Session + { + get + { + throw new NotImplementedException(); + } + } + #endregion + + #region Methods + public void Connect(ConnectionData connectionData) + { + throw new NotImplementedException(); + } + + public void Disconnect() + { + throw new NotImplementedException(); + } + + public void Reconnect() + { + throw new NotImplementedException(); + } + + public ConnectionInfo TestConnection(ConnectionData connectionData) + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/FabAccessAPI/ConnectionData.cs b/FabAccessAPI/ConnectionData.cs new file mode 100644 index 0000000..84bb26f --- /dev/null +++ b/FabAccessAPI/ConnectionData.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace FabAccessAPI +{ + public class ConnectionData + { + public Uri Host; + public Mechanism Mechanism; + public string Username; + public Dictionary Properties; + public Dictionary SecretProperties; + public DateTime LastTime; + } +} diff --git a/FabAccessAPI/ConnectionInfo.cs b/FabAccessAPI/ConnectionInfo.cs new file mode 100644 index 0000000..e0870a3 --- /dev/null +++ b/FabAccessAPI/ConnectionInfo.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace FabAccessAPI +{ + public class ConnectionInfo + { + public Version APIVersion; + public string ServerName; + public string ServerRelease; + public List Mechanisms; + } +} diff --git a/FabAccessAPI/ConnectionStatusChange.cs b/FabAccessAPI/ConnectionStatusChange.cs new file mode 100644 index 0000000..d6fd683 --- /dev/null +++ b/FabAccessAPI/ConnectionStatusChange.cs @@ -0,0 +1,23 @@ +namespace FabAccessAPI +{ + public enum ConnectionStatusChange + { + /// + /// Client has established connection to server. + /// + Connected, + /// + /// Client has closed connection to server. + /// + Disconnected, + /// + /// Connection was lost and Client has reestablished connection to server. + /// + Reconnected, + /// + /// Connection was lost and can be reestablished with reconnect + /// Connection should be closed if reconnecting fails. + /// + ConnectionLoss + } +} diff --git a/FabAccessAPI/Exceptions/APIIncompatibleException.cs b/FabAccessAPI/Exceptions/APIIncompatibleException.cs new file mode 100644 index 0000000..24f91ff --- /dev/null +++ b/FabAccessAPI/Exceptions/APIIncompatibleException.cs @@ -0,0 +1,22 @@ +using System; + +namespace FabAccessAPI.Exceptions +{ + public class APIIncompatibleException : Exception + { + public APIIncompatibleException() + { + + } + + public APIIncompatibleException(string message) : base(message) + { + + } + + public APIIncompatibleException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/FabAccessAPI/Exceptions/ConnectingFailedException.cs b/FabAccessAPI/Exceptions/ConnectingFailedException.cs new file mode 100644 index 0000000..9f96c18 --- /dev/null +++ b/FabAccessAPI/Exceptions/ConnectingFailedException.cs @@ -0,0 +1,22 @@ +using System; + +namespace FabAccessAPI.Exceptions +{ + public class ConnectingFailedException : Exception + { + public ConnectingFailedException() + { + + } + + public ConnectingFailedException(string message) : base(message) + { + + } + + public ConnectingFailedException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/FabAccessAPI/Exceptions/ReconnectingFailedException.cs b/FabAccessAPI/Exceptions/ReconnectingFailedException.cs new file mode 100644 index 0000000..4d4b810 --- /dev/null +++ b/FabAccessAPI/Exceptions/ReconnectingFailedException.cs @@ -0,0 +1,22 @@ +using System; + +namespace FabAccessAPI.Exceptions +{ + public class ReconnectingFailedException : Exception + { + public ReconnectingFailedException() + { + + } + + public ReconnectingFailedException(string message) : base(message) + { + + } + + public ReconnectingFailedException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/FabAccessAPI/IAPI.cs b/FabAccessAPI/IAPI.cs new file mode 100644 index 0000000..884f8bc --- /dev/null +++ b/FabAccessAPI/IAPI.cs @@ -0,0 +1,56 @@ +using FabAccessAPI.Schema; +using System; + +namespace FabAccessAPI +{ + public interface IAPI + { + /// + /// Data to establish connection. + /// + /// Without SecretProperties + ConnectionData ConnectionData { get; } + + /// + /// Information about the established connection. + /// + ConnectionInfo ConnectionInfo { get; } + + /// + /// Is API connected? + /// + bool IsConnected { get; } + + /// + /// Get session when connection is established + /// + Session Session { get; } + + /// + /// Event on changes in connection state. + /// + event EventHandler ConnectionStatusChanged; + + /// + /// Connect to BFFH Server + /// + /// + void Connect(ConnectionData connectionData); + + /// + /// Disconnect from BFFH Server + /// + void Disconnect(); + + /// + /// Reconnect after connection loss with the last ConnectionData + /// + void Reconnect(); + + /// + /// Connect to Server and get ConnectionInfo. + /// The Connection is not maintained. + /// + ConnectionInfo TestConnection(ConnectionData connectionData); + } +} diff --git a/FabAccessAPI/Mechanism.cs b/FabAccessAPI/Mechanism.cs new file mode 100644 index 0000000..0d196b3 --- /dev/null +++ b/FabAccessAPI/Mechanism.cs @@ -0,0 +1,7 @@ +namespace FabAccessAPI +{ + public enum Mechanism + { + PLAIN + } +} diff --git a/FabAccessAPI_Test/API_Test.cs b/FabAccessAPI_Test/API_Test.cs new file mode 100644 index 0000000..dd3f52a --- /dev/null +++ b/FabAccessAPI_Test/API_Test.cs @@ -0,0 +1,88 @@ + +using FabAccessAPI; +using FabAccessAPI.Exceptions; +using NUnit.Framework; +using System; +using System.Collections.Generic; + +namespace FabAccessAPI_Test +{ + public class API_Test + { + [TestCase("Admin1")] + public void ConnectDisconnect(string username) + { + API api = new API(); + + ConnectionData connectionData = new ConnectionData() + { + Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, + Mechanism = Mechanism.PLAIN, + Username = username, + Properties = new Dictionary() + { + { "Username", username } + }, + SecretProperties = new Dictionary() + { + { "Password", TestEnv.PASSWORD } + } + }; + + api.Connect(connectionData); + api.Disconnect(); + } + + [Test] + public void Connect_HostUnreachable() + { + API api = new API(); + + ConnectionData connectionData = new ConnectionData() + { + Host = new UriBuilder(TestEnv.SCHEMA, "NotReachable." + TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, + Mechanism = Mechanism.PLAIN, + Username = "UnknownUser", + Properties = new Dictionary() + { + { "Username", "UnknownUser" } + }, + SecretProperties = new Dictionary() + { + { "Password", TestEnv.PASSWORD } + } + }; + + Assert.Throws(() => + { + api.Connect(connectionData); + }); + } + + [Test] + public void Connect_InvalidCredentials() + { + API api = new API(); + + ConnectionData connectionData = new ConnectionData() + { + Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, + Mechanism = Mechanism.PLAIN, + Username = "UnknownUser", + Properties = new Dictionary() + { + { "Username", "UnknownUser" } + }, + SecretProperties = new Dictionary() + { + { "Password", TestEnv.PASSWORD } + } + }; + + Assert.Throws(() => + { + api.Connect(connectionData); + }); + } + } +} diff --git a/FabAccessAPI_Test/TestEnv.cs b/FabAccessAPI_Test/TestEnv.cs new file mode 100644 index 0000000..adf2f83 --- /dev/null +++ b/FabAccessAPI_Test/TestEnv.cs @@ -0,0 +1,10 @@ +namespace FabAccessAPI_Test +{ + public static class TestEnv + { + public const string SCHEMA = "fabaccess"; + public const string TESTSERVER = "bffh.lab.bln.kjknet.de"; + public const int TESTSERVER_PORT = 59666; + public const string PASSWORD = "secret"; + } +} From a9a3f9c545ba7a633d101fc51fca48fb7802bdef Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 10 May 2022 23:50:04 +0200 Subject: [PATCH 02/25] Changed Git Submodules --- .gitmodules | 2 +- FabAccessAPI/API.cs | 1 + FabAccessAPI/schema | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 648ccf2..9033f1b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,5 +16,5 @@ [submodule "external/capnproto-dotnetcore"] path = external/capnproto-dotnetcore url = https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git - branch = main + branch = master ignore = all diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index e66e960..c1bc7a0 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -14,6 +14,7 @@ namespace FabAccessAPI } #endregion + #region Events public event EventHandler ConnectionStatusChanged; #endregion diff --git a/FabAccessAPI/schema b/FabAccessAPI/schema index f1fa024..19f20f5 160000 --- a/FabAccessAPI/schema +++ b/FabAccessAPI/schema @@ -1 +1 @@ -Subproject commit f1fa0246130ff81abc2791b2c1a60b8b020257f7 +Subproject commit 19f20f5154f0eced6288ff56cac840025ee51da1 From bb4a74f8c4005041e996ab86fed8f4c777682080 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Wed, 11 May 2022 15:02:17 +0200 Subject: [PATCH 03/25] Added more API Service Methods --- Borepin/Borepin/Service/BFFH/BFFHService.cs | 27 +--- .../Exceptions/APIIncompatibleException.cs | 22 --- .../Exceptions/AllreadyConnectedException.cs | 22 --- .../AuthenticatingFailedException.cs | 22 --- .../Exceptions/ConnectingFailedException.cs | 22 --- FabAccessAPI/API.cs | 140 ++++++++++++++++-- FabAccessAPI/Auth.cs | 32 ++-- FabAccessAPI/Connection.cs | 4 +- FabAccessAPI/IAPI.cs | 7 +- FabAccessAPI/Mechanism.cs | 21 ++- FabAccessAPI_Test/API_Test.cs | 33 +++-- 11 files changed, 202 insertions(+), 150 deletions(-) delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs diff --git a/Borepin/Borepin/Service/BFFH/BFFHService.cs b/Borepin/Borepin/Service/BFFH/BFFHService.cs index d69d1b5..a0fcf48 100644 --- a/Borepin/Borepin/Service/BFFH/BFFHService.cs +++ b/Borepin/Borepin/Service/BFFH/BFFHService.cs @@ -130,11 +130,6 @@ namespace Borepin.Service.BFFH /// public async Task Connect(Connection connection) { - if (IsConnected) - { - throw new AllreadyConnectedException(); - } - string password; try { @@ -162,7 +157,6 @@ namespace Borepin.Service.BFFH if (! await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) { await Disconnect().ConfigureAwait(false); - throw new AuthenticatingFailedException(); } _CurrentConnection = new Connection_Plain(connection) @@ -182,10 +176,6 @@ namespace Borepin.Service.BFFH /// public async Task Connect(Connection connection, string password) { - if (IsConnected) - { - throw new AllreadyConnectedException(); - } try { @@ -201,7 +191,7 @@ namespace Borepin.Service.BFFH if (!await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) { await Disconnect().ConfigureAwait(false); - throw new AuthenticatingFailedException(); + } _CurrentConnection = new Connection_Plain(connection) @@ -239,15 +229,6 @@ namespace Borepin.Service.BFFH _APIConnection = new FabAccessAPI.Connection(rpcClient); } - catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) - { - throw new ReconnectingFailedException("Connecting failed", new ConnectingFailedException("Connecting failed", exception)); - } - - if (! await _AuthenticatePlainAsync(_CurrentConnection.Username, _CurrentConnection.Password).ConfigureAwait(false)) - { - throw new ReconnectingFailedException("Authentication failed", new AuthenticatingFailedException()); - } } /// @@ -316,11 +297,7 @@ namespace Borepin.Service.BFFH await _APIConnection.Auth("PLAIN", new Dictionary(StringComparer.Ordinal) { { "Username", username }, { "Password", password } }).ConfigureAwait(false); return await Task.FromResult(true).ConfigureAwait(false); } - catch(InvalidCredentialsException) - { - return await Task.FromResult(true).ConfigureAwait(false); - } - catch (AuthenticatingFailedException) + catch(UnsupportedMechanismException) { return await Task.FromResult(true).ConfigureAwait(false); } diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs deleted file mode 100644 index e676e0e..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class APIIncompatibleException : Exception - { - public APIIncompatibleException() - { - - } - - public APIIncompatibleException(string message) : base(message) - { - - } - - public APIIncompatibleException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs deleted file mode 100644 index aa96c7b..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class AllreadyConnectedException : Exception - { - public AllreadyConnectedException() - { - - } - - public AllreadyConnectedException(string message) : base(message) - { - - } - - public AllreadyConnectedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs deleted file mode 100644 index e753cdc..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class AuthenticatingFailedException : Exception - { - public AuthenticatingFailedException() - { - - } - - public AuthenticatingFailedException(string message) : base(message) - { - - } - - public AuthenticatingFailedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs deleted file mode 100644 index 082f442..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class ConnectingFailedException : Exception - { - public ConnectingFailedException() - { - - } - - public ConnectingFailedException(string message) : base(message) - { - - } - - public ConnectingFailedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index c1bc7a0..91042c5 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -1,11 +1,19 @@ -using FabAccessAPI.Schema; +using Capnp.Rpc; +using FabAccessAPI.Exceptions; +using FabAccessAPI.Schema; using System; +using System.Collections.Generic; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; namespace FabAccessAPI { public class API : IAPI { #region Private Members + private Connection _APIConnection; #endregion #region Constructors @@ -28,7 +36,7 @@ namespace FabAccessAPI { get { - throw new NotImplementedException(); + return _APIConnection != null && _APIConnection.RpcClient.State == ConnectionState.Active; } } @@ -42,24 +50,138 @@ namespace FabAccessAPI #endregion #region Methods - public void Connect(ConnectionData connectionData) + /// + /// Connect to server with ConnectionData + /// + /// + /// + public async Task Connect(ConnectionData connectionData) + { + if (IsConnected) + { + await Disconnect(); + } + + TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); + + _APIConnection = new Connection(rpcClient); + + try + { + await _Authenticate(connectionData).ConfigureAwait(false); + } + catch(System.Exception) + { + await Disconnect().ConfigureAwait(false); + throw; + } + } + + public Task Disconnect() + { + if (IsConnected) + { + _APIConnection.RpcClient?.Dispose(); + } + + _APIConnection = null; + ConnectionData = null; + ConnectionInfo = null; + + return Task.CompletedTask; + } + + public Task Reconnect() { throw new NotImplementedException(); } - public void Disconnect() + public async Task TestConnection(ConnectionData connectionData) { - throw new NotImplementedException(); + try + { + TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); + Connection testConnection = new Connection(rpcClient); + + rpcClient.Dispose(); + + ConnectionInfo connectionInfo = new ConnectionInfo() + { + APIVersion = testConnection. + } + + return true; + } + catch + { + return null; + } + } + #endregion + + #region Private Methods + private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + // TODO Cert Check + return true; } - public void Reconnect() + /// + /// Connect to server async with ConnectionData + /// + /// TLS Error + /// Based on RPC Exception + /// + private async Task _ConnectAsync(ConnectionData connectionData) { - throw new NotImplementedException(); + TcpRpcClient rpcClient = new TcpRpcClient(); + rpcClient.InjectMidlayer((tcpstream) => + { + var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); + try + { + sslStream.AuthenticateAsClient("bffhd"); + return sslStream; + } + catch (AuthenticationException) + { + sslStream.Close(); + throw; + } + }); + + try + { + rpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port); + await rpcClient.WhenConnected.ConfigureAwait(false); + + return rpcClient; + } + catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) + { + throw new ConnectingFailedException("Connecting failed", exception); + } } - public ConnectionInfo TestConnection(ConnectionData connectionData) + /// + /// Authenticate connection with ConnectionData + /// + /// + /// + /// + private async Task _Authenticate(ConnectionData connectionData) { - throw new NotImplementedException(); + Dictionary joinedProperties = new Dictionary(); + foreach(KeyValuePair keyValuePair in connectionData.Properties) + { + joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); + } + foreach (KeyValuePair keyValuePair in connectionData.SecretProperties) + { + joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); + } + + await _APIConnection.Auth(MechanismString.ToString(connectionData.Mechanism), joinedProperties).ConfigureAwait(false); } #endregion } diff --git a/FabAccessAPI/Auth.cs b/FabAccessAPI/Auth.cs index 457a091..231952a 100644 --- a/FabAccessAPI/Auth.cs +++ b/FabAccessAPI/Auth.cs @@ -24,6 +24,12 @@ namespace FabAccessAPI #endregion #region Methods + /// + /// Authenticate Connection to get Session + /// + /// + /// + /// public async Task Authenticate(string mech, Dictionary properties) { SaslMechanism? saslMechanism = SaslFactory.Create(mech); @@ -44,17 +50,7 @@ namespace FabAccessAPI { if(response.Failed != null) { - switch (response.Failed.Code) - { - case Response.Error.badMechanism: - throw new BadMechanismException(); - case Response.Error.invalidCredentials: - throw new InvalidCredentialsException(); - case Response.Error.aborted: - case Response.Error.failed: - default: - throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); - } + break; } if(response.Challenge != null) { @@ -71,6 +67,20 @@ namespace FabAccessAPI { return response.Successful.Session; } + else if (response.Failed != null) + { + switch (response.Failed.Code) + { + case Response.Error.badMechanism: + throw new BadMechanismException(); + case Response.Error.invalidCredentials: + throw new InvalidCredentialsException(); + case Response.Error.aborted: + case Response.Error.failed: + default: + throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); + } + } else { throw new AuthenticationFailedException(); diff --git a/FabAccessAPI/Connection.cs b/FabAccessAPI/Connection.cs index 00d9246..34ade82 100644 --- a/FabAccessAPI/Connection.cs +++ b/FabAccessAPI/Connection.cs @@ -41,7 +41,9 @@ namespace FabAccessAPI /// /// The desired authentication mechanism /// Key-Value data specific to the mechanism - /// + /// + /// + /// public async Task Auth(string mech, Dictionary kvs, CancellationToken cancellationToken_ = default) { IReadOnlyList? mechs = await _BootstrapCap.Mechanisms(); diff --git a/FabAccessAPI/IAPI.cs b/FabAccessAPI/IAPI.cs index 884f8bc..0d6d203 100644 --- a/FabAccessAPI/IAPI.cs +++ b/FabAccessAPI/IAPI.cs @@ -1,5 +1,6 @@ using FabAccessAPI.Schema; using System; +using System.Threading.Tasks; namespace FabAccessAPI { @@ -35,17 +36,17 @@ namespace FabAccessAPI /// Connect to BFFH Server /// /// - void Connect(ConnectionData connectionData); + Task Connect(ConnectionData connectionData); /// /// Disconnect from BFFH Server /// - void Disconnect(); + Task Disconnect(); /// /// Reconnect after connection loss with the last ConnectionData /// - void Reconnect(); + Task Reconnect(); /// /// Connect to Server and get ConnectionInfo. diff --git a/FabAccessAPI/Mechanism.cs b/FabAccessAPI/Mechanism.cs index 0d196b3..96a4e53 100644 --- a/FabAccessAPI/Mechanism.cs +++ b/FabAccessAPI/Mechanism.cs @@ -1,7 +1,24 @@ -namespace FabAccessAPI +using System; + +namespace FabAccessAPI { public enum Mechanism { - PLAIN + PLAIN, } + + public static class MechanismString + { + public static string ToString(Mechanism mechanism) + { + switch(mechanism) + { + case Mechanism.PLAIN: + return "PLAIN"; + default: + throw new ArgumentException("Mechanism not known."); + } + } + } + } diff --git a/FabAccessAPI_Test/API_Test.cs b/FabAccessAPI_Test/API_Test.cs index dd3f52a..e631ed8 100644 --- a/FabAccessAPI_Test/API_Test.cs +++ b/FabAccessAPI_Test/API_Test.cs @@ -4,13 +4,14 @@ using FabAccessAPI.Exceptions; using NUnit.Framework; using System; using System.Collections.Generic; +using System.Threading.Tasks; namespace FabAccessAPI_Test { public class API_Test { [TestCase("Admin1")] - public void ConnectDisconnect(string username) + public async Task ConnectDisconnect(string username) { API api = new API(); @@ -29,12 +30,12 @@ namespace FabAccessAPI_Test } }; - api.Connect(connectionData); - api.Disconnect(); + await api.Connect(connectionData); + await api.Disconnect(); } [Test] - public void Connect_HostUnreachable() + public async Task Connect_HostUnreachable() { API api = new API(); @@ -53,14 +54,19 @@ namespace FabAccessAPI_Test } }; - Assert.Throws(() => + try { - api.Connect(connectionData); - }); + await api.Connect(connectionData); + } + catch (ConnectingFailedException) + { + Assert.Pass(); + } + Assert.Fail(); } [Test] - public void Connect_InvalidCredentials() + public async Task Connect_InvalidCredentials() { API api = new API(); @@ -79,10 +85,15 @@ namespace FabAccessAPI_Test } }; - Assert.Throws(() => + try { - api.Connect(connectionData); - }); + await api.Connect(connectionData); + } + catch(InvalidCredentialsException) + { + Assert.Pass(); + } + Assert.Fail(); } } } From 0d5ad01496e664fa24d06b7cf6dd55a6ae2189ee Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 12 May 2022 23:08:37 +0200 Subject: [PATCH 04/25] Added: New API Class --- Borepin/Borepin/Service/BFFH/BFFHService.cs | 36 +- FabAccessAPI/API.cs | 200 ++++++++-- FabAccessAPI/Auth.cs | 91 ----- FabAccessAPI/Connection.cs | 65 ---- FabAccessAPI/ConnectionInfo.cs | 2 +- FabAccessAPI/IAPI.cs | 7 +- FabAccessAPI_Test/API_Test.cs | 166 ++++++--- FabAccessAPI_Test/API_TestEnv_Test.cs | 382 ++++++++++---------- FabAccessAPI_Test/Connection_Test.cs | 75 ---- FabAccessAPI_Test/TestEnv.cs | 26 +- 10 files changed, 514 insertions(+), 536 deletions(-) delete mode 100644 FabAccessAPI/Auth.cs delete mode 100644 FabAccessAPI/Connection.cs delete mode 100644 FabAccessAPI_Test/Connection_Test.cs diff --git a/Borepin/Borepin/Service/BFFH/BFFHService.cs b/Borepin/Borepin/Service/BFFH/BFFHService.cs index a0fcf48..52d310e 100644 --- a/Borepin/Borepin/Service/BFFH/BFFHService.cs +++ b/Borepin/Borepin/Service/BFFH/BFFHService.cs @@ -13,6 +13,7 @@ using FabAccessAPI.Exceptions; using System.Security.Cryptography.X509Certificates; using System.Net.Security; using System.Security.Authentication; +using FabAccessAPI; namespace Borepin.Service.BFFH { @@ -22,7 +23,6 @@ namespace Borepin.Service.BFFH private readonly ConnectionStorage _ConnectionStorage; private readonly ConnectionCredentialStorage _ConnectionCredentialStorage; - private FabAccessAPI.Connection _APIConnection; private Connection_Plain _CurrentConnection; #endregion @@ -37,31 +37,9 @@ namespace Borepin.Service.BFFH #region Fields /// - /// Current Connection of Service + /// API Connection /// - public Connection CurrentConnection - { - get - { - return _CurrentConnection; - } - } - - /// - /// Check if Service is connected to a Server - /// - public bool IsConnected - { - get - { - if (_APIConnection != null && _APIConnection.RpcClient != null) - { - return _APIConnection.RpcClient.State == Capnp.Rpc.ConnectionState.Active; - } - - return false; - } - } + public API API { get; private set; } #endregion #region Method @@ -78,7 +56,7 @@ namespace Borepin.Service.BFFH /// public async Task RemoveConnection(Connection connection) { - if (IsConnected && connection.Equals(CurrentConnection)) + if (API != null && API.IsConnected && connection.Equals(_CurrentConnection)) { await Disconnect().ConfigureAwait(false); } @@ -109,7 +87,6 @@ namespace Borepin.Service.BFFH { try { - TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false); rpcClient.Dispose(); @@ -176,7 +153,6 @@ namespace Borepin.Service.BFFH /// public async Task Connect(Connection connection, string password) { - try { TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false); @@ -229,6 +205,10 @@ namespace Borepin.Service.BFFH _APIConnection = new FabAccessAPI.Connection(rpcClient); } + catch + { + + } } /// diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index 91042c5..27af1d5 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -1,8 +1,10 @@ using Capnp.Rpc; using FabAccessAPI.Exceptions; using FabAccessAPI.Schema; +using S22.Sasl; using System; using System.Collections.Generic; +using System.Linq; using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; @@ -13,7 +15,8 @@ namespace FabAccessAPI public class API : IAPI { #region Private Members - private Connection _APIConnection; + private TcpRpcClient _TcpRpcClient; + private IBootstrap _Bootstrap; #endregion #region Constructors @@ -25,6 +28,25 @@ namespace FabAccessAPI #region Events public event EventHandler ConnectionStatusChanged; + + public void OnTcpRpcConnectionChanged(object sender, ConnectionStateChange args) + { + EventHandler eventHandler = ConnectionStatusChanged; + + if (eventHandler == null) + { + return; + } + + if (args.LastState == ConnectionState.Initializing && args.NewState == ConnectionState.Active) + { + eventHandler(this, ConnectionStatusChange.Connected); + } + if (args.LastState == ConnectionState.Active && args.NewState == ConnectionState.Down) + { + eventHandler(this, ConnectionStatusChange.ConnectionLoss); + } + } #endregion #region Members @@ -36,17 +58,11 @@ namespace FabAccessAPI { get { - return _APIConnection != null && _APIConnection.RpcClient.State == ConnectionState.Active; + return _TcpRpcClient != null && _TcpRpcClient.State == ConnectionState.Active; } } - public Session Session - { - get - { - throw new NotImplementedException(); - } - } + public Session Session { get; private set; } #endregion #region Methods @@ -55,20 +71,33 @@ namespace FabAccessAPI /// /// /// - public async Task Connect(ConnectionData connectionData) + public async Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null) { if (IsConnected) { await Disconnect(); } - TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); - - _APIConnection = new Connection(rpcClient); + if(tcpRpcClient == null) + { + _TcpRpcClient = new TcpRpcClient(); + } + else + { + _TcpRpcClient = tcpRpcClient; + } try { - await _Authenticate(connectionData).ConfigureAwait(false); + _TcpRpcClient.ConnectionStateChanged += OnTcpRpcConnectionChanged; + + await _ConnectAsync(_TcpRpcClient, connectionData).ConfigureAwait(false); + + _Bootstrap = _TcpRpcClient.GetMain(); + ConnectionInfo = await _GetConnectionInfo(_Bootstrap); + + Session = await _Authenticate(connectionData).ConfigureAwait(false); + ConnectionData = connectionData; } catch(System.Exception) { @@ -81,45 +110,68 @@ namespace FabAccessAPI { if (IsConnected) { - _APIConnection.RpcClient?.Dispose(); + _TcpRpcClient.Dispose(); } - - _APIConnection = null; + + _Bootstrap = null; + Session = null; + _TcpRpcClient = null; ConnectionData = null; ConnectionInfo = null; + EventHandler eventHandler = ConnectionStatusChanged; + if (eventHandler != null) + { + eventHandler(this, ConnectionStatusChange.Disconnected); + } + return Task.CompletedTask; } - public Task Reconnect() + public async Task Reconnect() { - throw new NotImplementedException(); + if (ConnectionData != null) + { + await Connect(ConnectionData); + } + + EventHandler eventHandler = ConnectionStatusChanged; + if (eventHandler != null) + { + eventHandler(this, ConnectionStatusChange.Reconnected); + } } - public async Task TestConnection(ConnectionData connectionData) + public async Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null) { try { - TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); - Connection testConnection = new Connection(rpcClient); - - rpcClient.Dispose(); - - ConnectionInfo connectionInfo = new ConnectionInfo() + if (tcpRpcClient == null) { - APIVersion = testConnection. + tcpRpcClient = new TcpRpcClient(); } - return true; + await _ConnectAsync(tcpRpcClient, connectionData).ConfigureAwait(false); + IBootstrap testBootstrap = tcpRpcClient.GetMain(); + + ConnectionInfo connectionInfo = await _GetConnectionInfo(testBootstrap).ConfigureAwait(false); + + tcpRpcClient.Dispose(); + + return connectionInfo; } catch { - return null; + throw new ConnectingFailedException(); } } #endregion #region Private Methods + /// + /// Validate Certificate + /// TODO: Do some validation + /// private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // TODO Cert Check @@ -132,9 +184,8 @@ namespace FabAccessAPI /// TLS Error /// Based on RPC Exception /// - private async Task _ConnectAsync(ConnectionData connectionData) + private async Task _ConnectAsync(TcpRpcClient rpcClient, ConnectionData connectionData) { - TcpRpcClient rpcClient = new TcpRpcClient(); rpcClient.InjectMidlayer((tcpstream) => { var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); @@ -154,8 +205,6 @@ namespace FabAccessAPI { rpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port); await rpcClient.WhenConnected.ConfigureAwait(false); - - return rpcClient; } catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) { @@ -163,13 +212,29 @@ namespace FabAccessAPI } } + /// + /// Create ConnectionInfo from Bootstrap + /// + private async Task _GetConnectionInfo(IBootstrap bootstrap) + { + ConnectionInfo connectionInfo = new ConnectionInfo() + { + APIVersion = await bootstrap.GetAPIVersion().ConfigureAwait(false), + Mechanisms = new List(await bootstrap.Mechanisms().ConfigureAwait(false)), + ServerName = (await bootstrap.GetServerRelease().ConfigureAwait(false)).Item1, + ServerRelease = (await bootstrap.GetServerRelease().ConfigureAwait(false)).Item2, + }; + + return connectionInfo; + } + /// /// Authenticate connection with ConnectionData /// /// /// /// - private async Task _Authenticate(ConnectionData connectionData) + private async Task _Authenticate(ConnectionData connectionData) { Dictionary joinedProperties = new Dictionary(); foreach(KeyValuePair keyValuePair in connectionData.Properties) @@ -181,7 +246,72 @@ namespace FabAccessAPI joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); } - await _APIConnection.Auth(MechanismString.ToString(connectionData.Mechanism), joinedProperties).ConfigureAwait(false); + IAuthentication? authentication = await _Bootstrap.CreateSession(MechanismString.ToString(connectionData.Mechanism)).ConfigureAwait(false); + + return await _SASLAuthenticate(authentication, MechanismString.ToString(connectionData.Mechanism), joinedProperties).ConfigureAwait(false); + } + + /// + /// Authenticate Connection to get Session + /// + /// + /// + /// + public async Task _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary properties) + { + SaslMechanism? saslMechanism = SaslFactory.Create(mech); + foreach (KeyValuePair entry in properties) + { + saslMechanism.Properties.Add(entry.Key, entry.Value); + } + + byte[] data = new byte[0]; + + if (saslMechanism.HasInitial) + { + data = saslMechanism.GetResponse(new byte[0]); + } + + Response? response = await authentication.Step(data); + while (!saslMechanism.IsCompleted) + { + if(response.Failed != null) + { + break; + } + if(response.Challenge != null) + { + byte[]? additional = saslMechanism.GetResponse(response.Challenge.ToArray()); + response = await authentication.Step(additional); + } + else + { + throw new AuthenticationFailedException(); + } + } + + if (response.Successful != null) + { + return response.Successful.Session; + } + else if (response.Failed != null) + { + switch (response.Failed.Code) + { + case Response.Error.badMechanism: + throw new BadMechanismException(); + case Response.Error.invalidCredentials: + throw new InvalidCredentialsException(); + case Response.Error.aborted: + case Response.Error.failed: + default: + throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); + } + } + else + { + throw new AuthenticationFailedException(); + } } #endregion } diff --git a/FabAccessAPI/Auth.cs b/FabAccessAPI/Auth.cs deleted file mode 100644 index 231952a..0000000 --- a/FabAccessAPI/Auth.cs +++ /dev/null @@ -1,91 +0,0 @@ -using FabAccessAPI.Schema; -using S22.Sasl; -using System.Collections.Generic; -using System.Threading.Tasks; -using FabAccessAPI.Exceptions; -using System.Linq; - -namespace FabAccessAPI -{ - /// - /// Authenticate with SASL - /// - public class Auth - { - #region Private Fields - private readonly IAuthentication _AuthCap; - #endregion - - #region Constructors - public Auth(IAuthentication authCap) - { - _AuthCap = authCap; - } - #endregion - - #region Methods - /// - /// Authenticate Connection to get Session - /// - /// - /// - /// - public async Task Authenticate(string mech, Dictionary properties) - { - SaslMechanism? saslMechanism = SaslFactory.Create(mech); - foreach (KeyValuePair entry in properties) - { - saslMechanism.Properties.Add(entry.Key, entry.Value); - } - - byte[] data = new byte[0]; - - if (saslMechanism.HasInitial) - { - data = saslMechanism.GetResponse(new byte[0]); - } - - Response? response = await _AuthCap.Step(data); - while (!saslMechanism.IsCompleted) - { - if(response.Failed != null) - { - break; - } - if(response.Challenge != null) - { - byte[]? additional = saslMechanism.GetResponse(response.Challenge.ToArray()); - response = await _AuthCap.Step(additional); - } - else - { - throw new AuthenticationFailedException(); - } - } - - if (response.Successful != null) - { - return response.Successful.Session; - } - else if (response.Failed != null) - { - switch (response.Failed.Code) - { - case Response.Error.badMechanism: - throw new BadMechanismException(); - case Response.Error.invalidCredentials: - throw new InvalidCredentialsException(); - case Response.Error.aborted: - case Response.Error.failed: - default: - throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); - } - } - else - { - throw new AuthenticationFailedException(); - } - } - #endregion - } -} diff --git a/FabAccessAPI/Connection.cs b/FabAccessAPI/Connection.cs deleted file mode 100644 index 34ade82..0000000 --- a/FabAccessAPI/Connection.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Capnp.Rpc; -using FabAccessAPI.Exceptions; -using FabAccessAPI.Schema; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace FabAccessAPI -{ - public class Connection - { - #region Private Fields - private readonly IBootstrap? _BootstrapCap = null; - private Auth? _Auth = null; - #endregion - - #region Constructors - /// - /// - /// - /// Should be an already configured and connected TcpRpcClient - public Connection(TcpRpcClient rpcClient) - { - RpcClient = rpcClient; - _BootstrapCap = RpcClient.GetMain(); - } - #endregion - - #region Fields - public TcpRpcClient? RpcClient { get; } = null; - - public Session? Session { get; private set; } = null; - #endregion - - #region Methods - /// - /// Authenticate this connection. - /// Calling this more then once is UB - /// - /// The desired authentication mechanism - /// Key-Value data specific to the mechanism - /// - /// - /// - public async Task Auth(string mech, Dictionary kvs, CancellationToken cancellationToken_ = default) - { - IReadOnlyList? mechs = await _BootstrapCap.Mechanisms(); - if (!mechs.Contains(mech)) - { - throw new UnsupportedMechanismException(); - } - - if (_Auth == null) - { - IAuthentication? authCap = await _BootstrapCap.CreateSession(mech, cancellationToken_).ConfigureAwait(false); - _Auth = new Auth(authCap); - } - - Session = await _Auth.Authenticate(mech, kvs); - } - #endregion - } -} diff --git a/FabAccessAPI/ConnectionInfo.cs b/FabAccessAPI/ConnectionInfo.cs index e0870a3..33c65e9 100644 --- a/FabAccessAPI/ConnectionInfo.cs +++ b/FabAccessAPI/ConnectionInfo.cs @@ -5,7 +5,7 @@ namespace FabAccessAPI { public class ConnectionInfo { - public Version APIVersion; + public Schema.Version APIVersion; public string ServerName; public string ServerRelease; public List Mechanisms; diff --git a/FabAccessAPI/IAPI.cs b/FabAccessAPI/IAPI.cs index 0d6d203..5818e34 100644 --- a/FabAccessAPI/IAPI.cs +++ b/FabAccessAPI/IAPI.cs @@ -1,4 +1,5 @@ -using FabAccessAPI.Schema; +using Capnp.Rpc; +using FabAccessAPI.Schema; using System; using System.Threading.Tasks; @@ -36,7 +37,7 @@ namespace FabAccessAPI /// Connect to BFFH Server /// /// - Task Connect(ConnectionData connectionData); + Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient); /// /// Disconnect from BFFH Server @@ -52,6 +53,6 @@ namespace FabAccessAPI /// Connect to Server and get ConnectionInfo. /// The Connection is not maintained. /// - ConnectionInfo TestConnection(ConnectionData connectionData); + Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient); } } diff --git a/FabAccessAPI_Test/API_Test.cs b/FabAccessAPI_Test/API_Test.cs index e631ed8..2cabfed 100644 --- a/FabAccessAPI_Test/API_Test.cs +++ b/FabAccessAPI_Test/API_Test.cs @@ -1,39 +1,17 @@  +using Capnp.Rpc; using FabAccessAPI; using FabAccessAPI.Exceptions; using NUnit.Framework; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace FabAccessAPI_Test { public class API_Test { - [TestCase("Admin1")] - public async Task ConnectDisconnect(string username) - { - API api = new API(); - - ConnectionData connectionData = new ConnectionData() - { - Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, - Mechanism = Mechanism.PLAIN, - Username = username, - Properties = new Dictionary() - { - { "Username", username } - }, - SecretProperties = new Dictionary() - { - { "Password", TestEnv.PASSWORD } - } - }; - - await api.Connect(connectionData); - await api.Disconnect(); - } - [Test] public async Task Connect_HostUnreachable() { @@ -41,12 +19,12 @@ namespace FabAccessAPI_Test ConnectionData connectionData = new ConnectionData() { - Host = new UriBuilder(TestEnv.SCHEMA, "NotReachable." + TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, + Host = new UriBuilder(TestEnv.SCHEMA, "UnkownHost" + TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, Mechanism = Mechanism.PLAIN, - Username = "UnknownUser", + Username = "UnkownUser", Properties = new Dictionary() { - { "Username", "UnknownUser" } + { "Username", "UnkownUser" } }, SecretProperties = new Dictionary() { @@ -70,20 +48,7 @@ namespace FabAccessAPI_Test { API api = new API(); - ConnectionData connectionData = new ConnectionData() - { - Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, - Mechanism = Mechanism.PLAIN, - Username = "UnknownUser", - Properties = new Dictionary() - { - { "Username", "UnknownUser" } - }, - SecretProperties = new Dictionary() - { - { "Password", TestEnv.PASSWORD } - } - }; + ConnectionData connectionData = TestEnv.CreateConnetionData("UnkownUser"); try { @@ -95,5 +60,124 @@ namespace FabAccessAPI_Test } Assert.Fail(); } + + [TestCase("Admin1")] + public async Task ConnectDisconnect(string username) + { + API api = new API(); + + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + + bool event_Connected = false; + bool event_Disconnected = false; + api.ConnectionStatusChanged += (sender, eventArgs) => + { + if (eventArgs == ConnectionStatusChange.Connected) + { + event_Connected = true; + } + if(eventArgs == ConnectionStatusChange.Disconnected) + { + event_Disconnected = true; + } + }; + + await api.Connect(connectionData); + + bool HasSesion = api.Session != null; + bool HasConnectionData = api.ConnectionData != null; + bool HasConnectionInfo = api.ConnectionInfo != null; + bool IsConnected = api.IsConnected; + + await api.Disconnect(); + + Thread.Sleep(3000); + Assert.Multiple(() => + { + Assert.IsTrue(event_Connected, "event_Connected"); + Assert.IsTrue(event_Disconnected, "event_Disconnected"); + + Assert.IsTrue(HasSesion, "HasSesion"); + Assert.IsTrue(HasConnectionData, "HasConnectionData"); + Assert.IsTrue(HasConnectionInfo, "HasConnectionInfo"); + Assert.IsTrue(IsConnected, "IsConnected"); + + Assert.IsFalse(api.IsConnected, "api.IsConnected"); + }); + } + + [TestCase("Admin1")] + public async Task TestConnectíon(string username) + { + API api = new API(); + + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + + ConnectionInfo connectionInfo = await api.TestConnection(connectionData); + + Assert.IsNotNull(connectionInfo); + } + + [TestCase("Admin1"), Explicit] + public async Task Reconnect(string username) + { + API api = new API(); + + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + + bool event_Connected = false; + bool event_ConnectionLoss = false; + bool event_Reconnect = false; + bool event_Disconnected = false; + + api.ConnectionStatusChanged += (sender, eventArgs) => + { + if (eventArgs == ConnectionStatusChange.Connected) + { + event_Connected = true; + } + if (eventArgs == ConnectionStatusChange.ConnectionLoss) + { + event_ConnectionLoss = true; + } + if (eventArgs == ConnectionStatusChange.Reconnected) + { + event_Reconnect = true; + } + if (eventArgs == ConnectionStatusChange.Disconnected) + { + event_Disconnected = true; + } + }; + + TcpRpcClient tcpRpcClient = new TcpRpcClient(); + await api.Connect(connectionData, tcpRpcClient); + + try + { + // Stop here and cut internet connection + await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); + } + catch + { + + } + Thread.Sleep(3000); + + // Stop here and connect with internet again + await api.Reconnect(); + await api.Disconnect(); + + Thread.Sleep(3000); + Assert.Multiple(() => + { + Assert.IsTrue(event_Connected, "event_Connected"); + Assert.IsTrue(event_ConnectionLoss, "event_ConnectionLoss"); + Assert.IsTrue(event_Reconnect, "event_Reconnect"); + Assert.IsTrue(event_Disconnected, "event_Disconnected"); + }); + } + + } } diff --git a/FabAccessAPI_Test/API_TestEnv_Test.cs b/FabAccessAPI_Test/API_TestEnv_Test.cs index 50fe060..8481345 100644 --- a/FabAccessAPI_Test/API_TestEnv_Test.cs +++ b/FabAccessAPI_Test/API_TestEnv_Test.cs @@ -12,50 +12,6 @@ using static FabAccessAPI.Schema.Machine; namespace FabAccessAPI_Test { - public static class API_TestEnv_Test - { - public const string TESTSERVER = "bffh.lab.bln.kjknet.de"; - public const int TESTSERVER_PORT = 59666; - public const string PASSWORD = "secret"; - - public static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - return true; - } - - public static async Task Connect(string username) - { - TcpRpcClient tcpRpcClient = new TcpRpcClient(); - tcpRpcClient.InjectMidlayer((tcpstream) => - { - var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); - try - { - sslStream.AuthenticateAsClient("bffhd"); - return sslStream; - } - catch (AuthenticationException) - { - sslStream.Close(); - throw; - } - }); - - tcpRpcClient.Connect(TESTSERVER, TESTSERVER_PORT); - await tcpRpcClient.WhenConnected; - - Connection connection = new Connection(tcpRpcClient); - await connection.Auth("PLAIN", new Dictionary(StringComparer.Ordinal) { { "Username", username }, { "Password", PASSWORD } }); - - return connection; - } - - public static void Disconnect(Connection connection) - { - connection.RpcClient.Dispose(); - } - } - [TestFixture, Parallelizable(ParallelScope.Children)] [Order(1)] public class MachineSystem_Test @@ -92,10 +48,11 @@ namespace FabAccessAPI_Test [Order(2)] public async Task AccessMachineSystem_Info(string username, bool expectAllow) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Assert.AreEqual(expectAllow, !((MachineSystem.InfoInterface_Proxy)session.MachineSystem.Info).IsNull); + Assert.AreEqual(expectAllow, !((MachineSystem.InfoInterface_Proxy)api.Session.MachineSystem.Info).IsNull); } [TestCase("Admin1", 15)] @@ -117,14 +74,15 @@ namespace FabAccessAPI_Test [Order(3)] public async Task ListMachines(string username, int expectedMachineCount) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - IReadOnlyList machine_list = await session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); + IReadOnlyList machine_list = await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); int result = machine_list.Count; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectedMachineCount, result); } @@ -156,14 +114,15 @@ namespace FabAccessAPI_Test [Order(4)] public async Task GetMachineByName(string username, string machineName, bool expectedAllow) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Optional optional = await session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false); + Optional optional = await api.Session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false); bool result = optional.Just != null; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectedAllow, result); } @@ -173,12 +132,13 @@ namespace FabAccessAPI_Test [Order(5)] public async Task GetMachineByName_WrongName(string username, string machineName) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Optional optional = await session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false); + Optional optional = await api.Session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.IsNull(optional.Just); } @@ -211,13 +171,14 @@ namespace FabAccessAPI_Test [Order(6)] public async Task GetMachineByURN(string username, string urn, bool expectedAllow) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Optional optional = await session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false); + Optional optional = await api.Session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false); bool result = optional.Just != null; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectedAllow, result); } @@ -228,12 +189,13 @@ namespace FabAccessAPI_Test [Order(7)] public async Task GetMachineByURN_WrongURN(string username, string urn) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Optional optional = await session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false); + Optional optional = await api.Session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.IsNull(optional.Just); } @@ -264,14 +226,15 @@ namespace FabAccessAPI_Test [Order(1)] public async Task InfoInterface(string username, string machineID, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; bool result = !((Machine.InfoInterface_Proxy)machine.Info).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -297,14 +260,15 @@ namespace FabAccessAPI_Test [Order(2)] public async Task ManageInterface(string username, string machineID, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; bool result = !((ManageInterface_Proxy)machine.Manage).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -330,14 +294,15 @@ namespace FabAccessAPI_Test [Order(3), Ignore("Not Implemented")] public async Task AdminInterface(string username, string machineID, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; bool result = !((AdminInterface_Proxy)machine.Admin).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -348,12 +313,13 @@ namespace FabAccessAPI_Test [Order(4)] public async Task ReadMachineData(string username, string machineID, string description, string wiki, string category) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.Multiple(() => { @@ -373,10 +339,11 @@ namespace FabAccessAPI_Test [SetUp] public async Task SetUp() { - Connection connection = await API_TestEnv_Test.Connect("Admin1"); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData("Admin1"); + await api.Connect(connectionData); - IReadOnlyList machine_list = await session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); + IReadOnlyList machine_list = await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); List tasks = new List(); foreach(Machine m in machine_list) @@ -394,26 +361,27 @@ namespace FabAccessAPI_Test [Order(1)] public async Task UseGiveBack(string username, string machineID) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine.Use.Use().ConfigureAwait(false); - machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine.Inuse.GiveBack().ConfigureAwait(false); - machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(MachineState.free, machine.State); } @@ -424,36 +392,38 @@ namespace FabAccessAPI_Test [Order(2), Ignore("Not Implemented")] public async Task TransferMachine(string username1, string username2, string machineID) { - Connection connection1 = await API_TestEnv_Test.Connect(username1); - Session session1 = connection1.Session; + API api1 = new API(); + ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1); + await api1.Connect(connectionData1); - Connection connection2 = await API_TestEnv_Test.Connect(username2); - Session session2 = connection1.Session; + API api2 = new API(); + ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2); + await api2.Connect(connectionData2); - Machine machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine1.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine1.Use.Use().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.Releasefortakeover().ConfigureAwait(false); - Machine machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Takeover.Accept().ConfigureAwait(false); - machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Inuse.GiveBack().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.AreEqual(MachineState.free, machine1.State); } @@ -464,36 +434,38 @@ namespace FabAccessAPI_Test [Order(3), Ignore("Not Implemented")] public async Task TransferMachine_Reject(string username1, string username2, string machineID) { - Connection connection1 = await API_TestEnv_Test.Connect(username1); - Session session1 = connection1.Session; + API api1 = new API(); + ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1); + await api1.Connect(connectionData1); - Connection connection2 = await API_TestEnv_Test.Connect(username2); - Session session2 = connection1.Session; + API api2 = new API(); + ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2); + await api2.Connect(connectionData2); - Machine machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine1.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine1.Use.Use().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.Releasefortakeover().ConfigureAwait(false); - Machine machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Takeover.Reject().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.GiveBack().ConfigureAwait(false); - machine2 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine2 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.AreEqual(MachineState.free, machine2.State); } @@ -504,33 +476,35 @@ namespace FabAccessAPI_Test [Order(4), Ignore("Not Implemented")] public async Task CheckMachine(string username1, string username2, string machineID) { - Connection connection1 = await API_TestEnv_Test.Connect(username1); - Session session1 = connection1.Session; + API api1 = new API(); + ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1); + await api1.Connect(connectionData1); - Connection connection2 = await API_TestEnv_Test.Connect(username2); - Session session2 = connection1.Session; + API api2 = new API(); + ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2); + await api2.Connect(connectionData2); - Machine machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine1.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine1.Use.Use().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.GiveBack().ConfigureAwait(false); - Machine machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Check.Check().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.AreEqual(MachineState.free, machine1.State); } @@ -541,40 +515,42 @@ namespace FabAccessAPI_Test [Order(5), Ignore("Not Implemented")] public async Task CheckMachine_Reject(string username1, string username2, string machineID) { - Connection connection1 = await API_TestEnv_Test.Connect(username1); - Session session1 = connection1.Session; + API api1 = new API(); + ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1); + await api1.Connect(connectionData1); - Connection connection2 = await API_TestEnv_Test.Connect(username2); - Session session2 = connection1.Session; + API api2 = new API(); + ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2); + await api2.Connect(connectionData2); - Machine machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine1.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine1.Use.Use().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.GiveBack().ConfigureAwait(false); - Machine machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Check.Reject().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.GiveBack().ConfigureAwait(false); - machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine2.Check.Check().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); Assert.AreEqual(MachineState.free, machine1.State); } @@ -583,37 +559,42 @@ namespace FabAccessAPI_Test [Order(4), Ignore("Not Implemented")] public async Task CheckMachine_NoPermission(string username1, string username2, string username3, string machineID) { - Connection connection1 = await API_TestEnv_Test.Connect(username1); - Session session1 = connection1.Session; + API api1 = new API(); + ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1); + await api1.Connect(connectionData1); - Connection connection2 = await API_TestEnv_Test.Connect(username2); - Session session2 = connection1.Session; + API api2 = new API(); + ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2); + await api2.Connect(connectionData2); - Connection connection3 = await API_TestEnv_Test.Connect(username3); - Session session3 = connection3.Session; + API api3 = new API(); + ConnectionData connectionData3 = TestEnv.CreateConnetionData(username3); + await api3.Connect(connectionData3); - Machine machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine1.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); + await api3.Disconnect(); Assert.Inconclusive("State is not 'free'"); } await machine1.Use.Use().ConfigureAwait(false); - machine1 = (await session1.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine1.Inuse.GiveBack().ConfigureAwait(false); - Machine machine2 = (await session2.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; bool result = ((CheckInterface_Proxy)machine2.Check).IsNull; - Machine machine3 = (await session3.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine3 = (await api3.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; await machine3.Check.Check().ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection1); - API_TestEnv_Test.Disconnect(connection2); + await api1.Disconnect(); + await api2.Disconnect(); + await api3.Disconnect(); Assert.IsTrue(result); } @@ -622,21 +603,22 @@ namespace FabAccessAPI_Test [Order(5)] public async Task CurrentUser(string username, string machineID) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - Machine machine = (await session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; + Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just; // Check State before run Test if (machine.State != MachineState.free) { - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.Inconclusive("State is not 'free'"); } MachineInfoExtended machineInfoExtended = await machine.Manage.GetMachineInfoExtended().ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.IsNull(machineInfoExtended.CurrentUser.Just); } @@ -653,12 +635,13 @@ namespace FabAccessAPI_Test [Order(1)] public async Task AccessPermissionSystem(string username, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - bool result = session.PermissionSystem != null; + bool result = api.Session.PermissionSystem != null; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -689,12 +672,13 @@ namespace FabAccessAPI_Test [Order(3), Ignore("Not Implemented")] public async Task ListRoles(string username, int expectRolesCount) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - IReadOnlyList roles_list = await session.PermissionSystem.Info.GetRoleList().ConfigureAwait(false); + IReadOnlyList roles_list = await api.Session.PermissionSystem.Info.GetRoleList().ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectRolesCount, roles_list.Count); } @@ -749,12 +733,13 @@ namespace FabAccessAPI_Test [Order(4)] public async Task GetUserSelf(string username) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.IsNotNull(user); } @@ -771,14 +756,15 @@ namespace FabAccessAPI_Test [Order(1)] public async Task InfoInterface(string username, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); bool result = !((User.InfoInterface_Proxy)user.Info).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -790,14 +776,15 @@ namespace FabAccessAPI_Test [Order(2), Ignore("Not Implemented")] public async Task ManageInterface(string username, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); bool result = !((User.ManageInterface_Proxy)user.Manage).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -809,14 +796,15 @@ namespace FabAccessAPI_Test [Order(3), Ignore("Not Implemented")] public async Task AdminInterface(string username, bool expectInterface) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); bool result = !((User.AdminInterface_Proxy)user.Admin).IsNull; - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.AreEqual(expectInterface, result); } @@ -828,12 +816,13 @@ namespace FabAccessAPI_Test [Order(4)] public async Task ReadUserData(string username) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); Assert.Multiple(() => { @@ -848,15 +837,16 @@ namespace FabAccessAPI_Test [Order(5), Ignore("Not Implemented")] public async Task ListUserRoles(string username, params string[] expect_roles) { - Connection connection = await API_TestEnv_Test.Connect(username); - Session session = connection.Session; + API api = new API(); + ConnectionData connectionData = TestEnv.CreateConnetionData(username); + await api.Connect(connectionData); - User user = await session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); + User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); List roles_user = new List(await user.Info.ListRoles().ConfigureAwait(false)); List expect_roles_list = new List(expect_roles); - API_TestEnv_Test.Disconnect(connection); + await api.Disconnect(); if (roles_user.Count != expect_roles_list.Count) { diff --git a/FabAccessAPI_Test/Connection_Test.cs b/FabAccessAPI_Test/Connection_Test.cs deleted file mode 100644 index f7a97eb..0000000 --- a/FabAccessAPI_Test/Connection_Test.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Capnp.Rpc; -using FabAccessAPI; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Net.Security; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; - -namespace FabAccessAPI_Test -{ - [TestFixture, Order(0)] - public class Connection_Test - { - const string TESTSERVER = "bffh.lab.bln.kjknet.de"; - const int TESTSERVER_PORT = 59666; - - private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - return true; - } - - [TestCase(TESTSERVER, TESTSERVER_PORT)] - public async Task Connect(string host, int port) - { - TcpRpcClient tcpRpcClient = new TcpRpcClient(); - tcpRpcClient.InjectMidlayer((tcpstream) => - { - var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); - try - { - sslStream.AuthenticateAsClient("bffhd"); - return sslStream; - } - catch (AuthenticationException) - { - sslStream.Close(); - throw; - } - }); - tcpRpcClient.Connect(host, port); - await tcpRpcClient.WhenConnected; - - Connection connection = new Connection(tcpRpcClient); - } - - [TestCase(TESTSERVER, TESTSERVER_PORT, "Admin1", "secret")] - public async Task Authenticate_PLAIN(string host, int port, string username, string password) - { - TcpRpcClient tcpRpcClient = new TcpRpcClient(); - tcpRpcClient.InjectMidlayer((tcpstream) => - { - var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); - try - { - sslStream.AuthenticateAsClient("bffhd"); - return sslStream; - } - catch (AuthenticationException) - { - sslStream.Close(); - throw; - } - }); - tcpRpcClient.Connect(host, port); - await tcpRpcClient.WhenConnected; - - Connection connection = new Connection(tcpRpcClient); - await connection.Auth("PLAIN", new Dictionary(StringComparer.Ordinal) { { "Username", username }, { "Password", password } }); - - Assert.IsNotNull(connection.Session); - } - } -} \ No newline at end of file diff --git a/FabAccessAPI_Test/TestEnv.cs b/FabAccessAPI_Test/TestEnv.cs index adf2f83..538b8fc 100644 --- a/FabAccessAPI_Test/TestEnv.cs +++ b/FabAccessAPI_Test/TestEnv.cs @@ -1,4 +1,8 @@ -namespace FabAccessAPI_Test +using FabAccessAPI; +using System; +using System.Collections.Generic; + +namespace FabAccessAPI_Test { public static class TestEnv { @@ -6,5 +10,25 @@ public const string TESTSERVER = "bffh.lab.bln.kjknet.de"; public const int TESTSERVER_PORT = 59666; public const string PASSWORD = "secret"; + + public static ConnectionData CreateConnetionData(string username) + { + ConnectionData connectionData = new ConnectionData() + { + Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri, + Mechanism = Mechanism.PLAIN, + Username = username, + Properties = new Dictionary() + { + { "Username", username } + }, + SecretProperties = new Dictionary() + { + { "Password", TestEnv.PASSWORD } + } + }; + + return connectionData; + } } } From 4f3521eec3cc7f8304bba44a16cbc7af61422d9c Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Mon, 16 May 2022 16:07:33 +0200 Subject: [PATCH 05/25] Start interagtion of new API Class --- .../Borepin.Android/Borepin.Android.csproj | 4 + .../Borepin.Android/PlatformInitializer.cs | 3 + Borepin/Borepin.UWP/Borepin.UWP.csproj | 4 + Borepin/Borepin.UWP/PlatformInitializer.cs | 3 + Borepin/Borepin.iOS/Borepin.iOS.csproj | 4 + Borepin/Borepin.iOS/PlatformInitializer.cs | 3 + Borepin/Borepin/App.xaml.cs | 10 +- Borepin/Borepin/Model/AuthenticationTyp.cs | 7 - Borepin/Borepin/Model/BFFHInstance.cs | 12 - Borepin/Borepin/Model/Connection.cs | 78 ----- Borepin/Borepin/Model/ConnectionTyp.cs | 8 - Borepin/Borepin/Model/Connection_Plain.cs | 19 -- Borepin/Borepin/Model/ListItem.cs | 7 - .../Storage/ConnectionCredentialStorage.cs | 76 ----- .../Model/Storage/ConnectionStorage.cs | 135 -------- .../Exceptions/MissingCredentialsException.cs | 22 -- Borepin/Borepin/Service/BFFH/BFFHService.cs | 287 ------------------ .../Exceptions/MissingCredentialsException.cs | 22 -- .../Exceptions/ReconnectingFailedException.cs | 22 -- Borepin/Borepin/Service/BFFH/IBFFHService.cs | 27 -- .../DuplicateConnectionException.cs | 16 +- .../Exceptions/InvalidConnectionExceptoin.cs | 26 ++ .../Exceptions/MissingConnectionException.cs | 16 +- .../Service/Storage/ILoginStorageService.cs | 14 + .../Service/Storage/LoginStorageService.cs | 112 +++++++ FabAccessAPI/API.cs | 30 +- FabAccessAPI/ConnectionData.cs | 20 +- 27 files changed, 224 insertions(+), 763 deletions(-) delete mode 100644 Borepin/Borepin/Model/AuthenticationTyp.cs delete mode 100644 Borepin/Borepin/Model/BFFHInstance.cs delete mode 100644 Borepin/Borepin/Model/Connection.cs delete mode 100644 Borepin/Borepin/Model/ConnectionTyp.cs delete mode 100644 Borepin/Borepin/Model/Connection_Plain.cs delete mode 100644 Borepin/Borepin/Model/ListItem.cs delete mode 100644 Borepin/Borepin/Model/Storage/ConnectionCredentialStorage.cs delete mode 100644 Borepin/Borepin/Model/Storage/ConnectionStorage.cs delete mode 100644 Borepin/Borepin/Model/Storage/Exceptions/MissingCredentialsException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/BFFHService.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/MissingCredentialsException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/ReconnectingFailedException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/IBFFHService.cs create mode 100644 Borepin/Borepin/Service/Storage/Exceptions/InvalidConnectionExceptoin.cs create mode 100644 Borepin/Borepin/Service/Storage/ILoginStorageService.cs create mode 100644 Borepin/Borepin/Service/Storage/LoginStorageService.cs diff --git a/Borepin/Borepin.Android/Borepin.Android.csproj b/Borepin/Borepin.Android/Borepin.Android.csproj index 5902707..aca6837 100644 --- a/Borepin/Borepin.Android/Borepin.Android.csproj +++ b/Borepin/Borepin.Android/Borepin.Android.csproj @@ -87,6 +87,10 @@ + + {3251FCE9-FEA3-4662-8BEB-636BE6732D48} + FabAccessAPI + {F93856BD-0C8D-4469-A8DB-6E513002BFD7} Borepin diff --git a/Borepin/Borepin.Android/PlatformInitializer.cs b/Borepin/Borepin.Android/PlatformInitializer.cs index 7d8bdc6..b26b6c6 100644 --- a/Borepin/Borepin.Android/PlatformInitializer.cs +++ b/Borepin/Borepin.Android/PlatformInitializer.cs @@ -1,6 +1,7 @@ using Borepin.Droid.Services; using Borepin.Service.Storage; using Borepin.Service.Versioning; +using FabAccessAPI; using Prism; using Prism.Ioc; @@ -13,6 +14,8 @@ namespace Borepin.Droid containerRegistry.Register(); containerRegistry.Register(); containerRegistry.Register(); + + containerRegistry.RegisterSingleton(); } } } \ No newline at end of file diff --git a/Borepin/Borepin.UWP/Borepin.UWP.csproj b/Borepin/Borepin.UWP/Borepin.UWP.csproj index b554349..ce20094 100644 --- a/Borepin/Borepin.UWP/Borepin.UWP.csproj +++ b/Borepin/Borepin.UWP/Borepin.UWP.csproj @@ -184,6 +184,10 @@ + + {3251FCE9-FEA3-4662-8BEB-636BE6732D48} + FabAccessAPI + {64ED6CAA-99A0-4EC4-B976-DCBD571F05D7} Borepin diff --git a/Borepin/Borepin.UWP/PlatformInitializer.cs b/Borepin/Borepin.UWP/PlatformInitializer.cs index 08027a6..4fc4a5e 100644 --- a/Borepin/Borepin.UWP/PlatformInitializer.cs +++ b/Borepin/Borepin.UWP/PlatformInitializer.cs @@ -3,6 +3,7 @@ using Prism; using Prism.Ioc; using Borepin.Service.Storage; using Borepin.Service.Versioning; +using FabAccessAPI; namespace Borepin.UWP { @@ -13,6 +14,8 @@ namespace Borepin.UWP containerRegistry.Register(); containerRegistry.Register(); containerRegistry.Register(); + + containerRegistry.RegisterSingleton(); } } } diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index 4f1a820..9af051d 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -192,6 +192,10 @@ + + {3251FCE9-FEA3-4662-8BEB-636BE6732D48} + FabAccessAPI + {F93856BD-0C8D-4469-A8DB-6E513002BFD7} Borepin diff --git a/Borepin/Borepin.iOS/PlatformInitializer.cs b/Borepin/Borepin.iOS/PlatformInitializer.cs index ff22291..4827500 100644 --- a/Borepin/Borepin.iOS/PlatformInitializer.cs +++ b/Borepin/Borepin.iOS/PlatformInitializer.cs @@ -1,6 +1,7 @@ using Borepin.iOS.Services; using Borepin.Service.Storage; using Borepin.Service.Versioning; +using FabAccessAPI; using Prism; using Prism.Ioc; @@ -13,6 +14,8 @@ namespace Borepin.iOS containerRegistry.Register(); containerRegistry.Register(); containerRegistry.Register(); + + containerRegistry.RegisterSingleton(); } } } \ No newline at end of file diff --git a/Borepin/Borepin/App.xaml.cs b/Borepin/Borepin/App.xaml.cs index 177c56b..702aad5 100644 --- a/Borepin/Borepin/App.xaml.cs +++ b/Borepin/Borepin/App.xaml.cs @@ -4,7 +4,6 @@ using Borepin.Page; using Xamarin.Forms; using Borepin.Dialog; using Borepin.DialogModel; -using Borepin.Service.BFFH; using Prism; using Borepin.Page.SetUpProcess; using Borepin.PageModel.SetUpProcess; @@ -12,6 +11,7 @@ using Borepin.Page.AddServerProcess; using Borepin.PageModel.AddServerProcess; using System; using Prism.Navigation; +using Borepin.Service.Storage; namespace Borepin { @@ -65,7 +65,13 @@ namespace Borepin #endregion #region Register Service - containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + + // NEED PLATFORM SPECIFIC SERVICE + // IPreferenceStorageService + // ISecretStorageService + // IVersioningService + // IAPI #endregion } } diff --git a/Borepin/Borepin/Model/AuthenticationTyp.cs b/Borepin/Borepin/Model/AuthenticationTyp.cs deleted file mode 100644 index 1a0d9f7..0000000 --- a/Borepin/Borepin/Model/AuthenticationTyp.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Borepin.Model -{ - public enum AuthenticationTyp - { - PLAIN, - } -} diff --git a/Borepin/Borepin/Model/BFFHInstance.cs b/Borepin/Borepin/Model/BFFHInstance.cs deleted file mode 100644 index c924f8a..0000000 --- a/Borepin/Borepin/Model/BFFHInstance.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -namespace Borepin.Model -{ - public class BFFHInstance - { - public Uri Address { get; set; } - - public string Name { get; set; } = ""; - - public string Description { get; set; } = ""; - } -} diff --git a/Borepin/Borepin/Model/Connection.cs b/Borepin/Borepin/Model/Connection.cs deleted file mode 100644 index 4d11ae4..0000000 --- a/Borepin/Borepin/Model/Connection.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Borepin.Model -{ - /// - /// Class to contain all Information about a Connection - /// - public class Connection - { - #region Constructors - public Connection() - { - Address = new Uri("http://127.0.0.1:59661"); - } - - public Connection(Connection connection) - { - ConnectionTyp = connection.ConnectionTyp; - AuthenticationTyp = connection.AuthenticationTyp; - Address = connection.Address; - Username = connection.Username; - LastTime = connection.LastTime; - } - #endregion - - #region Members - /// - /// Type of Connection - /// - public ConnectionTyp ConnectionTyp { get; set; } = ConnectionTyp.SINGLE; - - /// - /// Type of Authentication - /// - public AuthenticationTyp AuthenticationTyp { get; set; } = AuthenticationTyp.PLAIN; - - /// - /// Address to Host - /// - public Uri Address { get; set; } - - /// - /// Username for Connection - /// - public string Username { get; set; } = ""; - - /// - /// Last Timestamp connection was successfully established - /// - public DateTime LastTime { get; set; } - #endregion - - #region Methods - #region Equals and HashCode - public override bool Equals(object obj) - { - return obj is Connection connection && - EqualityComparer.Default.Equals(Address, connection.Address) && - string.Equals(Username, connection.Username, StringComparison.Ordinal) && - ConnectionTyp == connection.ConnectionTyp && - AuthenticationTyp == connection.AuthenticationTyp; - } - - public override int GetHashCode() - { - int hashCode = -904541792; - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Address); - hashCode = hashCode * -1521134295 + LastTime.GetHashCode(); - hashCode = hashCode * -1521134295 + StringComparer.Ordinal.GetHashCode(Username); - hashCode = hashCode * -1521134295 + ConnectionTyp.GetHashCode(); - hashCode = hashCode * -1521134295 + AuthenticationTyp.GetHashCode(); - return hashCode; - } - #endregion - #endregion - } -} \ No newline at end of file diff --git a/Borepin/Borepin/Model/ConnectionTyp.cs b/Borepin/Borepin/Model/ConnectionTyp.cs deleted file mode 100644 index 5b5115b..0000000 --- a/Borepin/Borepin/Model/ConnectionTyp.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Borepin.Model -{ - public enum ConnectionTyp - { - SINGLE, - FEDERATED, - } -} diff --git a/Borepin/Borepin/Model/Connection_Plain.cs b/Borepin/Borepin/Model/Connection_Plain.cs deleted file mode 100644 index 4dec051..0000000 --- a/Borepin/Borepin/Model/Connection_Plain.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Borepin.Model -{ - public class Connection_Plain : Connection - { - #region Constructors - public Connection_Plain(Connection connection) : base(connection) - { - - } - #endregion - - #region Members - /// - /// Password for Connection - /// - public string Password { get; set; } = ""; - #endregion - } -} diff --git a/Borepin/Borepin/Model/ListItem.cs b/Borepin/Borepin/Model/ListItem.cs deleted file mode 100644 index 6410fc8..0000000 --- a/Borepin/Borepin/Model/ListItem.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Borepin.Model -{ - public class ListItem - { - public string Value1 { get; set; } - } -} diff --git a/Borepin/Borepin/Model/Storage/ConnectionCredentialStorage.cs b/Borepin/Borepin/Model/Storage/ConnectionCredentialStorage.cs deleted file mode 100644 index 9105876..0000000 --- a/Borepin/Borepin/Model/Storage/ConnectionCredentialStorage.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Globalization; -using System.Threading.Tasks; -using Borepin.Service.Storage; -using Borepin.Service.Storage.Exceptions; - -namespace Borepin.Model.Storage -{ - /// - /// Store Credentials for Connection in SecureStorageService - /// - public class ConnectionCredentialStorage - { - #region Private Fields - private readonly ISecretStorageService _SecretStorageService; - #endregion - - #region Constructors - public ConnectionCredentialStorage(ISecretStorageService secretService) - { - _SecretStorageService = secretService; - } - #endregion - - #region Methods - /// - /// Get Password for Connection from SecureStorageService - /// - /// - /// - public async Task GetPassword(Connection connection) - { - if (connection.AuthenticationTyp != AuthenticationTyp.PLAIN) - { - throw new ArgumentException("AuthenticationTyp is not PLAIN", nameof(connection)); - } - - string password = await _SecretStorageService.GetAsync(string.Format(CultureInfo.InvariantCulture, "bffh_password_{0}_{1}", connection.Address.ToString(), connection.Username)).ConfigureAwait(false); - if (password == null) - { - throw new MissingConnectionException(); - } - - return password; - } - - /// - /// Add Password for Connection to SecureStorageService - /// - public async Task AddCredentials(Connection connection, string password) - { - await _SecretStorageService.SetAsync(string.Format(CultureInfo.InvariantCulture, "bffh_password_{0}_{1}", connection.Address.ToString(), connection.Username), password).ConfigureAwait(false); - } - - /// - /// Remove Password for Connection from SecureStorageService - /// - public Task RemoveCredentials(Connection connection) - { - _SecretStorageService.Remove(string.Format(CultureInfo.InvariantCulture, "bffh_password_{0}_{1}", connection.Address.ToString(), connection.Username)); - - return Task.CompletedTask; - } - - /// - /// Remove all Connections from SecureStorage - /// - public Task RemoveAllCredentials() - { - _SecretStorageService.RemoveAll(); - - return Task.CompletedTask; - } - #endregion - } -} diff --git a/Borepin/Borepin/Model/Storage/ConnectionStorage.cs b/Borepin/Borepin/Model/Storage/ConnectionStorage.cs deleted file mode 100644 index 3c8de2c..0000000 --- a/Borepin/Borepin/Model/Storage/ConnectionStorage.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Borepin.Service.Storage; -using Borepin.Service.Storage.Exceptions; -using Newtonsoft.Json; - -namespace Borepin.Model.Storage -{ - /// - /// Store Connection in PreferenceStorageService - /// - public class ConnectionStorage - { - #region Private Fields - private readonly IPreferenceStorageService _PreferenceService; - #endregion - - #region Constructors - public ConnectionStorage(IPreferenceStorageService preferenceService) - { - _PreferenceService = preferenceService; - } - #endregion - - #region Methods - /// - /// Get Connection List from Storage - /// - /// - public Task> GetConnectionList() - { - return Task.FromResult(_LoadConnectionFormStorage()); - } - - /// - /// Add Connection to Storage - /// - /// - public Task AddConnection(Connection connection) - { - IList connection_list = _LoadConnectionFormStorage(); - - if (connection_list.Contains(connection)) - { - throw new DuplicateConnectionException(); - } - - connection_list.Add(connection); - - _SaveConnectionToStorage(connection_list); - - return Task.FromResult(true); - } - - /// - /// Remove Connection from Storage - /// - public Task RemoveConnection(Connection connection) - { - IList connection_list = _LoadConnectionFormStorage(); - - if (!connection_list.Contains(connection)) - { - throw new MissingConnectionException(); - } - - while(connection_list.Contains(connection)) - { - connection_list.Remove(connection); - } - - _SaveConnectionToStorage(connection_list); - - return Task.FromResult(true); - } - - /// - /// Remove All Connection from Storage - /// - public Task RemoveAllConnections() - { - _SaveConnectionToStorage(new List()); - - return Task.FromResult(true); - } - - /// - /// Update Connections Timestamp in Storage - /// - /// - public Task UpdateConnectionTimestamp(Connection connection) - { - IList connection_list = _LoadConnectionFormStorage(); - - if (!connection_list.Contains(connection)) - { - throw new MissingConnectionException(); - } - - int index = connection_list.IndexOf(connection); - Connection connection_update = connection_list[index]; - connection_update.LastTime = DateTime.UtcNow; - connection_list[index] = connection_update; - - _SaveConnectionToStorage(connection_list); - - return Task.FromResult(true); - } - #endregion - - #region Private Methodss - private IList _LoadConnectionFormStorage() - { - List connection_list; - try - { - connection_list = JsonConvert.DeserializeObject>(_PreferenceService.Get("connection_list", "[]")); - } - catch (JsonSerializationException) - { - connection_list = new List(); - _PreferenceService.Set("connection_list", JsonConvert.SerializeObject(connection_list)); - } - - return connection_list; - } - - private void _SaveConnectionToStorage(IList connection_list) - { - _PreferenceService.Set("connection_list", JsonConvert.SerializeObject(connection_list)); - } - #endregion - } -} diff --git a/Borepin/Borepin/Model/Storage/Exceptions/MissingCredentialsException.cs b/Borepin/Borepin/Model/Storage/Exceptions/MissingCredentialsException.cs deleted file mode 100644 index f924028..0000000 --- a/Borepin/Borepin/Model/Storage/Exceptions/MissingCredentialsException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Model.Storage.Exceptions -{ - public class MissingCredentialsException : Exception - { - public MissingCredentialsException() - { - - } - - public MissingCredentialsException(string message) : base(message) - { - - } - - public MissingCredentialsException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/BFFHService.cs b/Borepin/Borepin/Service/BFFH/BFFHService.cs deleted file mode 100644 index 52d310e..0000000 --- a/Borepin/Borepin/Service/BFFH/BFFHService.cs +++ /dev/null @@ -1,287 +0,0 @@ -using System; -using Borepin.Model; -using System.Threading.Tasks; -using System.Collections.Generic; -using FabAccessAPI.Schema; - -using Borepin.Service.Storage; -using Borepin.Model.Storage; -using Borepin.Service.BFFH.Exceptions; -using Borepin.Service.Storage.Exceptions; -using Capnp.Rpc; -using FabAccessAPI.Exceptions; -using System.Security.Cryptography.X509Certificates; -using System.Net.Security; -using System.Security.Authentication; -using FabAccessAPI; - -namespace Borepin.Service.BFFH -{ - public class BFFHService : IBFFHService - { - #region Private Fields - private readonly ConnectionStorage _ConnectionStorage; - private readonly ConnectionCredentialStorage _ConnectionCredentialStorage; - - private Connection_Plain _CurrentConnection; - #endregion - - #region Constructors - public BFFHService(IPreferenceStorageService preferenceStorageService, ISecretStorageService secretStorageService) - { - _ConnectionStorage = new ConnectionStorage(preferenceStorageService); - _ConnectionCredentialStorage = new ConnectionCredentialStorage(secretStorageService); - } - #endregion - - #region Fields - - /// - /// API Connection - /// - public API API { get; private set; } - #endregion - - #region Method - /// - /// Get all known Connections from Storage - /// - public async Task> GetConnections() - { - return await _ConnectionStorage.GetConnectionList().ConfigureAwait(false); - } - - /// - /// Remove Connection from Storage - /// - public async Task RemoveConnection(Connection connection) - { - if (API != null && API.IsConnected && connection.Equals(_CurrentConnection)) - { - await Disconnect().ConfigureAwait(false); - } - - try - { - await _ConnectionCredentialStorage.RemoveCredentials(connection).ConfigureAwait(false); - } - catch (KeyNotFoundException) - { - - } - - try - { - await _ConnectionStorage.RemoveConnection(connection).ConfigureAwait(false); - } - catch (KeyNotFoundException) - { - - } - } - - /// - /// Test a if a Server is reachable - /// - public async Task TestConnection(Connection connection) - { - try - { - TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false); - rpcClient.Dispose(); - - return true; - } - catch - { - return false; - } - } - - /// - /// Connects to Server with Credential from ConnectionCredentialStorage - /// - /// - /// - /// - /// - public async Task Connect(Connection connection) - { - string password; - try - { - password = await _ConnectionCredentialStorage.GetPassword(connection).ConfigureAwait(false); - } - catch (KeyNotFoundException) - { - await _ConnectionCredentialStorage.RemoveAllCredentials().ConfigureAwait(false); - await _ConnectionStorage.RemoveAllConnections().ConfigureAwait(false); - - throw new MissingCredentialsException(); - } - - try - { - TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false); - - _APIConnection = new FabAccessAPI.Connection(rpcClient); - } - catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) - { - throw new ConnectingFailedException("Connecting failed", exception); - } - - if (! await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) - { - await Disconnect().ConfigureAwait(false); - } - - _CurrentConnection = new Connection_Plain(connection) - { - Password = password, - }; - await _ConnectionStorage.UpdateConnectionTimestamp(_CurrentConnection).ConfigureAwait(false); - } - - /// - /// Connects to Server with Password - /// Connection is saved to Storage if connecting was successfuss - /// - /// - /// - /// - /// - public async Task Connect(Connection connection, string password) - { - try - { - TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false); - - _APIConnection = new FabAccessAPI.Connection(rpcClient); - } - catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) - { - throw new ConnectingFailedException("Connecting failed", exception); - } - - if (!await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) - { - await Disconnect().ConfigureAwait(false); - - } - - _CurrentConnection = new Connection_Plain(connection) - { - Password = password, - }; - - try - { - await _ConnectionStorage.AddConnection(_CurrentConnection).ConfigureAwait(false); - } - catch(DuplicateConnectionException) - { - - } - await _ConnectionCredentialStorage.AddCredentials(_CurrentConnection, password).ConfigureAwait(false); - await _ConnectionStorage.UpdateConnectionTimestamp(_CurrentConnection).ConfigureAwait(false); - } - - /// - /// Reconnects to server if connection has lost - /// - /// - /// - public async Task Reconnect() - { - if (IsConnected || _CurrentConnection == null) - { - throw new InvalidOperationException(); - } - - try - { - TcpRpcClient rpcClient = await _ConnectAsync(_CurrentConnection.Address.Host, _CurrentConnection.Address.Port).ConfigureAwait(false); - - _APIConnection = new FabAccessAPI.Connection(rpcClient); - } - catch - { - - } - } - - /// - /// Disconnects from Server - /// - /// - public Task Disconnect() - { - if (IsConnected) - { - _APIConnection.RpcClient?.Dispose(); - } - - _APIConnection = null; - _CurrentConnection = null; - - return Task.CompletedTask; - } - - #region FabAccess API Systems - public async Task GetSession() - { - if (!IsConnected) - { - await Reconnect().ConfigureAwait(false); - } - - return _APIConnection.Session; - } - #endregion - #endregion - - #region Private Methods - private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - return true; - } - - private async Task _ConnectAsync(string host, int port) - { - TcpRpcClient rpcClient = new TcpRpcClient(); - rpcClient.InjectMidlayer((tcpstream) => - { - var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); - try - { - sslStream.AuthenticateAsClient("bffhd"); - return sslStream; - } - catch (AuthenticationException) - { - sslStream.Close(); - throw; - } - }); - rpcClient.Connect(host, port); - await rpcClient.WhenConnected.ConfigureAwait(false); - - return rpcClient; - } - - private async Task _AuthenticatePlainAsync(string username, string password) - { - try - { - await _APIConnection.Auth("PLAIN", new Dictionary(StringComparer.Ordinal) { { "Username", username }, { "Password", password } }).ConfigureAwait(false); - return await Task.FromResult(true).ConfigureAwait(false); - } - catch(UnsupportedMechanismException) - { - return await Task.FromResult(true).ConfigureAwait(false); - } - } - #endregion - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/MissingCredentialsException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/MissingCredentialsException.cs deleted file mode 100644 index 6f461a3..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/MissingCredentialsException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class MissingCredentialsException : Exception - { - public MissingCredentialsException() - { - - } - - public MissingCredentialsException(string message) : base(message) - { - - } - - public MissingCredentialsException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/ReconnectingFailedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/ReconnectingFailedException.cs deleted file mode 100644 index 161cb97..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/ReconnectingFailedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class ReconnectingFailedException : Exception - { - public ReconnectingFailedException() - { - - } - - public ReconnectingFailedException(string message) : base(message) - { - - } - - public ReconnectingFailedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/IBFFHService.cs b/Borepin/Borepin/Service/BFFH/IBFFHService.cs deleted file mode 100644 index b05d45e..0000000 --- a/Borepin/Borepin/Service/BFFH/IBFFHService.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Borepin.Model; -using FabAccessAPI.Schema; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Borepin.Service.BFFH -{ - public interface IBFFHService - { - Connection CurrentConnection { get; } - bool IsConnected { get; } - - Task> GetConnections(); - - Task RemoveConnection(Connection connection); - Task TestConnection(Connection connection); - - - Task Connect(Connection connection); - Task Connect(Connection connection, string password); - Task Reconnect(); - Task Disconnect(); - - - Task GetSession(); - } -} \ No newline at end of file diff --git a/Borepin/Borepin/Service/Storage/Exceptions/DuplicateConnectionException.cs b/Borepin/Borepin/Service/Storage/Exceptions/DuplicateConnectionException.cs index e1b3a9b..afe1761 100644 --- a/Borepin/Borepin/Service/Storage/Exceptions/DuplicateConnectionException.cs +++ b/Borepin/Borepin/Service/Storage/Exceptions/DuplicateConnectionException.cs @@ -1,22 +1,24 @@ -using System; +using FabAccessAPI; +using System; namespace Borepin.Service.Storage.Exceptions { public class DuplicateConnectionException : Exception { - public DuplicateConnectionException() + public readonly ConnectionData ConnectionData; + public DuplicateConnectionException(ConnectionData connectionData) { - + ConnectionData = connectionData; } - public DuplicateConnectionException(string message) : base(message) + public DuplicateConnectionException(ConnectionData connectionData, string message) : base(message) { - + ConnectionData = connectionData; } - public DuplicateConnectionException(string message, Exception inner) : base(message, inner) + public DuplicateConnectionException(ConnectionData connectionData, string message, Exception inner) : base(message, inner) { - + ConnectionData = connectionData; } } } diff --git a/Borepin/Borepin/Service/Storage/Exceptions/InvalidConnectionExceptoin.cs b/Borepin/Borepin/Service/Storage/Exceptions/InvalidConnectionExceptoin.cs new file mode 100644 index 0000000..e3a9de5 --- /dev/null +++ b/Borepin/Borepin/Service/Storage/Exceptions/InvalidConnectionExceptoin.cs @@ -0,0 +1,26 @@ +using FabAccessAPI; +using System; + +namespace Borepin.Service.Storage.Exceptions +{ + [Serializable] + internal class InvalidConnectionExceptoin : Exception + { + public readonly ConnectionData ConnectionData; + + public InvalidConnectionExceptoin(ConnectionData connectionData) + { + ConnectionData = connectionData; + } + + public InvalidConnectionExceptoin(ConnectionData connectionData, string message) : base(message) + { + ConnectionData = connectionData; + } + + public InvalidConnectionExceptoin(ConnectionData connectionData, string message, Exception innerException) : base(message, innerException) + { + ConnectionData = connectionData; + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/Service/Storage/Exceptions/MissingConnectionException.cs b/Borepin/Borepin/Service/Storage/Exceptions/MissingConnectionException.cs index 31748ae..da58f1e 100644 --- a/Borepin/Borepin/Service/Storage/Exceptions/MissingConnectionException.cs +++ b/Borepin/Borepin/Service/Storage/Exceptions/MissingConnectionException.cs @@ -1,22 +1,24 @@ -using System; +using FabAccessAPI; +using System; namespace Borepin.Service.Storage.Exceptions { public class MissingConnectionException : Exception { - public MissingConnectionException() + public readonly ConnectionData ConnectionData; + public MissingConnectionException(ConnectionData connectionData) { - + ConnectionData = connectionData; } - public MissingConnectionException(string message) : base(message) + public MissingConnectionException(ConnectionData connectionData, string message) : base(message) { - + ConnectionData = connectionData; } - public MissingConnectionException(string message, Exception inner) : base(message, inner) + public MissingConnectionException(ConnectionData connectionData, string message, Exception inner) : base(message, inner) { - + ConnectionData = connectionData; } } } diff --git a/Borepin/Borepin/Service/Storage/ILoginStorageService.cs b/Borepin/Borepin/Service/Storage/ILoginStorageService.cs new file mode 100644 index 0000000..4d67bda --- /dev/null +++ b/Borepin/Borepin/Service/Storage/ILoginStorageService.cs @@ -0,0 +1,14 @@ +using FabAccessAPI; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Borepin.Service.Storage +{ + public interface ILoginStorageService + { + Task> GetList(); + Task Add(ConnectionData connectionData); + Task Remove(ConnectionData connectionData); + Task UpdateTimestamp(ConnectionData connectionData); + } +} diff --git a/Borepin/Borepin/Service/Storage/LoginStorageService.cs b/Borepin/Borepin/Service/Storage/LoginStorageService.cs new file mode 100644 index 0000000..dd94775 --- /dev/null +++ b/Borepin/Borepin/Service/Storage/LoginStorageService.cs @@ -0,0 +1,112 @@ +using Borepin.Service.Storage.Exceptions; +using FabAccessAPI; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Borepin.Service.Storage +{ + public class LoginStorageService : ILoginStorageService + { + #region Static Members + const string StorageKey = "ConnectionData"; + #endregion + + #region Private Members + private readonly ISecretStorageService _SecretStorageService; + #endregion + + #region Constructors + public LoginStorageService(ISecretStorageService secretStorageService) + { + _SecretStorageService = secretStorageService; + } + #endregion + + #region Methods + public async Task> GetList() + { + return await _LoadConnectionData().ConfigureAwait(false); + } + + public async Task Add(ConnectionData connectionData) + { + if (connectionData.Host.Host == string.Empty || connectionData.Username == string.Empty) + { + throw new InvalidConnectionExceptoin(connectionData); + } + + IList connectionData_List = await _LoadConnectionData().ConfigureAwait(false); + if(connectionData_List.Contains(connectionData)) + { + throw new DuplicateConnectionException(connectionData); + } + + connectionData_List.Add(connectionData); + await _SaveConnectionData(connectionData_List).ConfigureAwait(false); + } + public async Task Remove(ConnectionData connectionData) + { + if (connectionData.Host.Host == string.Empty || connectionData.Username == string.Empty) + { + throw new InvalidConnectionExceptoin(connectionData); + } + + IList connectionData_List = await _LoadConnectionData().ConfigureAwait(false); + if (connectionData_List.Contains(connectionData)) + { + throw new MissingConnectionException(connectionData); + } + + connectionData_List.Remove(connectionData); + await _SaveConnectionData(connectionData_List).ConfigureAwait(false); + } + + public async Task UpdateTimestamp(ConnectionData connectionData) + { + if (connectionData.Host.Host == string.Empty || connectionData.Username == string.Empty) + { + throw new InvalidConnectionExceptoin(connectionData); + } + + IList connectionData_List = await _LoadConnectionData().ConfigureAwait(false); + if (connectionData_List.Contains(connectionData)) + { + throw new MissingConnectionException(connectionData); + } + + connectionData.LastTime = DateTime.UtcNow; + + connectionData_List.Remove(connectionData); + connectionData_List.Add(connectionData); + await _SaveConnectionData(connectionData_List).ConfigureAwait(false); + } + #endregion + + #region Private Methods + private async Task> _LoadConnectionData() + { + List connectionData_List; + try + { + string data = await _SecretStorageService.GetAsync(StorageKey).ConfigureAwait(false); + connectionData_List = JsonConvert.DeserializeObject>(data); + } + catch (JsonSerializationException) + { + connectionData_List = new List(); + await _SecretStorageService.SetAsync(StorageKey, JsonConvert.SerializeObject(connectionData_List)).ConfigureAwait(false); + } + + return connectionData_List; + } + + private async Task _SaveConnectionData(IList connectionData_List) + { + string data = JsonConvert.SerializeObject(connectionData_List); + await _SecretStorageService.SetAsync(StorageKey, data).ConfigureAwait(false); + } + #endregion + } +} diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index 27af1d5..d2e375d 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -119,11 +119,7 @@ namespace FabAccessAPI ConnectionData = null; ConnectionInfo = null; - EventHandler eventHandler = ConnectionStatusChanged; - if (eventHandler != null) - { - eventHandler(this, ConnectionStatusChange.Disconnected); - } + ConnectionStatusChanged?.Invoke(this, ConnectionStatusChange.Disconnected); return Task.CompletedTask; } @@ -135,11 +131,7 @@ namespace FabAccessAPI await Connect(ConnectionData); } - EventHandler eventHandler = ConnectionStatusChanged; - if (eventHandler != null) - { - eventHandler(this, ConnectionStatusChange.Reconnected); - } + ConnectionStatusChanged?.Invoke(this, ConnectionStatusChange.Reconnected); } public async Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null) @@ -172,7 +164,7 @@ namespace FabAccessAPI /// Validate Certificate /// TODO: Do some validation /// - private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + private static bool _RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // TODO Cert Check return true; @@ -188,7 +180,7 @@ namespace FabAccessAPI { rpcClient.InjectMidlayer((tcpstream) => { - var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); + var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(_RemoteCertificateValidationCallback)); try { sslStream.AuthenticateAsClient("bffhd"); @@ -236,19 +228,9 @@ namespace FabAccessAPI /// private async Task _Authenticate(ConnectionData connectionData) { - Dictionary joinedProperties = new Dictionary(); - foreach(KeyValuePair keyValuePair in connectionData.Properties) - { - joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); - } - foreach (KeyValuePair keyValuePair in connectionData.SecretProperties) - { - joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); - } - IAuthentication? authentication = await _Bootstrap.CreateSession(MechanismString.ToString(connectionData.Mechanism)).ConfigureAwait(false); - return await _SASLAuthenticate(authentication, MechanismString.ToString(connectionData.Mechanism), joinedProperties).ConfigureAwait(false); + return await _SASLAuthenticate(authentication, MechanismString.ToString(connectionData.Mechanism), connectionData.Properties).ConfigureAwait(false); } /// @@ -257,7 +239,7 @@ namespace FabAccessAPI /// /// /// - public async Task _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary properties) + private async Task _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary properties) { SaslMechanism? saslMechanism = SaslFactory.Create(mech); foreach (KeyValuePair entry in properties) diff --git a/FabAccessAPI/ConnectionData.cs b/FabAccessAPI/ConnectionData.cs index 84bb26f..a78ba38 100644 --- a/FabAccessAPI/ConnectionData.cs +++ b/FabAccessAPI/ConnectionData.cs @@ -9,7 +9,25 @@ namespace FabAccessAPI public Mechanism Mechanism; public string Username; public Dictionary Properties; - public Dictionary SecretProperties; public DateTime LastTime; + + public override bool Equals(object? obj) + { + return obj is ConnectionData data && + EqualityComparer.Default.Equals(Host, data.Host) && + Mechanism == data.Mechanism && + Username == data.Username && + EqualityComparer>.Default.Equals(Properties, data.Properties); + } + + public override int GetHashCode() + { + int hashCode = -1151110446; + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Host); + hashCode = hashCode * -1521134295 + Mechanism.GetHashCode(); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Username); + hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(Properties); + return hashCode; + } } } From 0ee3dc849749dfcfea31e638af51075e56d9c32e Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Mon, 16 May 2022 22:41:29 +0200 Subject: [PATCH 06/25] Added more new API Class --- .../Borepin.Android/Borepin.Android.csproj | 4 + .../Borepin.Android/PlatformInitializer.cs | 4 +- .../Services/APIBindedService.cs | 50 +++++++ Borepin/Borepin.Android/Services/APIBinder.cs | 18 +++ .../Borepin.Android/Services/APIService.cs | 28 ++++ .../Services/APIServiceConnection.cs | 32 +++++ Borepin/Borepin.UWP/Borepin.UWP.csproj | 1 + Borepin/Borepin.UWP/PlatformInitializer.cs | 4 +- Borepin/Borepin.UWP/Services/APIService.cs | 23 +++ Borepin/Borepin.iOS/Borepin.iOS.csproj | 1 + Borepin/Borepin.iOS/PlatformInitializer.cs | 4 +- Borepin/Borepin.iOS/Services/APIService.cs | 23 +++ Borepin/Borepin/App.xaml.cs | 7 +- Borepin/Borepin/Base/ConnectionModelBase.cs | 98 +++++++++---- .../Exceptions/InstanceIncorrectException.cs | 22 +++ Borepin/Borepin/Base/PageModelBase.cs | 16 +-- Borepin/Borepin/Borepin.csproj | 1 + .../AddServerProcess/AuthPlainPageModel.cs | 80 +++++------ .../AddServerProcess/SelectServerPageModel.cs | 136 ++++++------------ .../Borepin/PageModel/MachineListPageModel.cs | 4 +- Borepin/Borepin/PageModel/MachinePageModel.cs | 97 +++++-------- Borepin/Borepin/PageModel/ScanURNPageModel.cs | 68 +++------ .../Borepin/PageModel/ServerListPageModel.cs | 23 +-- Borepin/Borepin/PageModel/ServerPageModel.cs | 54 ++----- Borepin/Borepin/Service/IAPIService.cs | 9 ++ .../ViewModel/ServerListItemViewModel.cs | 7 +- FabAccessAPI/API.cs | 18 ++- FabAccessAPI/FabAccessAPI.csproj | 2 +- FabAccessAPI/IAPI.cs | 4 +- 29 files changed, 468 insertions(+), 370 deletions(-) create mode 100644 Borepin/Borepin.Android/Services/APIBindedService.cs create mode 100644 Borepin/Borepin.Android/Services/APIBinder.cs create mode 100644 Borepin/Borepin.Android/Services/APIService.cs create mode 100644 Borepin/Borepin.Android/Services/APIServiceConnection.cs create mode 100644 Borepin/Borepin.UWP/Services/APIService.cs create mode 100644 Borepin/Borepin.iOS/Services/APIService.cs create mode 100644 Borepin/Borepin/Base/Exceptions/InstanceIncorrectException.cs create mode 100644 Borepin/Borepin/Service/IAPIService.cs diff --git a/Borepin/Borepin.Android/Borepin.Android.csproj b/Borepin/Borepin.Android/Borepin.Android.csproj index aca6837..339d783 100644 --- a/Borepin/Borepin.Android/Borepin.Android.csproj +++ b/Borepin/Borepin.Android/Borepin.Android.csproj @@ -76,6 +76,10 @@ + + + + diff --git a/Borepin/Borepin.Android/PlatformInitializer.cs b/Borepin/Borepin.Android/PlatformInitializer.cs index b26b6c6..ac5fbc0 100644 --- a/Borepin/Borepin.Android/PlatformInitializer.cs +++ b/Borepin/Borepin.Android/PlatformInitializer.cs @@ -1,7 +1,7 @@ using Borepin.Droid.Services; +using Borepin.Service; using Borepin.Service.Storage; using Borepin.Service.Versioning; -using FabAccessAPI; using Prism; using Prism.Ioc; @@ -15,7 +15,7 @@ namespace Borepin.Droid containerRegistry.Register(); containerRegistry.Register(); - containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); } } } \ No newline at end of file diff --git a/Borepin/Borepin.Android/Services/APIBindedService.cs b/Borepin/Borepin.Android/Services/APIBindedService.cs new file mode 100644 index 0000000..e84859c --- /dev/null +++ b/Borepin/Borepin.Android/Services/APIBindedService.cs @@ -0,0 +1,50 @@ +using Android.App; +using Android.Content; +using Android.OS; +using FabAccessAPI; + +namespace Borepin.Droid.Services +{ + [Service(Name= "org.fab_infra.fabaccess.APIService")] + public class APIBindedService : Android.App.Service + { + #region Private Members + private IAPI _API; + #endregion + + #region Members + public IBinder Binder { get; private set; } + #endregion + + #region Methods + public IAPI GetAPI() + { + return _API; + } + + public override void OnCreate() + { + base.OnCreate(); + _API = new API(); + } + + public override IBinder OnBind(Intent intent) + { + Binder = new APIBinder(this); + return Binder; + } + + public override bool OnUnbind(Intent intent) + { + return base.OnUnbind(intent); + } + + public override void OnDestroy() + { + Binder = null; + _API = null; + base.OnDestroy(); + } + #endregion + } +} \ No newline at end of file diff --git a/Borepin/Borepin.Android/Services/APIBinder.cs b/Borepin/Borepin.Android/Services/APIBinder.cs new file mode 100644 index 0000000..5deeb3b --- /dev/null +++ b/Borepin/Borepin.Android/Services/APIBinder.cs @@ -0,0 +1,18 @@ +using Android.OS; + +namespace Borepin.Droid.Services +{ + public class APIBinder : Binder + { + #region Constructors + public APIBinder(APIBindedService service) + { + Service = service; + } + #endregion + + #region Members + public APIBindedService Service { get; private set; } + #endregion + } +} \ No newline at end of file diff --git a/Borepin/Borepin.Android/Services/APIService.cs b/Borepin/Borepin.Android/Services/APIService.cs new file mode 100644 index 0000000..815d895 --- /dev/null +++ b/Borepin/Borepin.Android/Services/APIService.cs @@ -0,0 +1,28 @@ +using Android.App; +using Android.Content; +using Borepin.Service; +using FabAccessAPI; + +namespace Borepin.Droid.Services +{ + public class APIService : IAPIService + { + #region Private Members + private readonly APIServiceConnection _APIServiceConnection; + #endregion + + #region Constructors + public APIService() + { + Context context = Application.Context; + Intent service = new Intent(context, typeof(APIBindedService)); + context.BindService(service, _APIServiceConnection, Bind.AutoCreate); + } + #endregion + + public IAPI GetAPI() + { + return _APIServiceConnection?.Binder?.Service?.GetAPI(); + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin.Android/Services/APIServiceConnection.cs b/Borepin/Borepin.Android/Services/APIServiceConnection.cs new file mode 100644 index 0000000..319d008 --- /dev/null +++ b/Borepin/Borepin.Android/Services/APIServiceConnection.cs @@ -0,0 +1,32 @@ +using Android.Content; +using Android.OS; +using FabAccessAPI; + +namespace Borepin.Droid.Services +{ + class APIServiceConnection : Java.Lang.Object, IServiceConnection + { + #region Members + public bool IsConnected + { + get + { + return Binder != null; + } + } + public APIBinder Binder { get; private set; } = null; + #endregion + + #region Methods + public void OnServiceConnected(ComponentName name, IBinder service) + { + Binder = service as APIBinder; + } + + public void OnServiceDisconnected(ComponentName name) + { + Binder = null; + } + #endregion + } +} \ No newline at end of file diff --git a/Borepin/Borepin.UWP/Borepin.UWP.csproj b/Borepin/Borepin.UWP/Borepin.UWP.csproj index ce20094..2f9fcd5 100644 --- a/Borepin/Borepin.UWP/Borepin.UWP.csproj +++ b/Borepin/Borepin.UWP/Borepin.UWP.csproj @@ -98,6 +98,7 @@ + diff --git a/Borepin/Borepin.UWP/PlatformInitializer.cs b/Borepin/Borepin.UWP/PlatformInitializer.cs index 4fc4a5e..9eacb3c 100644 --- a/Borepin/Borepin.UWP/PlatformInitializer.cs +++ b/Borepin/Borepin.UWP/PlatformInitializer.cs @@ -3,7 +3,7 @@ using Prism; using Prism.Ioc; using Borepin.Service.Storage; using Borepin.Service.Versioning; -using FabAccessAPI; +using Borepin.Service; namespace Borepin.UWP { @@ -15,7 +15,7 @@ namespace Borepin.UWP containerRegistry.Register(); containerRegistry.Register(); - containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); } } } diff --git a/Borepin/Borepin.UWP/Services/APIService.cs b/Borepin/Borepin.UWP/Services/APIService.cs new file mode 100644 index 0000000..f985225 --- /dev/null +++ b/Borepin/Borepin.UWP/Services/APIService.cs @@ -0,0 +1,23 @@ +using Borepin.Service; +using FabAccessAPI; + +namespace Borepin.UWP.Services +{ + public class APIService : IAPIService + { + #region Private Members + private readonly IAPI _API; + #endregion + + #region Constructors + public APIService() + { + _API = new API(); + } + #endregion + public IAPI GetAPI() + { + return _API; + } + } +} diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index 9af051d..49518ba 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -81,6 +81,7 @@ + diff --git a/Borepin/Borepin.iOS/PlatformInitializer.cs b/Borepin/Borepin.iOS/PlatformInitializer.cs index 4827500..26a09b8 100644 --- a/Borepin/Borepin.iOS/PlatformInitializer.cs +++ b/Borepin/Borepin.iOS/PlatformInitializer.cs @@ -1,7 +1,7 @@ using Borepin.iOS.Services; +using Borepin.Service; using Borepin.Service.Storage; using Borepin.Service.Versioning; -using FabAccessAPI; using Prism; using Prism.Ioc; @@ -15,7 +15,7 @@ namespace Borepin.iOS containerRegistry.Register(); containerRegistry.Register(); - containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); } } } \ No newline at end of file diff --git a/Borepin/Borepin.iOS/Services/APIService.cs b/Borepin/Borepin.iOS/Services/APIService.cs new file mode 100644 index 0000000..f311dab --- /dev/null +++ b/Borepin/Borepin.iOS/Services/APIService.cs @@ -0,0 +1,23 @@ +using Borepin.Service; +using FabAccessAPI; + +namespace Borepin.iOS.Services +{ + public class APIService : IAPIService + { + #region Private Members + private readonly IAPI _API; + #endregion + + #region Constructors + public APIService() + { + _API = new API(); + } + #endregion + public IAPI GetAPI() + { + return _API; + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/App.xaml.cs b/Borepin/Borepin/App.xaml.cs index 702aad5..4fc87c3 100644 --- a/Borepin/Borepin/App.xaml.cs +++ b/Borepin/Borepin/App.xaml.cs @@ -26,11 +26,6 @@ namespace Borepin { InitializeComponent(); - INavigationParameters parameters = new NavigationParameters() - { - { "instance", 0 }, - }; - await NavigationService.NavigateAsync(new Uri("https://borepin.fab-access.org/StartPage")).ConfigureAwait(false); } @@ -71,7 +66,7 @@ namespace Borepin // IPreferenceStorageService // ISecretStorageService // IVersioningService - // IAPI + // IAPIService #endregion } } diff --git a/Borepin/Borepin/Base/ConnectionModelBase.cs b/Borepin/Borepin/Base/ConnectionModelBase.cs index e999e7d..87b67f0 100644 --- a/Borepin/Borepin/Base/ConnectionModelBase.cs +++ b/Borepin/Borepin/Base/ConnectionModelBase.cs @@ -1,9 +1,8 @@ -using Borepin.Service.BFFH; -using Borepin.Service.BFFH.Exceptions; +using Borepin.Service; +using FabAccessAPI; using Prism.Navigation; using Prism.Services; using System.Threading.Tasks; -using Xamarin.Forms; namespace Borepin.Base { @@ -14,14 +13,56 @@ namespace Borepin.Base { #region Private Fields protected readonly IPageDialogService _PageDialogService; - protected readonly IBFFHService _BFFHService; + protected readonly IAPI _API; #endregion #region Constructors - protected ConnectionModelBase(INavigationService navigationService, IPageDialogService pageDialogService, IBFFHService bFFHService) : base(navigationService) + protected ConnectionModelBase(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService) { _PageDialogService = pageDialogService; - _BFFHService = bFFHService; + _API = apiService.GetAPI(); + _API.ConnectionStatusChanged += OnConnectionStatusChanged; + + IsConnected = _API.IsConnected; + } + #endregion + + #region Methods + public void OnConnectionStatusChanged(object sender, ConnectionStatusChange args) + { + switch(args) + { + case ConnectionStatusChange.Connected: + IsConnected = true; + LoadAPIData(); + break; + case ConnectionStatusChange.Reconnected: + ReloadAPIData(); + break; + case ConnectionStatusChange.ConnectionLoss: + case ConnectionStatusChange.Disconnected: + IsConnected = false; + break; + } + } + + public virtual Task LoadAPIData() + { + return Task.CompletedTask; + } + public virtual Task ReloadAPIData() + { + return Task.CompletedTask; + } + + public virtual Task LoadInstance(object instance) + { + return Task.CompletedTask; + } + + public virtual Task CreateInstance() + { + return Task.FromResult(null); } #endregion @@ -37,36 +78,31 @@ namespace Borepin.Base } #endregion - #region Methods - /// - /// Checks connection to Server. - /// Display message if Connection is lost. - /// - /// True if connection is ok. - public async Task CheckConnection() + #region INavigationAware + public override void OnNavigatedTo(INavigationParameters parameters) { - try + if(parameters.ContainsKey("instance")) { - if(_BFFHService.CurrentConnection != null && !_BFFHService.IsConnected) - { - await _BFFHService.Reconnect().ConfigureAwait(false); - } - else if(_BFFHService.CurrentConnection == null) - { - return false; - } - - return true; + LoadInstance(parameters.GetValue("instance")); } - catch (ReconnectingFailedException) + else { - Device.BeginInvokeOnMainThread(async () => - { - await _PageDialogService.DisplayAlertAsync("Connection failed", "Lost connection to server.", "Ok").ConfigureAwait(false); - }); + Log.Trace("No instance"); + LoadInstance(null); + } - IsConnected = false; - return false; + if(_API.IsConnected) + { + LoadAPIData(); + } + } + + public override void OnNavigatedFrom(INavigationParameters parameters) + { + object instance = CreateInstance(); + if(instance != null) + { + parameters.Add("instance", instance); } } #endregion diff --git a/Borepin/Borepin/Base/Exceptions/InstanceIncorrectException.cs b/Borepin/Borepin/Base/Exceptions/InstanceIncorrectException.cs new file mode 100644 index 0000000..632b89e --- /dev/null +++ b/Borepin/Borepin/Base/Exceptions/InstanceIncorrectException.cs @@ -0,0 +1,22 @@ +using System; + +namespace Borepin.Base.Exceptions +{ + public class InstanceIncorrectException : Exception + { + public InstanceIncorrectException() + { + + } + + public InstanceIncorrectException(string message) : base(message) + { + + } + + public InstanceIncorrectException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/Borepin/Borepin/Base/PageModelBase.cs b/Borepin/Borepin/Base/PageModelBase.cs index 8e51506..f4cf05d 100644 --- a/Borepin/Borepin/Base/PageModelBase.cs +++ b/Borepin/Borepin/Base/PageModelBase.cs @@ -1,6 +1,6 @@ -using Prism.Mvvm; +using NLog; +using Prism.Mvvm; using Prism.Navigation; -using System.Threading.Tasks; namespace Borepin.Base { @@ -9,6 +9,10 @@ namespace Borepin.Base /// public abstract class PageModelBase : BindableBase, INavigationAware { + #region Logger + protected static readonly Logger Log = LogManager.GetCurrentClassLogger(); + #endregion + #region Private Fields protected readonly INavigationService _NavigationService; @@ -30,14 +34,6 @@ namespace Borepin.Base } #endregion - #region Data - /// - /// Load Data async - /// - /// - public abstract Task LoadData(); - #endregion - #region INavigationAware public abstract void OnNavigatedTo(INavigationParameters parameters); public abstract void OnNavigatedFrom(INavigationParameters parameters); diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 6f5458e..33c442f 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -31,6 +31,7 @@ + diff --git a/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs b/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs index 656c023..e494e2e 100644 --- a/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs +++ b/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs @@ -1,10 +1,11 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using System.Windows.Input; using Borepin.Base; -using Borepin.Model; -using Borepin.Service.BFFH; -using Borepin.Service.BFFH.Exceptions; +using Borepin.Base.Exceptions; +using Borepin.Service; +using FabAccessAPI; using FabAccessAPI.Exceptions; using Prism.Commands; using Prism.Navigation; @@ -12,31 +13,32 @@ using Prism.Services; namespace Borepin.PageModel.AddServerProcess { - public class AuthPlainPageModel : PageModelBase + public class AuthPlainPageModel : ConnectionModelBase { #region Private Fields - private readonly IBFFHService _BFFHService; - private readonly IPageDialogService _PageDialogService; - - private Connection _Connection; + private ConnectionData _ConnectionData; #endregion #region Constructors - public AuthPlainPageModel(INavigationService navigationService, IBFFHService bffhService, IPageDialogService pageDialogService) : base(navigationService) + public AuthPlainPageModel(INavigationService navigationService, IAPIService apiService, IPageDialogService pageDialogService) : base(navigationService, pageDialogService, apiService) { - _BFFHService = bffhService; - _PageDialogService = pageDialogService; - AuthenticateCommand = new DelegateCommand(async () => await AuthenticateCommandExecute().ConfigureAwait(false)); } #endregion #region LoadData - public override Task LoadData() + public override Task LoadInstance(object instance) { - Username = _Connection.Username; - - IsBusy = false; + if(instance is ConnectionData) + { + _ConnectionData = instance as ConnectionData; + Username = _ConnectionData.Username; + } + else + { + throw new InstanceIncorrectException(); + } + return Task.CompletedTask; } #endregion @@ -68,16 +70,26 @@ namespace Borepin.PageModel.AddServerProcess { IsBusy = true; - _Connection.Username = Username; - - if (_BFFHService.IsConnected) + _ConnectionData = new ConnectionData() { - await _BFFHService.Disconnect().ConfigureAwait(true); + Host = _ConnectionData.Host, + Mechanism = Mechanism.PLAIN, + Username = Username, + Properties = new Dictionary(StringComparer.Ordinal) + { + { "username", Username }, + { "password", Password } + }, + }; + + if (_API.IsConnected) + { + await _API.Disconnect().ConfigureAwait(true); } try { - await _BFFHService.Connect(_Connection, Password).ConfigureAwait(true); + await _API.Connect(_ConnectionData).ConfigureAwait(true); } catch (ConnectingFailedException) { @@ -101,30 +113,10 @@ namespace Borepin.PageModel.AddServerProcess return; } - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage").ConfigureAwait(false); - } - #endregion - - #region INavigationAware - public override void OnNavigatedTo(INavigationParameters parameters) - { - if (parameters.ContainsKey("instance") && parameters["instance"] is Connection) + INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage").ConfigureAwait(false); + if(result.Exception != null) { - _Connection = parameters["instance"] as Connection; - } - else - { - _Connection = new Connection(); - } - - LoadData(); - } - - public override void OnNavigatedFrom(INavigationParameters parameters) - { - if(parameters.GetNavigationMode() == NavigationMode.Back) - { - parameters.Add("instance", _Connection); + Log.Fatal(result.Exception, "Navigating failed"); } } #endregion diff --git a/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs b/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs index c02997d..a8133d6 100644 --- a/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs +++ b/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs @@ -1,59 +1,56 @@ using Borepin.Base; -using Borepin.Model; -using Borepin.Service.BFFH; -using Prism.AppModel; +using Borepin.Service; +using FabAccessAPI; +using FabAccessAPI.Exceptions; +using Prism.Commands; using Prism.Navigation; using Prism.Services; -using Prism.Services.Dialogs; using System; -using System.Globalization; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Input; -using Xamarin.Forms; namespace Borepin.PageModel.AddServerProcess { - public class SelectServerPageModel : PageModelBase, IPageLifecycleAware + public class SelectServerPageModel : ConnectionModelBase { #region Private Fields - private readonly IBFFHService _BFFHService; - private readonly IPageDialogService _PageDialogService; - private readonly IDialogService _DialogService; - - private Connection _Connection; - private bool _Scanned; + private ConnectionData _ConnectionData; #endregion #region Constructors - public SelectServerPageModel(INavigationService navigationService, IBFFHService bffhService, IPageDialogService pageDialogService, IDialogService dialogService) : base(navigationService) + public SelectServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService) { - _BFFHService = bffhService; - _PageDialogService = pageDialogService; - _DialogService = dialogService; - - ConnectToServerCommand = new Command(async ()=> await ConnectToServerExecute().ConfigureAwait(false)); - DetectLocalServerCommand = new Command(DetectHostCommandExecute); - ScanCodeCommand = new Command(ScanCodeCommandExecute); + ConnectToServerCommand = new DelegateCommand(async () => await ConnectToServerExecute().ConfigureAwait(false)); + DetectLocalServerCommand = new DelegateCommand(DetectHostCommandExecute); + ScanCodeCommand = new DelegateCommand(ScanCodeCommandExecute); } #endregion #region LoadData - public override Task LoadData() + public override Task LoadInstance(object instance) { - Server = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", _Connection.Address.Host, _Connection.Address.Port); + if(instance is ConnectionData) + { + _ConnectionData = instance as ConnectionData; + Host = _ConnectionData.Host.ToString(); + } - IsBusy = false; return Task.CompletedTask; } + + public override Task CreateInstance() + { + return Task.FromResult(_ConnectionData); + } #endregion #region Fields - private string _Server; - public string Server + private string _Host; + public string Host { - get => _Server; - set => SetProperty(ref _Server, value); + get => _Host; + set => SetProperty(ref _Host, value); } #endregion @@ -71,13 +68,13 @@ namespace Borepin.PageModel.AddServerProcess try { string server_address = ""; - if(Regex.IsMatch(Server, "([a-zA-Z]{2,20}):\\/\\/", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(1))) + if(Regex.IsMatch(Host, "([a-zA-Z]{2,20}):\\/\\/", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(1))) { - server_address = Server; + server_address = Host; } else { - server_address = "http://" + Server; + server_address = "http://" + Host; } UriBuilder builder = new UriBuilder(server_address); @@ -86,9 +83,9 @@ namespace Borepin.PageModel.AddServerProcess builder.Port = 59661; } - _Connection = new Connection() + _ConnectionData = new ConnectionData() { - Address = builder.Uri, + Host = builder.Uri, }; } catch (UriFormatException) @@ -99,7 +96,11 @@ namespace Borepin.PageModel.AddServerProcess return; } - if (!await _BFFHService.TestConnection(_Connection).ConfigureAwait(true)) + try + { + await _API.TestConnection(_ConnectionData).ConfigureAwait(true); + } + catch(ConnectingFailedException) { await _PageDialogService.DisplayAlertAsync("Connection failed", "Unable to connect to server.", "Ok").ConfigureAwait(false); @@ -107,12 +108,11 @@ namespace Borepin.PageModel.AddServerProcess return; } - INavigationParameters parameters = new NavigationParameters() + INavigationResult result = await _NavigationService.NavigateAsync("AddServerProcess_ChooseAuthTypePage").ConfigureAwait(false); + if (result.Exception != null) { - {"instance", _Connection }, - }; - - await _NavigationService.NavigateAsync("AddServerProcess_ChooseAuthTypePage", parameters).ConfigureAwait(false); + Log.Fatal(result.Exception, "Navigating failed"); + } } private ICommand _ScanCodeCommand; @@ -123,16 +123,7 @@ namespace Borepin.PageModel.AddServerProcess } public void ScanCodeCommandExecute() { - _DialogService.ShowDialog("ScanDialog", ScanCodeCommandExecute_Dialog); - } - - public void ScanCodeCommandExecute_Dialog(IDialogResult result) - { - if (string.Equals(result.Parameters.GetValue("result"), "scanned", StringComparison.Ordinal)) - { - Server = result.Parameters["value"] as string; - _Scanned = true; - } + } private ICommand _DetectLocalServerCommand; @@ -144,52 +135,7 @@ namespace Borepin.PageModel.AddServerProcess public void DetectHostCommandExecute() { // Get Example Server Address - Server = "127.0.0.1:59661"; - } - #endregion - - #region IPageLifecycleAware - public async void OnAppearing() - { - if (_Scanned) - { - _Scanned = false; - - await ConnectToServerExecute().ConfigureAwait(false); - } - } - - public void OnDisappearing() - { - - } - #endregion - - #region INavigationAware - public override void OnNavigatedTo(INavigationParameters parameters) - { - if(_Connection == null) - { - if (parameters.ContainsKey("instance") && parameters["instance"] is Connection) - { - _Connection = parameters["instance"] as Connection; - } - else - { - _Connection = new Connection(); - } - - LoadData(); - } - else - { - IsBusy = false; - } - } - - public override void OnNavigatedFrom(INavigationParameters parameters) - { - + Host = "127.0.0.1:59661"; } #endregion } diff --git a/Borepin/Borepin/PageModel/MachineListPageModel.cs b/Borepin/Borepin/PageModel/MachineListPageModel.cs index ddf20a6..50c7dcb 100644 --- a/Borepin/Borepin/PageModel/MachineListPageModel.cs +++ b/Borepin/Borepin/PageModel/MachineListPageModel.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using System.Windows.Input; using Prism.Commands; using Prism.Navigation; -using Borepin.Service.BFFH; using Borepin.Base; using FabAccessAPI.Schema; using Prism.Services; @@ -12,6 +11,7 @@ using static FabAccessAPI.Schema.Machine; using System; using NaturalSort.Extension; using System.Linq; +using Borepin.Service; namespace Borepin.PageModel { @@ -22,7 +22,7 @@ namespace Borepin.PageModel #endregion #region Constructors - public MachineListPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IBFFHService bFFHService) : base(navigationService, pageDialogService, bFFHService) + public MachineListPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService) { SelectInstanceCommand = new DelegateCommand(SelectInstanceCommandExecute); ScanCodeCommand = new DelegateCommand(async () => await ScanCodeCommandExecute().ConfigureAwait(false)); diff --git a/Borepin/Borepin/PageModel/MachinePageModel.cs b/Borepin/Borepin/PageModel/MachinePageModel.cs index 78337c9..19b6f91 100644 --- a/Borepin/Borepin/PageModel/MachinePageModel.cs +++ b/Borepin/Borepin/PageModel/MachinePageModel.cs @@ -4,11 +4,10 @@ using Prism.Navigation; using System.Threading.Tasks; using System.Windows.Input; using FabAccessAPI.Schema; -using Borepin.Service.BFFH; -using static FabAccessAPI.Schema.MachineSystem; using Borepin.Model; using Prism.Services; -using Borepin.Service.BFFH.Exceptions; +using Borepin.Service; +using Borepin.Base.Exceptions; namespace Borepin.PageModel { @@ -20,7 +19,7 @@ namespace Borepin.PageModel #endregion #region Contructors - public MachinePageModel(INavigationService navigationService, IPageDialogService pageDialogService, IBFFHService bffhService) : base(navigationService, pageDialogService, bffhService) + public MachinePageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService) { UseMachineCommand = new DelegateCommand(UseMachineCommandExecute); GiveBackMachineCommand = new DelegateCommand(GiveBackMachineCommandExecute); @@ -29,34 +28,29 @@ namespace Borepin.PageModel #endregion #region Data - public override async Task LoadData() + public override Task LoadInstance(object instance) { IsBusy = true; - if (!await CheckConnection().ConfigureAwait(false)) - { - IsConnected = false; - IsBusy = false; - return; - } - - MachineSystem machineSystem; - try + if(instance is string) { - machineSystem = (await _BFFHService.GetSession().ConfigureAwait(false)).MachineSystem; + _ID = instance as string; } - catch(ReconnectingFailedException) + else { - await _PageDialogService.DisplayAlertAsync("Connection failed", "Lost connection to server.", "Ok").ConfigureAwait(false); - - return; + throw new InstanceIncorrectException(); } - _Machine = (await machineSystem.Info.GetMachine(_ID).ConfigureAwait(false)).Just; - MachineItem = new MachineVisualize(_Machine); - MachineItem.LoadData(); - IsBusy = false; + + return Task.CompletedTask; + } + + public override async Task LoadAPIData() + { + _Machine = (await _API.Session.MachineSystem.Info.GetMachine(_ID).ConfigureAwait(false)).Just; + MachineItem = new MachineVisualize(_Machine); + MachineItem.LoadData(); } #endregion @@ -81,19 +75,15 @@ namespace Borepin.PageModel public async void UseMachineCommandExecute() { IsBusy = true; - if (!await CheckConnection().ConfigureAwait(false)) + + if(_API.IsConnected) { - IsConnected = false; + Machine.IUseInterface useInterface = _Machine.Use; - IsBusy = false; - return; + await useInterface.Use().ConfigureAwait(false); + await LoadAPIData().ConfigureAwait(false); } - Machine.IUseInterface useInterface = _Machine.Use; - - await useInterface.Use().ConfigureAwait(false); - await LoadData().ConfigureAwait(false); - IsBusy = false; } @@ -107,19 +97,15 @@ namespace Borepin.PageModel public async void GiveBackMachineCommandExecute() { IsBusy = true; - if (!await CheckConnection().ConfigureAwait(false)) + + if (_API.IsConnected) { - IsConnected = false; + Machine.IInUseInterface inUseInterface = _Machine.Inuse; - IsBusy = false; - return; + await inUseInterface.GiveBack().ConfigureAwait(false); + await LoadAPIData().ConfigureAwait(false); } - Machine.IInUseInterface inUseInterface = _Machine.Inuse; - - await inUseInterface.GiveBack().ConfigureAwait(false); - await LoadData().ConfigureAwait(false); - IsBusy = false; } @@ -133,35 +119,18 @@ namespace Borepin.PageModel public async void ForceFreeMachineCommandExecute() { IsBusy = true; - if (!await CheckConnection().ConfigureAwait(false)) + + if (_API.IsConnected) { - IsConnected = false; - IsBusy = false; - return; + Machine.IManageInterface manageInterface = _Machine.Manage; + + await manageInterface.ForceFree().ConfigureAwait(false); + await LoadAPIData().ConfigureAwait(false); } - Machine.IManageInterface manageInterface = _Machine.Manage; - - await manageInterface.ForceFree().ConfigureAwait(false); - await LoadData().ConfigureAwait(false); - IsBusy = false; } #endregion - - #region INavigationService - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override async void OnNavigatedTo(INavigationParameters parameters) - { - _ID = parameters["id"] as string; - - await LoadData().ConfigureAwait(false); - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/ScanURNPageModel.cs b/Borepin/Borepin/PageModel/ScanURNPageModel.cs index 52bdeae..18d547f 100644 --- a/Borepin/Borepin/PageModel/ScanURNPageModel.cs +++ b/Borepin/Borepin/PageModel/ScanURNPageModel.cs @@ -1,6 +1,5 @@ using Borepin.Base; -using Borepin.Service.BFFH; -using Borepin.Service.BFFH.Exceptions; +using Borepin.Service; using FabAccessAPI.Schema; using Prism.Commands; using Prism.Navigation; @@ -17,7 +16,7 @@ namespace Borepin.PageModel class ScanURNPageModel : ConnectionModelBase { #region Contructors - public ScanURNPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IBFFHService bffhService) : base(navigationService, pageDialogService, bffhService) + public ScanURNPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService) { AbortCommand = new DelegateCommand(async () => await AbortCommandExecute().ConfigureAwait(true)); ScannedCommand = new DelegateCommand(async () => await ScannedCommandExecuteAsync().ConfigureAwait(false)); @@ -27,13 +26,6 @@ namespace Borepin.PageModel } #endregion - #region Data - public override async Task LoadData() - { - await Task.CompletedTask.ConfigureAwait(false); - } - #endregion - #region Fields public MobileBarcodeScanningOptions ScanOptions { @@ -98,28 +90,15 @@ namespace Borepin.PageModel return; } // END HACK - string id = null; - try - { - id = await QRToID(ScanResult.Text).ConfigureAwait(false); - } - catch(ReconnectingFailedException) - { - Device.BeginInvokeOnMainThread(async () => - { - await _PageDialogService.DisplayAlertAsync("Connection failed", "Please reconnect to the server.", "OK").ConfigureAwait(false); - IsScanning = true; - }); - return; - } + string id = await QRToID(ScanResult.Text).ConfigureAwait(false); if (id != null) { NavigationParameters parameters = new NavigationParameters - { - { "id", id }, - }; + { + { "id", id }, + }; Device.BeginInvokeOnMainThread(async () => { @@ -141,24 +120,21 @@ namespace Borepin.PageModel public async Task QRToID(string value) { - if (!_BFFHService.IsConnected) + if (_API.IsConnected) { - await _BFFHService.Reconnect().ConfigureAwait(false); - - IsConnected = false; - return null; + Optional optional = await _API.Session.MachineSystem.Info.GetMachineURN(value).ConfigureAwait(false); + + if (optional.Just == null) + { + return null; + } + + return optional.Just.Id; } - - MachineSystem machineSystem = (await _BFFHService.GetSession().ConfigureAwait(false)).MachineSystem; - - Optional optional = await machineSystem.Info.GetMachineURN(value).ConfigureAwait(false); - - if (optional.Just == null) + else { return null; } - - return optional.Just.Id; } private ICommand _AbortCommand; @@ -175,17 +151,5 @@ namespace Borepin.PageModel await _NavigationService.GoBackAsync().ConfigureAwait(false); } #endregion - - #region INavigationService - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override void OnNavigatedTo(INavigationParameters parameters) - { - - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/ServerListPageModel.cs b/Borepin/Borepin/PageModel/ServerListPageModel.cs index 286f27b..b030e80 100644 --- a/Borepin/Borepin/PageModel/ServerListPageModel.cs +++ b/Borepin/Borepin/PageModel/ServerListPageModel.cs @@ -2,25 +2,28 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; -using Borepin.Model; using System.Windows.Input; using Prism.Commands; using Prism.Navigation; -using Borepin.Service.BFFH; using Borepin.Base; +using Borepin.Service.Storage; +using FabAccessAPI; +using Borepin.Service; namespace Borepin.PageModel { public class ServerListPageModel : PageModelBase { #region Private Fields - private readonly IBFFHService _BFFHService; + private readonly ILoginStorageService _LoginStorageService; + private readonly IAPI _API; #endregion #region Constructors - public ServerListPageModel(INavigationService navigationService, IBFFHService bffhService) : base(navigationService) + public ServerListPageModel(INavigationService navigationService, ILoginStorageService loginStorageService, IAPIService apiService) : base(navigationService) { - _BFFHService = bffhService; + _LoginStorageService = loginStorageService; + _API = apiService.GetAPI(); AddInstancesCommand = new DelegateCommand(AddInstancesCommandExecute); SelectInstanceCommand = new DelegateCommand(SelectInstanceCommandExecute); @@ -28,14 +31,14 @@ namespace Borepin.PageModel #endregion #region Data - public override async Task LoadData() + public async Task LoadData() { - IList list = await _BFFHService.GetConnections().ConfigureAwait(false); - if (_BFFHService.IsConnected) + IList list = await _LoginStorageService.GetList().ConfigureAwait(false); + if (_API.IsConnected) { - ActiveConnection = new ServerListItemViewModel(_BFFHService.CurrentConnection); + ActiveConnection = new ServerListItemViewModel(_API.ConnectionData); - list.Remove(_BFFHService.CurrentConnection); + list.Remove(_API.ConnectionData); HasActiveConnection = true; } diff --git a/Borepin/Borepin/PageModel/ServerPageModel.cs b/Borepin/Borepin/PageModel/ServerPageModel.cs index 04ad232..a268796 100644 --- a/Borepin/Borepin/PageModel/ServerPageModel.cs +++ b/Borepin/Borepin/PageModel/ServerPageModel.cs @@ -1,7 +1,7 @@ using Borepin.Base; -using Borepin.Model; -using Borepin.Service.BFFH; -using Borepin.Service.BFFH.Exceptions; +using Borepin.Service; +using FabAccessAPI; +using FabAccessAPI.Exceptions; using Prism.Commands; using Prism.Navigation; using Prism.Services; @@ -13,22 +13,17 @@ using System.Windows.Input; namespace Borepin.PageModel { - public class ServerPageModel : PageModelBase + public class ServerPageModel : ConnectionModelBase { #region Private Fields private readonly IDialogService _DialogService; - private readonly IBFFHService _BFFHService; - private readonly IPageDialogService _PageDialogService; #endregion #region Constructors - public ServerPageModel(INavigationService navigationService, IDialogService dialogService, IBFFHService bffhService, IPageDialogService pageDialogService) : base(navigationService) + public ServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService, IDialogService dialogService,) : base(navigationService, pageDialogService, apiService) { _DialogService = dialogService; - _BFFHService = bffhService; - _PageDialogService = pageDialogService; - ConnectCommand = new DelegateCommand(async () => await ConnectCommandExecute().ConfigureAwait(false)); DisconnectCommand = new DelegateCommand(async () => await DisonnectCommandExecute().ConfigureAwait(false)); DeleteCommand = new DelegateCommand(DeleteCommandExecute); @@ -58,8 +53,8 @@ namespace Borepin.PageModel #endregion #region Fields - private Connection _Connection_Item; - public Connection Connection_Item + private ConnectionData _Connection_Item; + public ConnectionData Connection_Item { get => _Connection_Item; set => SetProperty(ref _Connection_Item, value); @@ -91,14 +86,14 @@ namespace Borepin.PageModel { IsBusy = true; - if(_BFFHService.IsConnected) + if(_API.IsConnected) { - await _BFFHService.Disconnect().ConfigureAwait(true); + await _API.Disconnect().ConfigureAwait(true); } try { - await _BFFHService.Connect(Connection_Item).ConfigureAwait(true); + await _API.Connect(Connection_Item).ConfigureAwait(true); } catch(ConnectingFailedException) { @@ -107,21 +102,13 @@ namespace Borepin.PageModel IsBusy = false; return; } - catch(AuthenticatingFailedException) + catch(AuthenticationFailedException) { await _PageDialogService.DisplayAlertAsync("Connection failed", "Unable to authenticate to server.", "Ok").ConfigureAwait(false); IsBusy = false; return; } - catch(MissingCredentialsException) - { - await _PageDialogService.DisplayAlertAsync("Secure Storage failed", "Unable to load connections from secure storage.\n Please recreate the connection.", "Ok").ConfigureAwait(false); - - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/ServerListPage").ConfigureAwait(false); - IsBusy = false; - return; - } await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage").ConfigureAwait(false); } @@ -134,7 +121,7 @@ namespace Borepin.PageModel } public async Task DisonnectCommandExecute() { - await _BFFHService.Disconnect().ConfigureAwait(false); + await _API.Disconnect().ConfigureAwait(false); await LoadData().ConfigureAwait(false); } @@ -170,22 +157,5 @@ namespace Borepin.PageModel } } #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override async void OnNavigatedTo(INavigationParameters parameters) - { - if(Connection_Item == null) - { - Connection_Item = parameters["instance"] as Connection; - - await LoadData().ConfigureAwait(false); - } - } - #endregion } } diff --git a/Borepin/Borepin/Service/IAPIService.cs b/Borepin/Borepin/Service/IAPIService.cs new file mode 100644 index 0000000..4937beb --- /dev/null +++ b/Borepin/Borepin/Service/IAPIService.cs @@ -0,0 +1,9 @@ +using FabAccessAPI; + +namespace Borepin.Service +{ + public interface IAPIService + { + IAPI GetAPI(); + } +} diff --git a/Borepin/Borepin/ViewModel/ServerListItemViewModel.cs b/Borepin/Borepin/ViewModel/ServerListItemViewModel.cs index 4d6b33f..4de8be4 100644 --- a/Borepin/Borepin/ViewModel/ServerListItemViewModel.cs +++ b/Borepin/Borepin/ViewModel/ServerListItemViewModel.cs @@ -1,4 +1,5 @@ using Borepin.Model; +using FabAccessAPI; using Prism.Mvvm; namespace Borepin.ViewModel @@ -6,16 +7,16 @@ namespace Borepin.ViewModel public class ServerListItemViewModel : BindableBase { #region Constructors - public ServerListItemViewModel(Connection instance) + public ServerListItemViewModel(ConnectionData instance) { Instance = instance; - Address = instance.Address.Host; + Address = instance.Host.Host; Username = instance.Username; } #endregion #region Fields - public readonly Connection Instance; + public readonly ConnectionData Instance; private string _Address; public string Address diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index d2e375d..d903c7f 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -1,6 +1,7 @@ using Capnp.Rpc; using FabAccessAPI.Exceptions; using FabAccessAPI.Schema; +using NLog; using S22.Sasl; using System; using System.Collections.Generic; @@ -14,6 +15,10 @@ namespace FabAccessAPI { public class API : IAPI { + #region Logger + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + #endregion + #region Private Members private TcpRpcClient _TcpRpcClient; private IBootstrap _Bootstrap; @@ -40,11 +45,14 @@ namespace FabAccessAPI if (args.LastState == ConnectionState.Initializing && args.NewState == ConnectionState.Active) { + Log.Trace("TcpRpcClient Event Connected"); eventHandler(this, ConnectionStatusChange.Connected); } if (args.LastState == ConnectionState.Active && args.NewState == ConnectionState.Down) { + Log.Trace("TcpRpcClient Event ConnectionLoss"); eventHandler(this, ConnectionStatusChange.ConnectionLoss); + _TcpRpcClient = null; } } #endregion @@ -98,11 +106,14 @@ namespace FabAccessAPI Session = await _Authenticate(connectionData).ConfigureAwait(false); ConnectionData = connectionData; + + Log.Info("API connected"); } - catch(System.Exception) + catch(System.Exception ex) { await Disconnect().ConfigureAwait(false); - throw; + Log.Warn(ex, "API connecting failed"); + throw ex; } } @@ -121,6 +132,8 @@ namespace FabAccessAPI ConnectionStatusChanged?.Invoke(this, ConnectionStatusChange.Disconnected); + Log.Info("API disconnected"); + return Task.CompletedTask; } @@ -132,6 +145,7 @@ namespace FabAccessAPI } ConnectionStatusChanged?.Invoke(this, ConnectionStatusChange.Reconnected); + Log.Info("API reconnected"); } public async Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null) diff --git a/FabAccessAPI/FabAccessAPI.csproj b/FabAccessAPI/FabAccessAPI.csproj index efab474..ba24ff4 100644 --- a/FabAccessAPI/FabAccessAPI.csproj +++ b/FabAccessAPI/FabAccessAPI.csproj @@ -12,8 +12,8 @@ - + diff --git a/FabAccessAPI/IAPI.cs b/FabAccessAPI/IAPI.cs index 5818e34..b2177e4 100644 --- a/FabAccessAPI/IAPI.cs +++ b/FabAccessAPI/IAPI.cs @@ -37,7 +37,7 @@ namespace FabAccessAPI /// Connect to BFFH Server /// /// - Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient); + Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null); /// /// Disconnect from BFFH Server @@ -53,6 +53,6 @@ namespace FabAccessAPI /// Connect to Server and get ConnectionInfo. /// The Connection is not maintained. /// - Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient); + Task TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null); } } From 3cf84220bf87e0db723e4f51115ad887fb631e74 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 17 May 2022 12:57:32 +0200 Subject: [PATCH 07/25] Move to new API Class and start debugging --- .../Borepin.Android/Borepin.Android.csproj | 2 +- Borepin/Borepin.GTK/Borepin.GTK.csproj | 4 +- Borepin/Borepin.GTK/app.config | 2 +- Borepin/Borepin.GTK/packages.config | 2 +- Borepin/Borepin.UWP/Borepin.UWP.csproj | 6 +- Borepin/Borepin.iOS/Borepin.iOS.csproj | 2 +- Borepin/Borepin.macOS/Borepin.macOS.csproj | 4 +- Borepin/Borepin.macOS/app.config | 2 +- Borepin/Borepin.macOS/packages.config | 2 +- Borepin/Borepin/Base/ConnectionModelBase.cs | 37 ++---------- Borepin/Borepin/Base/PageModelBase.cs | 50 +++++++++++++++- Borepin/Borepin/Borepin.csproj | 4 +- .../AddServerProcess/AuthPlainPageModel.cs | 2 +- .../ChooseAuthTypePageModel.cs | 58 ++++++++----------- .../AddServerProcess/SelectServerPageModel.cs | 7 ++- .../Borepin/PageModel/MachineListPageModel.cs | 46 ++++----------- Borepin/Borepin/PageModel/MachinePageModel.cs | 4 -- Borepin/Borepin/PageModel/MainPageModel.cs | 35 +++-------- Borepin/Borepin/PageModel/ScanPageModel.cs | 27 ++++----- .../Borepin/PageModel/ServerListPageModel.cs | 15 +---- Borepin/Borepin/PageModel/ServerPageModel.cs | 43 ++++++++++---- .../SetUpProcess/WelcomePageModel.cs | 23 +------- Borepin/Borepin/PageModel/StartPageModel.cs | 56 ++++++------------ Borepin_Test/Borepin_Test.csproj | 2 +- FabAccessAPI/FabAccessAPI.csproj | 2 +- FabAccessAPI_Test/API_Test.cs | 8 +-- FabAccessAPI_Test/FabAccessAPI_Test.csproj | 4 +- FabAccessAPI_Test/TestEnv.cs | 7 +-- 28 files changed, 188 insertions(+), 268 deletions(-) diff --git a/Borepin/Borepin.Android/Borepin.Android.csproj b/Borepin/Borepin.Android/Borepin.Android.csproj index 339d783..b8e91b3 100644 --- a/Borepin/Borepin.Android/Borepin.Android.csproj +++ b/Borepin/Borepin.Android/Borepin.Android.csproj @@ -68,7 +68,7 @@ 8.1.97 - + diff --git a/Borepin/Borepin.GTK/Borepin.GTK.csproj b/Borepin/Borepin.GTK/Borepin.GTK.csproj index 88376b3..1d5964f 100644 --- a/Borepin/Borepin.GTK/Borepin.GTK.csproj +++ b/Borepin/Borepin.GTK/Borepin.GTK.csproj @@ -42,8 +42,8 @@ False ..\..\..\..\..\..\..\Program Files (x86)\GtkSharp\2.12\lib\gtk-sharp-2.0\atk-sharp.dll - - ..\..\packages\DryIoc.dll.5.0.0\lib\net45\DryIoc.dll + + ..\..\packages\DryIoc.dll.5.0.2\lib\net45\DryIoc.dll False diff --git a/Borepin/Borepin.GTK/app.config b/Borepin/Borepin.GTK/app.config index 6d5260f..66373bc 100644 --- a/Borepin/Borepin.GTK/app.config +++ b/Borepin/Borepin.GTK/app.config @@ -12,7 +12,7 @@ - + diff --git a/Borepin/Borepin.GTK/packages.config b/Borepin/Borepin.GTK/packages.config index dc56bb3..fa48c82 100644 --- a/Borepin/Borepin.GTK/packages.config +++ b/Borepin/Borepin.GTK/packages.config @@ -1,6 +1,6 @@  - + diff --git a/Borepin/Borepin.UWP/Borepin.UWP.csproj b/Borepin/Borepin.UWP/Borepin.UWP.csproj index 2f9fcd5..620bb6d 100644 --- a/Borepin/Borepin.UWP/Borepin.UWP.csproj +++ b/Borepin/Borepin.UWP/Borepin.UWP.csproj @@ -182,9 +182,13 @@ - + + + {c587aac3-50a7-4871-a50d-7880b6f24ef6} + Capnp.Net.Runtime + {3251FCE9-FEA3-4662-8BEB-636BE6732D48} FabAccessAPI diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index 49518ba..5a52689 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -186,7 +186,7 @@ 8.1.97 - + 5.0.0.2401 diff --git a/Borepin/Borepin.macOS/Borepin.macOS.csproj b/Borepin/Borepin.macOS/Borepin.macOS.csproj index ea2c31f..9130cc0 100644 --- a/Borepin/Borepin.macOS/Borepin.macOS.csproj +++ b/Borepin/Borepin.macOS/Borepin.macOS.csproj @@ -59,8 +59,8 @@ - - ..\..\packages\DryIoc.dll.5.0.0\lib\netstandard2.1\DryIoc.dll + + ..\..\packages\DryIoc.dll.5.0.2\lib\netstandard2.1\DryIoc.dll ..\..\packages\Prism.Core.8.1.97\lib\netstandard2.0\Prism.dll diff --git a/Borepin/Borepin.macOS/app.config b/Borepin/Borepin.macOS/app.config index 9218e1a..5cf16ce 100644 --- a/Borepin/Borepin.macOS/app.config +++ b/Borepin/Borepin.macOS/app.config @@ -8,7 +8,7 @@ - + diff --git a/Borepin/Borepin.macOS/packages.config b/Borepin/Borepin.macOS/packages.config index 869649c..fdabcd9 100644 --- a/Borepin/Borepin.macOS/packages.config +++ b/Borepin/Borepin.macOS/packages.config @@ -1,6 +1,6 @@  - + diff --git a/Borepin/Borepin/Base/ConnectionModelBase.cs b/Borepin/Borepin/Base/ConnectionModelBase.cs index 87b67f0..7cc07b3 100644 --- a/Borepin/Borepin/Base/ConnectionModelBase.cs +++ b/Borepin/Borepin/Base/ConnectionModelBase.cs @@ -12,14 +12,12 @@ namespace Borepin.Base public abstract class ConnectionModelBase : PageModelBase { #region Private Fields - protected readonly IPageDialogService _PageDialogService; protected readonly IAPI _API; #endregion #region Constructors - protected ConnectionModelBase(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService) + protected ConnectionModelBase(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService) { - _PageDialogService = pageDialogService; _API = apiService.GetAPI(); _API.ConnectionStatusChanged += OnConnectionStatusChanged; @@ -54,16 +52,6 @@ namespace Borepin.Base { return Task.CompletedTask; } - - public virtual Task LoadInstance(object instance) - { - return Task.CompletedTask; - } - - public virtual Task CreateInstance() - { - return Task.FromResult(null); - } #endregion #region Fields @@ -79,30 +67,13 @@ namespace Borepin.Base #endregion #region INavigationAware - public override void OnNavigatedTo(INavigationParameters parameters) + public override async Task OnNavigatedToVirtual(INavigationParameters parameters) { - if(parameters.ContainsKey("instance")) - { - LoadInstance(parameters.GetValue("instance")); - } - else - { - Log.Trace("No instance"); - LoadInstance(null); - } + await base.OnNavigatedToVirtual(parameters).ConfigureAwait(false); if(_API.IsConnected) { - LoadAPIData(); - } - } - - public override void OnNavigatedFrom(INavigationParameters parameters) - { - object instance = CreateInstance(); - if(instance != null) - { - parameters.Add("instance", instance); + await LoadAPIData().ConfigureAwait(false); } } #endregion diff --git a/Borepin/Borepin/Base/PageModelBase.cs b/Borepin/Borepin/Base/PageModelBase.cs index f4cf05d..9c054d7 100644 --- a/Borepin/Borepin/Base/PageModelBase.cs +++ b/Borepin/Borepin/Base/PageModelBase.cs @@ -1,6 +1,8 @@ using NLog; using Prism.Mvvm; using Prism.Navigation; +using Prism.Services; +using System.Threading.Tasks; namespace Borepin.Base { @@ -15,10 +17,12 @@ namespace Borepin.Base #region Private Fields protected readonly INavigationService _NavigationService; + protected readonly IPageDialogService _PageDialogService; - protected PageModelBase(INavigationService navigationService) + protected PageModelBase(INavigationService navigationService, IPageDialogService pageDialogService) { _NavigationService = navigationService; + _PageDialogService = pageDialogService; } #endregion @@ -34,9 +38,49 @@ namespace Borepin.Base } #endregion + #region Mehtods + public virtual Task LoadInstance(object instance) + { + return Task.CompletedTask; + } + + public virtual Task CreateInstance() + { + return Task.FromResult(null); + } + #endregion + #region INavigationAware - public abstract void OnNavigatedTo(INavigationParameters parameters); - public abstract void OnNavigatedFrom(INavigationParameters parameters); + public async void OnNavigatedTo(INavigationParameters parameters) + { + await OnNavigatedToVirtual(parameters).ConfigureAwait(false); + IsBusy = false; + } + public async void OnNavigatedFrom(INavigationParameters parameters) + { + await OnNavigatedFromVirtual(parameters).ConfigureAwait(false); + } + + public virtual async Task OnNavigatedToVirtual(INavigationParameters parameters) + { + if (parameters.ContainsKey("instance")) + { + await LoadInstance(parameters.GetValue("instance")).ConfigureAwait(false); + } + else + { + Log.Trace("No instance"); + await LoadInstance(null).ConfigureAwait(false); + } + } + public virtual async Task OnNavigatedFromVirtual(INavigationParameters parameters) + { + object instance = await CreateInstance().ConfigureAwait(false); + if (instance != null) + { + parameters.Add("instance", instance); + } + } #endregion } } \ No newline at end of file diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 33c442f..97ed6e0 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -25,13 +25,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs b/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs index e494e2e..3d28024 100644 --- a/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs +++ b/Borepin/Borepin/PageModel/AddServerProcess/AuthPlainPageModel.cs @@ -78,7 +78,7 @@ namespace Borepin.PageModel.AddServerProcess Properties = new Dictionary(StringComparer.Ordinal) { { "username", Username }, - { "password", Password } + { "password", Password }, }, }; diff --git a/Borepin/Borepin/PageModel/AddServerProcess/ChooseAuthTypePageModel.cs b/Borepin/Borepin/PageModel/AddServerProcess/ChooseAuthTypePageModel.cs index e5be535..2e3f618 100644 --- a/Borepin/Borepin/PageModel/AddServerProcess/ChooseAuthTypePageModel.cs +++ b/Borepin/Borepin/PageModel/AddServerProcess/ChooseAuthTypePageModel.cs @@ -1,6 +1,8 @@ using Borepin.Base; -using Borepin.Model; +using Borepin.Base.Exceptions; +using FabAccessAPI; using Prism.Navigation; +using Prism.Services; using System.Threading.Tasks; using System.Windows.Input; using Xamarin.Forms; @@ -10,23 +12,34 @@ namespace Borepin.PageModel.AddServerProcess public class ChooseAuthTypePageModel : PageModelBase { #region Private Fields - private Connection _Connection; + private ConnectionData _ConnectionData; #endregion #region Contructors - public ChooseAuthTypePageModel(INavigationService navigationService) : base(navigationService) + public ChooseAuthTypePageModel(INavigationService navigationService, IPageDialogService pageDialogService) : base(navigationService, pageDialogService) { AuthPlainCommand = new Command(AuthPlainCommandExecute); } #endregion #region LoadData - public override Task LoadData() + public override Task LoadInstance(object instance) { - IsBusy = false; - + if(instance is ConnectionData) + { + _ConnectionData = instance as ConnectionData; + } + else + { + throw new InstanceIncorrectException(); + } return Task.CompletedTask; } + + public override Task CreateInstance() + { + return Task.FromResult(_ConnectionData); + } #endregion #region Commands @@ -38,37 +51,12 @@ namespace Borepin.PageModel.AddServerProcess } public async void AuthPlainCommandExecute() { - _Connection.AuthenticationTyp = AuthenticationTyp.PLAIN; + _ConnectionData.Mechanism = Mechanism.PLAIN; - INavigationParameters parameters = new NavigationParameters() + INavigationResult result = await _NavigationService.NavigateAsync("AddServerProcess_AuthPlainPage").ConfigureAwait(false); + if(result.Exception != null) { - {"instance", _Connection }, - }; - - await _NavigationService.NavigateAsync("AddServerProcess_AuthPlainPage", parameters).ConfigureAwait(false); - } - #endregion - - #region INavigationAware - public override void OnNavigatedTo(INavigationParameters parameters) - { - if (parameters.ContainsKey("instance") && parameters["instance"] is Connection) - { - _Connection = parameters["instance"] as Connection; - } - else - { - _Connection = new Connection(); - } - - LoadData(); - } - - public override void OnNavigatedFrom(INavigationParameters parameters) - { - if (parameters.GetNavigationMode() == NavigationMode.Back) - { - parameters.Add("instance", _Connection); + Log.Fatal(result.Exception, "Navigating failed"); } } #endregion diff --git a/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs b/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs index a8133d6..ba73052 100644 --- a/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs +++ b/Borepin/Borepin/PageModel/AddServerProcess/SelectServerPageModel.cs @@ -12,14 +12,14 @@ using System.Windows.Input; namespace Borepin.PageModel.AddServerProcess { - public class SelectServerPageModel : ConnectionModelBase + public class SelectServerPageModel : PageModelBase { #region Private Fields private ConnectionData _ConnectionData; #endregion #region Constructors - public SelectServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService) + public SelectServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService) : base(navigationService, pageDialogService) { ConnectToServerCommand = new DelegateCommand(async () => await ConnectToServerExecute().ConfigureAwait(false)); DetectLocalServerCommand = new DelegateCommand(DetectHostCommandExecute); @@ -98,7 +98,8 @@ namespace Borepin.PageModel.AddServerProcess try { - await _API.TestConnection(_ConnectionData).ConfigureAwait(true); + API api = new API(); + await api.TestConnection(_ConnectionData).ConfigureAwait(true); } catch(ConnectingFailedException) { diff --git a/Borepin/Borepin/PageModel/MachineListPageModel.cs b/Borepin/Borepin/PageModel/MachineListPageModel.cs index 50c7dcb..c4663a7 100644 --- a/Borepin/Borepin/PageModel/MachineListPageModel.cs +++ b/Borepin/Borepin/PageModel/MachineListPageModel.cs @@ -31,23 +31,11 @@ namespace Borepin.PageModel #endregion #region Data - public override async Task LoadData() + public override async Task LoadAPIData() { - if (! await CheckConnection().ConfigureAwait(false)) - { - IsConnected = false; + User user_self = await _API.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false); - IsBusy = false; - return; - } - - IsConnected = true; - - MachineSystem machineSystem = (await _BFFHService.GetSession().ConfigureAwait(false)).MachineSystem; - UserSystem userSystem = (await _BFFHService.GetSession().ConfigureAwait(false)).UserSystem; - User user_self = await userSystem.Info.GetUserSelf().ConfigureAwait(false); - - IReadOnlyList machine_list = await machineSystem.Info.GetMachineList().ConfigureAwait(false); + IReadOnlyList machine_list = await _API.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false); List viewmodel_list_user_assigned = new List(); List viewmodel_list_not_user_assigned = new List(); @@ -71,8 +59,6 @@ namespace Borepin.PageModel viewmodel_list_sorted.AddRange(viewmodel_list_user_assigned.OrderBy(x => x.Name, StringComparison.OrdinalIgnoreCase.WithNaturalSort())); viewmodel_list_sorted.AddRange(viewmodel_list_not_user_assigned.OrderBy(x => x.Name, StringComparison.OrdinalIgnoreCase.WithNaturalSort())); MachineListItemViewModel_List = viewmodel_list_sorted; - - IsBusy = false; } #endregion @@ -101,7 +87,11 @@ namespace Borepin.PageModel } public async Task RefreshCommandExecute() { - await LoadData().ConfigureAwait(true); + if(_API.IsConnected) + { + await LoadAPIData().ConfigureAwait(true); + } + IsRefreshing = false; } @@ -143,16 +133,14 @@ namespace Borepin.PageModel public async void ScanCode_Result(string value) { - if (! _BFFHService.IsConnected) + if (! _API.IsConnected) { IsConnected = false; IsBusy = false; return; } - MachineSystem machineInterface = (await _BFFHService.GetSession().ConfigureAwait(false)).MachineSystem; - - Machine machine = (await machineInterface.Info.GetMachineURN(value).ConfigureAwait(false)).Just; + Machine machine = (await _API.Session.MachineSystem.Info.GetMachineURN(value).ConfigureAwait(false)).Just; if(machine == null) { @@ -186,19 +174,5 @@ namespace Borepin.PageModel } #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override async void OnNavigatedTo(INavigationParameters parameters) - { - IsBusy = true; - - await LoadData().ConfigureAwait(false); - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/MachinePageModel.cs b/Borepin/Borepin/PageModel/MachinePageModel.cs index 19b6f91..9f2dfe5 100644 --- a/Borepin/Borepin/PageModel/MachinePageModel.cs +++ b/Borepin/Borepin/PageModel/MachinePageModel.cs @@ -30,8 +30,6 @@ namespace Borepin.PageModel #region Data public override Task LoadInstance(object instance) { - IsBusy = true; - if(instance is string) { _ID = instance as string; @@ -41,8 +39,6 @@ namespace Borepin.PageModel throw new InstanceIncorrectException(); } - IsBusy = false; - return Task.CompletedTask; } diff --git a/Borepin/Borepin/PageModel/MainPageModel.cs b/Borepin/Borepin/PageModel/MainPageModel.cs index 36afcd8..218a68e 100644 --- a/Borepin/Borepin/PageModel/MainPageModel.cs +++ b/Borepin/Borepin/PageModel/MainPageModel.cs @@ -1,9 +1,8 @@ -using System; -using System.Threading.Tasks; -using System.Windows.Input; +using System.Windows.Input; using Borepin.Base; using Borepin.Service.Versioning; using Prism.Navigation; +using Prism.Services; using Xamarin.Forms; namespace Borepin.PageModel @@ -15,21 +14,13 @@ namespace Borepin.PageModel #endregion #region Constructors - public MainPageModel(INavigationService navigationService, IVersioningService versioningService) : base(navigationService) + public MainPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IVersioningService versioningService) : base(navigationService, pageDialogService) { _VersioningService = versioningService; - - NavigateCommand = new Command(NavigateCommandExecute); - } - #endregion - - #region LoadData - public override Task LoadData() - { CurrentVersion = _VersioningService.CurrentVersion; CurrentBuild = _VersioningService.CurrentBuild; - return Task.CompletedTask; + NavigateCommand = new Command(NavigateCommandExecute); } #endregion @@ -58,19 +49,11 @@ namespace Borepin.PageModel } public async void NavigateCommandExecute(string view) { - await _NavigationService.NavigateAsync($"NavigationPage/{ view }").ConfigureAwait(false); - } - #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override async void OnNavigatedTo(INavigationParameters parameters) - { - await LoadData().ConfigureAwait(false); + INavigationResult result = await _NavigationService.NavigateAsync($"NavigationPage/{ view }").ConfigureAwait(false); + if(result.Exception != null) + { + Log.Fatal(result.Exception, "Navigating failed"); + } } #endregion } diff --git a/Borepin/Borepin/PageModel/ScanPageModel.cs b/Borepin/Borepin/PageModel/ScanPageModel.cs index 139da66..b1de8a4 100644 --- a/Borepin/Borepin/PageModel/ScanPageModel.cs +++ b/Borepin/Borepin/PageModel/ScanPageModel.cs @@ -1,6 +1,7 @@ using Borepin.Base; using Prism.Commands; using Prism.Navigation; +using Prism.Services; using System; using System.Threading.Tasks; using System.Windows.Input; @@ -16,7 +17,7 @@ namespace Borepin.PageModel #endregion #region Contructors - public ScanPageModel(INavigationService navigationService) : base(navigationService) + public ScanPageModel(INavigationService navigationService, IPageDialogService pageDialogService) : base(navigationService, pageDialogService) { AbortCommand = new DelegateCommand(async () => await AbortCommandExecute().ConfigureAwait(true)); ScannedCommand = new DelegateCommand(ScannedCommandExecute); @@ -27,9 +28,15 @@ namespace Borepin.PageModel #endregion #region Data - public override async Task LoadData() + public override Task LoadInstance(object instance) { - await Task.CompletedTask.ConfigureAwait(false); + _Instance = instance; + return Task.CompletedTask; + } + + public override Task CreateInstance() + { + return Task.FromResult(_Instance); } #endregion @@ -73,7 +80,6 @@ namespace Borepin.PageModel { { "result", "scanned" }, { "value", ScanResult.Text }, - { "instance", _Instance }, }; Device.BeginInvokeOnMainThread(async () => @@ -96,22 +102,9 @@ namespace Borepin.PageModel INavigationParameters parameters = new NavigationParameters() { { "result", "abort" }, - { "instance", _Instance }, }; await _NavigationService.GoBackAsync(parameters).ConfigureAwait(false); } #endregion - - #region INavigationService - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override void OnNavigatedTo(INavigationParameters parameters) - { - _Instance = parameters.GetValue("instance"); - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/ServerListPageModel.cs b/Borepin/Borepin/PageModel/ServerListPageModel.cs index b030e80..9e6959c 100644 --- a/Borepin/Borepin/PageModel/ServerListPageModel.cs +++ b/Borepin/Borepin/PageModel/ServerListPageModel.cs @@ -9,6 +9,7 @@ using Borepin.Base; using Borepin.Service.Storage; using FabAccessAPI; using Borepin.Service; +using Prism.Services; namespace Borepin.PageModel { @@ -20,7 +21,7 @@ namespace Borepin.PageModel #endregion #region Constructors - public ServerListPageModel(INavigationService navigationService, ILoginStorageService loginStorageService, IAPIService apiService) : base(navigationService) + public ServerListPageModel(INavigationService navigationService, IPageDialogService pageDialogService, ILoginStorageService loginStorageService, IAPIService apiService) : base(navigationService, pageDialogService) { _LoginStorageService = loginStorageService; _API = apiService.GetAPI(); @@ -106,17 +107,5 @@ namespace Borepin.PageModel await _NavigationService.NavigateAsync("AddServerProcess_SelectServerPage").ConfigureAwait(false); } #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override async void OnNavigatedTo(INavigationParameters parameters) - { - await LoadData().ConfigureAwait(false); - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/ServerPageModel.cs b/Borepin/Borepin/PageModel/ServerPageModel.cs index a268796..4349251 100644 --- a/Borepin/Borepin/PageModel/ServerPageModel.cs +++ b/Borepin/Borepin/PageModel/ServerPageModel.cs @@ -1,5 +1,7 @@ using Borepin.Base; +using Borepin.Base.Exceptions; using Borepin.Service; +using Borepin.Service.Storage; using FabAccessAPI; using FabAccessAPI.Exceptions; using Prism.Commands; @@ -17,12 +19,14 @@ namespace Borepin.PageModel { #region Private Fields private readonly IDialogService _DialogService; + private readonly ILoginStorageService _LoginStorageService; #endregion #region Constructors - public ServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService, IDialogService dialogService,) : base(navigationService, pageDialogService, apiService) + public ServerPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService, IDialogService dialogService, ILoginStorageService loginStorageService) : base(navigationService, pageDialogService, apiService) { _DialogService = dialogService; + _LoginStorageService = loginStorageService; ConnectCommand = new DelegateCommand(async () => await ConnectCommandExecute().ConfigureAwait(false)); DisconnectCommand = new DelegateCommand(async () => await DisonnectCommandExecute().ConfigureAwait(false)); @@ -31,20 +35,29 @@ namespace Borepin.PageModel #endregion #region Data - public override Task LoadData() + public override Task LoadInstance(object instance) { - if (_BFFHService.CurrentConnection != null && Connection_Item != null) + if(instance is ConnectionData) { - InstanceIsActiveConnection = Connection_Item.Equals(_BFFHService.CurrentConnection); + Connection_Item = instance as ConnectionData; + } + else + { + throw new InstanceIncorrectException(); + } + + if (_API.ConnectionData != null && Connection_Item != null) + { + InstanceIsActiveConnection = Connection_Item.Equals(_API.ConnectionData); } else { InstanceIsActiveConnection = false; } - if(_Connection_Item != null && _Connection_Item.Address != null) + if(_Connection_Item != null && _Connection_Item.Host != null) { - DisplayAddress = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", _Connection_Item.Address.Host, _Connection_Item.Address.Port); + DisplayAddress = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", _Connection_Item.Host.Host, _Connection_Item.Host.Port); } IsBusy = false; @@ -110,7 +123,11 @@ namespace Borepin.PageModel return; } - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage").ConfigureAwait(false); + INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage").ConfigureAwait(false); + if(result.Exception != null) + { + Log.Fatal(result.Exception, "Navigating failed"); + } } private ICommand _DisconnectCommand; @@ -123,7 +140,7 @@ namespace Borepin.PageModel { await _API.Disconnect().ConfigureAwait(false); - await LoadData().ConfigureAwait(false); + await LoadInstance(Connection_Item).ConfigureAwait(false); } private ICommand _DeleteCommand; @@ -149,11 +166,15 @@ namespace Borepin.PageModel { if(string.Equals(result.Parameters.GetValue("result"), "confirm", StringComparison.Ordinal)) { - Connection connection = result.Parameters.GetValue("instance"); + ConnectionData connectionData = result.Parameters.GetValue("instance"); - await _BFFHService.RemoveConnection(connection).ConfigureAwait(false); + await _LoginStorageService.Remove(connectionData).ConfigureAwait(false); - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/ServerListPage").ConfigureAwait(false); + INavigationResult result_nav = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/ServerListPage").ConfigureAwait(false); + if(result_nav.Exception != null) + { + Log.Fatal(result.Exception, "Navigating failed"); + } } } #endregion diff --git a/Borepin/Borepin/PageModel/SetUpProcess/WelcomePageModel.cs b/Borepin/Borepin/PageModel/SetUpProcess/WelcomePageModel.cs index ff4e8a4..2f82a3b 100644 --- a/Borepin/Borepin/PageModel/SetUpProcess/WelcomePageModel.cs +++ b/Borepin/Borepin/PageModel/SetUpProcess/WelcomePageModel.cs @@ -1,7 +1,7 @@ using Borepin.Base; using Prism.Commands; using Prism.Navigation; -using System; +using Prism.Services; using System.Threading.Tasks; using System.Windows.Input; @@ -10,19 +10,12 @@ namespace Borepin.PageModel.SetUpProcess public class WelcomePageModel : PageModelBase { #region Constructors - public WelcomePageModel(INavigationService navigationService) : base(navigationService) + public WelcomePageModel(INavigationService navigationService, IPageDialogService pageDialogService) : base(navigationService, pageDialogService) { NextCommand = new DelegateCommand(NextCommandCommandExecute); } #endregion - #region Data - public override Task LoadData() - { - return Task.CompletedTask; - } - #endregion - #region Commands private ICommand _NextCommand; public ICommand NextCommand @@ -35,17 +28,5 @@ namespace Borepin.PageModel.SetUpProcess await _NavigationService.NavigateAsync("AddServerProcess_SelectServerPage").ConfigureAwait(false); } #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override void OnNavigatedTo(INavigationParameters parameters) - { - - } - #endregion } } diff --git a/Borepin/Borepin/PageModel/StartPageModel.cs b/Borepin/Borepin/PageModel/StartPageModel.cs index 20f72d5..8c07818 100644 --- a/Borepin/Borepin/PageModel/StartPageModel.cs +++ b/Borepin/Borepin/PageModel/StartPageModel.cs @@ -1,51 +1,45 @@ using Borepin.Base; -using Borepin.Model; -using Borepin.Service.BFFH; +using Borepin.Service.Storage; +using FabAccessAPI; using Prism.AppModel; using Prism.Navigation; +using Prism.Services; using System.Collections.Generic; -using System.Threading.Tasks; namespace Borepin.PageModel { - public class StartPageModel : PageModelBase, IPageLifecycleAware, IInitialize + public class StartPageModel : PageModelBase, IPageLifecycleAware { #region Private Fields - private readonly IBFFHService _BFFHService; + private readonly ILoginStorageService _LoginStorageService; #endregion #region Constructors - public StartPageModel(INavigationService navigationService, IBFFHService bffhService) : base(navigationService) + public StartPageModel(INavigationService navigationService, IPageDialogService pageDialogService, ILoginStorageService loginStorageService) : base(navigationService, pageDialogService) { - _BFFHService = bffhService; - } - #endregion - - #region LoadData - public override Task LoadData() - { - return Task.CompletedTask; - } - #endregion - - #region IInitialize - public void Initialize(INavigationParameters parameters) - { - + _LoginStorageService = loginStorageService; } #endregion #region IPageLifecycleAware public async void OnAppearing() { - IList connection_list = await _BFFHService.GetConnections().ConfigureAwait(false); - if (connection_list.Count == 0) + IList connectionData_List = await _LoginStorageService.GetList().ConfigureAwait(false); + if (connectionData_List.Count == 0) { - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/SetUpProcess_WelcomePage").ConfigureAwait(false); + INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/SetUpProcess_WelcomePage").ConfigureAwait(false); + if (result.Exception != null) + { + Log.Fatal(result.Exception, "Navigating failed"); + } } else { - await _NavigationService.NavigateAsync("/MainPage/NavigationPage/ServerListPage").ConfigureAwait(false); + INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/ServerListPage").ConfigureAwait(false); + if (result.Exception != null) + { + Log.Fatal(result.Exception, "Navigating failed"); + } } } @@ -54,17 +48,5 @@ namespace Borepin.PageModel } #endregion - - #region INavigationAware - public override void OnNavigatedFrom(INavigationParameters parameters) - { - - } - - public override void OnNavigatedTo(INavigationParameters parameters) - { - - } - #endregion } } diff --git a/Borepin_Test/Borepin_Test.csproj b/Borepin_Test/Borepin_Test.csproj index 9a58262..91d2aa3 100644 --- a/Borepin_Test/Borepin_Test.csproj +++ b/Borepin_Test/Borepin_Test.csproj @@ -5,7 +5,7 @@ - + diff --git a/FabAccessAPI/FabAccessAPI.csproj b/FabAccessAPI/FabAccessAPI.csproj index ba24ff4..4baf904 100644 --- a/FabAccessAPI/FabAccessAPI.csproj +++ b/FabAccessAPI/FabAccessAPI.csproj @@ -13,7 +13,7 @@ - + diff --git a/FabAccessAPI_Test/API_Test.cs b/FabAccessAPI_Test/API_Test.cs index 2cabfed..fdc0c7d 100644 --- a/FabAccessAPI_Test/API_Test.cs +++ b/FabAccessAPI_Test/API_Test.cs @@ -1,5 +1,4 @@ - -using Capnp.Rpc; +using Capnp.Rpc; using FabAccessAPI; using FabAccessAPI.Exceptions; using NUnit.Framework; @@ -24,10 +23,7 @@ namespace FabAccessAPI_Test Username = "UnkownUser", Properties = new Dictionary() { - { "Username", "UnkownUser" } - }, - SecretProperties = new Dictionary() - { + { "Username", "UnkownUser" }, { "Password", TestEnv.PASSWORD } } }; diff --git a/FabAccessAPI_Test/FabAccessAPI_Test.csproj b/FabAccessAPI_Test/FabAccessAPI_Test.csproj index d867fe2..87292d1 100644 --- a/FabAccessAPI_Test/FabAccessAPI_Test.csproj +++ b/FabAccessAPI_Test/FabAccessAPI_Test.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -10,7 +10,7 @@ - + diff --git a/FabAccessAPI_Test/TestEnv.cs b/FabAccessAPI_Test/TestEnv.cs index 538b8fc..d331553 100644 --- a/FabAccessAPI_Test/TestEnv.cs +++ b/FabAccessAPI_Test/TestEnv.cs @@ -20,12 +20,9 @@ namespace FabAccessAPI_Test Username = username, Properties = new Dictionary() { - { "Username", username } + { "Username", username }, + { "Password", TestEnv.PASSWORD }, }, - SecretProperties = new Dictionary() - { - { "Password", TestEnv.PASSWORD } - } }; return connectionData; From ec48a8b9939d2bbac1064cfd854cf804fb5eab99 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 17 May 2022 15:03:39 +0200 Subject: [PATCH 08/25] First working App with new API Class --- Borepin/Borepin/App.xaml.cs | 1 - Borepin/Borepin/Borepin.csproj | 4 +- Borepin/Borepin/Helpers/TranslateExtension.cs | 45 --------------- .../MultilingualResources/Borepin.de.xlf | 40 ------------- .../MultilingualResources/Borepin.en.xlf | 40 ------------- .../AddServerProcess/SelectServerPage.xaml | 2 +- .../Page/SetUpProcess/WelcomePage.xaml | 8 +-- .../AddServerProcess/AuthPlainPageModel.cs | 29 +++++++--- .../AddServerProcess/SelectServerPageModel.cs | 1 - .../Borepin/PageModel/MachineListPageModel.cs | 2 +- .../Borepin/PageModel/ServerListPageModel.cs | 4 +- Borepin/Borepin/PageModel/ServerPageModel.cs | 14 +++-- Borepin/Borepin/PageModel/StartPageModel.cs | 23 +++++--- .../Resources/Text/TextResource.Designer.cs | 57 ++++++++++++------- .../Resources/Text/TextResource.en.resx | 15 ----- .../Borepin/Resources/Text/TextResource.resx | 3 - .../Service/Storage/LoginStorageService.cs | 19 +++++-- FabAccessAPI/ConnectionData.cs | 16 ++++-- 18 files changed, 119 insertions(+), 204 deletions(-) delete mode 100644 Borepin/Borepin/Helpers/TranslateExtension.cs delete mode 100644 Borepin/Borepin/MultilingualResources/Borepin.de.xlf delete mode 100644 Borepin/Borepin/MultilingualResources/Borepin.en.xlf delete mode 100644 Borepin/Borepin/Resources/Text/TextResource.en.resx diff --git a/Borepin/Borepin/App.xaml.cs b/Borepin/Borepin/App.xaml.cs index 4fc87c3..76e7c3e 100644 --- a/Borepin/Borepin/App.xaml.cs +++ b/Borepin/Borepin/App.xaml.cs @@ -10,7 +10,6 @@ using Borepin.PageModel.SetUpProcess; using Borepin.Page.AddServerProcess; using Borepin.PageModel.AddServerProcess; using System; -using Prism.Navigation; using Borepin.Service.Storage; namespace Borepin diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 97ed6e0..0307902 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -21,8 +21,11 @@ + + + @@ -32,7 +35,6 @@ - diff --git a/Borepin/Borepin/Helpers/TranslateExtension.cs b/Borepin/Borepin/Helpers/TranslateExtension.cs deleted file mode 100644 index 77139d0..0000000 --- a/Borepin/Borepin/Helpers/TranslateExtension.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Plugin.Multilingual; -using System; -using System.Reflection; -using System.Resources; -using Xamarin.Forms; -using Xamarin.Forms.Xaml; - -namespace Borepin.Helpers -{ - [ContentProperty("Text")] - public class TranslateExtension : IMarkupExtension - { - const string _ResourceId = "Borepin.Resources.Text.TextResource"; - - static readonly Lazy _Resmgr = new Lazy(() => new ResourceManager(_ResourceId, typeof(TranslateExtension).GetTypeInfo().Assembly)); - - public string Text { get; set; } - - public object ProvideValue(IServiceProvider serviceProvider) - { - if (Text == null) - { - return ""; - } - - System.Globalization.CultureInfo ci = CrossMultilingual.Current.CurrentCultureInfo; - - string translation = _Resmgr.Value.GetString(Text, ci); - - if (translation == null) - { - -#if DEBUG - //throw new ArgumentException( - // String.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name), - // "Text"); - translation = "!MISSING TEXT!"; -#else - translation = Text; // returns the key, which GETS DISPLAYED TO THE USER -#endif - } - return translation; - } - } -} diff --git a/Borepin/Borepin/MultilingualResources/Borepin.de.xlf b/Borepin/Borepin/MultilingualResources/Borepin.de.xlf deleted file mode 100644 index ee215de..0000000 --- a/Borepin/Borepin/MultilingualResources/Borepin.de.xlf +++ /dev/null @@ -1,40 +0,0 @@ - - - -
- -
- - - -
- -
- -
- - - - Automate your Space with FabAccess - Automate your Space with FabAccess - - - Welcome - Welcome - - - Begin working - Begin working - - - Login to your Space - Login to your Space - - - Wenn du dieses Logo siehst, dann kannst du es scannen - Wenn du dieses Logo siehst, dann kannst du es scannen - - - -
-
\ No newline at end of file diff --git a/Borepin/Borepin/MultilingualResources/Borepin.en.xlf b/Borepin/Borepin/MultilingualResources/Borepin.en.xlf deleted file mode 100644 index ae8fdc1..0000000 --- a/Borepin/Borepin/MultilingualResources/Borepin.en.xlf +++ /dev/null @@ -1,40 +0,0 @@ - - - -
- -
- - - -
- -
- -
- - - - Automate your Space with FabAccess - Automate your Space with FabAccess - - - Welcome - Welcome - - - Begin working - Begin working - - - Login to your Space - Login to your Space - - - Wenn du dieses Logo siehst, dann kannst du es scannen - Wenn du dieses Logo siehst, dann kannst du es scannen - - - -
-
\ No newline at end of file diff --git a/Borepin/Borepin/Page/AddServerProcess/SelectServerPage.xaml b/Borepin/Borepin/Page/AddServerProcess/SelectServerPage.xaml index ed588ac..fef59c0 100644 --- a/Borepin/Borepin/Page/AddServerProcess/SelectServerPage.xaml +++ b/Borepin/Borepin/Page/AddServerProcess/SelectServerPage.xaml @@ -16,7 +16,7 @@ - +