btcpayserver/BTCPayServer/Hosting/BTCPayServerServices.cs

311 lines
15 KiB
C#
Raw Normal View History

2017-09-13 08:47:34 +02:00
using BTCPayServer.Configuration;
using BTCPayServer.Services.Altcoins.Monero;
using Microsoft.Extensions.Logging;
2017-09-13 08:47:34 +02:00
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.AspNetCore.Http;
using NBitpayClient;
using NBitcoin;
using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using BTCPayServer.Services;
2017-10-20 21:06:37 +02:00
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Fees;
2017-09-15 12:25:02 +02:00
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using BTCPayServer.Controllers;
using BTCPayServer.Services.Mails;
2017-09-27 16:56:43 +02:00
using System.Threading;
using BTCPayServer.Services.Wallets;
using BTCPayServer.Logging;
using BTCPayServer.HostedServices;
2019-01-14 22:43:29 +01:00
using BTCPayServer.PaymentRequest;
2019-05-24 08:11:38 +02:00
using BTCPayServer.Payments;
using BTCPayServer.Payments.Bitcoin;
using BTCPayServer.Payments.Changelly;
2019-01-07 09:52:27 +01:00
using BTCPayServer.Payments.Lightning;
2020-01-06 13:57:32 +01:00
using BTCPayServer.Payments.PayJoin;
2018-04-29 19:33:42 +02:00
using BTCPayServer.Security;
2019-01-14 22:43:29 +01:00
using BTCPayServer.Services.PaymentRequests;
2018-07-26 15:32:24 +02:00
using Microsoft.AspNetCore.Mvc.ModelBinding;
using NBXplorer.DerivationStrategy;
using NicolasDorier.RateLimits;
using Npgsql;
2019-02-19 05:04:58 +01:00
using BTCPayServer.Services.Apps;
using BTCPayServer.U2F;
using BundlerMinifier.TagHelpers;
2019-10-12 13:35:30 +02:00
using Microsoft.AspNetCore.Authorization;
using BTCPayServer.Security.Bitpay;
using Serilog;
2020-03-27 04:55:21 +01:00
using BTCPayServer.Security.GreenField;
using BTCPayServer.Services.Labels;
2017-09-13 08:47:34 +02:00
namespace BTCPayServer.Hosting
{
public static class BTCPayServerServices
{
public static IServiceCollection AddBTCPayServer(this IServiceCollection services, IConfiguration configuration)
{
2019-10-03 10:06:49 +02:00
services.AddSingleton<MvcNewtonsoftJsonOptions>(o => o.GetRequiredService<IOptions<MvcNewtonsoftJsonOptions>>().Value);
services.AddDbContext<ApplicationDbContext>((provider, o) =>
{
var factory = provider.GetRequiredService<ApplicationDbContextFactory>();
factory.ConfigureBuilder(o);
});
2018-08-21 07:33:13 +02:00
services.AddHttpClient();
2019-06-18 06:37:24 +02:00
services.AddHttpClient(nameof(ExplorerClientProvider), httpClient =>
{
httpClient.Timeout = Timeout.InfiniteTimeSpan;
});
2020-01-06 13:57:32 +01:00
services.AddPayJoinServices();
services.AddMoneroLike();
services.TryAddSingleton<SettingsRepository>();
services.TryAddSingleton<LabelFactory>();
services.TryAddSingleton<TorServices>();
services.TryAddSingleton<SocketFactory>();
services.TryAddSingleton<LightningClientFactoryService>();
services.TryAddSingleton<InvoicePaymentNotification>();
services.TryAddSingleton<BTCPayServerOptions>(o =>
o.GetRequiredService<IOptions<BTCPayServerOptions>>().Value);
services.AddStartupTask<MigrationStartupTask>();
services.TryAddSingleton<InvoiceRepository>(o =>
{
var opts = o.GetRequiredService<BTCPayServerOptions>();
var dbContext = o.GetRequiredService<ApplicationDbContextFactory>();
var dbpath = Path.Combine(opts.DataDir, "InvoiceDB");
if (!Directory.Exists(dbpath))
Directory.CreateDirectory(dbpath);
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>());
});
services.AddSingleton<BTCPayServerEnvironment>();
services.TryAddSingleton<TokenRepository>();
services.TryAddSingleton<WalletRepository>();
services.TryAddSingleton<EventAggregator>();
2019-01-14 22:43:29 +01:00
services.TryAddSingleton<PaymentRequestService>();
services.TryAddSingleton<U2FService>();
services.TryAddSingleton<ApplicationDbContextFactory>(o =>
{
var opts = o.GetRequiredService<BTCPayServerOptions>();
ApplicationDbContextFactory dbContext = null;
if (!String.IsNullOrEmpty(opts.PostgresConnectionString))
{
Logs.Configuration.LogInformation($"Postgres DB used ({opts.PostgresConnectionString})");
dbContext = new ApplicationDbContextFactory(DatabaseType.Postgres, opts.PostgresConnectionString);
}
else if(!String.IsNullOrEmpty(opts.MySQLConnectionString))
{
Logs.Configuration.LogInformation($"MySQL DB used ({opts.MySQLConnectionString})");
2019-09-06 08:13:26 +02:00
Logs.Configuration.LogWarning("MySQL is not widely tested and should be considered experimental, we advise you to use postgres instead.");
dbContext = new ApplicationDbContextFactory(DatabaseType.MySQL, opts.MySQLConnectionString);
}
else
{
var connStr = "Data Source=" + Path.Combine(opts.DataDir, "sqllite.db");
Logs.Configuration.LogInformation($"SQLite DB used ({connStr})");
2019-09-06 08:13:26 +02:00
Logs.Configuration.LogWarning("MySQL is not widely tested and should be considered experimental, we advise you to use postgres instead.");
dbContext = new ApplicationDbContextFactory(DatabaseType.Sqlite, connStr);
}
return dbContext;
});
services.TryAddSingleton<BTCPayNetworkProvider>(o =>
{
var opts = o.GetRequiredService<BTCPayServerOptions>();
return opts.NetworkProvider;
});
2019-02-19 05:04:58 +01:00
services.TryAddSingleton<AppService>();
services.TryAddTransient<Safe>();
services.TryAddSingleton<Ganss.XSS.HtmlSanitizer>(o =>
{
var htmlSanitizer = new Ganss.XSS.HtmlSanitizer();
htmlSanitizer.RemovingAtRule += (sender, args) =>
{
};
htmlSanitizer.RemovingTag += (sender, args) =>
{
if (args.Tag.TagName.Equals("img", StringComparison.InvariantCultureIgnoreCase))
{
if (!args.Tag.ClassList.Contains("img-fluid"))
{
args.Tag.ClassList.Add("img-fluid");
}
args.Cancel = true;
}
};
htmlSanitizer.RemovingAttribute += (sender, args) =>
{
if (args.Tag.TagName.Equals("img", StringComparison.InvariantCultureIgnoreCase) &&
args.Attribute.Name.Equals("src", StringComparison.InvariantCultureIgnoreCase) &&
args.Reason == Ganss.XSS.RemoveReason.NotAllowedUrlValue)
{
args.Cancel = true;
}
};
htmlSanitizer.RemovingStyle += (sender, args) => { args.Cancel = true; };
htmlSanitizer.AllowedAttributes.Add("class");
htmlSanitizer.AllowedTags.Add("iframe");
htmlSanitizer.AllowedTags.Remove("img");
htmlSanitizer.AllowedAttributes.Add("webkitallowfullscreen");
htmlSanitizer.AllowedAttributes.Add("allowfullscreen");
return htmlSanitizer;
});
2018-07-22 11:38:14 +02:00
services.TryAddSingleton<LightningConfigurationProvider>();
2018-03-23 09:27:48 +01:00
services.TryAddSingleton<LanguageService>();
2018-01-07 20:14:35 +01:00
services.TryAddSingleton<NBXplorerDashboard>();
services.TryAddSingleton<StoreRepository>();
2019-01-14 22:43:29 +01:00
services.TryAddSingleton<PaymentRequestRepository>();
services.TryAddSingleton<BTCPayWalletProvider>();
services.TryAddSingleton<WalletReceiveStateService>();
services.TryAddSingleton<CurrencyNameTable>(CurrencyNameTable.Instance);
services.TryAddSingleton<IFeeProviderFactory>(o => new NBXplorerFeeProviderFactory(o.GetRequiredService<ExplorerClientProvider>())
{
Fallback = new FeeRate(100L, 1)
});
services.AddSingleton<CssThemeManager>();
2018-07-26 15:32:24 +02:00
services.Configure<MvcOptions>((o) => {
o.Filters.Add(new ContentSecurityPolicyCssThemeManager());
o.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(WalletId)));
o.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(DerivationStrategyBase)));
});
services.AddSingleton<IHostedService, CssThemeManagerHostedService>();
services.AddSingleton<HostedServices.CheckConfigurationHostedService>();
services.AddSingleton<IHostedService, HostedServices.CheckConfigurationHostedService>(o => o.GetRequiredService<CheckConfigurationHostedService>());
2019-05-24 08:11:38 +02:00
services.AddSingleton<BitcoinLikePaymentHandler>();
services.AddSingleton<IPaymentMethodHandler>(provider => provider.GetService<BitcoinLikePaymentHandler>());
services.AddSingleton<IHostedService, NBXplorerListener>();
2019-01-07 09:52:27 +01:00
services.AddSingleton<LightningLikePaymentHandler>();
2019-05-24 08:11:38 +02:00
services.AddSingleton<IPaymentMethodHandler>(provider => provider.GetService<LightningLikePaymentHandler>());
services.AddSingleton<IHostedService, LightningListener>();
services.AddSingleton<PaymentMethodHandlerDictionary>();
services.AddSingleton<ChangellyClientProvider>();
services.AddSingleton<IHostedService, NBXplorerWaiters>();
services.AddSingleton<IHostedService, InvoiceNotificationManager>();
services.AddSingleton<IHostedService, InvoiceWatcher>();
services.AddSingleton<IHostedService, RatesHostedService>();
2019-01-16 11:14:45 +01:00
services.AddSingleton<IHostedService, BackgroundJobSchedulerHostedService>();
services.AddSingleton<IHostedService, AppHubStreamer>();
services.AddSingleton<IHostedService, AppInventoryUpdaterHostedService>();
services.AddSingleton<IHostedService, TransactionLabelMarkerHostedService>();
services.AddSingleton<IHostedService, UserEventHostedService>();
2019-07-24 10:59:30 +02:00
services.AddSingleton<IHostedService, DynamicDnsHostedService>();
2019-03-17 13:07:24 +01:00
services.AddSingleton<IHostedService, TorServicesHostedService>();
2019-01-14 22:43:29 +01:00
services.AddSingleton<IHostedService, PaymentRequestStreamer>();
services.AddSingleton<IHostedService, WalletReceiveCacheUpdater>();
2019-01-16 11:14:45 +01:00
services.AddSingleton<IBackgroundJobClient, BackgroundJobClient>();
2019-10-12 13:35:30 +02:00
services.AddScoped<IAuthorizationHandler, CookieAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, BitpayAuthorizationHandler>();
services.TryAddSingleton<ExplorerClientProvider>();
services.TryAddSingleton<Bitpay>(o =>
{
2018-04-19 09:54:25 +02:00
if (o.GetRequiredService<BTCPayServerOptions>().NetworkType == NetworkType.Mainnet)
return new Bitpay(new Key(), new Uri("https://bitpay.com/"));
else
return new Bitpay(new Key(), new Uri("https://test.bitpay.com/"));
});
services.TryAddSingleton<RateProviderFactory>();
services.TryAddSingleton<RateFetcher>();
services.TryAddScoped<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<AccessTokenController>();
services.AddTransient<InvoiceController>();
2018-12-28 12:07:15 +01:00
services.AddTransient<AppsPublicController>();
2019-01-14 22:43:29 +01:00
services.AddTransient<PaymentRequestController>();
// Add application services.
2019-01-06 15:53:37 +01:00
services.AddSingleton<EmailSenderFactory>();
services.AddAPIKeyAuthentication();
services.AddBtcPayServerAuthenticationSchemes();
2019-10-12 13:35:30 +02:00
services.AddAuthorization(o => o.AddBTCPayPolicies());
// bundling
services.AddSingleton<IBundleProvider, ResourceBundleProvider>();
services.AddTransient<BundleOptions>(provider =>
{
var opts = provider.GetRequiredService<BTCPayServerOptions>();
var bundle = new BundleOptions();
2018-08-25 16:08:46 +02:00
bundle.UseBundles = opts.BundleJsCss;
bundle.AppendVersion = true;
return bundle;
});
2017-09-15 12:25:02 +02:00
services.AddCors(options =>
{
options.AddPolicy(CorsPolicies.All, p => p.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
});
services.AddSingleton(provider =>
{
var btcPayEnv = provider.GetService<BTCPayServerEnvironment>();
var rateLimits = new RateLimitService();
if (btcPayEnv.IsDevelopping)
{
rateLimits.SetZone($"zone={ZoneLimits.Login} rate=1000r/min burst=100 nodelay");
rateLimits.SetZone($"zone={ZoneLimits.Register} rate=1000r/min burst=100 nodelay");
2020-01-06 13:57:32 +01:00
rateLimits.SetZone($"zone={ZoneLimits.PayJoin} rate=1000r/min burst=100 nodelay");
}
else
{
rateLimits.SetZone($"zone={ZoneLimits.Login} rate=5r/min burst=3 nodelay");
rateLimits.SetZone($"zone={ZoneLimits.Register} rate=2r/min burst=2 nodelay");
2020-03-13 16:52:50 +01:00
rateLimits.SetZone($"zone={ZoneLimits.PayJoin} rate=5r/min burst=3 nodelay");
}
return rateLimits;
});
services.AddLogging(logBuilder =>
{
var debugLogFile = BTCPayServerOptions.GetDebugLog(configuration);
if (!string.IsNullOrEmpty(debugLogFile))
{
Serilog.Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Is(BTCPayServerOptions.GetDebugLogLevel(configuration))
.WriteTo.File(debugLogFile, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: MAX_DEBUG_LOG_FILE_SIZE, rollOnFileSizeLimit: true, retainedFileCountLimit: 1)
.CreateLogger();
2020-01-16 06:00:31 +01:00
logBuilder.AddProvider(new Serilog.Extensions.Logging.SerilogLoggerProvider(Log.Logger));
}
});
return services;
}
private const long MAX_DEBUG_LOG_FILE_SIZE = 2000000; // If debug log is in use roll it every N MB.
private static void AddBtcPayServerAuthenticationSchemes(this IServiceCollection services)
{
services.AddAuthentication()
.AddCookie()
.AddBitpayAuthentication()
.AddAPIKeyAuthentication();
}
2017-09-13 08:47:34 +02:00
public static IApplicationBuilder UsePayServer(this IApplicationBuilder app)
{
app.UseMiddleware<BTCPayMiddleware>();
return app;
}
public static IApplicationBuilder UseHeadersOverride(this IApplicationBuilder app)
{
app.UseMiddleware<HeadersOverrideMiddleware>();
return app;
}
}
2017-09-13 08:47:34 +02:00
}