diff --git a/BTCPayServer.Tests/BTCPayServer.Tests.csproj b/BTCPayServer.Tests/BTCPayServer.Tests.csproj index 5951f6af1..b0c7b0e26 100644 --- a/BTCPayServer.Tests/BTCPayServer.Tests.csproj +++ b/BTCPayServer.Tests/BTCPayServer.Tests.csproj @@ -24,7 +24,7 @@ - + all diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index bd641793d..e2a1a253b 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -2332,10 +2332,27 @@ namespace BTCPayServer.Tests s.Server.ActivateLightning(); await s.StartAsync(); await s.Server.EnsureChannelsSetup(); + + // Create users + var user = s.RegisterNewUser(); + var userAccount = s.AsTestAccount(); + s.GoToHome(); + s.Logout(); + s.GoToRegister(); s.RegisterNewUser(true); + + // Setup store and associate user s.CreateNewStore(); s.GoToStore(); s.AddLightningNode(LightningConnectionType.CLightning, false); + s.GoToStore(StoreNavPages.Users); + s.Driver.FindElement(By.Id("Email")).Clear(); + s.Driver.FindElement(By.Id("Email")).SendKeys(user); + new SelectElement(s.Driver.FindElement(By.Id("Role"))).SelectByValue("Guest"); + s.Driver.FindElement(By.Id("AddUser")).Click(); + Assert.Contains("User added successfully", s.FindAlertMessage().Text); + + // Setup POS s.Driver.FindElement(By.Id("StoreNav-CreatePointOfSale")).Click(); s.Driver.FindElement(By.Id("AppName")).SendKeys(Guid.NewGuid().ToString()); s.Driver.FindElement(By.Id("Create")).Click(); @@ -2360,6 +2377,8 @@ namespace BTCPayServer.Tests s.Driver.WaitForElement(By.ClassName("keypad")); // basic checks + var keypadUrl = s.Driver.Url; + s.Driver.FindElement(By.Id("RecentTransactionsToggle")); Assert.Contains("EUR", s.Driver.FindElement(By.Id("Currency")).Text); Assert.Contains("0,00", s.Driver.FindElement(By.Id("Amount")).Text); Assert.Equal("", s.Driver.FindElement(By.Id("Calculation")).Text); @@ -2405,6 +2424,19 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("DetailsToggle")).Click(); s.Driver.WaitForElement(By.Id("PaymentDetails-TotalFiat")); Assert.Contains("1 222,21 €", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text); + + // Guest user can access recent transactions + s.GoToHome(); + s.Logout(); + s.LogIn(user, userAccount.RegisterDetails.Password); + s.GoToUrl(keypadUrl); + s.Driver.FindElement(By.Id("RecentTransactionsToggle")); + s.GoToHome(); + s.Logout(); + + // Unauthenticated user can't access recent transactions + s.GoToUrl(keypadUrl); + s.Driver.ElementDoesNotExist(By.Id("RecentTransactionsToggle")); } [Fact] diff --git a/BTCPayServer/Security/CookieAuthorizationHandler.cs b/BTCPayServer/Security/CookieAuthorizationHandler.cs index 15c3180be..9391f4866 100644 --- a/BTCPayServer/Security/CookieAuthorizationHandler.cs +++ b/BTCPayServer/Security/CookieAuthorizationHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Contracts; @@ -74,10 +73,10 @@ namespace BTCPayServer.Security // resolve from app if (routeData.Values.TryGetValue("appId", out var vAppId) && vAppId is string appId) { - app = await _appService.GetAppDataIfOwner(userId, appId); + app = await _appService.GetAppData(userId, appId); if (storeId == null) { - storeId = app?.StoreDataId ?? String.Empty; + storeId = app?.StoreDataId ?? string.Empty; } else if (app?.StoreDataId != storeId) { @@ -90,7 +89,7 @@ namespace BTCPayServer.Security paymentRequest = await _paymentRequestRepository.FindPaymentRequest(payReqId, userId); if (storeId == null) { - storeId = paymentRequest?.StoreDataId ?? String.Empty; + storeId = paymentRequest?.StoreDataId ?? string.Empty; } else if (paymentRequest?.StoreDataId != storeId) { @@ -103,7 +102,7 @@ namespace BTCPayServer.Security invoice = await _invoiceRepository.GetInvoice(invoiceId); if (storeId == null) { - storeId = invoice?.StoreId ?? String.Empty; + storeId = invoice?.StoreId ?? string.Empty; } else if (invoice?.StoreId != storeId) { diff --git a/BTCPayServer/Services/Apps/AppService.cs b/BTCPayServer/Services/Apps/AppService.cs index b5c678c40..6b0422701 100644 --- a/BTCPayServer/Services/Apps/AppService.cs +++ b/BTCPayServer/Services/Apps/AppService.cs @@ -371,10 +371,26 @@ namespace BTCPayServer.Services.Apps return null; await using var ctx = _ContextFactory.CreateContext(); var app = await ctx.UserStore - .Include(store => store.StoreRole) - .Where(us => us.ApplicationUserId == userId && us.StoreRole.Permissions.Contains(Policies.CanModifyStoreSettings)) - .SelectMany(us => us.StoreData.Apps.Where(a => a.Id == appId)) - .FirstOrDefaultAsync(); + .Include(store => store.StoreRole) + .Where(us => us.ApplicationUserId == userId && us.StoreRole.Permissions.Contains(Policies.CanModifyStoreSettings)) + .SelectMany(us => us.StoreData.Apps.Where(a => a.Id == appId)) + .FirstOrDefaultAsync(); + if (app == null) + return null; + if (type != null && type != app.AppType) + return null; + return app; + } + + public async Task GetAppData(string userId, string appId, string? type = null) + { + if (userId == null || appId == null) + return null; + await using var ctx = _ContextFactory.CreateContext(); + var app = await ctx.UserStore + .Where(us => us.ApplicationUserId == userId && us.StoreData != null && us.StoreData.UserStores.Any(u => u.ApplicationUserId == userId)) + .SelectMany(us => us.StoreData.Apps.Where(a => a.Id == appId)) + .FirstOrDefaultAsync(); if (app == null) return null; if (type != null && type != app.AppType) diff --git a/BTCPayServer/Views/UIStores/StoreUsers.cshtml b/BTCPayServer/Views/UIStores/StoreUsers.cshtml index 35247dcc6..db996040e 100644 --- a/BTCPayServer/Views/UIStores/StoreUsers.cshtml +++ b/BTCPayServer/Views/UIStores/StoreUsers.cshtml @@ -33,7 +33,7 @@
- +