diff --git a/BTCPayApp.Desktop/DesktopDataDirectoryProvider.cs b/BTCPayApp.Desktop/DesktopDataDirectoryProvider.cs new file mode 100644 index 0000000..4f16736 --- /dev/null +++ b/BTCPayApp.Desktop/DesktopDataDirectoryProvider.cs @@ -0,0 +1,51 @@ +using BTCPayApp.Core.Contracts; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace BTCPayApp.Desktop; + +public class DesktopDataDirectoryProvider : IDataDirectoryProvider +{ + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + + public DesktopDataDirectoryProvider(IConfiguration configuration, ILogger logger) + { + _configuration = configuration; + _logger = logger; + } + + private string? _result = null; + public virtual Task GetAppDataDirectory() + { + if (_result != null) + return Task.FromResult(_result); + var def = "BTCPayApp"; + var dirName = _configuration.GetValue("BTCPAYAPP_DIRNAME", def); + _result = GetDirectory(dirName?? def); + _logger.LogInformation($"Using data directory: {_result}"); + return Task.FromResult(_result); + } + + private string GetDirectory(string appDirectory) + { + var environmentVariable1 = _configuration.GetValue("HOME"); + var environmentVariable2 = _configuration.GetValue("APPDATA"); + string str; + if (!string.IsNullOrEmpty(environmentVariable1) && string.IsNullOrEmpty(environmentVariable2)) + str = Path.Combine(environmentVariable1, "." + appDirectory.ToLowerInvariant()); + else if (!string.IsNullOrEmpty(environmentVariable2)) + { + str = Path.Combine(environmentVariable2, appDirectory); + } + else + { + throw new DirectoryNotFoundException( + "Could not find suitable datadir environment variables HOME or APPDATA are not set"); + } + + if (!Directory.Exists(str)) + Directory.CreateDirectory(str); + return str; + } +} \ No newline at end of file diff --git a/BTCPayApp.Desktop/DesktopSecureConfigProvider.cs b/BTCPayApp.Desktop/DesktopSecureConfigProvider.cs new file mode 100644 index 0000000..4e8aa84 --- /dev/null +++ b/BTCPayApp.Desktop/DesktopSecureConfigProvider.cs @@ -0,0 +1,66 @@ +using System.Text.Json; +using BTCPayApp.Core.Contracts; +using Microsoft.AspNetCore.DataProtection; + +namespace BTCPayApp.Desktop; + +public class DesktopSecureConfigProvider: ISecureConfigProvider +{ + private readonly IDataProtector _dataProtector; + + public DesktopSecureConfigProvider(IDataDirectoryProvider directoryProvider, IDataProtectionProvider dataProtectionProvider) + { + _dataProtector = dataProtectionProvider.CreateProtector("SecureConfig"); + _configDir = directoryProvider.GetAppDataDirectory().ContinueWith(task => + { + var res = Path.Combine(task.Result, "config"); + Directory.CreateDirectory(res); + return res; + }); + } + + private readonly Task _configDir; + + public async Task Get(string key) + { + var dir = Path.Combine(await _configDir, key); + if (!File.Exists(dir)) + { + return default; + } + var raw = await File.ReadAllTextAsync(dir); + var json = await ReadFromRaw(raw); + return JsonSerializer.Deserialize(json); + } + + + public async Task Set(string key, T? value) + { + var dir = Path.Combine(await _configDir, key); + if (value is null) + { + if (File.Exists(dir)) + { + File.Delete(dir); + } + } + else + { + var raw = JsonSerializer.Serialize(value); + await File.WriteAllTextAsync(dir, await WriteFromRaw(raw)); + } + } + + public async Task> List(string prefix) + { + var dir = await _configDir; + if (!Directory.Exists(dir)) + { + return Array.Empty(); + } + return Directory.GetFiles(dir, $"{prefix}*").Select(Path.GetFileName).Where(p => p?.StartsWith(prefix) is true)!; + } + + protected Task ReadFromRaw(string str) => Task.FromResult(_dataProtector.Unprotect(str)); + protected Task WriteFromRaw(string str) => Task.FromResult(_dataProtector.Protect(str)); +} \ No newline at end of file diff --git a/BTCPayApp.Desktop/StartupExtensions.cs b/BTCPayApp.Desktop/StartupExtensions.cs index d84dbc2..027ce96 100644 --- a/BTCPayApp.Desktop/StartupExtensions.cs +++ b/BTCPayApp.Desktop/StartupExtensions.cs @@ -1,7 +1,4 @@ -using System.Text.Json; -using BTCPayApp.Core.Contracts; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.Extensions.Configuration; +using BTCPayApp.Core.Contracts; using Microsoft.Extensions.DependencyInjection; using Plugin.Fingerprint; using Plugin.Fingerprint.Abstractions; @@ -22,126 +19,4 @@ public static IServiceCollection ConfigureBTCPayAppDesktop(this IServiceCollecti serviceCollection.AddSingleton(); return serviceCollection; } -} - -public class DesktopSecureConfigProvider: ISecureConfigProvider -{ - private readonly IDataProtector _dataProtector; - - public DesktopSecureConfigProvider(IDataDirectoryProvider directoryProvider, IDataProtectionProvider dataProtectionProvider) - { - _dataProtector = dataProtectionProvider.CreateProtector("SecureConfig"); - _configDir = directoryProvider.GetAppDataDirectory().ContinueWith(task => - { - var res = Path.Combine(task.Result, "config"); - Directory.CreateDirectory(res); - return res; - }); - } - - private readonly Task _configDir; - - public async Task Get(string key) - { - var dir = Path.Combine(await _configDir, key); - if (!File.Exists(dir)) - { - return default; - } - var raw = await File.ReadAllTextAsync(dir); - var json = await ReadFromRaw(raw); - return JsonSerializer.Deserialize(json); - } - - - public async Task Set(string key, T? value) - { - var dir = Path.Combine(await _configDir, key); - if (value is null) - { - if (File.Exists(dir)) - { - File.Delete(dir); - } - } - else - { - var raw = JsonSerializer.Serialize(value); - await File.WriteAllTextAsync(dir, await WriteFromRaw(raw)); - } - } - - public async Task> List(string prefix) - { - var dir = await _configDir; - if (!Directory.Exists(dir)) - { - return Array.Empty(); - } - return Directory.GetFiles(dir, $"{prefix}*").Select(Path.GetFileName).Where(p => p?.StartsWith(prefix) is true)!; - } - - protected Task ReadFromRaw(string str) => Task.FromResult(_dataProtector.Unprotect(str)); - protected Task WriteFromRaw(string str) => Task.FromResult(_dataProtector.Protect(str)); -} - -public class StubFingerprintProvider: IFingerprint -{ - public Task GetAvailabilityAsync(bool allowAlternativeAuthentication = false) - { - return Task.FromResult(FingerprintAvailability.NoImplementation); - } - - public Task IsAvailableAsync(bool allowAlternativeAuthentication = false) - { - return Task.FromResult(false); - } - - public Task AuthenticateAsync(AuthenticationRequestConfiguration authRequestConfig, - CancellationToken cancellationToken = new CancellationToken()) - { - throw new NotImplementedException(); - } - - public Task GetAuthenticationTypeAsync() - { - throw new NotImplementedException(); - } -} -public class DesktopDataDirectoryProvider : IDataDirectoryProvider -{ - private readonly IConfiguration _configuration; - - public DesktopDataDirectoryProvider(IConfiguration configuration) - { - _configuration = configuration; - } - public virtual Task GetAppDataDirectory() - { - var def = "BTCPayApp"; - var dirName = _configuration.GetValue("BTCPAYAPP_DIRNAME", def); - return Task.FromResult(GetDirectory(dirName ?? def)); - } - - private string GetDirectory(string appDirectory) - { - var environmentVariable1 = _configuration.GetValue("HOME"); - var environmentVariable2 = _configuration.GetValue("APPDATA"); - string str; - if (!string.IsNullOrEmpty(environmentVariable1) && string.IsNullOrEmpty(environmentVariable2)) - str = Path.Combine(environmentVariable1, "." + appDirectory.ToLowerInvariant()); - else if (!string.IsNullOrEmpty(environmentVariable2)) - { - str = Path.Combine(environmentVariable2, appDirectory); - } - else - { - throw new DirectoryNotFoundException( - "Could not find suitable datadir environment variables HOME or APPDATA are not set"); - } - - if (!Directory.Exists(str)) - Directory.CreateDirectory(str); - return str; - } -} +} \ No newline at end of file diff --git a/BTCPayApp.Desktop/StubFingerprintProvider.cs b/BTCPayApp.Desktop/StubFingerprintProvider.cs new file mode 100644 index 0000000..989bfe9 --- /dev/null +++ b/BTCPayApp.Desktop/StubFingerprintProvider.cs @@ -0,0 +1,27 @@ +using Plugin.Fingerprint.Abstractions; + +namespace BTCPayApp.Desktop; + +public class StubFingerprintProvider: IFingerprint +{ + public Task GetAvailabilityAsync(bool allowAlternativeAuthentication = false) + { + return Task.FromResult(FingerprintAvailability.NoImplementation); + } + + public Task IsAvailableAsync(bool allowAlternativeAuthentication = false) + { + return Task.FromResult(false); + } + + public Task AuthenticateAsync(AuthenticationRequestConfiguration authRequestConfig, + CancellationToken cancellationToken = new CancellationToken()) + { + throw new NotImplementedException(); + } + + public Task GetAuthenticationTypeAsync() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/BTCPayApp.Maui/BTCPayApp.Maui.csproj b/BTCPayApp.Maui/BTCPayApp.Maui.csproj index bdbccb5..80ac352 100644 --- a/BTCPayApp.Maui/BTCPayApp.Maui.csproj +++ b/BTCPayApp.Maui/BTCPayApp.Maui.csproj @@ -34,6 +34,7 @@ true ios-arm64 True + false