diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldUsersController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldUsersController.cs
index 5db16c948..877aa5dca 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldUsersController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldUsersController.cs
@@ -117,7 +117,7 @@ namespace BTCPayServer.Controllers.Greenfield
if (user.RequiresApproval)
{
- var loginLink = _callbackGenerator.ForLogin(user, Request);
+ var loginLink = _callbackGenerator.ForLogin(user);
return await _userService.SetUserApproval(user.Id, request.Approved, loginLink)
? Ok()
: this.CreateAPIError("invalid-state", $"User is already {(request.Approved ? "approved" : "unapproved")}");
@@ -416,8 +416,8 @@ namespace BTCPayServer.Controllers.Greenfield
var currentUser = await _userManager.GetUserAsync(User);
var userEvent = currentUser switch
{
- { } invitedBy => await UserEvent.Invited.Create(user, invitedBy, _callbackGenerator, Request, request.SendInvitationEmail is not false),
- _ => await UserEvent.Registered.Create(user, _callbackGenerator, Request)
+ { } invitedBy => await UserEvent.Invited.Create(user, invitedBy, _callbackGenerator, request.SendInvitationEmail is not false),
+ _ => await UserEvent.Registered.Create(user, _callbackGenerator)
};
_eventAggregator.Publish(userEvent);
diff --git a/BTCPayServer/Controllers/UIAccountController.cs b/BTCPayServer/Controllers/UIAccountController.cs
index 2239559d6..d35f06b40 100644
--- a/BTCPayServer/Controllers/UIAccountController.cs
+++ b/BTCPayServer/Controllers/UIAccountController.cs
@@ -267,7 +267,7 @@ namespace BTCPayServer.Controllers
{
RememberMe = rememberMe,
UserId = user.Id,
- LNURLEndpoint = new Uri(callbackGenerator.ForLNUrlAuth(user, r, Request))
+ LNURLEndpoint = new Uri(callbackGenerator.ForLNUrlAuth(user, r))
};
}
return null;
@@ -573,7 +573,7 @@ namespace BTCPayServer.Controllers
RegisteredAdmin = true;
}
- eventAggregator.Publish(await UserEvent.Registered.Create(user, callbackGenerator, Request));
+ eventAggregator.Publish(await UserEvent.Registered.Create(user, callbackGenerator));
RegisteredUserId = user.Id;
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Account created."].Value;
@@ -640,7 +640,7 @@ namespace BTCPayServer.Controllers
var result = await userManager.ConfirmEmailAsync(user, code);
if (result.Succeeded)
{
- var approvalLink = callbackGenerator.ForApproval(user, Request);
+ var approvalLink = callbackGenerator.ForApproval(user);
eventAggregator.Publish(new UserEvent.ConfirmedEmail(user, approvalLink));
var hasPassword = await userManager.HasPasswordAsync(user);
@@ -686,7 +686,7 @@ namespace BTCPayServer.Controllers
{
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
- var callbackUri = await callbackGenerator.ForPasswordReset(user, Request);
+ var callbackUri = await callbackGenerator.ForPasswordReset(user);
eventAggregator.Publish(new UserEvent.PasswordResetRequested(user, callbackUri));
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
diff --git a/BTCPayServer/Controllers/UIManageController.cs b/BTCPayServer/Controllers/UIManageController.cs
index 7c1535d92..5fbcaaf4f 100644
--- a/BTCPayServer/Controllers/UIManageController.cs
+++ b/BTCPayServer/Controllers/UIManageController.cs
@@ -219,7 +219,7 @@ namespace BTCPayServer.Controllers
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
- var callbackUrl = await _callbackGenerator.ForEmailConfirmation(user, Request);
+ var callbackUrl = await _callbackGenerator.ForEmailConfirmation(user);
_eventAggregator.Publish(new UserEvent.ConfirmationEmailRequested(user, callbackUrl));
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Verification email sent. Please check your email."].Value;
return RedirectToAction(nameof(Index));
diff --git a/BTCPayServer/Controllers/UIServerController.Users.cs b/BTCPayServer/Controllers/UIServerController.Users.cs
index b52ac5112..e4de5a95a 100644
--- a/BTCPayServer/Controllers/UIServerController.Users.cs
+++ b/BTCPayServer/Controllers/UIServerController.Users.cs
@@ -69,7 +69,7 @@ namespace BTCPayServer.Controllers
InvitationUrl =
string.IsNullOrEmpty(blob?.InvitationToken)
? null
- : _callbackGenerator.ForInvitation(u.Id, blob.InvitationToken, Request),
+ : _callbackGenerator.ForInvitation(u.Id, blob.InvitationToken),
EmailConfirmed = u.RequiresEmailConfirmation ? u.EmailConfirmed : null,
Approved = u.RequiresApproval ? u.Approved : null,
Created = u.Created,
@@ -95,7 +95,7 @@ namespace BTCPayServer.Controllers
Id = user.Id,
Email = user.Email,
Name = blob?.Name,
- InvitationUrl = string.IsNullOrEmpty(blob?.InvitationToken) ? null : _callbackGenerator.ForInvitation(user.Id, blob.InvitationToken, Request),
+ InvitationUrl = string.IsNullOrEmpty(blob?.InvitationToken) ? null : _callbackGenerator.ForInvitation(user.Id, blob.InvitationToken),
ImageUrl = string.IsNullOrEmpty(blob?.ImageUrl) ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), UnresolvedUri.Create(blob.ImageUrl)),
EmailConfirmed = user.RequiresEmailConfirmation ? user.EmailConfirmed : null,
Approved = user.RequiresApproval ? user.Approved : null,
@@ -117,7 +117,7 @@ namespace BTCPayServer.Controllers
if (user.RequiresApproval && viewModel.Approved.HasValue && user.Approved != viewModel.Approved.Value)
{
- var loginLink = _callbackGenerator.ForLogin(user, Request);
+ var loginLink = _callbackGenerator.ForLogin(user);
approvalStatusChanged = await _userService.SetUserApproval(user.Id, viewModel.Approved.Value, loginLink);
}
if (user.RequiresEmailConfirmation && viewModel.EmailConfirmed.HasValue && user.EmailConfirmed != viewModel.EmailConfirmed)
@@ -261,7 +261,7 @@ namespace BTCPayServer.Controllers
var currentUser = await _UserManager.GetUserAsync(HttpContext.User);
var sendEmail = model.SendInvitationEmail && ViewData["CanSendEmail"] is true;
- var evt = await UserEvent.Invited.Create(user, currentUser, _callbackGenerator, Request, sendEmail);
+ var evt = await UserEvent.Invited.Create(user, currentUser, _callbackGenerator, sendEmail);
_eventAggregator.Publish(evt);
var info = sendEmail
@@ -383,7 +383,7 @@ namespace BTCPayServer.Controllers
if (user == null)
return NotFound();
- var loginLink = _callbackGenerator.ForLogin(user, Request);
+ var loginLink = _callbackGenerator.ForLogin(user);
await _userService.SetUserApproval(userId, approved, loginLink);
TempData[WellKnownTempData.SuccessMessage] = approved
@@ -411,7 +411,7 @@ namespace BTCPayServer.Controllers
throw new ApplicationException($"Unable to load user with ID '{userId}'.");
}
- var callbackUrl = await _callbackGenerator.ForEmailConfirmation(user, Request);
+ var callbackUrl = await _callbackGenerator.ForEmailConfirmation(user);
_eventAggregator.Publish(new UserEvent.ConfirmationEmailRequested(user, callbackUrl));
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Verification email sent"].Value;
return RedirectToAction(nameof(ListUsers));
diff --git a/BTCPayServer/Controllers/UIStoresController.Users.cs b/BTCPayServer/Controllers/UIStoresController.Users.cs
index afbaa8f65..915d0e0b8 100644
--- a/BTCPayServer/Controllers/UIStoresController.Users.cs
+++ b/BTCPayServer/Controllers/UIStoresController.Users.cs
@@ -74,7 +74,7 @@ public partial class UIStoresController
(await _userManager.CreateAsync(user)) is { Succeeded: true })
{
var invitationEmail = await _emailSenderFactory.IsComplete();
- var evt = await UserEvent.Invited.Create(user!, currentUser, _callbackGenerator, Request, invitationEmail);
+ var evt = await UserEvent.Invited.Create(user!, currentUser, _callbackGenerator, invitationEmail);
_eventAggregator.Publish(evt);
inviteInfo = invitationEmail
? StringLocalizer["An invitation email has been sent.
You may alternatively share this link with them: {0}", evt.InvitationLink]
diff --git a/BTCPayServer/Events/UserEvent.cs b/BTCPayServer/Events/UserEvent.cs
index 140f57b54..95085711b 100644
--- a/BTCPayServer/Events/UserEvent.cs
+++ b/BTCPayServer/Events/UserEvent.cs
@@ -30,10 +30,10 @@ public class UserEvent(ApplicationUser user)
{
public string ApprovalLink { get; } = approvalLink;
public string ConfirmationEmailLink { get; set; } = confirmationEmail;
- public static async Task Create(ApplicationUser user, CallbackGenerator callbackGenerator, HttpRequest request)
+ public static async Task Create(ApplicationUser user, CallbackGenerator callbackGenerator)
{
- var approvalLink = callbackGenerator.ForApproval(user, request);
- var confirmationEmail = await callbackGenerator.ForEmailConfirmation(user, request);
+ var approvalLink = callbackGenerator.ForApproval(user);
+ var confirmationEmail = await callbackGenerator.ForEmailConfirmation(user);
return new Registered(user, approvalLink, confirmationEmail);
}
}
@@ -43,11 +43,11 @@ public class UserEvent(ApplicationUser user)
public ApplicationUser InvitedByUser { get; } = invitedBy;
public string InvitationLink { get; } = invitationLink;
- public static async Task Create(ApplicationUser user, ApplicationUser currentUser, CallbackGenerator callbackGenerator, HttpRequest request, bool sendEmail)
+ public static async Task Create(ApplicationUser user, ApplicationUser currentUser, CallbackGenerator callbackGenerator, bool sendEmail)
{
- var invitationLink = await callbackGenerator.ForInvitation(user, request);
- var approvalLink = callbackGenerator.ForApproval(user, request);
- var confirmationEmail = await callbackGenerator.ForEmailConfirmation(user, request);
+ var invitationLink = await callbackGenerator.ForInvitation(user);
+ var approvalLink = callbackGenerator.ForApproval(user);
+ var confirmationEmail = await callbackGenerator.ForEmailConfirmation(user);
return new Invited(user, currentUser, invitationLink, approvalLink, confirmationEmail)
{
SendInvitationEmail = sendEmail
diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs
index 1e0f9408b..fb1d1529a 100644
--- a/BTCPayServer/Hosting/BTCPayServerServices.cs
+++ b/BTCPayServer/Hosting/BTCPayServerServices.cs
@@ -87,7 +87,7 @@ namespace BTCPayServer.Hosting
}
public static IServiceCollection AddBTCPayServer(this IServiceCollection services, IConfiguration configuration, Logs logs)
{
- services.TryAddSingleton();
+ services.TryAddScoped();
services.TryAddSingleton();
services.TryAddSingleton();
services.TryAddSingleton();
diff --git a/BTCPayServer/Services/CallbackGenerator.cs b/BTCPayServer/Services/CallbackGenerator.cs
index 2e8dbd9ae..25d10c3ff 100644
--- a/BTCPayServer/Services/CallbackGenerator.cs
+++ b/BTCPayServer/Services/CallbackGenerator.cs
@@ -15,118 +15,93 @@ using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Http.Extensions;
using NBitcoin.DataEncoders;
using System.Runtime.CompilerServices;
+using BTCPayServer.Abstractions;
namespace BTCPayServer.Services
{
- public class CallbackGenerator(LinkGenerator linkGenerator, UserManager userManager)
+ public class CallbackGenerator(
+ LinkGenerator linkGenerator,
+ UserManager userManager,
+ IHttpContextAccessor httpContextAccessor)
{
public LinkGenerator LinkGenerator { get; } = linkGenerator;
public UserManager UserManager { get; } = userManager;
- public string ForLNUrlAuth(ApplicationUser user, byte[] r, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(
- action: nameof(UILNURLAuthController.LoginResponse),
- controller: "UILNURLAuth",
- values: new { userId = user.Id, action = "login", tag = "login", k1 = Encoders.Hex.EncodeData(r) },
- request.Scheme,
- request.Host,
- request.PathBase) ?? throw Bug();
- }
+ public string ForLNUrlAuth(ApplicationUser user, byte[] r)
+ => LinkGenerator.GetUriByAction(
+ action: nameof(UILNURLAuthController.LoginResponse),
+ controller: "UILNURLAuth",
+ values: new { userId = user.Id, action = "login", tag = "login", k1 = Encoders.Hex.EncodeData(r) },
+ GetRequestBaseUrl());
- public string StoreUsersLink(string storeId, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(nameof(UIStoresController.StoreUsers), "UIStores",
- new { storeId }, request.Scheme, request.Host, request.PathBase) ?? throw Bug();
- }
+ private RequestBaseUrl GetRequestBaseUrl()
+ => httpContextAccessor.HttpContext?.Request.GetRequestBaseUrl() ?? throw new InvalidOperationException($"You should be in a HttpContext to call this method");
- public async Task ForEmailConfirmation(ApplicationUser user, HttpRequest request)
+ public string StoreUsersLink(string storeId)
+ => LinkGenerator.GetUriByAction(nameof(UIStoresController.StoreUsers), "UIStores",
+ new { storeId }, GetRequestBaseUrl());
+
+ public async Task ForEmailConfirmation(ApplicationUser user)
{
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
return LinkGenerator.GetUriByAction(nameof(UIAccountController.ConfirmEmail), "UIAccount",
- new { userId = user.Id, code }, request.Scheme, request.Host, request.PathBase) ?? throw Bug();
+ new { userId = user.Id, code }, GetRequestBaseUrl());
}
- public async Task ForInvitation(ApplicationUser user, HttpRequest request)
+
+ public async Task ForInvitation(ApplicationUser user)
{
- var code = await UserManager.GenerateInvitationTokenAsync(user.Id) ?? throw Bug();
- return ForInvitation(user.Id, code, request);
+ var code = await UserManager.GenerateInvitationTokenAsync(user.Id);
+ return ForInvitation(user.Id, code ?? "???");
}
- public string ForInvitation(string userId, string code, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(nameof(UIAccountController.AcceptInvite), "UIAccount",
- new { userId, code }, request.Scheme, request.Host, request.PathBase) ?? throw Bug();
- }
- public async Task ForPasswordReset(ApplicationUser user, HttpRequest request)
+
+ public string ForInvitation(string userId, string code)
+ => LinkGenerator.GetUriByAction(nameof(UIAccountController.AcceptInvite), "UIAccount",
+ new { userId, code }, GetRequestBaseUrl());
+
+ public async Task ForPasswordReset(ApplicationUser user)
{
var code = await UserManager.GeneratePasswordResetTokenAsync(user);
return LinkGenerator.GetUriByAction(
action: nameof(UIAccountController.SetPassword),
controller: "UIAccount",
values: new { userId = user.Id, code },
- scheme: request.Scheme,
- host: request.Host,
- pathBase: request.PathBase
- ) ?? throw Bug();
+ GetRequestBaseUrl());
}
- public string ForApproval(ApplicationUser user, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(nameof(UIServerController.User), "UIServer",
- new { userId = user.Id }, request.Scheme, request.Host, request.PathBase) ?? throw Bug();
- }
- public string ForLogin(ApplicationUser user, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(nameof(UIAccountController.Login), "UIAccount", new { email = user.Email }, request.Scheme, request.Host, request.PathBase) ?? throw Bug();
- }
+ public string ForApproval(ApplicationUser user)
+ => LinkGenerator.GetUriByAction(nameof(UIServerController.User), "UIServer",
+ new { userId = user.Id }, GetRequestBaseUrl());
- private Exception Bug([CallerMemberName] string? name = null) => new InvalidOperationException($"Error generating link for {name} (Report this bug to BTCPay Server github repository)");
+ public string ForLogin(ApplicationUser user)
+ => LinkGenerator.GetUriByAction(nameof(UIAccountController.Login), "UIAccount",
+ new { email = user.Email }, GetRequestBaseUrl());
- public string WalletTransactionsLink(WalletId walletId, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(
- action: nameof(UIWalletsController.WalletTransactions),
- controller: "UIWallets",
- values: new { walletId = walletId.ToString() },
- scheme: request.Scheme,
- host: request.Host,
- pathBase: request.PathBase
- ) ?? throw Bug();
- }
+ public string WalletTransactionsLink(WalletId walletId)
+ => LinkGenerator.GetUriByAction(
+ action: nameof(UIWalletsController.WalletTransactions),
+ controller: "UIWallets",
+ values: new { walletId = walletId.ToString() },
+ GetRequestBaseUrl());
- public string PaymentRequestByIdLink(string payReqId, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(
- action: nameof(UIPaymentRequestController.ViewPaymentRequest),
- controller: "UIPaymentRequest",
- values: new { payReqId },
- scheme: request.Scheme,
- host: request.Host,
- pathBase: request.PathBase
- ) ?? throw Bug();
- }
+ public string PaymentRequestByIdLink(string payReqId)
+ => LinkGenerator.GetUriByAction(
+ action: nameof(UIPaymentRequestController.ViewPaymentRequest),
+ controller: "UIPaymentRequest",
+ values: new { payReqId },
+ GetRequestBaseUrl());
- public string PaymentRequestListLink(string storeId, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(
- action: nameof(UIPaymentRequestController.GetPaymentRequests),
- controller: "UIPaymentRequest",
- values: new { storeId },
- scheme: request.Scheme,
- host: request.Host,
- pathBase: request.PathBase
- ) ?? throw Bug();
- }
+ public string PaymentRequestListLink(string storeId)
+ => LinkGenerator.GetUriByAction(
+ action: nameof(UIPaymentRequestController.GetPaymentRequests),
+ controller: "UIPaymentRequest",
+ values: new { storeId },
+ GetRequestBaseUrl());
- public string InvoiceLink(string invoiceId, HttpRequest request)
- {
- return LinkGenerator.GetUriByAction(
- action: nameof(UIInvoiceController.Invoice),
- controller: "UIInvoice",
- values: new { invoiceId },
- scheme: request.Scheme,
- host: request.Host,
- pathBase: request.PathBase
- ) ?? throw Bug();
- }
+ public string InvoiceLink(string invoiceId)
+ => LinkGenerator.GetUriByAction(
+ action: nameof(UIInvoiceController.Invoice),
+ controller: "UIInvoice",
+ values: new { invoiceId },
+ GetRequestBaseUrl());
}
}
diff --git a/BTCPayServer/Services/UserService.cs b/BTCPayServer/Services/UserService.cs
index bda7b749a..16cae10eb 100644
--- a/BTCPayServer/Services/UserService.cs
+++ b/BTCPayServer/Services/UserService.cs
@@ -90,7 +90,7 @@ namespace BTCPayServer.Services
? null
: await uriResolver.Resolve(request.GetAbsoluteRootUri(), UnresolvedUri.Create(blob.ImageUrl)),
InvitationUrl = string.IsNullOrEmpty(blob.InvitationToken) ? null
- : callbackGenerator.ForInvitation(data.Id, blob.InvitationToken, request)
+ : callbackGenerator.ForInvitation(data.Id, blob.InvitationToken)
};
}
diff --git a/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml b/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml
index 1795fa572..7fdd1bff6 100644
--- a/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml
+++ b/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml
@@ -123,7 +123,7 @@