mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-09 08:14:21 +01:00
App domain redirect (#4391)
* Fix duplicates in GetAllApps with allowNoUser * Use domain mapping as canonical reference and redirect to it * Revert domain mapping to hostname instead of URL
This commit is contained in:
@@ -843,6 +843,7 @@ namespace BTCPayServer.Tests
|
||||
select = new SelectElement(s.Driver.FindElement(By.Id("DomainToAppMapping_0__AppId")));
|
||||
select.SelectByText("Point of", true);
|
||||
s.Driver.FindElement(By.Id("SaveButton")).Click();
|
||||
Assert.Contains("Policies updated successfully", s.FindAlertMessage().Text);
|
||||
|
||||
s.Logout();
|
||||
s.LogIn(userId);
|
||||
|
||||
@@ -758,22 +758,21 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// After login, if there is an app on "/", we should redirect to BTCPay explicit home route, and not to the app.
|
||||
if (PoliciesSettings.RootAppId is not null && PoliciesSettings.RootAppType is not null)
|
||||
return RedirectToAction(nameof(UIHomeController.Home), "UIHome");
|
||||
if (PoliciesSettings.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");
|
||||
}
|
||||
}
|
||||
|
||||
// After login, if there is an app on "/", we should redirect to BTCPay explicit home route, and not to the app.
|
||||
if (PoliciesSettings.RootAppId is not null && PoliciesSettings.RootAppType is not null)
|
||||
return RedirectToAction(nameof(UIHomeController.Home), "UIHome");
|
||||
|
||||
if (PoliciesSettings.DomainToAppMapping is { } mapping)
|
||||
{
|
||||
var matchedDomainMapping = mapping.FirstOrDefault(item =>
|
||||
item.Domain.Equals(HttpContext.Request.Host.Host, StringComparison.InvariantCultureIgnoreCase));
|
||||
if (matchedDomainMapping is not null)
|
||||
return RedirectToAction(nameof(UIHomeController.Home), "UIHome");
|
||||
}
|
||||
|
||||
return RedirectToAction(nameof(UIHomeController.Index), "UIHome");
|
||||
}
|
||||
|
||||
private bool CanLoginOrRegister()
|
||||
{
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@@ -15,45 +12,62 @@ namespace BTCPayServer.Filters
|
||||
{
|
||||
public DomainMappingConstraintAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DomainMappingConstraintAttribute(AppType appType)
|
||||
{
|
||||
AppType = appType;
|
||||
}
|
||||
|
||||
public int Order => 100;
|
||||
public AppType? AppType { get; set; }
|
||||
private AppType? AppType { get; }
|
||||
|
||||
public bool Accept(ActionConstraintContext context)
|
||||
{
|
||||
if (context.RouteContext.RouteData.Values.ContainsKey("appId"))
|
||||
return true;
|
||||
var hasAppId = context.RouteContext.RouteData.Values.ContainsKey("appId");
|
||||
var policies = context.RouteContext.HttpContext.RequestServices.GetService<PoliciesSettings>();
|
||||
if (policies?.DomainToAppMapping is { } mapping)
|
||||
var mapping = policies?.DomainToAppMapping;
|
||||
var hasDomainMapping = mapping is { Count: > 0 };
|
||||
|
||||
if (hasAppId && hasDomainMapping)
|
||||
{
|
||||
var matchedDomainMapping = mapping.FirstOrDefault(item =>
|
||||
item.Domain.Equals(context.RouteContext.HttpContext.Request.Host.Host, StringComparison.InvariantCultureIgnoreCase));
|
||||
var appId = (string)context.RouteContext.RouteData.Values["appId"];
|
||||
var matchedDomainMapping = mapping.FirstOrDefault(item => item.AppId == appId);
|
||||
|
||||
// App is accessed via path, redirect to canonical domain
|
||||
if (matchedDomainMapping != null)
|
||||
{
|
||||
if (!(AppType is { } appType))
|
||||
var req = context.RouteContext.HttpContext.Request;
|
||||
var url = new UriBuilder(req.Scheme, matchedDomainMapping.Domain).ToString();
|
||||
context.RouteContext.HttpContext.Response.Redirect(url);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDomainMapping)
|
||||
{
|
||||
var matchedDomainMapping = mapping.FirstOrDefault(item =>
|
||||
item.Domain.Equals(context.RouteContext.HttpContext.Request.Host.Host,
|
||||
StringComparison.InvariantCultureIgnoreCase));
|
||||
if (matchedDomainMapping != null)
|
||||
{
|
||||
if (AppType is not { } appType)
|
||||
return false;
|
||||
if (appType != matchedDomainMapping.AppType)
|
||||
return false;
|
||||
context.RouteContext.RouteData.Values.Add("appId", matchedDomainMapping.AppId);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AppType == policies.RootAppType)
|
||||
{
|
||||
context.RouteContext.RouteData.Values.Add("appId", policies.RootAppId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return AppType is null;
|
||||
}
|
||||
|
||||
return AppType is null;
|
||||
if (AppType == policies.RootAppType)
|
||||
{
|
||||
context.RouteContext.RouteData.Values.Add("appId", policies.RootAppId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasAppId || AppType is null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ namespace BTCPayServer.Services.Apps
|
||||
(storeId == null || us.StoreDataId == storeId))
|
||||
.Join(ctx.Apps, us => us.StoreDataId, app => app.StoreDataId,
|
||||
(us, app) =>
|
||||
new ListAppsViewModel.ListAppViewModel()
|
||||
new ListAppsViewModel.ListAppViewModel
|
||||
{
|
||||
IsOwner = us.Role == StoreRoles.Owner,
|
||||
StoreId = us.StoreDataId,
|
||||
@@ -455,6 +455,12 @@ namespace BTCPayServer.Services.Apps
|
||||
})
|
||||
.OrderBy(b => b.Created)
|
||||
.ToArrayAsync();
|
||||
|
||||
// allowNoUser can lead to apps being included twice, unify them with distinct
|
||||
if (allowNoUser)
|
||||
{
|
||||
listApps = listApps.DistinctBy(a => a.Id).ToArray();
|
||||
}
|
||||
|
||||
foreach (ListAppsViewModel.ListAppViewModel app in listApps)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user