After login, redirect user to the main page even if root app configured (#3429)

This commit is contained in:
Nicolas Dorier
2022-02-07 21:18:22 +09:00
committed by GitHub
parent cd94a9fac1
commit c8b9906ef3
7 changed files with 79 additions and 26 deletions

View File

@@ -350,7 +350,7 @@ namespace BTCPayServer.Tests
var user = s.Server.NewAccount(); var user = s.Server.NewAccount();
await user.GrantAccessAsync(); await user.GrantAccessAsync();
s.GoToLogin(); s.GoToLogin();
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password);
user.RegisterDerivationScheme("BTC"); user.RegisterDerivationScheme("BTC");
await s.Server.ExplorerNode.GenerateAsync(1); await s.Server.ExplorerNode.GenerateAsync(1);

View File

@@ -43,7 +43,7 @@ namespace BTCPayServer.Tests
await user.GrantAccessAsync(); await user.GrantAccessAsync();
await user.MakeAdmin(false); await user.MakeAdmin(false);
s.GoToLogin(); s.GoToLogin();
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password);
s.GoToProfile(ManageNavPages.APIKeys); s.GoToProfile(ManageNavPages.APIKeys);
s.Driver.FindElement(By.Id("AddApiKey")).Click(); s.Driver.FindElement(By.Id("AddApiKey")).Click();
@@ -53,7 +53,7 @@ namespace BTCPayServer.Tests
await user.MakeAdmin(); await user.MakeAdmin();
s.Logout(); s.Logout();
s.GoToLogin(); s.GoToLogin();
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password);
s.GoToProfile(ManageNavPages.APIKeys); s.GoToProfile(ManageNavPages.APIKeys);
s.Driver.FindElement(By.Id("AddApiKey")).Click(); s.Driver.FindElement(By.Id("AddApiKey")).Click();
Assert.Contains("btcpay.server.canmodifyserversettings", s.Driver.PageSource); Assert.Contains("btcpay.server.canmodifyserversettings", s.Driver.PageSource);
@@ -196,7 +196,7 @@ namespace BTCPayServer.Tests
await user.MakeAdmin(false); await user.MakeAdmin(false);
s.Logout(); s.Logout();
s.GoToLogin(); s.GoToLogin();
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password); s.LogIn(user.RegisterDetails.Email, user.RegisterDetails.Password);
s.GoToProfile(ManageNavPages.APIKeys); s.GoToProfile(ManageNavPages.APIKeys);
s.Driver.FindElement(By.Id("AddApiKey")).Click(); s.Driver.FindElement(By.Id("AddApiKey")).Click();
int checkedPermissionCount = 0; int checkedPermissionCount = 0;

View File

@@ -349,7 +349,7 @@ namespace BTCPayServer.Tests
Driver.FindElement(By.Id("Nav-Logout")).Click(); 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("Email")).SendKeys(user);
Driver.FindElement(By.Id("Password")).SendKeys(password); Driver.FindElement(By.Id("Password")).SendKeys(password);

View File

@@ -112,7 +112,7 @@ namespace BTCPayServer.Tests
await u2.MakeAdmin(false); await u2.MakeAdmin(false);
s.GoToLogin(); s.GoToLogin();
s.Login(u1.RegisterDetails.Email, u1.RegisterDetails.Password); s.LogIn(u1.RegisterDetails.Email, u1.RegisterDetails.Password);
s.GoToProfile(); s.GoToProfile();
s.Driver.FindElement(By.Id("Email")).Clear(); s.Driver.FindElement(By.Id("Email")).Clear();
s.Driver.FindElement(By.Id("Email")).SendKeys(u2.RegisterDetails.Email); s.Driver.FindElement(By.Id("Email")).SendKeys(u2.RegisterDetails.Email);
@@ -576,11 +576,10 @@ namespace BTCPayServer.Tests
[Fact(Timeout = TestTimeout)] [Fact(Timeout = TestTimeout)]
public async Task CanCreateAppPoS() public async Task CanCreateAppPoS()
{ {
using var s = CreateSeleniumTester(); using var s = CreateSeleniumTester(newDb: true);
await s.StartAsync(); await s.StartAsync();
s.RegisterNewUser(); var userId = s.RegisterNewUser(true);
s.CreateNewStore(); s.CreateNewStore();
s.Driver.FindElement(By.Id("StoreNav-CreateApp")).Click(); s.Driver.FindElement(By.Id("StoreNav-CreateApp")).Click();
s.Driver.FindElement(By.Name("AppName")).SendKeys("PoS" + Guid.NewGuid()); s.Driver.FindElement(By.Name("AppName")).SendKeys("PoS" + Guid.NewGuid());
s.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("Point of Sale"); s.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("Point of Sale");
@@ -614,9 +613,46 @@ namespace BTCPayServer.Tests
s.Driver.Url = posBaseUrl + "/cart"; s.Driver.Url = posBaseUrl + "/cart";
Assert.True(s.Driver.PageSource.Contains("Cart"), "Cart PoS not showing correct view"); Assert.True(s.Driver.PageSource.Contains("Cart"), "Cart PoS not showing correct view");
s.Driver.Close(); // Let's set change the root app
s.Driver.SwitchTo().Window(windows[0]); 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)] [Fact(Timeout = TestTimeout)]
@@ -1718,7 +1754,7 @@ retry:
TestUtils.Eventually(() => s.FindAlertMessage()); TestUtils.Eventually(() => s.FindAlertMessage());
s.Logout(); s.Logout();
s.Login(user, "123456"); s.LogIn(user, "123456");
var section = s.Driver.FindElement(By.Id("lnurlauth-section")); var section = s.Driver.FindElement(By.Id("lnurlauth-section"));
links = section.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href")); links = section.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href"));
Assert.Equal(2,links.Count()); Assert.Equal(2,links.Count());

View File

@@ -85,7 +85,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> Login(string returnUrl = null, string email = null) public async Task<IActionResult> Login(string returnUrl = null, string email = null)
{ {
if (User.Identity.IsAuthenticated && string.IsNullOrEmpty(returnUrl)) if (User.Identity.IsAuthenticated && string.IsNullOrEmpty(returnUrl))
return RedirectToLocal(); return await RedirectToLocal();
// Clear the existing external cookie to ensure a clean login process // Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); 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); _logger.LogInformation("User with ID {UserId} logged in with a login code.", user.Id);
await _signInManager.SignInAsync(user, false, "LoginCode"); await _signInManager.SignInAsync(user, false, "LoginCode");
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
return await Login(returnUrl, null); return await Login(returnUrl, null);
} }
@@ -194,7 +194,7 @@ namespace BTCPayServer.Controllers
if (result.Succeeded) if (result.Succeeded)
{ {
_logger.LogInformation($"User '{user.Id}' logged in."); _logger.LogInformation($"User '{user.Id}' logged in.");
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
if (result.RequiresTwoFactor) if (result.RequiresTwoFactor)
{ {
@@ -293,7 +293,7 @@ namespace BTCPayServer.Controllers
_lnurlAuthService.FinalLoginStore.TryRemove(viewModel.UserId, out _); _lnurlAuthService.FinalLoginStore.TryRemove(viewModel.UserId, out _);
await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2"); await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2");
_logger.LogInformation("User logged in."); _logger.LogInformation("User logged in.");
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
errorMessage = "Invalid login attempt."; errorMessage = "Invalid login attempt.";
@@ -344,7 +344,7 @@ namespace BTCPayServer.Controllers
{ {
await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2"); await _signInManager.SignInAsync(user, viewModel.RememberMe, "FIDO2");
_logger.LogInformation("User logged in."); _logger.LogInformation("User logged in.");
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
errorMessage = "Invalid login attempt."; errorMessage = "Invalid login attempt.";
@@ -423,7 +423,7 @@ namespace BTCPayServer.Controllers
if (result.Succeeded) if (result.Succeeded)
{ {
_logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id); _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id);
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
else if (result.IsLockedOut) else if (result.IsLockedOut)
{ {
@@ -492,7 +492,7 @@ namespace BTCPayServer.Controllers
if (result.Succeeded) if (result.Succeeded)
{ {
_logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id); _logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id);
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
if (result.IsLockedOut) if (result.IsLockedOut)
{ {
@@ -582,7 +582,7 @@ namespace BTCPayServer.Controllers
{ {
if (logon) if (logon)
await _signInManager.SignInAsync(user, isPersistent: false); await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl); return await RedirectToLocal(returnUrl);
} }
else else
{ {
@@ -607,7 +607,7 @@ namespace BTCPayServer.Controllers
await _signInManager.SignOutAsync(); await _signInManager.SignOutAsync();
HttpContext.DeleteUserPrefsCookie(); HttpContext.DeleteUserPrefsCookie();
_logger.LogInformation("User logged out."); _logger.LogInformation("User logged out.");
return RedirectToAction(nameof(UIHomeController.Index), "UIHome"); return RedirectToAction(nameof(UIAccountController.Login));
} }
[HttpGet("/register/confirm-email")] [HttpGet("/register/confirm-email")]
@@ -749,7 +749,7 @@ namespace BTCPayServer.Controllers
} }
} }
private IActionResult RedirectToLocal(string returnUrl = null) private async Task<IActionResult> RedirectToLocal(string returnUrl = null)
{ {
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)) if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{ {
@@ -757,6 +757,17 @@ namespace BTCPayServer.Controllers
} }
else 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"); return RedirectToAction(nameof(UIHomeController.Index), "UIHome");
} }
} }

View File

@@ -63,6 +63,12 @@ namespace BTCPayServer.Controllers
SignInManager = signInManager; SignInManager = signInManager;
} }
[HttpGet("home")]
public Task<IActionResult> Home()
{
return Index();
}
[Route("")] [Route("")]
[DomainMappingConstraint] [DomainMappingConstraint]
public async Task<IActionResult> Index() public async Task<IActionResult> Index()

View File

@@ -121,7 +121,7 @@
<select asp-for="RootAppId" asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.RootAppId))" class="form-select w-auto"></select> <select asp-for="RootAppId" asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.RootAppId))" class="form-select w-auto"></select>
@if (!Model.DomainToAppMapping.Any()) @if (!Model.DomainToAppMapping.Any())
{ {
<button type="submit" name="command" value="add-domain" class="btn btn-link px-0">Map specific domains to specific apps</button> <button id="AddDomainButton" type="submit" name="command" value="add-domain" class="btn btn-link px-0">Map specific domains to specific apps</button>
} }
</div> </div>
@@ -129,7 +129,7 @@
{ {
<h5 class="mt-5 mb-0"> <h5 class="mt-5 mb-0">
Domain to app mapping Domain to app mapping
<button type="submit" name="command" value="add-domain" class="btn btn-secondary btn-sm ms-2">Add domain mapping</button> <button id="AddDomainButton" type="submit" name="command" value="add-domain" class="btn btn-secondary btn-sm ms-2">Add domain mapping</button>
</h5> </h5>
<div class="list-group list-group-flush mb-2"> <div class="list-group list-group-flush mb-2">
@for (var index = 0; index < Model.DomainToAppMapping.Count; index++) @for (var index = 0; index < Model.DomainToAppMapping.Count; index++)
@@ -201,7 +201,7 @@
</div> </div>
</div> </div>
<button type="submit" class="btn btn-primary" name="command" value="Save">Save</button> <button id="SaveButton" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</form> </form>
@section PageFootContent { @section PageFootContent {