From c8b9906ef3386fce91cdb7057af15c9dfbaf7cf0 Mon Sep 17 00:00:00 2001 From: Nicolas Dorier Date: Mon, 7 Feb 2022 21:18:22 +0900 Subject: [PATCH] After login, redirect user to the main page even if root app configured (#3429) --- .../AltcoinTests/AltcoinTests.cs | 2 +- BTCPayServer.Tests/ApiKeysTests.cs | 6 +-- BTCPayServer.Tests/SeleniumTester.cs | 2 +- BTCPayServer.Tests/SeleniumTests.cs | 52 ++++++++++++++++--- .../Controllers/UIAccountController.cs | 31 +++++++---- BTCPayServer/Controllers/UIHomeController.cs | 6 +++ BTCPayServer/Views/UIServer/Policies.cshtml | 6 +-- 7 files changed, 79 insertions(+), 26 deletions(-) diff --git a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs index 47b43eb7b..b9be03195 100644 --- a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs +++ b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs @@ -350,7 +350,7 @@ namespace BTCPayServer.Tests var user = s.Server.NewAccount(); await user.GrantAccessAsync(); s.GoToLogin(); - s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); + s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password); user.RegisterDerivationScheme("BTC"); await s.Server.ExplorerNode.GenerateAsync(1); diff --git a/BTCPayServer.Tests/ApiKeysTests.cs b/BTCPayServer.Tests/ApiKeysTests.cs index 88d92c32a..ded6da050 100644 --- a/BTCPayServer.Tests/ApiKeysTests.cs +++ b/BTCPayServer.Tests/ApiKeysTests.cs @@ -43,7 +43,7 @@ namespace BTCPayServer.Tests await user.GrantAccessAsync(); await user.MakeAdmin(false); s.GoToLogin(); - s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); + s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password); s.GoToProfile(ManageNavPages.APIKeys); s.Driver.FindElement(By.Id("AddApiKey")).Click(); @@ -53,7 +53,7 @@ namespace BTCPayServer.Tests await user.MakeAdmin(); s.Logout(); s.GoToLogin(); - s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); + s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password); s.GoToProfile(ManageNavPages.APIKeys); s.Driver.FindElement(By.Id("AddApiKey")).Click(); Assert.Contains("btcpay.server.canmodifyserversettings", s.Driver.PageSource); @@ -196,7 +196,7 @@ namespace BTCPayServer.Tests await user.MakeAdmin(false); s.Logout(); s.GoToLogin(); - s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); + s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password); s.GoToProfile(ManageNavPages.APIKeys); s.Driver.FindElement(By.Id("AddApiKey")).Click(); int checkedPermissionCount = 0; diff --git a/BTCPayServer.Tests/SeleniumTester.cs b/BTCPayServer.Tests/SeleniumTester.cs index e5cac541d..d9095afe9 100644 --- a/BTCPayServer.Tests/SeleniumTester.cs +++ b/BTCPayServer.Tests/SeleniumTester.cs @@ -349,7 +349,7 @@ namespace BTCPayServer.Tests Driver.FindElement(By.Id("Nav-Logout")).Click(); } - public void Login(string user, string password) + public void LogIn(string user, string password) { Driver.FindElement(By.Id("Email")).SendKeys(user); Driver.FindElement(By.Id("Password")).SendKeys(password); diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index fb57d050f..59155a835 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -112,7 +112,7 @@ namespace BTCPayServer.Tests await u2.MakeAdmin(false); s.GoToLogin(); - s.Login(u1.RegisterDetails.Email, u1.RegisterDetails.Password); + s.LogIn(u1.RegisterDetails.Email, u1.RegisterDetails.Password); s.GoToProfile(); s.Driver.FindElement(By.Id("Email")).Clear(); s.Driver.FindElement(By.Id("Email")).SendKeys(u2.RegisterDetails.Email); @@ -576,11 +576,10 @@ namespace BTCPayServer.Tests [Fact(Timeout = TestTimeout)] public async Task CanCreateAppPoS() { - using var s = CreateSeleniumTester(); + using var s = CreateSeleniumTester(newDb: true); await s.StartAsync(); - s.RegisterNewUser(); + var userId = s.RegisterNewUser(true); s.CreateNewStore(); - s.Driver.FindElement(By.Id("StoreNav-CreateApp")).Click(); s.Driver.FindElement(By.Name("AppName")).SendKeys("PoS" + Guid.NewGuid()); s.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("Point of Sale"); @@ -614,9 +613,46 @@ namespace BTCPayServer.Tests s.Driver.Url = posBaseUrl + "/cart"; Assert.True(s.Driver.PageSource.Contains("Cart"), "Cart PoS not showing correct view"); - - s.Driver.Close(); - s.Driver.SwitchTo().Window(windows[0]); + + // Let's set change the root app + s.GoToHome(); + s.GoToServer(ServerNavPages.Policies); + s.Driver.ScrollTo(By.Id("RootAppId")); + var select = new SelectElement(s.Driver.FindElement(By.Id("RootAppId"))); + select.SelectByText("Point of", true); + s.Driver.FindElement(By.Id("SaveButton")).Click(); + s.FindAlertMessage(); + + s.Logout(); + s.GoToLogin(); + s.LogIn(userId); + // Make sure after login, we are not redirected to the PoS + Assert.DoesNotContain("Tea shop", s.Driver.PageSource); + // We are only if explicitely going to / + s.GoToUrl("/"); + Assert.Contains("Tea shop", s.Driver.PageSource); + s.Driver.Navigate().Back(); + + // Let's check with domain mapping as well. + s.GoToServer(ServerNavPages.Policies); + s.Driver.ScrollTo(By.Id("RootAppId")); + select = new SelectElement(s.Driver.FindElement(By.Id("RootAppId"))); + select.SelectByText("None", true); + s.Driver.FindElement(By.Id("SaveButton")).Click(); + s.Driver.ScrollTo(By.Id("RootAppId")); + s.Driver.FindElement(By.Id("AddDomainButton")).Click(); + s.Driver.FindElement(By.Id("DomainToAppMapping_0__Domain")).SendKeys(new Uri(s.Driver.Url, UriKind.Absolute).DnsSafeHost); + select = new SelectElement(s.Driver.FindElement(By.Id("DomainToAppMapping_0__AppId"))); + select.SelectByText("Point of", true); + s.Driver.FindElement(By.Id("SaveButton")).Click(); + + s.Logout(); + s.LogIn(userId); + // Make sure after login, we are not redirected to the PoS + Assert.DoesNotContain("Tea shop", s.Driver.PageSource); + // We are only if explicitely going to / + s.GoToUrl("/"); + Assert.Contains("Tea shop", s.Driver.PageSource); } [Fact(Timeout = TestTimeout)] @@ -1718,7 +1754,7 @@ retry: TestUtils.Eventually(() => s.FindAlertMessage()); s.Logout(); - s.Login(user, "123456"); + s.LogIn(user, "123456"); var section = s.Driver.FindElement(By.Id("lnurlauth-section")); links = section.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href")); Assert.Equal(2,links.Count()); diff --git a/BTCPayServer/Controllers/UIAccountController.cs b/BTCPayServer/Controllers/UIAccountController.cs index b58f7e2e2..5a35ff2b5 100644 --- a/BTCPayServer/Controllers/UIAccountController.cs +++ b/BTCPayServer/Controllers/UIAccountController.cs @@ -85,7 +85,7 @@ namespace BTCPayServer.Controllers public async Task Login(string returnUrl = null, string email = null) { if (User.Identity.IsAuthenticated && string.IsNullOrEmpty(returnUrl)) - return RedirectToLocal(); + return await RedirectToLocal(); // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); @@ -119,7 +119,7 @@ namespace BTCPayServer.Controllers _logger.LogInformation("User with ID {UserId} logged in with a login code.", user.Id); await _signInManager.SignInAsync(user, false, "LoginCode"); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } return await Login(returnUrl, null); } @@ -194,7 +194,7 @@ namespace BTCPayServer.Controllers if (result.Succeeded) { _logger.LogInformation($"User '{user.Id}' logged in."); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } if (result.RequiresTwoFactor) { @@ -293,7 +293,7 @@ namespace BTCPayServer.Controllers _lnurlAuthService.FinalLoginStore.TryRemove(viewModel.UserId, out _); await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2"); _logger.LogInformation("User logged in."); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } errorMessage = "Invalid login attempt."; @@ -344,7 +344,7 @@ namespace BTCPayServer.Controllers { await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2"); _logger.LogInformation("User logged in."); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } errorMessage = "Invalid login attempt."; @@ -423,7 +423,7 @@ namespace BTCPayServer.Controllers if (result.Succeeded) { _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } else if (result.IsLockedOut) { @@ -492,7 +492,7 @@ namespace BTCPayServer.Controllers if (result.Succeeded) { _logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } if (result.IsLockedOut) { @@ -582,7 +582,7 @@ namespace BTCPayServer.Controllers { if (logon) await _signInManager.SignInAsync(user, isPersistent: false); - return RedirectToLocal(returnUrl); + return await RedirectToLocal(returnUrl); } else { @@ -607,7 +607,7 @@ namespace BTCPayServer.Controllers await _signInManager.SignOutAsync(); HttpContext.DeleteUserPrefsCookie(); _logger.LogInformation("User logged out."); - return RedirectToAction(nameof(UIHomeController.Index), "UIHome"); + return RedirectToAction(nameof(UIAccountController.Login)); } [HttpGet("/register/confirm-email")] @@ -749,7 +749,7 @@ namespace BTCPayServer.Controllers } } - private IActionResult RedirectToLocal(string returnUrl = null) + private async Task RedirectToLocal(string returnUrl = null) { if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)) { @@ -757,6 +757,17 @@ namespace BTCPayServer.Controllers } else { + // After login, if there is an app on "/", we should redirect to BTCPay explicit home route, and not to the app. + var policies = await _SettingsRepository.GetPolicies(); + if (policies?.RootAppId is not null && policies?.RootAppType is not null) + return RedirectToAction(nameof(UIHomeController.Home), "UIHome"); + if (policies?.DomainToAppMapping is { } mapping) + { + var matchedDomainMapping = mapping.FirstOrDefault(item => + item.Domain.Equals(this.HttpContext.Request.Host.Host, StringComparison.InvariantCultureIgnoreCase)); + if (matchedDomainMapping is not null) + return RedirectToAction(nameof(UIHomeController.Home), "UIHome"); + } return RedirectToAction(nameof(UIHomeController.Index), "UIHome"); } } diff --git a/BTCPayServer/Controllers/UIHomeController.cs b/BTCPayServer/Controllers/UIHomeController.cs index 27704ce5f..c6500b35a 100644 --- a/BTCPayServer/Controllers/UIHomeController.cs +++ b/BTCPayServer/Controllers/UIHomeController.cs @@ -63,6 +63,12 @@ namespace BTCPayServer.Controllers SignInManager = signInManager; } + [HttpGet("home")] + public Task Home() + { + return Index(); + } + [Route("")] [DomainMappingConstraint] public async Task Index() diff --git a/BTCPayServer/Views/UIServer/Policies.cshtml b/BTCPayServer/Views/UIServer/Policies.cshtml index ce7375b09..79746860c 100644 --- a/BTCPayServer/Views/UIServer/Policies.cshtml +++ b/BTCPayServer/Views/UIServer/Policies.cshtml @@ -121,7 +121,7 @@ @if (!Model.DomainToAppMapping.Any()) { - + } @@ -129,7 +129,7 @@ {
Domain to app mapping - +
@for (var index = 0; index < Model.DomainToAppMapping.Count; index++) @@ -201,7 +201,7 @@
- + @section PageFootContent {