From 58d01738ab8d7e20bd8c0111309a31e3a9e0b69e Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Wed, 6 Jan 2021 15:51:13 +0100 Subject: [PATCH] More Options refactoring (#2179) * More Options refactoring Continues refactoring config classes to use the propert Options pattern where possible. DataDirectories and DatabaseOptions are now configured the Options pattern and the BTCPayOptions is now moved alongside the other config setup * Move COnfigure logic for Options to the Startup --- .../Configuration/DataDirectories.cs | 12 ++ .../Contracts/BaseDbContextFactory.cs | 13 +- .../Models/DatabaseOptions.cs | 36 ----- .../ApplicationDbContextFactory.cs | 3 +- .../Services/TestPluginDbContextFactory.cs | 2 +- .../Configuration/BTCPayServerOptions.cs | 2 +- BTCPayServer/Configuration/DataDirectories.cs | 26 ---- .../Configuration/ExternalServicesOptions.cs | 26 ---- .../Configuration/LightningNetworkOptions.cs | 46 ------ .../Configuration/NBXplorerOptions.cs | 17 -- BTCPayServer/Controllers/StorageController.cs | 6 +- BTCPayServer/Extensions.cs | 21 +-- BTCPayServer/Hosting/BTCPayServerServices.cs | 146 ++++++++++++++---- BTCPayServer/Hosting/Startup.cs | 8 +- BTCPayServer/Plugins/PluginManager.cs | 2 +- BTCPayServer/Plugins/PluginService.cs | 19 +-- .../FileSystemFileProviderService.cs | 13 +- BTCPayServer/Storage/StorageExtensions.cs | 15 +- 18 files changed, 179 insertions(+), 234 deletions(-) create mode 100644 BTCPayServer.Abstractions/Configuration/DataDirectories.cs delete mode 100644 BTCPayServer/Configuration/DataDirectories.cs diff --git a/BTCPayServer.Abstractions/Configuration/DataDirectories.cs b/BTCPayServer.Abstractions/Configuration/DataDirectories.cs new file mode 100644 index 000000000..0e5f25a87 --- /dev/null +++ b/BTCPayServer.Abstractions/Configuration/DataDirectories.cs @@ -0,0 +1,12 @@ +namespace BTCPayServer.Configuration +{ + public class DataDirectories + { + public string DataDir { get; set; } + public string PluginDir { get; set; } + public string TempStorageDir { get; set; } + public string StorageDir { get; set; } + } + + +} diff --git a/BTCPayServer.Abstractions/Contracts/BaseDbContextFactory.cs b/BTCPayServer.Abstractions/Contracts/BaseDbContextFactory.cs index 0997c9120..f70ca307e 100644 --- a/BTCPayServer.Abstractions/Contracts/BaseDbContextFactory.cs +++ b/BTCPayServer.Abstractions/Contracts/BaseDbContextFactory.cs @@ -3,6 +3,7 @@ using BTCPayServer.Abstractions.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.Extensions.Options; using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations; @@ -10,10 +11,10 @@ namespace BTCPayServer.Abstractions.Contracts { public abstract class BaseDbContextFactory where T: DbContext { - private readonly DatabaseOptions _options; + private readonly IOptions _options; private readonly string _schemaPrefix; - public BaseDbContextFactory(DatabaseOptions options, string schemaPrefix) + public BaseDbContextFactory(IOptions options, string schemaPrefix) { _options = options; _schemaPrefix = schemaPrefix; @@ -65,10 +66,10 @@ namespace BTCPayServer.Abstractions.Contracts public void ConfigureBuilder(DbContextOptionsBuilder builder) { - switch (_options.DatabaseType) + switch (_options.Value.DatabaseType) { case DatabaseType.Sqlite: - builder.UseSqlite(_options.ConnectionString, o => + builder.UseSqlite(_options.Value.ConnectionString, o => { if (!string.IsNullOrEmpty(_schemaPrefix)) { @@ -78,7 +79,7 @@ namespace BTCPayServer.Abstractions.Contracts break; case DatabaseType.Postgres: builder - .UseNpgsql(_options.ConnectionString, o => + .UseNpgsql(_options.Value.ConnectionString, o => { o.EnableRetryOnFailure(10); if (!string.IsNullOrEmpty(_schemaPrefix)) @@ -89,7 +90,7 @@ namespace BTCPayServer.Abstractions.Contracts .ReplaceService(); break; case DatabaseType.MySQL: - builder.UseMySql(_options.ConnectionString, o => + builder.UseMySql(_options.Value.ConnectionString, o => { o.EnableRetryOnFailure(10); diff --git a/BTCPayServer.Abstractions/Models/DatabaseOptions.cs b/BTCPayServer.Abstractions/Models/DatabaseOptions.cs index 4f682083e..b4a3f8801 100644 --- a/BTCPayServer.Abstractions/Models/DatabaseOptions.cs +++ b/BTCPayServer.Abstractions/Models/DatabaseOptions.cs @@ -1,43 +1,7 @@ -using System; -using System.IO; -using System.Runtime.InteropServices.ComTypes; -using Microsoft.Extensions.Configuration; - namespace BTCPayServer.Abstractions.Models { public class DatabaseOptions { - public DatabaseOptions(IConfiguration conf, string dataDir) - { - var postgresConnectionString = conf["postgres"]; - var mySQLConnectionString = conf["mysql"]; - var sqliteFileName = conf["sqlitefile"]; - - if (!string.IsNullOrEmpty(postgresConnectionString)) - { - DatabaseType = DatabaseType.Postgres; - ConnectionString = postgresConnectionString; - } - else if (!string.IsNullOrEmpty(mySQLConnectionString)) - { - DatabaseType = DatabaseType.MySQL; - ConnectionString = mySQLConnectionString; - } - else if (!string.IsNullOrEmpty(sqliteFileName)) - { - var connStr = "Data Source=" + (Path.IsPathRooted(sqliteFileName) - ? sqliteFileName - : Path.Combine(dataDir, sqliteFileName)); - - DatabaseType = DatabaseType.Sqlite; - ConnectionString = sqliteFileName; - } - else - { - throw new InvalidOperationException("No database option was configured."); - } - } - public DatabaseType DatabaseType { get; set; } public string ConnectionString { get; set; } } diff --git a/BTCPayServer.Data/ApplicationDbContextFactory.cs b/BTCPayServer.Data/ApplicationDbContextFactory.cs index 9aefd3e64..fe5dbf569 100644 --- a/BTCPayServer.Data/ApplicationDbContextFactory.cs +++ b/BTCPayServer.Data/ApplicationDbContextFactory.cs @@ -1,12 +1,13 @@ using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Models; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; namespace BTCPayServer.Data { public class ApplicationDbContextFactory : BaseDbContextFactory { - public ApplicationDbContextFactory(DatabaseOptions options) : base(options, "") + public ApplicationDbContextFactory(IOptions options) : base(options, "") { } diff --git a/BTCPayServer.Plugins.Test/Services/TestPluginDbContextFactory.cs b/BTCPayServer.Plugins.Test/Services/TestPluginDbContextFactory.cs index 778faa6f3..b3ba36034 100644 --- a/BTCPayServer.Plugins.Test/Services/TestPluginDbContextFactory.cs +++ b/BTCPayServer.Plugins.Test/Services/TestPluginDbContextFactory.cs @@ -23,7 +23,7 @@ namespace BTCPayServer.Plugins.Test public class TestPluginDbContextFactory : BaseDbContextFactory { - public TestPluginDbContextFactory(DatabaseOptions options) : base(options, "BTCPayServer.Plugins.Test") + public TestPluginDbContextFactory(IOptions options) : base(options, "BTCPayServer.Plugins.Test") { } diff --git a/BTCPayServer/Configuration/BTCPayServerOptions.cs b/BTCPayServer/Configuration/BTCPayServerOptions.cs index 836a824ac..51462482f 100644 --- a/BTCPayServer/Configuration/BTCPayServerOptions.cs +++ b/BTCPayServer/Configuration/BTCPayServerOptions.cs @@ -44,7 +44,7 @@ namespace BTCPayServer.Configuration { if (!Path.IsPathRooted(logfile)) { - logfile = Path.Combine(new DataDirectories(configuration).DataDir, logfile); + logfile = Path.Combine(new DataDirectories().Configure(configuration).DataDir, logfile); } } return logfile; diff --git a/BTCPayServer/Configuration/DataDirectories.cs b/BTCPayServer/Configuration/DataDirectories.cs deleted file mode 100644 index d5fa4b93d..000000000 --- a/BTCPayServer/Configuration/DataDirectories.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; - -namespace BTCPayServer.Configuration -{ - public class DataDirectories - { - public DataDirectories(IConfiguration conf) - { - var networkType = DefaultConfiguration.GetNetworkType(conf); - var defaultSettings = BTCPayDefaultSettings.GetDefaultSettings(networkType); - DataDir = conf["datadir"] ?? defaultSettings.DefaultDataDirectory; - PluginDir = conf["plugindir"] ?? defaultSettings.DefaultPluginDirectory; - StorageDir = Path.Combine(DataDir, Storage.Services.Providers.FileSystemStorage.FileSystemFileProviderService.LocalStorageDirectoryName); - TempStorageDir = Path.Combine(StorageDir, "tmp"); - } - public string DataDir { get; } - public string PluginDir { get; } - public string TempStorageDir { get; } - public string StorageDir { get; set; } - } -} diff --git a/BTCPayServer/Configuration/ExternalServicesOptions.cs b/BTCPayServer/Configuration/ExternalServicesOptions.cs index a6ffd4465..9846e82da 100644 --- a/BTCPayServer/Configuration/ExternalServicesOptions.cs +++ b/BTCPayServer/Configuration/ExternalServicesOptions.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Configuration; -using NBitcoin; namespace BTCPayServer.Configuration { @@ -11,28 +8,5 @@ namespace BTCPayServer.Configuration public Dictionary OtherExternalServices { get; set; } = new Dictionary(); public ExternalServices ExternalServices { get; set; } = new ExternalServices(); - public void Configure(IConfiguration configuration, BTCPayNetworkProvider btcPayNetworkProvider) - { - foreach (var net in btcPayNetworkProvider.GetAll().OfType()) - { - ExternalServices.Load(net.CryptoCode, configuration); - } - - ExternalServices.LoadNonCryptoServices(configuration); - - var services = configuration.GetOrDefault("externalservices", null); - if (services != null) - { - foreach (var service in services.Split(new[] {';', ','}, StringSplitOptions.RemoveEmptyEntries) - .Select(p => (p, SeparatorIndex: p.IndexOf(':', StringComparison.OrdinalIgnoreCase))) - .Where(p => p.SeparatorIndex != -1) - .Select(p => (Name: p.p.Substring(0, p.SeparatorIndex), - Link: p.p.Substring(p.SeparatorIndex + 1)))) - { - if (Uri.TryCreate(service.Link, UriKind.RelativeOrAbsolute, out var uri)) - OtherExternalServices.AddOrReplace(service.Name, uri); - } - } - } } } diff --git a/BTCPayServer/Configuration/LightningNetworkOptions.cs b/BTCPayServer/Configuration/LightningNetworkOptions.cs index f92556000..9d31483a1 100644 --- a/BTCPayServer/Configuration/LightningNetworkOptions.cs +++ b/BTCPayServer/Configuration/LightningNetworkOptions.cs @@ -1,10 +1,5 @@ -using System; using System.Collections.Generic; -using System.Linq; using BTCPayServer.Lightning; -using BTCPayServer.Logging; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; namespace BTCPayServer.Configuration { @@ -12,46 +7,5 @@ namespace BTCPayServer.Configuration { public Dictionary InternalLightningByCryptoCode { get; set; } = new Dictionary(); - - public void Configure(IConfiguration conf, BTCPayNetworkProvider networkProvider) - { - foreach (var net in networkProvider.GetAll().OfType()) - { - var lightning = conf.GetOrDefault($"{net.CryptoCode}.lightning", string.Empty); - if (lightning.Length != 0) - { - if (!LightningConnectionString.TryParse(lightning, true, out var connectionString, - out var error)) - { - Logs.Configuration.LogWarning($"Invalid setting {net.CryptoCode}.lightning, " + - Environment.NewLine + - $"If you have a c-lightning server use: 'type=clightning;server=/root/.lightning/lightning-rpc', " + - Environment.NewLine + - $"If you have a lightning charge server: 'type=charge;server=https://charge.example.com;api-token=yourapitoken'" + - Environment.NewLine + - $"If you have a lnd server: 'type=lnd-rest;server=https://lnd:lnd@lnd.example.com;macaroon=abf239...;certthumbprint=2abdf302...'" + - Environment.NewLine + - $" lnd server: 'type=lnd-rest;server=https://lnd:lnd@lnd.example.com;macaroonfilepath=/root/.lnd/admin.macaroon;certthumbprint=2abdf302...'" + - Environment.NewLine + - $"If you have an eclair server: 'type=eclair;server=http://eclair.com:4570;password=eclairpassword;bitcoin-host=bitcoind:37393;bitcoin-auth=bitcoinrpcuser:bitcoinrpcpassword" + - Environment.NewLine + - $" eclair server: 'type=eclair;server=http://eclair.com:4570;password=eclairpassword;bitcoin-host=bitcoind:37393" + - Environment.NewLine + - $"Error: {error}" + Environment.NewLine + - "This service will not be exposed through BTCPay Server"); - } - else - { - if (connectionString.IsLegacy) - { - Logs.Configuration.LogWarning( - $"Setting {net.CryptoCode}.lightning is a deprecated format, it will work now, but please replace it for future versions with '{connectionString.ToString()}'"); - } - - InternalLightningByCryptoCode.Add(net.CryptoCode, connectionString); - } - } - } - } } } diff --git a/BTCPayServer/Configuration/NBXplorerOptions.cs b/BTCPayServer/Configuration/NBXplorerOptions.cs index 0839ae14e..c671546ec 100644 --- a/BTCPayServer/Configuration/NBXplorerOptions.cs +++ b/BTCPayServer/Configuration/NBXplorerOptions.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Configuration; namespace BTCPayServer.Configuration { @@ -12,19 +9,5 @@ namespace BTCPayServer.Configuration get; set; } = new List(); - - public void Configure(IConfiguration conf, BTCPayNetworkProvider provider) - { - foreach (BTCPayNetwork btcPayNetwork in provider.GetAll().OfType()) - { - NBXplorerConnectionSetting setting = new NBXplorerConnectionSetting(); - setting.CryptoCode = btcPayNetwork.CryptoCode; - setting.ExplorerUri = conf.GetOrDefault($"{btcPayNetwork.CryptoCode}.explorer.url", - btcPayNetwork.NBXplorerNetwork.DefaultSettings.DefaultUrl); - setting.CookieFile = conf.GetOrDefault($"{btcPayNetwork.CryptoCode}.explorer.cookiefile", - btcPayNetwork.NBXplorerNetwork.DefaultSettings.DefaultCookieFile); - NBXplorerConnectionSettings.Add(setting); - } - } } } diff --git a/BTCPayServer/Controllers/StorageController.cs b/BTCPayServer/Controllers/StorageController.cs index 3bcd562c2..835baa45c 100644 --- a/BTCPayServer/Controllers/StorageController.cs +++ b/BTCPayServer/Controllers/StorageController.cs @@ -1,7 +1,5 @@ using System.Threading.Tasks; -using BTCPayServer.Configuration; using BTCPayServer.Storage.Services; -using BTCPayServer.Storage.Services.Providers.FileSystemStorage; using Microsoft.AspNetCore.Mvc; namespace BTCPayServer.Storage @@ -10,12 +8,10 @@ namespace BTCPayServer.Storage public class StorageController : Controller { private readonly FileService _FileService; - private readonly string _dir; - public StorageController(FileService fileService, DataDirectories datadirs) + public StorageController(FileService fileService) { _FileService = fileService; - _dir = datadirs.TempStorageDir; } [HttpGet("{fileId}")] diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index 216cd343c..ff13bfdaf 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Net; using System.Net.WebSockets; @@ -375,15 +376,6 @@ namespace BTCPayServer request.Host.ToUriComponent()) + relativeOrAbsolute.ToString().WithStartingSlash(), UriKind.Absolute); } - public static IServiceCollection ConfigureBTCPayServer(this IServiceCollection services, IConfiguration conf) - { - services.Configure(o => - { - o.LoadArgs(conf); - }); - return services; - } - public static string GetSIN(this ClaimsPrincipal principal) { return principal.Claims.Where(c => c.Type == Security.Bitpay.BitpayClaims.SIN).Select(c => c.Value).FirstOrDefault(); @@ -497,6 +489,17 @@ namespace BTCPayServer return result; } + public static DataDirectories Configure(this DataDirectories dataDirectories, IConfiguration configuration) + { + var networkType = DefaultConfiguration.GetNetworkType(configuration); + var defaultSettings = BTCPayDefaultSettings.GetDefaultSettings(networkType); + dataDirectories.DataDir = configuration["datadir"] ?? defaultSettings.DefaultDataDirectory; + dataDirectories.PluginDir = configuration["plugindir"] ?? defaultSettings.DefaultPluginDirectory; + dataDirectories.StorageDir = Path.Combine(dataDirectories.DataDir , Storage.Services.Providers.FileSystemStorage.FileSystemFileProviderService.LocalStorageDirectoryName); + dataDirectories.TempStorageDir = Path.Combine(dataDirectories.StorageDir, "tmp"); + return dataDirectories; + } + private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj); private static T Private(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj); } diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index e8653aaa3..8dbd90234 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -11,6 +11,7 @@ using BTCPayServer.Configuration; using BTCPayServer.Controllers; using BTCPayServer.Data; using BTCPayServer.HostedServices; +using BTCPayServer.Lightning; using BTCPayServer.Logging; using BTCPayServer.PaymentRequest; using BTCPayServer.Payments; @@ -105,7 +106,6 @@ namespace BTCPayServer.Hosting services.AddStartupTask(); services.TryAddSingleton(o => { - var datadirs = o.GetRequiredService(); var dbContext = o.GetRequiredService(); return new InvoiceRepository(dbContext, o.GetRequiredService(), o.GetService()); }); @@ -115,50 +115,130 @@ namespace BTCPayServer.Hosting services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(o => - { - try - { - var dbOptions = new DatabaseOptions(o.GetRequiredService(), - o.GetRequiredService().DataDir); - if (dbOptions.DatabaseType == DatabaseType.Postgres) - { - Logs.Configuration.LogInformation($"Postgres DB used"); - } - else if (dbOptions.DatabaseType == DatabaseType.MySQL) - { - Logs.Configuration.LogInformation($"MySQL DB used"); - Logs.Configuration.LogWarning("MySQL is not widely tested and should be considered experimental, we advise you to use postgres instead."); - } - else if (dbOptions.DatabaseType == DatabaseType.Sqlite) - { - Logs.Configuration.LogInformation($"SQLite DB used"); - Logs.Configuration.LogWarning("SQLite is not widely tested and should be considered experimental, we advise you to use postgres instead."); - } - return dbOptions; - } - catch (Exception ex) - { - throw new ConfigException($"No database option was configured. ({ex.Message})"); - } - }); services.AddSingleton(); + services.AddOptions().Configure( + (options) => + { + options.LoadArgs(configuration); + }); + services.AddOptions().Configure( + (options) => + { + options.Configure(configuration); + }); + services.AddOptions().Configure>( + (options, datadirs) => + { + var postgresConnectionString = configuration["postgres"]; + var mySQLConnectionString = configuration["mysql"]; + var sqliteFileName = configuration["sqlitefile"]; + + if (!string.IsNullOrEmpty(postgresConnectionString)) + { + options.DatabaseType = DatabaseType.Postgres; + options.ConnectionString = postgresConnectionString; + } + else if (!string.IsNullOrEmpty(mySQLConnectionString)) + { + options.DatabaseType = DatabaseType.MySQL; + options.ConnectionString = mySQLConnectionString; + } + else if (!string.IsNullOrEmpty(sqliteFileName)) + { + var connStr = "Data Source=" + (Path.IsPathRooted(sqliteFileName) + ? sqliteFileName + : Path.Combine(datadirs.Value.DataDir, sqliteFileName)); + + options.DatabaseType = DatabaseType.Sqlite; + options.ConnectionString = sqliteFileName; + } + else + { + throw new InvalidOperationException("No database option was configured."); + } + }); services.AddOptions().Configure( (options, btcPayNetworkProvider) => { - options.Configure(configuration, btcPayNetworkProvider); + foreach (BTCPayNetwork btcPayNetwork in btcPayNetworkProvider.GetAll().OfType()) + { + NBXplorerConnectionSetting setting = + new NBXplorerConnectionSetting + { + CryptoCode = btcPayNetwork.CryptoCode, + ExplorerUri = configuration.GetOrDefault( + $"{btcPayNetwork.CryptoCode}.explorer.url", + btcPayNetwork.NBXplorerNetwork.DefaultSettings.DefaultUrl), + CookieFile = configuration.GetOrDefault( + $"{btcPayNetwork.CryptoCode}.explorer.cookiefile", + btcPayNetwork.NBXplorerNetwork.DefaultSettings.DefaultCookieFile) + }; + options.NBXplorerConnectionSettings.Add(setting); + } }); - services.AddOptions().Configure( (options, btcPayNetworkProvider) => { - options.Configure(configuration, btcPayNetworkProvider); + foreach (var net in btcPayNetworkProvider.GetAll().OfType()) + { + var lightning = configuration.GetOrDefault($"{net.CryptoCode}.lightning", string.Empty); + if (lightning.Length != 0) + { + if (!LightningConnectionString.TryParse(lightning, true, out var connectionString, + out var error)) + { + Logs.Configuration.LogWarning($"Invalid setting {net.CryptoCode}.lightning, " + + Environment.NewLine + + $"If you have a c-lightning server use: 'type=clightning;server=/root/.lightning/lightning-rpc', " + + Environment.NewLine + + $"If you have a lightning charge server: 'type=charge;server=https://charge.example.com;api-token=yourapitoken'" + + Environment.NewLine + + $"If you have a lnd server: 'type=lnd-rest;server=https://lnd:lnd@lnd.example.com;macaroon=abf239...;certthumbprint=2abdf302...'" + + Environment.NewLine + + $" lnd server: 'type=lnd-rest;server=https://lnd:lnd@lnd.example.com;macaroonfilepath=/root/.lnd/admin.macaroon;certthumbprint=2abdf302...'" + + Environment.NewLine + + $"If you have an eclair server: 'type=eclair;server=http://eclair.com:4570;password=eclairpassword;bitcoin-host=bitcoind:37393;bitcoin-auth=bitcoinrpcuser:bitcoinrpcpassword" + + Environment.NewLine + + $" eclair server: 'type=eclair;server=http://eclair.com:4570;password=eclairpassword;bitcoin-host=bitcoind:37393" + + Environment.NewLine + + $"Error: {error}" + Environment.NewLine + + "This service will not be exposed through BTCPay Server"); + } + else + { + if (connectionString.IsLegacy) + { + Logs.Configuration.LogWarning( + $"Setting {net.CryptoCode}.lightning is a deprecated format, it will work now, but please replace it for future versions with '{connectionString.ToString()}'"); + } + options.InternalLightningByCryptoCode.Add(net.CryptoCode, connectionString); + } + } + } }); services.AddOptions().Configure( (options, btcPayNetworkProvider) => { - options.Configure(configuration, btcPayNetworkProvider); + foreach (var net in btcPayNetworkProvider.GetAll().OfType()) + { + options.ExternalServices.Load(net.CryptoCode, configuration); + } + + options.ExternalServices.LoadNonCryptoServices(configuration); + + var services = configuration.GetOrDefault("externalservices", null); + if (services != null) + { + foreach (var service in services.Split(new[] {';', ','}, StringSplitOptions.RemoveEmptyEntries) + .Select(p => (p, SeparatorIndex: p.IndexOf(':', StringComparison.OrdinalIgnoreCase))) + .Where(p => p.SeparatorIndex != -1) + .Select(p => (Name: p.p.Substring(0, p.SeparatorIndex), + Link: p.p.Substring(p.SeparatorIndex + 1)))) + { + if (Uri.TryCreate(service.Link, UriKind.RelativeOrAbsolute, out var uri)) + options.OtherExternalServices.AddOrReplace(service.Name, uri); + } + } }); services.TryAddSingleton(o => configuration.ConfigureNetworkProvider()); diff --git a/BTCPayServer/Hosting/Startup.cs b/BTCPayServer/Hosting/Startup.cs index f69ce135c..447d722a0 100644 --- a/BTCPayServer/Hosting/Startup.cs +++ b/BTCPayServer/Hosting/Startup.cs @@ -21,6 +21,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; using NBitcoin; @@ -45,11 +46,10 @@ namespace BTCPayServer.Hosting public void ConfigureServices(IServiceCollection services) { Logs.Configure(LoggerFactory); - services.ConfigureBTCPayServer(Configuration); services.AddMemoryCache(); services.AddDataProtection() .SetApplicationName("BTCPay Server") - .PersistKeysToFileSystem(new DirectoryInfo(new DataDirectories(Configuration).DataDir)); + .PersistKeysToFileSystem(new DirectoryInfo(new DataDirectories().Configure(Configuration).DataDir)); services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); @@ -156,7 +156,7 @@ namespace BTCPayServer.Hosting IWebHostEnvironment env, IServiceProvider prov, BTCPayServerOptions options, - DataDirectories dataDirectories, + IOptions dataDirectories, ILoggerFactory loggerFactory) { Logs.Configuration.LogInformation($"Root Path: {options.RootPath}"); @@ -172,7 +172,7 @@ namespace BTCPayServer.Hosting }); } } - private static void ConfigureCore(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider prov, ILoggerFactory loggerFactory, DataDirectories dataDirectories) + private static void ConfigureCore(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider prov, ILoggerFactory loggerFactory, IOptions dataDirectories) { Logs.Configure(loggerFactory); app.UsePlugins(); diff --git a/BTCPayServer/Plugins/PluginManager.cs b/BTCPayServer/Plugins/PluginManager.cs index de9c15292..c8a3bddf6 100644 --- a/BTCPayServer/Plugins/PluginManager.cs +++ b/BTCPayServer/Plugins/PluginManager.cs @@ -28,7 +28,7 @@ namespace BTCPayServer.Plugins IConfiguration config, ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger(typeof(PluginManager)); - var pluginsFolder = new DataDirectories(config).PluginDir; + var pluginsFolder = new DataDirectories().Configure(config).PluginDir; var plugins = new List(); diff --git a/BTCPayServer/Plugins/PluginService.cs b/BTCPayServer/Plugins/PluginService.cs index 8e264294b..871c625c9 100644 --- a/BTCPayServer/Plugins/PluginService.cs +++ b/BTCPayServer/Plugins/PluginService.cs @@ -11,19 +11,20 @@ using BTCPayServer.Configuration; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Newtonsoft.Json; namespace BTCPayServer.Plugins { public class PluginService: IPluginHookService { - private readonly DataDirectories _datadirs; + private readonly IOptions _datadirs; private readonly BTCPayServerOptions _options; private readonly HttpClient _githubClient; private readonly IEnumerable _actions; private readonly IEnumerable _filters; public PluginService(IEnumerable btcPayServerPlugins, - IHttpClientFactory httpClientFactory, DataDirectories datadirs, BTCPayServerOptions options, IEnumerable actions, IEnumerable filters) + IHttpClientFactory httpClientFactory, IOptions datadirs, BTCPayServerOptions options, IEnumerable actions, IEnumerable filters) { LoadedPlugins = btcPayServerPlugins; _githubClient = httpClientFactory.CreateClient(); @@ -50,7 +51,7 @@ namespace BTCPayServer.Plugins public async Task DownloadRemotePlugin(string plugin) { - var dest = _datadirs.PluginDir; + var dest = _datadirs.Value.PluginDir; var resp = await _githubClient .GetStringAsync(new Uri($"https://api.github.com/repos/{_options.PluginRemote}/contents")); var files = JsonConvert.DeserializeObject(resp); @@ -67,19 +68,19 @@ namespace BTCPayServer.Plugins public void InstallPlugin(string plugin) { - var dest = _datadirs.PluginDir; + var dest = _datadirs.Value.PluginDir; UninstallPlugin(plugin); PluginManager.QueueCommands(dest, ("install", plugin)); } public void UpdatePlugin(string plugin) { - var dest = _datadirs.PluginDir; + var dest = _datadirs.Value.PluginDir; PluginManager.QueueCommands(dest, ("update", plugin)); } public async Task UploadPlugin(IFormFile plugin) { - var dest = _datadirs.PluginDir; + var dest = _datadirs.Value.PluginDir; var filedest = Path.Combine(dest, plugin.FileName); Directory.CreateDirectory(Path.GetDirectoryName(filedest)); if (Path.GetExtension(filedest) == PluginManager.BTCPayPluginSuffix) @@ -91,7 +92,7 @@ namespace BTCPayServer.Plugins public void UninstallPlugin(string plugin) { - var dest = _datadirs.PluginDir; + var dest = _datadirs.Value.PluginDir; PluginManager.QueueCommands(dest, ("delete", plugin)); } @@ -126,12 +127,12 @@ namespace BTCPayServer.Plugins public (string command, string plugin)[] GetPendingCommands() { - return PluginManager.GetPendingCommands(_datadirs.PluginDir); + return PluginManager.GetPendingCommands(_datadirs.Value.PluginDir); } public void CancelCommands(string plugin) { - PluginManager.CancelCommands(_datadirs.PluginDir, plugin); + PluginManager.CancelCommands(_datadirs.Value.PluginDir, plugin); } public async Task ApplyAction(string hook, object args) diff --git a/BTCPayServer/Storage/Services/Providers/FileSystemStorage/FileSystemFileProviderService.cs b/BTCPayServer/Storage/Services/Providers/FileSystemStorage/FileSystemFileProviderService.cs index 0f795827a..ece998eec 100644 --- a/BTCPayServer/Storage/Services/Providers/FileSystemStorage/FileSystemFileProviderService.cs +++ b/BTCPayServer/Storage/Services/Providers/FileSystemStorage/FileSystemFileProviderService.cs @@ -5,6 +5,7 @@ using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Storage.Models; using BTCPayServer.Storage.Services.Providers.FileSystemStorage.Configuration; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using TwentyTwenty.Storage; using TwentyTwenty.Storage.Local; @@ -14,9 +15,9 @@ namespace BTCPayServer.Storage.Services.Providers.FileSystemStorage public class FileSystemFileProviderService : BaseTwentyTwentyStorageFileProviderServiceBase { - private readonly DataDirectories _datadirs; + private readonly IOptions _datadirs; - public FileSystemFileProviderService(DataDirectories datadirs) + public FileSystemFileProviderService(IOptions datadirs) { _datadirs = datadirs; } @@ -30,14 +31,14 @@ namespace BTCPayServer.Storage.Services.Providers.FileSystemStorage protected override Task GetStorageProvider(FileSystemStorageConfiguration configuration) { return Task.FromResult( - new LocalStorageProvider(new DirectoryInfo(_datadirs.StorageDir).FullName)); + new LocalStorageProvider(new DirectoryInfo(_datadirs.Value.StorageDir).FullName)); } public override async Task GetFileUrl(Uri baseUri, StoredFile storedFile, StorageSettings configuration) { var baseResult = await base.GetFileUrl(baseUri, storedFile, configuration); var url = new Uri(baseUri, LocalStorageDirectoryName); - return baseResult.Replace(new DirectoryInfo(_datadirs.StorageDir).FullName, url.AbsoluteUri, + return baseResult.Replace(new DirectoryInfo(_datadirs.Value.StorageDir).FullName, url.AbsoluteUri, StringComparison.InvariantCultureIgnoreCase); } @@ -53,13 +54,13 @@ namespace BTCPayServer.Storage.Services.Providers.FileSystemStorage IsDownload = isDownload }; var name = Guid.NewGuid().ToString(); - var fullPath = Path.Combine(_datadirs.TempStorageDir, name); + var fullPath = Path.Combine(_datadirs.Value.TempStorageDir, name); if (!File.Exists(fullPath)) { File.Create(fullPath).Dispose(); } - await File.WriteAllTextAsync(Path.Combine(_datadirs.TempStorageDir, name), JsonConvert.SerializeObject(localFileDescriptor)); + await File.WriteAllTextAsync(Path.Combine(_datadirs.Value.TempStorageDir, name), JsonConvert.SerializeObject(localFileDescriptor)); return new Uri(baseUri, $"{LocalStorageDirectoryName}tmp/{name}{(isDownload ? "?download" : string.Empty)}").AbsoluteUri; } diff --git a/BTCPayServer/Storage/StorageExtensions.cs b/BTCPayServer/Storage/StorageExtensions.cs index fda11eb9a..3ac61395f 100644 --- a/BTCPayServer/Storage/StorageExtensions.cs +++ b/BTCPayServer/Storage/StorageExtensions.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NBitcoin.Logging; namespace BTCPayServer.Storage @@ -28,28 +29,28 @@ namespace BTCPayServer.Storage // serviceCollection.AddSingleton(); } - public static void UseProviderStorage(this IApplicationBuilder builder, DataDirectories datadirs) + public static void UseProviderStorage(this IApplicationBuilder builder, IOptions datadirs) { try { DirectoryInfo dirInfo; - if (!Directory.Exists(datadirs.StorageDir)) + if (!Directory.Exists(datadirs.Value.StorageDir)) { - dirInfo = Directory.CreateDirectory(datadirs.StorageDir); + dirInfo = Directory.CreateDirectory(datadirs.Value.StorageDir); } else { - dirInfo = new DirectoryInfo(datadirs.StorageDir); + dirInfo = new DirectoryInfo(datadirs.Value.StorageDir); } DirectoryInfo tmpdirInfo; - if (!Directory.Exists(datadirs.TempStorageDir)) + if (!Directory.Exists(datadirs.Value.TempStorageDir)) { - tmpdirInfo = Directory.CreateDirectory(datadirs.TempStorageDir); + tmpdirInfo = Directory.CreateDirectory(datadirs.Value.TempStorageDir); } else { - tmpdirInfo = new DirectoryInfo(datadirs.TempStorageDir); + tmpdirInfo = new DirectoryInfo(datadirs.Value.TempStorageDir); } builder.UseStaticFiles(new StaticFileOptions()