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; + } } }