diff --git a/BTCPayServer.Abstractions/Extensions/HttpRequestExtensions.cs b/BTCPayServer.Abstractions/Extensions/HttpRequestExtensions.cs
index f0706daec..39522d040 100644
--- a/BTCPayServer.Abstractions/Extensions/HttpRequestExtensions.cs
+++ b/BTCPayServer.Abstractions/Extensions/HttpRequestExtensions.cs
@@ -12,14 +12,10 @@ public static class HttpRequestExtensions
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
}
+ public static RequestBaseUrl GetRequestBaseUrl(this HttpRequest request) => new (request);
+
public static string GetAbsoluteRoot(this HttpRequest request)
- {
- return string.Concat(
- request.Scheme,
- "://",
- request.Host.ToUriComponent(),
- request.PathBase.ToUriComponent());
- }
+ => request.GetRequestBaseUrl().ToString();
public static Uri GetAbsoluteRootUri(this HttpRequest request)
{
@@ -105,7 +101,7 @@ public static class HttpRequestExtensions
}
///
- /// Will return an absolute URL.
+ /// Will return an absolute URL.
/// If `relativeOrAbsolute` is absolute, returns it.
/// If `relativeOrAbsolute` is relative, send absolute url based on the HOST of this request (without PathBase)
///
diff --git a/BTCPayServer.Abstractions/RequestBaseUrl.cs b/BTCPayServer.Abstractions/RequestBaseUrl.cs
new file mode 100644
index 000000000..a3c223a49
--- /dev/null
+++ b/BTCPayServer.Abstractions/RequestBaseUrl.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.AspNetCore.Http;
+
+namespace BTCPayServer.Abstractions;
+
+public record RequestBaseUrl(string Scheme, HostString Host, PathString PathBase)
+{
+ public static RequestBaseUrl FromUrl(Uri url)
+ => new RequestBaseUrl(url.Scheme, new HostString(url.Authority), new PathString(url.AbsolutePath));
+
+ public static RequestBaseUrl FromUrl(string url)
+ {
+ if (TryFromUrl(url, out var result))
+ return result;
+ throw new FormatException("Invalid RequestBaseUrl");
+ }
+ public static bool TryFromUrl(string url, [MaybeNullWhen(false)] out RequestBaseUrl result)
+ {
+ ArgumentNullException.ThrowIfNull(url);
+ result = null;
+ if (!Uri.TryCreate(url, UriKind.Absolute, out var o))
+ return false;
+ result = FromUrl(o);
+ return true;
+ }
+
+ public RequestBaseUrl(HttpRequest request) : this(request.Scheme, request.Host, request.PathBase)
+ {
+
+ }
+
+ public override string ToString()
+ => string.Concat(
+ Scheme,
+ "://",
+ Host.ToUriComponent(),
+ PathBase.ToUriComponent());
+}
diff --git a/BTCPayServer.Data/ApplicationDbContextExtensions.cs b/BTCPayServer.Data/ApplicationDbContextExtensions.cs
new file mode 100644
index 000000000..6969fae86
--- /dev/null
+++ b/BTCPayServer.Data/ApplicationDbContextExtensions.cs
@@ -0,0 +1,21 @@
+#nullable enable
+using System;
+using System.Data.Common;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+
+namespace BTCPayServer.Data;
+
+public static partial class ApplicationDbContextExtensions
+{
+ public static DbContext GetDbContext(this DbSet dbSet) where T : class
+ {
+ var infrastructure = dbSet as IInfrastructure;
+ var serviceProvider = infrastructure.Instance;
+ var currentDbContext = (ICurrentDbContext)serviceProvider.GetService(typeof(ICurrentDbContext))!;
+ return currentDbContext.Context;
+ }
+
+ public static DbConnection GetDbConnection(this DbSet dbSet) where T : class
+ => dbSet.GetDbContext().Database.GetDbConnection();
+}
diff --git a/BTCPayServer.Data/ApplicationDbContextFactory.cs b/BTCPayServer.Data/ApplicationDbContextFactory.cs
index feeb31209..0f1dfb3dd 100644
--- a/BTCPayServer.Data/ApplicationDbContextFactory.cs
+++ b/BTCPayServer.Data/ApplicationDbContextFactory.cs
@@ -2,6 +2,7 @@ using System;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Models;
using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
@@ -22,6 +23,11 @@ namespace BTCPayServer.Data
var builder = new DbContextOptionsBuilder();
builder.UseLoggerFactory(LoggerFactory);
builder.AddInterceptors(MigrationInterceptor.Instance);
+ builder.ConfigureWarnings(w =>
+ {
+ w.Log((CoreEventId.OptimisticConcurrencyException, LogLevel.Debug));
+ w.Log((CoreEventId.SaveChangesFailed, LogLevel.Debug));
+ });
ConfigureBuilder(builder, npgsqlOptionsAction);
return new ApplicationDbContext(builder.Options);
}
diff --git a/BTCPayServer.Rating/CurrencyNameTable.cs b/BTCPayServer.Rating/CurrencyNameTable.cs
index 5a0430abe..87a665b98 100644
--- a/BTCPayServer.Rating/CurrencyNameTable.cs
+++ b/BTCPayServer.Rating/CurrencyNameTable.cs
@@ -120,6 +120,9 @@ namespace BTCPayServer.Services.Rates
return ni;
return null;
}
+ public NumberFormatInfo GetNumberFormatInfoOrDefault(string currency)
+ => GetNumberFormatInfo(currency) ?? GetNumberFormatInfo("USD")!;
+
public IFormatProvider GetCurrencyProvider(string currency)
{
diff --git a/BTCPayServer/Components/InvoiceStatus/InvoiceStatus.cs b/BTCPayServer/Components/InvoiceStatus/InvoiceStatus.cs
index 8efb5f8ec..c73a9adf9 100644
--- a/BTCPayServer/Components/InvoiceStatus/InvoiceStatus.cs
+++ b/BTCPayServer/Components/InvoiceStatus/InvoiceStatus.cs
@@ -6,13 +6,13 @@ namespace BTCPayServer.Components.InvoiceStatus
{
public class InvoiceStatus : ViewComponent
{
- public IViewComponentResult Invoke(InvoiceState state, List payments, string invoiceId, bool isArchived = false, bool hasRefund = false)
+ public IViewComponentResult Invoke(InvoiceState state, List payments = null, string invoiceId = null, bool isArchived = false, bool hasRefund = false)
{
var vm = new InvoiceStatusViewModel
{
State = state,
- Payments = payments,
- InvoiceId = invoiceId,
+ Payments = payments ?? new(),
+ InvoiceId = invoiceId ?? string.Empty,
IsArchived = isArchived,
HasRefund = hasRefund
};
diff --git a/BTCPayServer/Components/MainNav/MainNav.cs b/BTCPayServer/Components/MainNav/MainNav.cs
index e04bfc036..2c33e18d1 100644
--- a/BTCPayServer/Components/MainNav/MainNav.cs
+++ b/BTCPayServer/Components/MainNav/MainNav.cs
@@ -104,7 +104,7 @@ namespace BTCPayServer.Components.MainNav
catch when (cts.IsCancellationRequested) { }
}
}
-
+
vm.DerivationSchemes = derivationSchemes;
vm.LightningNodes = lightningNodes;
@@ -116,12 +116,13 @@ namespace BTCPayServer.Components.MainNav
{
Id = a.Id,
AppName = a.AppName,
- AppType = a.AppType
+ AppType = a.AppType,
+ Data = a.App
}).ToList();
vm.ArchivedAppsCount = apps.Count(a => a.Archived);
}
-
+
var user = await _userManager.GetUserAsync(HttpContext.User);
if (user != null)
{
diff --git a/BTCPayServer/Components/MainNav/MainNavViewModel.cs b/BTCPayServer/Components/MainNav/MainNavViewModel.cs
index d5083d117..830e745a5 100644
--- a/BTCPayServer/Components/MainNav/MainNavViewModel.cs
+++ b/BTCPayServer/Components/MainNav/MainNavViewModel.cs
@@ -21,5 +21,6 @@ namespace BTCPayServer.Components.MainNav
public string Id { get; set; }
public string AppName { get; set; }
public string AppType { get; set; }
+ public AppData Data { get; set; }
}
}