#nullable enable using System.Linq; using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Client; using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Plugins.Emails.Services; using BTCPayServer.Plugins.Monetization; using BTCPayServer.Plugins.Wallets; using BTCPayServer.Services; using BTCPayServer.Services.Apps; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Labels; using BTCPayServer.Services.Rates; using BTCPayServer.Services.Stores; using BTCPayServer.Services.Wallets; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using StoreData = BTCPayServer.Data.StoreData; namespace BTCPayServer.Controllers; [Route("stores")] [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] public partial class UIStoresController : Controller { public UIStoresController( BTCPayServerOptions btcpayServerOptions, BTCPayServerEnvironment btcpayEnv, StoreRepository storeRepo, UserManager userManager, BTCPayWalletProvider walletProvider, BTCPayNetworkProvider networkProvider, RateFetcher rateFactory, ExplorerClientProvider explorerProvider, LanguageService langService, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary, PoliciesSettings policiesSettings, IAuthorizationService authorizationService, AppService appService, IFileService fileService, IDataProtectionProvider dataProtector, IOptions lightningNetworkOptions, IOptions externalServiceOptions, IHtmlHelper html, DefaultRulesCollection defaultRules, EmailSenderFactory emailSenderFactory, WalletFileParsers onChainWalletParsers, UIUserStoresController userStoresController, CallbackGenerator callbackGenerator, UriResolver uriResolver, CurrencyNameTable currencyNameTable, IStringLocalizer stringLocalizer, EventAggregator eventAggregator, LightningHistogramService lnHistogramService, LightningClientFactoryService lightningClientFactory, StoreLabelRepository storeLabelRepository) { _rateFactory = rateFactory; _storeRepo = storeRepo; _userManager = userManager; _langService = langService; _walletProvider = walletProvider; _handlers = paymentMethodHandlerDictionary; _policiesSettings = policiesSettings; _authorizationService = authorizationService; _appService = appService; _fileService = fileService; _networkProvider = networkProvider; _explorerProvider = explorerProvider; _btcpayServerOptions = btcpayServerOptions; _btcPayEnv = btcpayEnv; _externalServiceOptions = externalServiceOptions; _emailSenderFactory = emailSenderFactory; _onChainWalletParsers = onChainWalletParsers; _userStoresController = userStoresController; _callbackGenerator = callbackGenerator; _uriResolver = uriResolver; _currencyNameTable = currencyNameTable; _eventAggregator = eventAggregator; _html = html; _defaultRules = defaultRules; _dataProtector = dataProtector.CreateProtector("ConfigProtector"); _lightningNetworkOptions = lightningNetworkOptions.Value; _lnHistogramService = lnHistogramService; _lightningClientFactory = lightningClientFactory; StringLocalizer = stringLocalizer; _storeLabelRepository = storeLabelRepository; } private readonly BTCPayServerOptions _btcpayServerOptions; private readonly BTCPayServerEnvironment _btcPayEnv; private readonly BTCPayNetworkProvider _networkProvider; private readonly BTCPayWalletProvider _walletProvider; private readonly StoreRepository _storeRepo; private readonly UserManager _userManager; private readonly RateFetcher _rateFactory; private readonly CurrencyNameTable _currencyNameTable; private readonly ExplorerClientProvider _explorerProvider; private readonly LanguageService _langService; private readonly PaymentMethodHandlerDictionary _handlers; private readonly DefaultRulesCollection _defaultRules; private readonly PoliciesSettings _policiesSettings; private readonly IAuthorizationService _authorizationService; private readonly AppService _appService; private readonly IFileService _fileService; private readonly IOptions _externalServiceOptions; private readonly EmailSenderFactory _emailSenderFactory; private readonly WalletFileParsers _onChainWalletParsers; private readonly UIUserStoresController _userStoresController; private readonly CallbackGenerator _callbackGenerator; private readonly UriResolver _uriResolver; private readonly EventAggregator _eventAggregator; private readonly IHtmlHelper _html; private readonly LightningNetworkOptions _lightningNetworkOptions; private readonly IDataProtector _dataProtector; private readonly LightningHistogramService _lnHistogramService; private readonly LightningClientFactoryService _lightningClientFactory; private readonly StoreLabelRepository _storeLabelRepository; public IStringLocalizer StringLocalizer { get; } [AllowAnonymous] [HttpGet("{storeId}/index")] public async Task Index(string storeId) { var userId = GetUserId(); if (userId is null) return Forbid(); // We do not need to pass userId to FindStore, because the user may just be an admin var store = await _storeRepo.FindStore(storeId); if (store is null) return NotFound(); IActionResult? redirect = null; if ((await _authorizationService.AuthorizeAsync(User, storeId, Policies.CanModifyStoreSettings)).Succeeded) { redirect = RedirectToAction(nameof(Dashboard), new { storeId }); } else if ((await _authorizationService.AuthorizeAsync(User, storeId, Policies.CanViewInvoices)).Succeeded) { redirect = RedirectToAction(nameof(UIInvoiceController.ListInvoices), "UIInvoice", new { storeId }); } else if ((await _authorizationService.AuthorizeAsync(User, storeId, WalletPolicies.CanViewWallet)).Succeeded) { redirect = RedirectToConfiguredWallet(store) ?? RedirectToAction(nameof(UIWalletsController.ListWallets), "UIWallets", new { area = WalletsPlugin.Area }); } if (redirect is null) return Forbid(); HttpContext.SetStoreData(store); HttpContext.SetPreferredStoreId(storeId); return redirect; } private IActionResult? RedirectToConfiguredWallet(StoreData store) { AddPaymentMethods(store, store.GetStoreBlob(), out var derivationSchemes, out _); var defaultPaymentId = store.GetDefaultPaymentId(); var walletId = derivationSchemes .Where(s => s.Enabled && s.WalletSupported) .OrderByDescending(s => s.PaymentMethodId == defaultPaymentId) .ThenByDescending(s => s.Crypto == _networkProvider.DefaultCryptoCode) .Select(s => s.WalletId) .FirstOrDefault(); return walletId is null ? null : RedirectToAction(nameof(UIWalletsController.WalletTransactions), "UIWallets", new { area = WalletsPlugin.Area, walletId = walletId.ToString() }); } public StoreData CurrentStore => HttpContext.GetStoreData(); public PaymentMethodOptionViewModel.Format[] GetEnabledPaymentMethodChoices(StoreData storeData) { var enabled = storeData.GetEnabledPaymentIds(); return enabled .Select(o => new PaymentMethodOptionViewModel.Format() { Name = o.ToString(), Value = o.ToString(), PaymentId = o }).ToArray(); } private string? GetUserId() => User.Identity?.AuthenticationType != AuthenticationSchemes.Cookie ? null : User.GetIdOrNull(); }