diff --git a/.run/Build and pack extensions.run.xml b/.run/Build and pack extensions.run.xml deleted file mode 100644 index 72b7ea83c..000000000 --- a/.run/Build and pack extensions.run.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/BTCPayServer.Abstractions/Models/BaseBTCPayServerPlugin.cs b/BTCPayServer.Abstractions/Models/BaseBTCPayServerPlugin.cs index d5c42b39c..9ba24a61b 100644 --- a/BTCPayServer.Abstractions/Models/BaseBTCPayServerPlugin.cs +++ b/BTCPayServer.Abstractions/Models/BaseBTCPayServerPlugin.cs @@ -21,7 +21,6 @@ namespace BTCPayServer.Abstractions.Models public abstract string Description { get; } public bool SystemPlugin { get; set; } - public bool SystemExtension { get; set; } public virtual IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } = Array.Empty(); public virtual void Execute(IApplicationBuilder applicationBuilder, diff --git a/BTCPayServer.Abstractions/Services/PluginAction.cs b/BTCPayServer.Abstractions/Services/PluginAction.cs index 35aaff142..8b034cbad 100644 --- a/BTCPayServer.Abstractions/Services/PluginAction.cs +++ b/BTCPayServer.Abstractions/Services/PluginAction.cs @@ -5,7 +5,7 @@ namespace BTCPayServer.Abstractions.Services { public abstract class PluginAction:IPluginHookAction { - public string Hook { get; } + public abstract string Hook { get; } public Task Execute(object args) { return Execute(args is T args1 ? args1 : default); diff --git a/BTCPayServer.Abstractions/Services/PluginHookFilter.cs b/BTCPayServer.Abstractions/Services/PluginHookFilter.cs index 02751b980..5bb564f88 100644 --- a/BTCPayServer.Abstractions/Services/PluginHookFilter.cs +++ b/BTCPayServer.Abstractions/Services/PluginHookFilter.cs @@ -5,7 +5,8 @@ namespace BTCPayServer.Abstractions.Services { public abstract class PluginHookFilter:IPluginHookFilter { - public string Hook { get; } + public abstract string Hook { get; } + public Task Execute(object args) { return Execute(args is T args1 ? args1 : default).ContinueWith(task => task.Result as object); diff --git a/BTCPayServer.Common/BTCPayNetwork.cs b/BTCPayServer.Common/BTCPayNetwork.cs index 19a8e77c5..d43b599f3 100644 --- a/BTCPayServer.Common/BTCPayNetwork.cs +++ b/BTCPayServer.Common/BTCPayNetwork.cs @@ -53,7 +53,7 @@ namespace BTCPayServer public bool SupportRBF { get; internal set; } public string LightningImagePath { get; set; } public BTCPayDefaultSettings DefaultSettings { get; set; } - public KeyPath CoinType { get; internal set; } + public KeyPath CoinType { get; set; } public Dictionary ElectrumMapping = new Dictionary(); @@ -132,7 +132,7 @@ namespace BTCPayServer { private string _blockExplorerLink; public bool ShowSyncSummary { get; set; } = true; - public string CryptoCode { get; internal set; } + public string CryptoCode { get; set; } public string BlockExplorerLink { @@ -161,7 +161,7 @@ namespace BTCPayServer } public string CryptoImagePath { get; set; } - public string[] DefaultRateRules { get; internal set; } = Array.Empty(); + public string[] DefaultRateRules { get; set; } = Array.Empty(); public override string ToString() { return CryptoCode; diff --git a/BTCPayServer.Common/BTCPayNetworkProvider.cs b/BTCPayServer.Common/BTCPayNetworkProvider.cs index 77b96d4f2..8e975798f 100644 --- a/BTCPayServer.Common/BTCPayNetworkProvider.cs +++ b/BTCPayServer.Common/BTCPayNetworkProvider.cs @@ -8,8 +8,7 @@ namespace BTCPayServer { public partial class BTCPayNetworkProvider { - readonly Dictionary _Networks = new Dictionary(); - + protected readonly Dictionary _Networks = new Dictionary(); private readonly NBXplorerNetworkProvider _NBXplorerNetworkProvider; public NBXplorerNetworkProvider NBXplorerNetworkProvider diff --git a/BTCPayServer.PluginPacker/Program.cs b/BTCPayServer.PluginPacker/Program.cs index d09f9e67b..6fac20b7b 100644 --- a/BTCPayServer.PluginPacker/Program.cs +++ b/BTCPayServer.PluginPacker/Program.cs @@ -43,6 +43,7 @@ namespace BTCPayServer.PluginPacker } ZipFile.CreateFromDirectory(directory, outputFile + ".btcpay", CompressionLevel.Optimal, false); File.WriteAllText(outputFile + ".btcpay.json", json); + Console.WriteLine($"Created {outputFile}.btcpay at {directory}"); } private static Type[] GetAllExtensionTypesFromAssembly(Assembly assembly) diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index f002fcc0c..1fb61dee4 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -1186,7 +1186,7 @@ namespace BTCPayServer.Controllers var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike ? Url.Content(network.CryptoImagePath) : Url.Content(network.LightningImagePath); - return "/" + res; + return Request.GetRelativePathOrAbsolute(res); } } diff --git a/BTCPayServer/HostedServices/DbMigrationsHostedService.cs b/BTCPayServer/HostedServices/DbMigrationsHostedService.cs index 9e69a784d..225d98e2b 100644 --- a/BTCPayServer/HostedServices/DbMigrationsHostedService.cs +++ b/BTCPayServer/HostedServices/DbMigrationsHostedService.cs @@ -7,6 +7,7 @@ using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Services; using BTCPayServer.Services.Invoices; +using Microsoft.Extensions.Options; namespace BTCPayServer.HostedServices { @@ -18,9 +19,9 @@ namespace BTCPayServer.HostedServices private readonly InvoiceRepository _invoiceRepository; private readonly SettingsRepository _settingsRepository; private readonly ApplicationDbContextFactory _dbContextFactory; - private readonly DataDirectories _datadirs; + private readonly IOptions _datadirs; - public DbMigrationsHostedService(InvoiceRepository invoiceRepository, SettingsRepository settingsRepository, ApplicationDbContextFactory dbContextFactory, DataDirectories datadirs) + public DbMigrationsHostedService(InvoiceRepository invoiceRepository, SettingsRepository settingsRepository, ApplicationDbContextFactory dbContextFactory, IOptions datadirs) { _invoiceRepository = invoiceRepository; _settingsRepository = settingsRepository; @@ -48,7 +49,7 @@ namespace BTCPayServer.HostedServices private async Task MigratedInvoiceTextSearchToDb(int startFromPage) { // deleting legacy DBriize database if present - var dbpath = Path.Combine(_datadirs.DataDir, "InvoiceDB"); + var dbpath = Path.Combine(_datadirs.Value.DataDir, "InvoiceDB"); if (Directory.Exists(dbpath)) { Directory.Delete(dbpath, true); diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 8dbd90234..8c6f6b9f3 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -70,7 +70,6 @@ namespace BTCPayServer.Hosting } public static IServiceCollection AddBTCPayServer(this IServiceCollection services, IConfiguration configuration) { - services.AddSingleton(); services.AddSingleton(o => o.GetRequiredService>().Value); services.AddDbContext((provider, o) => { @@ -244,7 +243,7 @@ namespace BTCPayServer.Hosting services.TryAddSingleton(); services.AddSingleton(); - services.AddSingleton(provider => provider.GetService()); + services.AddSingleton(); services.TryAddTransient(); services.TryAddSingleton(o => { diff --git a/BTCPayServer/Plugins/PluginHookService.cs b/BTCPayServer/Plugins/PluginHookService.cs new file mode 100644 index 000000000..650be76fe --- /dev/null +++ b/BTCPayServer/Plugins/PluginHookService.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using Microsoft.Extensions.Logging; + +namespace BTCPayServer.Plugins +{ + public class PluginHookService : IPluginHookService + { + private readonly IEnumerable _actions; + private readonly IEnumerable _filters; + private readonly ILogger _logger; + + public PluginHookService(IEnumerable actions, IEnumerable filters, + ILogger logger) + { + _actions = actions; + _filters = filters; + _logger = logger; + } + + // Trigger simple action hook for registered plugins + public async Task ApplyAction(string hook, object args) + { + var filters = _actions + .Where(filter => filter.Hook.Equals(hook, StringComparison.InvariantCultureIgnoreCase)).ToList(); + foreach (IPluginHookAction pluginHookFilter in filters) + { + try + { + await pluginHookFilter.Execute(args); + } + catch (Exception e) + { + _logger.LogError(e, $"Action on hook {hook} failed"); + } + } + } + + // Trigger hook on which registered plugins can optionally return modified args or new object back + public async Task ApplyFilter(string hook, object args) + { + var filters = _filters + .Where(filter => filter.Hook.Equals(hook, StringComparison.InvariantCultureIgnoreCase)).ToList(); + foreach (IPluginHookFilter pluginHookFilter in filters) + { + try + { + args = await pluginHookFilter.Execute(args); + } + catch (Exception e) + { + _logger.LogError(e, $"Filter on hook {hook} failed"); + } + } + + return args; + } + } +} diff --git a/BTCPayServer/Plugins/PluginService.cs b/BTCPayServer/Plugins/PluginService.cs index 871c625c9..d5a8e279c 100644 --- a/BTCPayServer/Plugins/PluginService.cs +++ b/BTCPayServer/Plugins/PluginService.cs @@ -16,23 +16,19 @@ using Newtonsoft.Json; namespace BTCPayServer.Plugins { - public class PluginService: IPluginHookService + public class PluginService { - private readonly IOptions _datadirs; - private readonly BTCPayServerOptions _options; + private readonly IOptions _dataDirectories; + private readonly BTCPayServerOptions _btcPayServerOptions; private readonly HttpClient _githubClient; - private readonly IEnumerable _actions; - private readonly IEnumerable _filters; public PluginService(IEnumerable btcPayServerPlugins, - IHttpClientFactory httpClientFactory, IOptions datadirs, BTCPayServerOptions options, IEnumerable actions, IEnumerable filters) + IHttpClientFactory httpClientFactory, BTCPayServerOptions btcPayServerOptions, IOptions dataDirectories) { LoadedPlugins = btcPayServerPlugins; _githubClient = httpClientFactory.CreateClient(); _githubClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("btcpayserver", "1")); - _datadirs = datadirs; - _options = options; - _actions = actions; - _filters = filters; + _btcPayServerOptions = btcPayServerOptions; + _dataDirectories = dataDirectories; } public IEnumerable LoadedPlugins { get; } @@ -40,7 +36,7 @@ namespace BTCPayServer.Plugins public async Task> GetRemotePlugins() { var resp = await _githubClient - .GetStringAsync(new Uri($"https://api.github.com/repos/{_options.PluginRemote}/contents")); + .GetStringAsync(new Uri($"https://api.github.com/repos/{_btcPayServerOptions.PluginRemote}/contents")); var files = JsonConvert.DeserializeObject(resp); return await Task.WhenAll(files.Where(file => file.Name.EndsWith($"{PluginManager.BTCPayPluginSuffix}.json", StringComparison.InvariantCulture)).Select(async file => { @@ -51,9 +47,9 @@ namespace BTCPayServer.Plugins public async Task DownloadRemotePlugin(string plugin) { - var dest = _datadirs.Value.PluginDir; + var dest = _dataDirectories.Value.PluginDir; var resp = await _githubClient - .GetStringAsync(new Uri($"https://api.github.com/repos/{_options.PluginRemote}/contents")); + .GetStringAsync(new Uri($"https://api.github.com/repos/{_btcPayServerOptions.PluginRemote}/contents")); var files = JsonConvert.DeserializeObject(resp); var ext = files.SingleOrDefault(file => file.Name == $"{plugin}{PluginManager.BTCPayPluginSuffix}"); if (ext is null) @@ -68,19 +64,19 @@ namespace BTCPayServer.Plugins public void InstallPlugin(string plugin) { - var dest = _datadirs.Value.PluginDir; + var dest = _dataDirectories.Value.PluginDir; UninstallPlugin(plugin); PluginManager.QueueCommands(dest, ("install", plugin)); } public void UpdatePlugin(string plugin) { - var dest = _datadirs.Value.PluginDir; + var dest = _dataDirectories.Value.PluginDir; PluginManager.QueueCommands(dest, ("update", plugin)); } public async Task UploadPlugin(IFormFile plugin) { - var dest = _datadirs.Value.PluginDir; + var dest = _dataDirectories.Value.PluginDir; var filedest = Path.Combine(dest, plugin.FileName); Directory.CreateDirectory(Path.GetDirectoryName(filedest)); if (Path.GetExtension(filedest) == PluginManager.BTCPayPluginSuffix) @@ -92,7 +88,7 @@ namespace BTCPayServer.Plugins public void UninstallPlugin(string plugin) { - var dest = _datadirs.Value.PluginDir; + var dest = _dataDirectories.Value.PluginDir; PluginManager.QueueCommands(dest, ("delete", plugin)); } @@ -127,34 +123,12 @@ namespace BTCPayServer.Plugins public (string command, string plugin)[] GetPendingCommands() { - return PluginManager.GetPendingCommands(_datadirs.Value.PluginDir); + return PluginManager.GetPendingCommands(_dataDirectories.Value.PluginDir); } public void CancelCommands(string plugin) { - PluginManager.CancelCommands(_datadirs.Value.PluginDir, plugin); - } - - public async Task ApplyAction(string hook, object args) - { - var filters = _actions - .Where(filter => filter.Hook.Equals(hook, StringComparison.InvariantCultureIgnoreCase)).ToList(); - foreach (IPluginHookAction pluginHookFilter in filters) - { - await pluginHookFilter.Execute(args); - } - } - - public async Task ApplyFilter(string hook, object args) - { - var filters = _filters - .Where(filter => filter.Hook.Equals(hook, StringComparison.InvariantCultureIgnoreCase)).ToList(); - foreach (IPluginHookFilter pluginHookFilter in filters) - { - args = await pluginHookFilter.Execute(args); - } - - return args; + PluginManager.CancelCommands(_dataDirectories.Value.PluginDir, plugin); } } } diff --git a/btcpayserver.sln b/btcpayserver.sln index 095cf7a63..8e46fb7bb 100644 --- a/btcpayserver.sln +++ b/btcpayserver.sln @@ -278,5 +278,6 @@ Global GlobalSection(NestedProjects) = preSolution {545AFC8E-7BC2-43D9-84CA-F9468F4FF295} = {1FC7F660-ADF1-4D55-B61A-85C6AB083C33} {7DC94B25-1CFC-4170-AA41-7BA983E4C0B8} = {1FC7F660-ADF1-4D55-B61A-85C6AB083C33} + {3E7D4925-0CA6-4A86-87BA-5BD00E5AA4A5} = {1FC7F660-ADF1-4D55-B61A-85C6AB083C33} EndGlobalSection EndGlobal