2020-10-21 14:02:20 +02:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading.Tasks;
|
2020-11-17 13:46:23 +01:00
|
|
|
using BTCPayServer.Abstractions.Contracts;
|
|
|
|
using BTCPayServer.Abstractions.Extensions;
|
|
|
|
using BTCPayServer.Abstractions.Models;
|
2020-10-21 14:02:20 +02:00
|
|
|
using BTCPayServer.Configuration;
|
|
|
|
using BTCPayServer.Plugins;
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2023-01-16 12:12:51 +01:00
|
|
|
using static BTCPayServer.Plugins.PluginService;
|
2020-10-21 14:02:20 +02:00
|
|
|
|
|
|
|
namespace BTCPayServer.Controllers
|
|
|
|
{
|
2022-01-07 04:32:00 +01:00
|
|
|
public partial class UIServerController
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
[HttpGet("server/plugins")]
|
|
|
|
public async Task<IActionResult> ListPlugins(
|
|
|
|
[FromServices] PluginService pluginService,
|
2024-10-09 13:47:11 +02:00
|
|
|
[FromServices] BTCPayServerOptions btcPayServerOptions,
|
|
|
|
string search = null)
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
IEnumerable<PluginService.AvailablePlugin> availablePlugins;
|
|
|
|
try
|
|
|
|
{
|
2024-10-09 13:47:11 +02:00
|
|
|
availablePlugins = await pluginService.GetRemotePlugins(search);
|
2020-10-21 14:02:20 +02:00
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
Severity = StatusMessageModel.StatusSeverity.Error,
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["Remote plugins lookup failed. Try again later."].Value
|
2020-10-21 14:02:20 +02:00
|
|
|
});
|
|
|
|
availablePlugins = Array.Empty<PluginService.AvailablePlugin>();
|
|
|
|
}
|
2023-01-16 12:12:51 +01:00
|
|
|
var availablePluginsByIdentifier = new Dictionary<string, AvailablePlugin>();
|
|
|
|
foreach (var p in availablePlugins)
|
|
|
|
availablePluginsByIdentifier.TryAdd(p.Identifier, p);
|
2020-10-21 14:02:20 +02:00
|
|
|
var res = new ListPluginsViewModel()
|
|
|
|
{
|
|
|
|
Installed = pluginService.LoadedPlugins,
|
|
|
|
Available = availablePlugins,
|
|
|
|
Commands = pluginService.GetPendingCommands(),
|
2021-04-01 05:27:22 +02:00
|
|
|
Disabled = pluginService.GetDisabledPlugins(),
|
2023-02-24 13:52:46 +01:00
|
|
|
CanShowRestart = true,
|
2023-01-16 12:12:51 +01:00
|
|
|
DownloadedPluginsByIdentifier = availablePluginsByIdentifier
|
2020-10-21 14:02:20 +02:00
|
|
|
};
|
|
|
|
return View(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ListPluginsViewModel
|
|
|
|
{
|
|
|
|
public IEnumerable<IBTCPayServerPlugin> Installed { get; set; }
|
|
|
|
public IEnumerable<PluginService.AvailablePlugin> Available { get; set; }
|
|
|
|
public (string command, string plugin)[] Commands { get; set; }
|
|
|
|
public bool CanShowRestart { get; set; }
|
2024-01-18 09:15:16 +01:00
|
|
|
public Dictionary<string, Version> Disabled { get; set; }
|
2023-01-16 12:12:51 +01:00
|
|
|
public Dictionary<string, AvailablePlugin> DownloadedPluginsByIdentifier { get; set; } = new Dictionary<string, AvailablePlugin>();
|
2020-10-21 14:02:20 +02:00
|
|
|
}
|
|
|
|
|
2024-10-11 12:35:37 +02:00
|
|
|
[HttpPost("server/plugins/uninstall-all")]
|
|
|
|
public IActionResult UnInstallAllDisabledPlugin(
|
|
|
|
[FromServices] PluginService pluginService, string plugin)
|
|
|
|
{
|
|
|
|
var disabled = pluginService.GetDisabledPlugins();
|
|
|
|
foreach (var d in disabled)
|
|
|
|
pluginService.UninstallPlugin(d.Key);
|
|
|
|
return RedirectToAction(nameof(ListPlugins));
|
|
|
|
}
|
|
|
|
|
2020-10-21 14:02:20 +02:00
|
|
|
[HttpPost("server/plugins/uninstall")]
|
|
|
|
public IActionResult UnInstallPlugin(
|
|
|
|
[FromServices] PluginService pluginService, string plugin)
|
|
|
|
{
|
|
|
|
pluginService.UninstallPlugin(plugin);
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["Plugin scheduled to be uninstalled."].Value,
|
2020-10-21 14:02:20 +02:00
|
|
|
Severity = StatusMessageModel.StatusSeverity.Success
|
|
|
|
});
|
|
|
|
|
|
|
|
return RedirectToAction("ListPlugins");
|
|
|
|
}
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2020-10-21 14:02:20 +02:00
|
|
|
[HttpPost("server/plugins/cancel")]
|
|
|
|
public IActionResult CancelPluginCommands(
|
|
|
|
[FromServices] PluginService pluginService, string plugin)
|
|
|
|
{
|
|
|
|
pluginService.CancelCommands(plugin);
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["Plugin action cancelled."].Value,
|
2020-10-21 14:02:20 +02:00
|
|
|
Severity = StatusMessageModel.StatusSeverity.Success
|
|
|
|
});
|
|
|
|
|
|
|
|
return RedirectToAction("ListPlugins");
|
|
|
|
}
|
|
|
|
|
|
|
|
[HttpPost("server/plugins/install")]
|
|
|
|
public async Task<IActionResult> InstallPlugin(
|
2022-11-21 02:23:25 +01:00
|
|
|
[FromServices] PluginService pluginService, string plugin, bool update = false, string version = null)
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2022-11-21 02:23:25 +01:00
|
|
|
await pluginService.DownloadRemotePlugin(plugin, version);
|
2020-11-05 15:43:14 +01:00
|
|
|
if (update)
|
|
|
|
{
|
|
|
|
pluginService.UpdatePlugin(plugin);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pluginService.InstallPlugin(plugin);
|
|
|
|
}
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["Plugin scheduled to be installed."].Value,
|
2020-10-21 14:02:20 +02:00
|
|
|
Severity = StatusMessageModel.StatusSeverity.Success
|
|
|
|
});
|
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["The plugin could not be downloaded. Try again later."].Value,
|
2021-12-31 08:59:02 +01:00
|
|
|
Severity = StatusMessageModel.StatusSeverity.Error
|
2020-10-21 14:02:20 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return RedirectToAction("ListPlugins");
|
|
|
|
}
|
|
|
|
|
|
|
|
[HttpPost("server/plugins/upload")]
|
|
|
|
public async Task<IActionResult> UploadPlugin([FromServices] PluginService pluginService,
|
|
|
|
List<IFormFile> files)
|
|
|
|
{
|
2021-03-19 10:55:07 +01:00
|
|
|
foreach (var formFile in files.Where(file => file.Length > 0).Where(file => file.FileName.IsValidFileName()))
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
await pluginService.UploadPlugin(formFile);
|
|
|
|
pluginService.InstallPlugin(formFile.FileName.TrimEnd(PluginManager.BTCPayPluginSuffix,
|
|
|
|
StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
}
|
|
|
|
|
2024-10-17 15:51:40 +02:00
|
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
2022-03-23 16:03:39 +01:00
|
|
|
{
|
2024-10-17 15:51:40 +02:00
|
|
|
Message = StringLocalizer["Files uploaded, restart server to load plugins"].Value,
|
2022-03-23 16:03:39 +01:00
|
|
|
Severity = StatusMessageModel.StatusSeverity.Success
|
|
|
|
});
|
|
|
|
return RedirectToAction("ListPlugins");
|
2020-10-21 14:02:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|