btcpayserver/BTCPayServer/HostedServices/MigratorHostedService.cs
nicolas.dorier ae4b2ab1fd
Fix #875
2019-06-03 16:46:35 +09:00

210 lines
8.1 KiB
C#

using System;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Services;
using BTCPayServer.Services.Stores;
using BTCPayServer.Logging;
namespace BTCPayServer.HostedServices
{
public class MigratorHostedService : BaseAsyncService
{
private ApplicationDbContextFactory _DBContextFactory;
private StoreRepository _StoreRepository;
private BTCPayNetworkProvider _NetworkProvider;
private SettingsRepository _Settings;
public MigratorHostedService(
BTCPayNetworkProvider networkProvider,
StoreRepository storeRepository,
ApplicationDbContextFactory dbContextFactory,
SettingsRepository settingsRepository)
{
_DBContextFactory = dbContextFactory;
_StoreRepository = storeRepository;
_NetworkProvider = networkProvider;
_Settings = settingsRepository;
}
internal override Task[] InitializeTasks()
{
return new[]
{
Update()
};
}
private async Task Update()
{
try
{
var settings = (await _Settings.GetSettingAsync<MigrationSettings>()) ?? new MigrationSettings();
if (!settings.DeprecatedLightningConnectionStringCheck)
{
await DeprecatedLightningConnectionStringCheck();
settings.DeprecatedLightningConnectionStringCheck = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.UnreachableStoreCheck)
{
await UnreachableStoreCheck();
settings.UnreachableStoreCheck = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.ConvertMultiplierToSpread)
{
await ConvertMultiplierToSpread();
settings.ConvertMultiplierToSpread = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.ConvertNetworkFeeProperty)
{
await ConvertNetworkFeeProperty();
settings.ConvertNetworkFeeProperty = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.ConvertCrowdfundOldSettings)
{
await ConvertCrowdfundOldSettings();
settings.ConvertCrowdfundOldSettings = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.ConvertWalletKeyPathRoots)
{
await ConvertConvertWalletKeyPathRoots();
settings.ConvertWalletKeyPathRoots = true;
await _Settings.UpdateSetting(settings);
}
}
catch (Exception ex)
{
Logs.PayServer.LogError(ex, "Error on the MigratorHostedService");
throw;
}
}
private async Task ConvertConvertWalletKeyPathRoots()
{
bool save = false;
using (var ctx = _DBContextFactory.CreateContext())
{
foreach (var store in await ctx.Stores.ToArrayAsync())
{
#pragma warning disable CS0618 // Type or member is obsolete
_StoreRepository.PrepareEntity(store);
var blob = store.GetStoreBlob();
if (blob.WalletKeyPathRoots == null)
continue;
foreach (var scheme in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<DerivationSchemeSettings>())
{
if (blob.WalletKeyPathRoots.TryGetValue(scheme.PaymentId.ToString().ToLowerInvariant(), out var root))
{
scheme.AccountKeyPath = new NBitcoin.KeyPath(root);
store.SetSupportedPaymentMethod(scheme);
save = true;
}
}
blob.WalletKeyPathRoots = null;
store.SetStoreBlob(blob);
#pragma warning restore CS0618 // Type or member is obsolete
}
if (save)
await ctx.SaveChangesAsync();
}
}
private async Task ConvertCrowdfundOldSettings()
{
using (var ctx = _DBContextFactory.CreateContext())
{
foreach (var app in ctx.Apps.Where(a => a.AppType == "Crowdfund"))
{
var settings = app.GetSettings<Services.Apps.CrowdfundSettings>();
#pragma warning disable CS0618 // Type or member is obsolete
if (settings.UseAllStoreInvoices)
#pragma warning restore CS0618 // Type or member is obsolete
{
app.TagAllInvoices = true;
}
}
await ctx.SaveChangesAsync();
}
}
private async Task ConvertNetworkFeeProperty()
{
using (var ctx = _DBContextFactory.CreateContext())
{
foreach (var store in await ctx.Stores.ToArrayAsync())
{
_StoreRepository.PrepareEntity(store);
var blob = store.GetStoreBlob();
#pragma warning disable CS0618 // Type or member is obsolete
if (blob.NetworkFeeDisabled != null)
{
blob.NetworkFeeMode = blob.NetworkFeeDisabled.Value ? NetworkFeeMode.Never : NetworkFeeMode.Always;
blob.NetworkFeeDisabled = null;
store.SetStoreBlob(blob);
}
#pragma warning restore CS0618 // Type or member is obsolete
}
await ctx.SaveChangesAsync();
}
}
private async Task ConvertMultiplierToSpread()
{
using (var ctx = _DBContextFactory.CreateContext())
{
foreach (var store in await ctx.Stores.ToArrayAsync())
{
_StoreRepository.PrepareEntity(store);
var blob = store.GetStoreBlob();
#pragma warning disable CS0612 // Type or member is obsolete
decimal multiplier = 1.0m;
if (blob.RateRules != null && blob.RateRules.Count != 0)
{
foreach (var rule in blob.RateRules)
{
multiplier = rule.Apply(null, multiplier);
}
}
blob.RateRules = null;
blob.Spread = Math.Min(1.0m, Math.Max(0m, -(multiplier - 1.0m)));
store.SetStoreBlob(blob);
#pragma warning restore CS0612 // Type or member is obsolete
}
await ctx.SaveChangesAsync();
}
}
private Task UnreachableStoreCheck()
{
return _StoreRepository.CleanUnreachableStores();
}
private async Task DeprecatedLightningConnectionStringCheck()
{
using (var ctx = _DBContextFactory.CreateContext())
{
foreach (var store in await ctx.Stores.ToArrayAsync())
{
_StoreRepository.PrepareEntity(store);
foreach (var method in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<Payments.Lightning.LightningSupportedPaymentMethod>())
{
var lightning = method.GetLightningUrl();
if (lightning.IsLegacy)
{
method.SetLightningUrl(lightning);
store.SetSupportedPaymentMethod(method);
}
}
}
await ctx.SaveChangesAsync();
}
}
}
}