mirror of
https://gitlab.com/fabinfra/fabaccess/borepin.git
synced 2025-03-12 14:51:44 +01:00
Start interagtion of new API Class
This commit is contained in:
parent
0d5ad01496
commit
4f3521eec3
@ -87,6 +87,10 @@
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj">
|
||||
<Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project>
|
||||
<Name>FabAccessAPI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Borepin\Borepin.csproj">
|
||||
<Project>{F93856BD-0C8D-4469-A8DB-6E513002BFD7}</Project>
|
||||
<Name>Borepin</Name>
|
||||
|
@ -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<IPreferenceStorageService, PreferenceStorageService>();
|
||||
containerRegistry.Register<ISecretStorageService, SecretStorage>();
|
||||
containerRegistry.Register<IVersioningService, VersioningService>();
|
||||
|
||||
containerRegistry.RegisterSingleton<IAPI, API>();
|
||||
}
|
||||
}
|
||||
}
|
@ -184,6 +184,10 @@
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.7.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj">
|
||||
<Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project>
|
||||
<Name>FabAccessAPI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Borepin\Borepin.csproj">
|
||||
<Project>{64ED6CAA-99A0-4EC4-B976-DCBD571F05D7}</Project>
|
||||
<Name>Borepin</Name>
|
||||
|
@ -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<IPreferenceStorageService, PreferenceStorageService>();
|
||||
containerRegistry.Register<ISecretStorageService, SecretStorageService>();
|
||||
containerRegistry.Register<IVersioningService, VersioningService>();
|
||||
|
||||
containerRegistry.RegisterSingleton<IAPI, API>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,10 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj">
|
||||
<Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project>
|
||||
<Name>FabAccessAPI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Borepin\Borepin.csproj">
|
||||
<Project>{F93856BD-0C8D-4469-A8DB-6E513002BFD7}</Project>
|
||||
<Name>Borepin</Name>
|
||||
|
@ -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<IPreferenceStorageService, PreferenceStorageService>();
|
||||
containerRegistry.Register<ISecretStorageService, SecretStorageService>();
|
||||
containerRegistry.Register<IVersioningService, VersioningService>();
|
||||
|
||||
containerRegistry.RegisterSingleton<IAPI, API>();
|
||||
}
|
||||
}
|
||||
}
|
@ -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<IBFFHService, BFFHService>();
|
||||
containerRegistry.RegisterSingleton<ILoginStorageService, LoginStorageService>();
|
||||
|
||||
// NEED PLATFORM SPECIFIC SERVICE
|
||||
// IPreferenceStorageService
|
||||
// ISecretStorageService
|
||||
// IVersioningService
|
||||
// IAPI
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
namespace Borepin.Model
|
||||
{
|
||||
public enum AuthenticationTyp
|
||||
{
|
||||
PLAIN,
|
||||
}
|
||||
}
|
@ -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; } = "";
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Borepin.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to contain all Information about a Connection
|
||||
/// </summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// Type of Connection
|
||||
/// </summary>
|
||||
public ConnectionTyp ConnectionTyp { get; set; } = ConnectionTyp.SINGLE;
|
||||
|
||||
/// <summary>
|
||||
/// Type of Authentication
|
||||
/// </summary>
|
||||
public AuthenticationTyp AuthenticationTyp { get; set; } = AuthenticationTyp.PLAIN;
|
||||
|
||||
/// <summary>
|
||||
/// Address to Host
|
||||
/// </summary>
|
||||
public Uri Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Username for Connection
|
||||
/// </summary>
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Last Timestamp connection was successfully established
|
||||
/// </summary>
|
||||
public DateTime LastTime { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
#region Equals and HashCode
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is Connection connection &&
|
||||
EqualityComparer<Uri>.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<Uri>.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
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace Borepin.Model
|
||||
{
|
||||
public enum ConnectionTyp
|
||||
{
|
||||
SINGLE,
|
||||
FEDERATED,
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
namespace Borepin.Model
|
||||
{
|
||||
public class Connection_Plain : Connection
|
||||
{
|
||||
#region Constructors
|
||||
public Connection_Plain(Connection connection) : base(connection)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
/// <summary>
|
||||
/// Password for Connection
|
||||
/// </summary>
|
||||
public string Password { get; set; } = "";
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace Borepin.Model
|
||||
{
|
||||
public class ListItem
|
||||
{
|
||||
public string Value1 { get; set; }
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Store Credentials for Connection in SecureStorageService
|
||||
/// </summary>
|
||||
public class ConnectionCredentialStorage
|
||||
{
|
||||
#region Private Fields
|
||||
private readonly ISecretStorageService _SecretStorageService;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public ConnectionCredentialStorage(ISecretStorageService secretService)
|
||||
{
|
||||
_SecretStorageService = secretService;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Get Password for Connection from SecureStorageService
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
/// <exception cref="MissingConnectionException"></exception>
|
||||
public async Task<string> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Password for Connection to SecureStorageService
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove Password for Connection from SecureStorageService
|
||||
/// </summary>
|
||||
public Task RemoveCredentials(Connection connection)
|
||||
{
|
||||
_SecretStorageService.Remove(string.Format(CultureInfo.InvariantCulture, "bffh_password_{0}_{1}", connection.Address.ToString(), connection.Username));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all Connections from SecureStorage
|
||||
/// </summary>
|
||||
public Task RemoveAllCredentials()
|
||||
{
|
||||
_SecretStorageService.RemoveAll();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Store Connection in PreferenceStorageService
|
||||
/// </summary>
|
||||
public class ConnectionStorage
|
||||
{
|
||||
#region Private Fields
|
||||
private readonly IPreferenceStorageService _PreferenceService;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public ConnectionStorage(IPreferenceStorageService preferenceService)
|
||||
{
|
||||
_PreferenceService = preferenceService;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Get Connection List from Storage
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<IList<Connection>> GetConnectionList()
|
||||
{
|
||||
return Task.FromResult(_LoadConnectionFormStorage());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Connection to Storage
|
||||
/// </summary>
|
||||
/// <exception cref="DuplicateConnectionException"></exception>
|
||||
public Task<bool> AddConnection(Connection connection)
|
||||
{
|
||||
IList<Connection> connection_list = _LoadConnectionFormStorage();
|
||||
|
||||
if (connection_list.Contains(connection))
|
||||
{
|
||||
throw new DuplicateConnectionException();
|
||||
}
|
||||
|
||||
connection_list.Add(connection);
|
||||
|
||||
_SaveConnectionToStorage(connection_list);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove Connection from Storage
|
||||
/// </summary>
|
||||
public Task<bool> RemoveConnection(Connection connection)
|
||||
{
|
||||
IList<Connection> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove All Connection from Storage
|
||||
/// </summary>
|
||||
public Task<bool> RemoveAllConnections()
|
||||
{
|
||||
_SaveConnectionToStorage(new List<Connection>());
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update Connections Timestamp in Storage
|
||||
/// </summary>
|
||||
/// <exception cref="MissingConnectionException"></exception>
|
||||
public Task<bool> UpdateConnectionTimestamp(Connection connection)
|
||||
{
|
||||
IList<Connection> 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<Connection> _LoadConnectionFormStorage()
|
||||
{
|
||||
List<Connection> connection_list;
|
||||
try
|
||||
{
|
||||
connection_list = JsonConvert.DeserializeObject<List<Connection>>(_PreferenceService.Get("connection_list", "[]"));
|
||||
}
|
||||
catch (JsonSerializationException)
|
||||
{
|
||||
connection_list = new List<Connection>();
|
||||
_PreferenceService.Set("connection_list", JsonConvert.SerializeObject(connection_list));
|
||||
}
|
||||
|
||||
return connection_list;
|
||||
}
|
||||
|
||||
private void _SaveConnectionToStorage(IList<Connection> connection_list)
|
||||
{
|
||||
_PreferenceService.Set("connection_list", JsonConvert.SerializeObject(connection_list));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// API Connection
|
||||
/// </summary>
|
||||
public API API { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Method
|
||||
/// <summary>
|
||||
/// Get all known Connections from Storage
|
||||
/// </summary>
|
||||
public async Task<IList<Connection>> GetConnections()
|
||||
{
|
||||
return await _ConnectionStorage.GetConnectionList().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove Connection from Storage
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test a if a Server is reachable
|
||||
/// </summary>
|
||||
public async Task<bool> TestConnection(Connection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpRpcClient rpcClient = await _ConnectAsync(connection.Address.Host, connection.Address.Port).ConfigureAwait(false);
|
||||
rpcClient.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to Server with Credential from ConnectionCredentialStorage
|
||||
/// </summary>
|
||||
/// <exception cref="AllreadyConnectedException"></exception>
|
||||
/// <exception cref="MissingCredentialsException"></exception>
|
||||
/// <exception cref="ConnectingFailedException"></exception>
|
||||
/// <exception cref="AuthenticatingFailedException"></exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to Server with Password
|
||||
/// Connection is saved to Storage if connecting was successfuss
|
||||
/// </summary>
|
||||
/// <exception cref="AllreadyConnectedException"></exception>
|
||||
/// <exception cref="MissingCredentialsException"></exception>
|
||||
/// <exception cref="ConnectingFailedException"></exception>
|
||||
/// <exception cref="AuthenticatingFailedException"></exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reconnects to server if connection has lost
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
/// <exception cref="ReconnectingFailedException"></exception>
|
||||
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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects from Server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task Disconnect()
|
||||
{
|
||||
if (IsConnected)
|
||||
{
|
||||
_APIConnection.RpcClient?.Dispose();
|
||||
}
|
||||
|
||||
_APIConnection = null;
|
||||
_CurrentConnection = null;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#region FabAccess API Systems
|
||||
public async Task<Session> 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<TcpRpcClient> _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<bool> _AuthenticatePlainAsync(string username, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _APIConnection.Auth("PLAIN", new Dictionary<string, object>(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
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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<IList<Connection>> GetConnections();
|
||||
|
||||
Task RemoveConnection(Connection connection);
|
||||
Task<bool> TestConnection(Connection connection);
|
||||
|
||||
|
||||
Task Connect(Connection connection);
|
||||
Task Connect(Connection connection, string password);
|
||||
Task Reconnect();
|
||||
Task Disconnect();
|
||||
|
||||
|
||||
Task<Session> GetSession();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
Borepin/Borepin/Service/Storage/ILoginStorageService.cs
Normal file
14
Borepin/Borepin/Service/Storage/ILoginStorageService.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using FabAccessAPI;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Borepin.Service.Storage
|
||||
{
|
||||
public interface ILoginStorageService
|
||||
{
|
||||
Task<IList<ConnectionData>> GetList();
|
||||
Task Add(ConnectionData connectionData);
|
||||
Task Remove(ConnectionData connectionData);
|
||||
Task UpdateTimestamp(ConnectionData connectionData);
|
||||
}
|
||||
}
|
112
Borepin/Borepin/Service/Storage/LoginStorageService.cs
Normal file
112
Borepin/Borepin/Service/Storage/LoginStorageService.cs
Normal file
@ -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<IList<ConnectionData>> 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> 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> 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> 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<IList<ConnectionData>> _LoadConnectionData()
|
||||
{
|
||||
List<ConnectionData> connectionData_List;
|
||||
try
|
||||
{
|
||||
string data = await _SecretStorageService.GetAsync(StorageKey).ConfigureAwait(false);
|
||||
connectionData_List = JsonConvert.DeserializeObject<List<ConnectionData>>(data);
|
||||
}
|
||||
catch (JsonSerializationException)
|
||||
{
|
||||
connectionData_List = new List<ConnectionData>();
|
||||
await _SecretStorageService.SetAsync(StorageKey, JsonConvert.SerializeObject(connectionData_List)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return connectionData_List;
|
||||
}
|
||||
|
||||
private async Task _SaveConnectionData(IList<ConnectionData> connectionData_List)
|
||||
{
|
||||
string data = JsonConvert.SerializeObject(connectionData_List);
|
||||
await _SecretStorageService.SetAsync(StorageKey, data).ConfigureAwait(false);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -119,11 +119,7 @@ namespace FabAccessAPI
|
||||
ConnectionData = null;
|
||||
ConnectionInfo = null;
|
||||
|
||||
EventHandler<ConnectionStatusChange> 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<ConnectionStatusChange> eventHandler = ConnectionStatusChanged;
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(this, ConnectionStatusChange.Reconnected);
|
||||
}
|
||||
ConnectionStatusChanged?.Invoke(this, ConnectionStatusChange.Reconnected);
|
||||
}
|
||||
|
||||
public async Task<ConnectionInfo> TestConnection(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null)
|
||||
@ -172,7 +164,7 @@ namespace FabAccessAPI
|
||||
/// Validate Certificate
|
||||
/// TODO: Do some validation
|
||||
/// </summary>
|
||||
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
|
||||
/// <exception cref="AuthenticationFailedException"></exception>
|
||||
private async Task<Session> _Authenticate(ConnectionData connectionData)
|
||||
{
|
||||
Dictionary<string, object> joinedProperties = new Dictionary<string, object>();
|
||||
foreach(KeyValuePair<string, object> keyValuePair in connectionData.Properties)
|
||||
{
|
||||
joinedProperties.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
foreach (KeyValuePair<string, object> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -257,7 +239,7 @@ namespace FabAccessAPI
|
||||
/// <exception cref="BadMechanismException"></exception>
|
||||
/// <exception cref="InvalidCredentialsException"></exception>
|
||||
/// <exception cref="AuthenticationFailedException"></exception>
|
||||
public async Task<Session> _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary<string, object> properties)
|
||||
private async Task<Session> _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary<string, object> properties)
|
||||
{
|
||||
SaslMechanism? saslMechanism = SaslFactory.Create(mech);
|
||||
foreach (KeyValuePair<string, object> entry in properties)
|
||||
|
@ -9,7 +9,25 @@ namespace FabAccessAPI
|
||||
public Mechanism Mechanism;
|
||||
public string Username;
|
||||
public Dictionary<string, object> Properties;
|
||||
public Dictionary<string, object> SecretProperties;
|
||||
public DateTime LastTime;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ConnectionData data &&
|
||||
EqualityComparer<Uri>.Default.Equals(Host, data.Host) &&
|
||||
Mechanism == data.Mechanism &&
|
||||
Username == data.Username &&
|
||||
EqualityComparer<Dictionary<string, object>>.Default.Equals(Properties, data.Properties);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hashCode = -1151110446;
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<Uri>.Default.GetHashCode(Host);
|
||||
hashCode = hashCode * -1521134295 + Mechanism.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Username);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<Dictionary<string, object>>.Default.GetHashCode(Properties);
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user