mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-21 22:11:48 +01:00
Add suggestion list for currency inputs (#3347)
* Move tagHelpers in their own directory * Add suggestion list for currency inputs
This commit is contained in:
parent
30db0cd4f4
commit
11d6588249
15 changed files with 280 additions and 224 deletions
|
@ -143,6 +143,8 @@ namespace BTCPayServer.Services.Rates
|
||||||
return currencies;
|
return currencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CurrencyData> Currencies => _Currencies.Values;
|
||||||
|
|
||||||
public CurrencyData GetCurrencyData(string currency, bool useFallback)
|
public CurrencyData GetCurrencyData(string currency, bool useFallback)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(currency);
|
ArgumentNullException.ThrowIfNull(currency);
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Security
|
|
||||||
{
|
|
||||||
[HtmlTargetElement(Attributes = nameof(Permission))]
|
|
||||||
public class PermissionTagHelper : TagHelper
|
|
||||||
{
|
|
||||||
private readonly IAuthorizationService _authorizationService;
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private readonly ILogger<PermissionTagHelper> _logger;
|
|
||||||
|
|
||||||
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor, ILogger<PermissionTagHelper> logger)
|
|
||||||
{
|
|
||||||
_authorizationService = authorizationService;
|
|
||||||
_httpContextAccessor = httpContextAccessor;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Permission { get; set; }
|
|
||||||
public string PermissionResource { get; set; }
|
|
||||||
|
|
||||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(Permission))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = $"{Permission}_{PermissionResource}";
|
|
||||||
if (!_httpContextAccessor.HttpContext.Items.TryGetValue(key, out var cachedResult))
|
|
||||||
{
|
|
||||||
var result = await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User,
|
|
||||||
PermissionResource,
|
|
||||||
Permission);
|
|
||||||
|
|
||||||
cachedResult = result;
|
|
||||||
_httpContextAccessor.HttpContext.Items.Add(key, result);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!((AuthorizationResult)cachedResult).Succeeded)
|
|
||||||
{
|
|
||||||
output.SuppressOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Configuration;
|
|
||||||
using BTCPayServer.Security;
|
|
||||||
using BTCPayServer.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
|
||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
|
||||||
using NBitcoin;
|
|
||||||
using NBitcoin.Crypto;
|
|
||||||
|
|
||||||
namespace BTCPayServer.TagHelpers
|
|
||||||
{
|
|
||||||
[HtmlTargetElement("srv-model")]
|
|
||||||
public class SrvModel : TagHelper
|
|
||||||
{
|
|
||||||
private readonly Safe _safe;
|
|
||||||
private readonly ContentSecurityPolicies _csp;
|
|
||||||
|
|
||||||
public SrvModel(Safe safe, ContentSecurityPolicies csp)
|
|
||||||
{
|
|
||||||
_safe = safe;
|
|
||||||
_csp = csp;
|
|
||||||
}
|
|
||||||
public string VarName { get; set; } = "srvModel";
|
|
||||||
public object Model { get; set; }
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
output.TagName = "script";
|
|
||||||
output.TagMode = TagMode.StartTagAndEndTag;
|
|
||||||
output.Attributes.Add(new TagHelperAttribute("type", "text/javascript"));
|
|
||||||
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
|
||||||
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
|
||||||
_csp.Add("script-src", $"'nonce-{nonce}'");
|
|
||||||
output.Content.SetHtmlContent($"var {VarName} = {_safe.Json(Model)};");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add a nonce-* so the inline-script can pass CSP rule when they are rendered server-side
|
|
||||||
/// </summary>
|
|
||||||
[HtmlTargetElement("script")]
|
|
||||||
public class CSPInlineScriptTagHelper : TagHelper
|
|
||||||
{
|
|
||||||
private readonly ContentSecurityPolicies _csp;
|
|
||||||
|
|
||||||
public CSPInlineScriptTagHelper(ContentSecurityPolicies csp)
|
|
||||||
{
|
|
||||||
_csp = csp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
if (output.Attributes.ContainsName("src"))
|
|
||||||
return;
|
|
||||||
if (output.Attributes.TryGetAttribute("type", out var attr))
|
|
||||||
{
|
|
||||||
if (attr.Value?.ToString() != "text/javascript")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
|
||||||
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
|
||||||
_csp.Add("script-src", $"'nonce-{nonce}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add 'unsafe-hashes' and sha256- to allow inline event handlers in CSP
|
|
||||||
/// </summary>
|
|
||||||
[HtmlTargetElement(Attributes = "onclick")]
|
|
||||||
[HtmlTargetElement(Attributes = "onkeypress")]
|
|
||||||
[HtmlTargetElement(Attributes = "onchange")]
|
|
||||||
[HtmlTargetElement(Attributes = "onsubmit")]
|
|
||||||
public class CSPEventTagHelper : TagHelper
|
|
||||||
{
|
|
||||||
public const string EventNames = "onclick,onkeypress,onchange,onsubmit";
|
|
||||||
private readonly ContentSecurityPolicies _csp;
|
|
||||||
|
|
||||||
readonly static HashSet<string> EventSet = EventNames.Split(',')
|
|
||||||
.ToHashSet();
|
|
||||||
public CSPEventTagHelper(ContentSecurityPolicies csp)
|
|
||||||
{
|
|
||||||
_csp = csp;
|
|
||||||
}
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
foreach (var attr in output.Attributes)
|
|
||||||
{
|
|
||||||
var n = attr.Name.ToLowerInvariant();
|
|
||||||
if (EventSet.Contains(n))
|
|
||||||
{
|
|
||||||
_csp.AllowUnsafeHashes(attr.Value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add sha256- to allow inline event handlers in CSP
|
|
||||||
/// </summary>
|
|
||||||
[HtmlTargetElement("template", Attributes = "csp-allow")]
|
|
||||||
public class CSPTemplate : TagHelper
|
|
||||||
{
|
|
||||||
private readonly ContentSecurityPolicies _csp;
|
|
||||||
public CSPTemplate(ContentSecurityPolicies csp)
|
|
||||||
{
|
|
||||||
_csp = csp;
|
|
||||||
}
|
|
||||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
output.Attributes.RemoveAll("csp-allow");
|
|
||||||
var childContent = await output.GetChildContentAsync();
|
|
||||||
var content = childContent.GetContent();
|
|
||||||
_csp.AllowInline(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add sha256- to allow inline event handlers in a:href=javascript:
|
|
||||||
/// </summary>
|
|
||||||
[HtmlTargetElement("a", Attributes = "csp-allow")]
|
|
||||||
public class CSPA : TagHelper
|
|
||||||
{
|
|
||||||
private readonly ContentSecurityPolicies _csp;
|
|
||||||
public CSPA(ContentSecurityPolicies csp)
|
|
||||||
{
|
|
||||||
_csp = csp;
|
|
||||||
}
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
output.Attributes.RemoveAll("csp-allow");
|
|
||||||
if (output.Attributes.TryGetAttribute("href", out var attr))
|
|
||||||
{
|
|
||||||
var v = attr.Value.ToString();
|
|
||||||
if (v.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_csp.AllowUnsafeHashes(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that <svg><use href=/ are correctly working if rootpath is present
|
|
||||||
[HtmlTargetElement("use", Attributes = "href")]
|
|
||||||
public class SVGUse : UrlResolutionTagHelper
|
|
||||||
{
|
|
||||||
private readonly IFileVersionProvider _fileVersionProvider;
|
|
||||||
|
|
||||||
public SVGUse(IUrlHelperFactory urlHelperFactory, HtmlEncoder htmlEncoder, IFileVersionProvider fileVersionProvider):base(urlHelperFactory, htmlEncoder)
|
|
||||||
{
|
|
||||||
_fileVersionProvider = fileVersionProvider;
|
|
||||||
}
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
|
||||||
{
|
|
||||||
var attr = output.Attributes["href"].Value.ToString();
|
|
||||||
attr = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, attr);
|
|
||||||
output.Attributes.SetAttribute("href", attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
29
BTCPayServer/TagHelpers/CSPA.cs
Normal file
29
BTCPayServer/TagHelpers/CSPA.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using BTCPayServer.Security;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add sha256- to allow inline event handlers in a:href=javascript:
|
||||||
|
/// </summary>
|
||||||
|
[HtmlTargetElement("a", Attributes = "csp-allow")]
|
||||||
|
public class CSPA : TagHelper
|
||||||
|
{
|
||||||
|
private readonly ContentSecurityPolicies _csp;
|
||||||
|
public CSPA(ContentSecurityPolicies csp)
|
||||||
|
{
|
||||||
|
_csp = csp;
|
||||||
|
}
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
output.Attributes.RemoveAll("csp-allow");
|
||||||
|
if (output.Attributes.TryGetAttribute("href", out var attr))
|
||||||
|
{
|
||||||
|
var v = attr.Value.ToString();
|
||||||
|
if (v.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_csp.AllowUnsafeHashes(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
BTCPayServer/TagHelpers/CSPEventTagHelper.cs
Normal file
37
BTCPayServer/TagHelpers/CSPEventTagHelper.cs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using BTCPayServer.Security;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add 'unsafe-hashes' and sha256- to allow inline event handlers in CSP
|
||||||
|
/// </summary>
|
||||||
|
[HtmlTargetElement(Attributes = "onclick")]
|
||||||
|
[HtmlTargetElement(Attributes = "onkeypress")]
|
||||||
|
[HtmlTargetElement(Attributes = "onchange")]
|
||||||
|
[HtmlTargetElement(Attributes = "onsubmit")]
|
||||||
|
public class CSPEventTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public const string EventNames = "onclick,onkeypress,onchange,onsubmit";
|
||||||
|
private readonly ContentSecurityPolicies _csp;
|
||||||
|
|
||||||
|
readonly static HashSet<string> EventSet = EventNames.Split(',')
|
||||||
|
.ToHashSet();
|
||||||
|
public CSPEventTagHelper(ContentSecurityPolicies csp)
|
||||||
|
{
|
||||||
|
_csp = csp;
|
||||||
|
}
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
foreach (var attr in output.Attributes)
|
||||||
|
{
|
||||||
|
var n = attr.Name.ToLowerInvariant();
|
||||||
|
if (EventSet.Contains(n))
|
||||||
|
{
|
||||||
|
_csp.AllowUnsafeHashes(attr.Value.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
BTCPayServer/TagHelpers/CSPInlineScriptTagHelper.cs
Normal file
33
BTCPayServer/TagHelpers/CSPInlineScriptTagHelper.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using BTCPayServer.Security;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
using NBitcoin;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a nonce-* so the inline-script can pass CSP rule when they are rendered server-side
|
||||||
|
/// </summary>
|
||||||
|
[HtmlTargetElement("script")]
|
||||||
|
public class CSPInlineScriptTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
private readonly ContentSecurityPolicies _csp;
|
||||||
|
|
||||||
|
public CSPInlineScriptTagHelper(ContentSecurityPolicies csp)
|
||||||
|
{
|
||||||
|
_csp = csp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
if (output.Attributes.ContainsName("src"))
|
||||||
|
return;
|
||||||
|
if (output.Attributes.TryGetAttribute("type", out var attr))
|
||||||
|
{
|
||||||
|
if (attr.Value?.ToString() != "text/javascript")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
||||||
|
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
||||||
|
_csp.Add("script-src", $"'nonce-{nonce}'");
|
||||||
|
}
|
||||||
|
}
|
24
BTCPayServer/TagHelpers/CSPTemplate.cs
Normal file
24
BTCPayServer/TagHelpers/CSPTemplate.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Security;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add sha256- to allow inline event handlers in CSP
|
||||||
|
/// </summary>
|
||||||
|
[HtmlTargetElement("template", Attributes = "csp-allow")]
|
||||||
|
public class CSPTemplate : TagHelper
|
||||||
|
{
|
||||||
|
private readonly ContentSecurityPolicies _csp;
|
||||||
|
public CSPTemplate(ContentSecurityPolicies csp)
|
||||||
|
{
|
||||||
|
_csp = csp;
|
||||||
|
}
|
||||||
|
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
output.Attributes.RemoveAll("csp-allow");
|
||||||
|
var childContent = await output.GetChildContentAsync();
|
||||||
|
var content = childContent.GetContent();
|
||||||
|
_csp.AllowInline(content);
|
||||||
|
}
|
||||||
|
}
|
44
BTCPayServer/TagHelpers/CurrenciesSuggestionsTagHelper.cs
Normal file
44
BTCPayServer/TagHelpers/CurrenciesSuggestionsTagHelper.cs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
using BTCPayServer.Services.Rates;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BTCPayServer.TagHelpers
|
||||||
|
{
|
||||||
|
[HtmlTargetElement("input", Attributes = "currency-selection")]
|
||||||
|
public class CurrenciesSuggestionsTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
private readonly CurrencyNameTable _currencies;
|
||||||
|
|
||||||
|
public CurrenciesSuggestionsTagHelper(CurrencyNameTable currencies)
|
||||||
|
{
|
||||||
|
_currencies = currencies;
|
||||||
|
}
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
output.Attributes.RemoveAll("currency-selection");
|
||||||
|
output.PostElement.AppendHtml("<datalist id=\"currency-selection-suggestion\">");
|
||||||
|
var currencies = _currencies.Currencies.Where(c => !c.Crypto).Select(c => c.Code).OrderBy(c => c).ToList();
|
||||||
|
int pos = 0;
|
||||||
|
InsertAt(currencies, "BTC", pos++);
|
||||||
|
InsertAt(currencies, "SATS", pos++);
|
||||||
|
InsertAt(currencies, "USD", pos++);
|
||||||
|
InsertAt(currencies, "EUR", pos++);
|
||||||
|
InsertAt(currencies, "JPY", pos++);
|
||||||
|
InsertAt(currencies, "CNY", pos++);
|
||||||
|
foreach (var curr in currencies)
|
||||||
|
{
|
||||||
|
output.PostElement.AppendHtml($"<option value=\"{curr}\">");
|
||||||
|
}
|
||||||
|
output.PostElement.AppendHtml("</datalist>");
|
||||||
|
output.Attributes.Add("list", "currency-selection-suggestion");
|
||||||
|
base.Process(context, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertAt(List<string> currencies, string curr, int idx)
|
||||||
|
{
|
||||||
|
currencies.Remove(curr);
|
||||||
|
currencies.Insert(idx, curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
BTCPayServer/TagHelpers/PermissionTagHelper.cs
Normal file
50
BTCPayServer/TagHelpers/PermissionTagHelper.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
|
||||||
|
[HtmlTargetElement(Attributes = nameof(Permission))]
|
||||||
|
public class PermissionTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
private readonly IAuthorizationService _authorizationService;
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
private readonly ILogger<PermissionTagHelper> _logger;
|
||||||
|
|
||||||
|
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor, ILogger<PermissionTagHelper> logger)
|
||||||
|
{
|
||||||
|
_authorizationService = authorizationService;
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Permission { get; set; }
|
||||||
|
public string PermissionResource { get; set; }
|
||||||
|
|
||||||
|
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Permission))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = $"{Permission}_{PermissionResource}";
|
||||||
|
if (!_httpContextAccessor.HttpContext.Items.TryGetValue(key, out var cachedResult))
|
||||||
|
{
|
||||||
|
var result = await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User,
|
||||||
|
PermissionResource,
|
||||||
|
Permission);
|
||||||
|
|
||||||
|
cachedResult = result;
|
||||||
|
_httpContextAccessor.HttpContext.Items.Add(key, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!((AuthorizationResult)cachedResult).Succeeded)
|
||||||
|
{
|
||||||
|
output.SuppressOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
26
BTCPayServer/TagHelpers/SVGUse.cs
Normal file
26
BTCPayServer/TagHelpers/SVGUse.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
// Make sure that <svg><use href=/ are correctly working if rootpath is present
|
||||||
|
[HtmlTargetElement("use", Attributes = "href")]
|
||||||
|
public class SVGUse : UrlResolutionTagHelper
|
||||||
|
{
|
||||||
|
private readonly IFileVersionProvider _fileVersionProvider;
|
||||||
|
|
||||||
|
public SVGUse(IUrlHelperFactory urlHelperFactory, HtmlEncoder htmlEncoder, IFileVersionProvider fileVersionProvider) : base(urlHelperFactory, htmlEncoder)
|
||||||
|
{
|
||||||
|
_fileVersionProvider = fileVersionProvider;
|
||||||
|
}
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
var attr = output.Attributes["href"].Value.ToString();
|
||||||
|
attr = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, attr);
|
||||||
|
output.Attributes.SetAttribute("href", attr);
|
||||||
|
}
|
||||||
|
}
|
30
BTCPayServer/TagHelpers/SrvModel.cs
Normal file
30
BTCPayServer/TagHelpers/SrvModel.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using BTCPayServer.Security;
|
||||||
|
using BTCPayServer.Services;
|
||||||
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
using NBitcoin;
|
||||||
|
namespace BTCPayServer.TagHelpers;
|
||||||
|
|
||||||
|
[HtmlTargetElement("srv-model")]
|
||||||
|
public class SrvModel : TagHelper
|
||||||
|
{
|
||||||
|
private readonly Safe _safe;
|
||||||
|
private readonly ContentSecurityPolicies _csp;
|
||||||
|
|
||||||
|
public SrvModel(Safe safe, ContentSecurityPolicies csp)
|
||||||
|
{
|
||||||
|
_safe = safe;
|
||||||
|
_csp = csp;
|
||||||
|
}
|
||||||
|
public string VarName { get; set; } = "srvModel";
|
||||||
|
public object Model { get; set; }
|
||||||
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
|
{
|
||||||
|
output.TagName = "script";
|
||||||
|
output.TagMode = TagMode.StartTagAndEndTag;
|
||||||
|
output.Attributes.Add(new TagHelperAttribute("type", "text/javascript"));
|
||||||
|
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
||||||
|
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
||||||
|
_csp.Add("script-src", $"'nonce-{nonce}'");
|
||||||
|
output.Content.SetHtmlContent($"var {VarName} = {_safe.Json(Model)};");
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Currency" class="form-label"></label>
|
<label asp-for="Currency" class="form-label"></label>
|
||||||
<input asp-for="Currency" class="form-control" placeholder="Use store's default settings" />
|
<input asp-for="Currency" currency-selection class="form-control" placeholder="Use store's default settings" />
|
||||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Currency" class="form-label"></label>
|
<label asp-for="Currency" class="form-label"></label>
|
||||||
<input asp-for="Currency" class="form-control" />
|
<input asp-for="Currency" currency-selection class="form-control" />
|
||||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Views.Stores
|
@using BTCPayServer.Views.Stores
|
||||||
@model BTCPayServer.Models.WalletViewModels.NewPullPaymentModel
|
@model BTCPayServer.Models.WalletViewModels.NewPullPaymentModel
|
||||||
@{
|
@{
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-4">
|
<div class="form-group col-4">
|
||||||
<label asp-for="Currency" class="form-label"></label>
|
<label asp-for="Currency" class="form-label"></label>
|
||||||
<input asp-for="Currency" class="form-control"/>
|
<input asp-for="Currency" currency-selection class="form-control"/>
|
||||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<h3 class="mb-3">Payment</h3>
|
<h3 class="mb-3">Payment</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="DefaultCurrency" class="form-label"></label>
|
<label asp-for="DefaultCurrency" class="form-label"></label>
|
||||||
<input asp-for="DefaultCurrency" class="form-control" style="max-width:10ch;" />
|
<input asp-for="DefaultCurrency" currency-selection class="form-control" style="max-width:10ch;" />
|
||||||
<span asp-validation-for="DefaultCurrency" class="text-danger"></span>
|
<span asp-validation-for="DefaultCurrency" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group d-flex align-items-center">
|
<div class="form-group d-flex align-items-center">
|
||||||
|
|
Loading…
Add table
Reference in a new issue