Validate the name of controllers when LinkGenerator

This commit is contained in:
nicolas.dorier 2022-01-08 14:15:26 +09:00
parent 88bc1c64d2
commit 47d8d3cdb1
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
2 changed files with 78 additions and 1 deletions

View File

@ -140,6 +140,7 @@ namespace BTCPayServer.Hosting
.AddRazorRuntimeCompilation()
.AddPlugins(services, Configuration, LoggerFactory)
.AddControllersAsServices();
ValidateControllerNameTransformer.Register(services);
services.TryAddScoped<ContentSecurityPolicies>();
services.Configure<IdentityOptions>(options =>
@ -268,7 +269,7 @@ namespace BTCPayServer.Hosting
PaymentRequestHub.Register(endpoints);
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute("default", "{controller:validate=Home}/{action=Index}/{id?}");
});
app.UsePlugins();
}

View File

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace BTCPayServer.Hosting
{
public class ValidateControllerNameTransformer : IOutboundParameterTransformer
{
public static void Register(IServiceCollection services)
{
services.AddRouting(opts =>
{
opts.ConstraintMap["validate"] = typeof(ValidateControllerNameTransformer);
});
services.AddTransient<IApplicationModelProvider, ApplicitionModelProvider>();
services.AddSingleton<ControllerNameList>();
}
public class ControllerNotFoundException : Exception
{
public ControllerNotFoundException(string controllerName) : base($"The controller {controllerName} has not been found")
{
}
}
public class ControllerNameList : HashSet<string>
{
}
public class ApplicitionModelProvider : IApplicationModelProvider
{
public ApplicitionModelProvider(ControllerNameList list)
{
List = list;
}
public int Order => 0;
public ControllerNameList List { get; }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
if (List.Count != 0)
return;
lock (List)
{
foreach (var controller in context.Result.Controllers)
{
List.Add(controller.ControllerName);
}
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
}
}
private readonly ControllerNameList list;
public ValidateControllerNameTransformer(ControllerNameList list)
{
this.list = list;
}
public string TransformOutbound(object value)
{
if (value is not string str)
return null;
if (!list.Contains(str))
throw new ControllerNotFoundException(str);
return str;
}
}
}