mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-03 09:29:10 +01:00
Use Safe.Raw and Safe.Json instead of Html.Raw and the JsonHelper, move sanitization at the View level (#960)
This commit is contained in:
parent
6b355cbe1b
commit
be5597085b
32 changed files with 132 additions and 82 deletions
|
@ -34,7 +34,7 @@
|
|||
<PackageReference Include="BuildBundlerMinifier" Version="2.9.406" />
|
||||
<PackageReference Include="BundlerMinifier.Core" Version="2.9.406" />
|
||||
<PackageReference Include="BundlerMinifier.TagHelpers" Version="2.9.406" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="4.0.207" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="4.0.217" />
|
||||
<PackageReference Include="LedgerWallet" Version="2.0.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.2" />
|
||||
|
@ -47,7 +47,7 @@
|
|||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.2" />
|
||||
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.3" />
|
||||
<PackageReference Include="NicolasDorier.RateLimits" Version="1.0.0.7" />
|
||||
<PackageReference Include="NicolasDorier.RateLimits" Version="1.0.0.9" />
|
||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.18" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.2" />
|
||||
<PackageReference Include="OpenIddict" Version="2.0.0" />
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
Version = u2fChallenge[0].version,
|
||||
Challenge = u2fChallenge[0].challenge,
|
||||
Challenges = JsonConvert.SerializeObject(u2fChallenge),
|
||||
Challenges = u2fChallenge,
|
||||
AppId = u2fChallenge[0].appId,
|
||||
UserId = user.Id,
|
||||
RememberMe = rememberMe
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace BTCPayServer.Controllers
|
|||
EnforceTargetAmount = vm.EnforceTargetAmount,
|
||||
StartDate = vm.StartDate?.ToUniversalTime(),
|
||||
TargetCurrency = vm.TargetCurrency,
|
||||
Description = _htmlSanitizer.Sanitize( vm.Description),
|
||||
Description = vm.Description,
|
||||
EndDate = vm.EndDate?.ToUniversalTime(),
|
||||
TargetAmount = vm.TargetAmount,
|
||||
CustomCSSLink = vm.CustomCSSLink,
|
||||
|
|
|
@ -30,7 +30,6 @@ namespace BTCPayServer.Controllers
|
|||
EventAggregator eventAggregator,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
CurrencyNameTable currencies,
|
||||
HtmlSanitizer htmlSanitizer,
|
||||
EmailSenderFactory emailSenderFactory,
|
||||
AppService AppService)
|
||||
{
|
||||
|
@ -39,7 +38,6 @@ namespace BTCPayServer.Controllers
|
|||
_EventAggregator = eventAggregator;
|
||||
_NetworkProvider = networkProvider;
|
||||
_currencies = currencies;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
_emailSenderFactory = emailSenderFactory;
|
||||
_AppService = AppService;
|
||||
}
|
||||
|
@ -49,7 +47,6 @@ namespace BTCPayServer.Controllers
|
|||
private readonly EventAggregator _EventAggregator;
|
||||
private BTCPayNetworkProvider _NetworkProvider;
|
||||
private readonly CurrencyNameTable _currencies;
|
||||
private readonly HtmlSanitizer _htmlSanitizer;
|
||||
private readonly EmailSenderFactory _emailSenderFactory;
|
||||
private AppService _AppService;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.ManageViewModels;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -11,6 +12,7 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
public partial class ManageController
|
||||
{
|
||||
private const string RecoveryCodesKey = nameof(RecoveryCodesKey);
|
||||
private const string AuthenicatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6";
|
||||
|
||||
[HttpGet]
|
||||
|
@ -80,18 +82,8 @@ namespace BTCPayServer.Controllers
|
|||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
||||
if (string.IsNullOrEmpty(unformattedKey))
|
||||
{
|
||||
await _userManager.ResetAuthenticatorKeyAsync(user);
|
||||
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
||||
}
|
||||
|
||||
var model = new EnableAuthenticatorViewModel
|
||||
{
|
||||
SharedKey = FormatKey(unformattedKey),
|
||||
AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey)
|
||||
};
|
||||
var model = new EnableAuthenticatorViewModel();
|
||||
await LoadSharedKeyAndQrCodeUriAsync(user, model);
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
@ -100,32 +92,36 @@ namespace BTCPayServer.Controllers
|
|||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> EnableAuthenticator(EnableAuthenticatorViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
await LoadSharedKeyAndQrCodeUriAsync(user, model);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Strip spaces and hypens
|
||||
var verificationCode = model.Code.Replace(" ", string.Empty, StringComparison.InvariantCulture)
|
||||
.Replace("-", string.Empty, StringComparison.InvariantCulture);
|
||||
var verificationCode = model.Code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
||||
|
||||
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
|
||||
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
|
||||
|
||||
if (!is2faTokenValid)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Code), "Verification code is invalid.");
|
||||
ModelState.AddModelError("Code", "Verification code is invalid.");
|
||||
await LoadSharedKeyAndQrCodeUriAsync(user, model);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
await _userManager.SetTwoFactorEnabledAsync(user, true);
|
||||
_logger.LogInformation("User with ID {UserId} has enabled 2FA with an authenticator app.", user.Id);
|
||||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
||||
TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
|
||||
|
||||
return RedirectToAction(nameof(GenerateRecoveryCodes));
|
||||
}
|
||||
|
||||
|
@ -153,7 +149,20 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GenerateRecoveryCodes()
|
||||
public IActionResult GenerateRecoveryCodes()
|
||||
{
|
||||
var recoveryCodes = (string[])TempData[RecoveryCodesKey];
|
||||
if (recoveryCodes == null)
|
||||
{
|
||||
return RedirectToAction(nameof(TwoFactorAuthentication));
|
||||
}
|
||||
|
||||
var model = new GenerateRecoveryCodesViewModel {RecoveryCodes = recoveryCodes};
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GenerateRecoveryCodesWarning()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
|
@ -163,16 +172,10 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
if (!user.TwoFactorEnabled)
|
||||
{
|
||||
throw new ApplicationException(
|
||||
$"Cannot generate recovery codes for user with ID '{user.Id}' as they do not have 2FA enabled.");
|
||||
throw new ApplicationException($"Cannot generate recovery codes for user with ID '{user.Id}' because they do not have 2FA enabled.");
|
||||
}
|
||||
|
||||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
||||
var model = new GenerateRecoveryCodesViewModel {RecoveryCodes = recoveryCodes.ToArray()};
|
||||
|
||||
_logger.LogInformation("User with ID {UserId} has generated new 2FA recovery codes.", user.Id);
|
||||
|
||||
return View(model);
|
||||
return View(nameof(GenerateRecoveryCodesWarning));
|
||||
}
|
||||
|
||||
private string GenerateQrCodeUri(string email, string unformattedKey)
|
||||
|
@ -201,5 +204,19 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
return result.ToString().ToLowerInvariant();
|
||||
}
|
||||
|
||||
|
||||
private async Task LoadSharedKeyAndQrCodeUriAsync(ApplicationUser user, EnableAuthenticatorViewModel model)
|
||||
{
|
||||
var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
||||
if (string.IsNullOrEmpty(unformattedKey))
|
||||
{
|
||||
await _userManager.ResetAuthenticatorKeyAsync(user);
|
||||
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
||||
}
|
||||
|
||||
model.SharedKey = FormatKey(unformattedKey);
|
||||
model.AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace BTCPayServer.Controllers
|
|||
private readonly PaymentRequestService _PaymentRequestService;
|
||||
private readonly EventAggregator _EventAggregator;
|
||||
private readonly CurrencyNameTable _Currencies;
|
||||
private readonly HtmlSanitizer _htmlSanitizer;
|
||||
private readonly InvoiceRepository _InvoiceRepository;
|
||||
|
||||
public PaymentRequestController(
|
||||
|
@ -52,7 +51,6 @@ namespace BTCPayServer.Controllers
|
|||
PaymentRequestService paymentRequestService,
|
||||
EventAggregator eventAggregator,
|
||||
CurrencyNameTable currencies,
|
||||
HtmlSanitizer htmlSanitizer,
|
||||
InvoiceRepository invoiceRepository)
|
||||
{
|
||||
_InvoiceController = invoiceController;
|
||||
|
@ -62,7 +60,6 @@ namespace BTCPayServer.Controllers
|
|||
_PaymentRequestService = paymentRequestService;
|
||||
_EventAggregator = eventAggregator;
|
||||
_Currencies = currencies;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
_InvoiceRepository = invoiceRepository;
|
||||
}
|
||||
|
||||
|
@ -152,7 +149,7 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
blob.Title = viewModel.Title;
|
||||
blob.Email = viewModel.Email;
|
||||
blob.Description = _htmlSanitizer.Sanitize(viewModel.Description);
|
||||
blob.Description = viewModel.Description;
|
||||
blob.Amount = viewModel.Amount;
|
||||
blob.ExpiryDate = viewModel.ExpiryDate?.ToUniversalTime();
|
||||
blob.Currency = viewModel.Currency;
|
||||
|
|
|
@ -126,6 +126,7 @@ namespace BTCPayServer.Hosting
|
|||
});
|
||||
|
||||
services.TryAddSingleton<AppService>();
|
||||
services.TryAddTransient<Safe>();
|
||||
services.TryAddSingleton<Ganss.XSS.HtmlSanitizer>(o =>
|
||||
{
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.ComponentModel;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace BTCPayServer.Models.ManageViewModels
|
||||
{
|
||||
|
@ -15,9 +16,10 @@ namespace BTCPayServer.Models.ManageViewModels
|
|||
[Display(Name = "Verification Code")]
|
||||
public string Code { get; set; }
|
||||
|
||||
[ReadOnly(true)]
|
||||
[BindNever]
|
||||
public string SharedKey { get; set; }
|
||||
|
||||
[BindNever]
|
||||
public string AuthenticatorUri { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,10 +283,10 @@ namespace BTCPayServer.Services.Apps
|
|||
.Where(kv => kv.Value != null)
|
||||
.Select(c => new ViewPointOfSaleViewModel.Item()
|
||||
{
|
||||
Description = _HtmlSanitizer.Sanitize(c.GetDetailString("description")),
|
||||
Description = c.GetDetailString("description"),
|
||||
Id = c.Key,
|
||||
Image = _HtmlSanitizer.Sanitize(c.GetDetailString("image")),
|
||||
Title = _HtmlSanitizer.Sanitize(c.GetDetailString("title") ?? c.Key),
|
||||
Image = c.GetDetailString("image"),
|
||||
Title = c.GetDetailString("title") ?? c.Key,
|
||||
Price = c.GetDetail("price")
|
||||
.Select(cc => new ViewPointOfSaleViewModel.Item.ItemPrice()
|
||||
{
|
||||
|
|
34
BTCPayServer/Services/Safe.cs
Normal file
34
BTCPayServer/Services/Safe.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Ganss.XSS;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace BTCPayServer.Services
|
||||
{
|
||||
public class Safe
|
||||
{
|
||||
private readonly IHtmlHelper _htmlHelper;
|
||||
private readonly IJsonHelper _jsonHelper;
|
||||
private readonly HtmlSanitizer _htmlSanitizer;
|
||||
|
||||
public Safe(IHtmlHelper htmlHelper, IJsonHelper jsonHelper, HtmlSanitizer htmlSanitizer)
|
||||
{
|
||||
_htmlHelper = htmlHelper;
|
||||
_jsonHelper = jsonHelper;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
}
|
||||
|
||||
public IHtmlContent Raw(string value)
|
||||
{
|
||||
return _htmlHelper.Raw(_htmlSanitizer.Sanitize(value));
|
||||
}
|
||||
|
||||
public IHtmlContent Json(object model)
|
||||
{
|
||||
return _htmlHelper.Raw(_jsonHelper.Serialize(model));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Services.U2F.Models
|
||||
|
@ -18,7 +19,7 @@ namespace BTCPayServer.Services.U2F.Models
|
|||
public string DeviceResponse { get; set; }
|
||||
|
||||
[Display(Name = "Challenges")]
|
||||
public string Challenges { get; set; }
|
||||
public List<ServerChallenge> Challenges { get; set; }
|
||||
|
||||
[Display(Name = "Challenge")]
|
||||
public string Challenge { get; set; }
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
};
|
||||
setTimeout(function() {
|
||||
window.u2f.sign(
|
||||
"@Model.AppId",
|
||||
"@Model.Challenge",
|
||||
@Html.Raw(@Model.Challenges), function (data) {
|
||||
@Safe.Json(Model.AppId),
|
||||
@Safe.Json(Model.Challenge),
|
||||
@Safe.Json(Model.Challenges), function (data) {
|
||||
if (data.errorCode) {
|
||||
$("#error-response").text(errorMap[data.errorCode]);
|
||||
return;
|
||||
|
|
|
@ -30,17 +30,17 @@
|
|||
@item.Price.Value
|
||||
if (item.Custom)
|
||||
{
|
||||
Html.Raw("or more");
|
||||
Safe.Raw("or more");
|
||||
}
|
||||
}
|
||||
else if (item.Custom)
|
||||
{
|
||||
Html.Raw("Any amount");
|
||||
Safe.Raw("Any amount");
|
||||
}
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<p class="card-text overflow-hidden">@Html.Raw(item.Description)</p>
|
||||
<p class="card-text overflow-hidden">@Safe.Raw(item.Description)</p>
|
||||
|
||||
</div>
|
||||
@if (Model.ViewCrowdfundViewModel.PerkCount.ContainsKey(item.Id))
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-12">
|
||||
<div class="card-text overflow-hidden">@Html.Raw(Model.Description)</div>
|
||||
<div class="card-text overflow-hidden">@Safe.Raw(Model.Description)</div>
|
||||
</div>
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<partial
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
@if (!Context.Request.Query.ContainsKey("simple"))
|
||||
{
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
<bundle name="wwwroot/bundles/crowdfund-bundle-1.min.js"></bundle>
|
||||
<bundle name="wwwroot/bundles/crowdfund-bundle-2.min.js"></bundle>
|
||||
|
@ -33,7 +33,7 @@
|
|||
@if (!string.IsNullOrEmpty(Model.EmbeddedCSS))
|
||||
{
|
||||
<style>
|
||||
@Html.Raw(Model.EmbeddedCSS);
|
||||
@Safe.Raw(Model.EmbeddedCSS);
|
||||
</style>
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
{
|
||||
<link rel="stylesheet" href="~/cart/css/style.css">
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
<bundle name="wwwroot/bundles/cart-bundle.min.js" />
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>You need to pay <b>@Model.Amount</b> to <b>@Model.Address</b></p>
|
||||
<div id="qrCode"></div>
|
||||
<div id="qrCodeData" data-url="@Html.Raw(Model.BitcoinUri)" style="margin-bottom:20px;"></div>
|
||||
<div id="qrCodeData" data-url="@Model.BitcoinUri" style="margin-bottom:20px;"></div>
|
||||
<p>
|
||||
<a class="btn btn-primary" href="@Model.BitcoinUri">
|
||||
<span>Open in wallet</span>
|
||||
|
@ -52,7 +52,7 @@
|
|||
<script type="text/javascript">
|
||||
new QRCode(document.getElementById("qrCode"),
|
||||
{
|
||||
text: "@Html.Raw(Model.BitcoinUri)",
|
||||
text: @Safe.Json(Model.BitcoinUri),
|
||||
width: 200,
|
||||
height: 200,
|
||||
useSVG: true
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<bundle name="wwwroot/bundles/checkout-bundle.min.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
|
||||
<bundle name="wwwroot/bundles/checkout-bundle.min.js" />
|
||||
|
@ -114,8 +114,8 @@
|
|||
</div>
|
||||
</invoice>
|
||||
<script type="text/javascript">
|
||||
var availableLanguages = @Html.Raw(Json.Serialize(langService.GetLanguages().Select((language) => language.Code)));;
|
||||
var storeDefaultLang = "@Model.DefaultLang";
|
||||
var availableLanguages = @Safe.Json(langService.GetLanguages().Select((language) => language.Code));;
|
||||
var storeDefaultLang = @Safe.Json(@Model.DefaultLang);
|
||||
var fallbackLanguage = "en";
|
||||
startingLanguage = computeStartingLanguage();
|
||||
// initialization
|
||||
|
@ -123,7 +123,7 @@
|
|||
.use(window.i18nextXHRBackend)
|
||||
.init({
|
||||
backend: {
|
||||
loadPath: '@(Model.RootPath)locales/{{lng}}.json'
|
||||
loadPath: @Safe.Json($"{Model.RootPath}locales/{{{{lng}}}}.json")
|
||||
},
|
||||
lng: startingLanguage,
|
||||
fallbackLng: fallbackLanguage,
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
};
|
||||
|
||||
setTimeout(function() {
|
||||
var request = { "challenge": "@Model.Challenge", "version": "@Model.Version", "appId": "@Model.AppId" };
|
||||
var request = { "challenge": @Safe.Json(Model.Challenge), "version": @Safe.Json(Model.Version), "appId": @Safe.Json(Model.AppId) };
|
||||
var registerRequests = [{version: request.version, challenge: request.challenge}];
|
||||
u2f.register(request.appId, registerRequests, [],
|
||||
function(data) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<li>
|
||||
<p>Scan the QR Code or enter this key <kbd>@Model.SharedKey</kbd> into your two factor authenticator app. Spaces and casing do not matter.</p>
|
||||
<div id="qrCode"></div>
|
||||
<div id="qrCodeData" data-url="@Html.Raw(Model.AuthenticatorUri)"></div>
|
||||
<div id="qrCodeData" data-url="@Model.AuthenticatorUri"></div>
|
||||
<br />
|
||||
</li>
|
||||
<li>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<script type="text/javascript">
|
||||
new QRCode(document.getElementById("qrCode"),
|
||||
{
|
||||
text: "@Html.Raw(Model.AuthenticatorUri)",
|
||||
text: @Safe.Json(Model.AuthenticatorUri),
|
||||
width: 200,
|
||||
height: 200,
|
||||
useSVG: true
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="w-100 p-2">@Html.Raw(Model.Description)</div>
|
||||
<div class="w-100 p-2">@Safe.Raw(Model.Description)</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
@if (!Context.Request.Query.ContainsKey("simple"))
|
||||
{
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle-1.min.js"></bundle>
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle-2.min.js"></bundle>
|
||||
|
@ -34,7 +34,7 @@
|
|||
@if (!string.IsNullOrEmpty(Model.EmbeddedCSS))
|
||||
{
|
||||
<style>
|
||||
@Html.Raw(Model.EmbeddedCSS);
|
||||
@Safe.Raw(Model.EmbeddedCSS);
|
||||
</style>
|
||||
}
|
||||
</head>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<bundle name="wwwroot/bundles/lightning-node-info-bundle.min.js" />
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
|
||||
|
||||
window.onload = function() {
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
{
|
||||
<div class="form-group">
|
||||
<div id="qrCode"></div>
|
||||
<div id="qrCodeData" data-url="@Html.Raw(Model.ServiceLink)"></div>
|
||||
<div id="qrCodeData" data-url="@Model.ServiceLink"></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
@ -70,7 +70,7 @@
|
|||
<script type="text/javascript">
|
||||
new QRCode(document.getElementById("qrCode"),
|
||||
{
|
||||
text: "@Html.Raw(Model.ServiceLink)",
|
||||
text: @Safe.Json(Model.ServiceLink),
|
||||
width: 200,
|
||||
height: 200,
|
||||
useSVG: true
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
{
|
||||
<div class="form-group">
|
||||
<div id="qrCode"></div>
|
||||
<div id="qrCodeData" data-url="@Html.Raw(Model.QRCode)"></div>
|
||||
<div id="qrCodeData" data-url="@Model.QRCode"></div>
|
||||
</div>
|
||||
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a></p>
|
||||
<div id="detailsQR" class="collapse">
|
||||
|
@ -184,7 +184,7 @@
|
|||
<script type="text/javascript">
|
||||
new QRCode(document.getElementById("qrCode"),
|
||||
{
|
||||
text: "@Html.Raw(Model.QRCode)",
|
||||
text: @Safe.Json(Model.QRCode),
|
||||
width: 200,
|
||||
height: 200,
|
||||
useSVG: true
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
{
|
||||
<div class="form-group">
|
||||
<div id="qrCode"></div>
|
||||
<div id="qrCodeData" data-url="@Html.Raw(Model.ServiceLink)"></div>
|
||||
<div id="qrCodeData" data-url="@Model.ServiceLink"></div>
|
||||
</div>
|
||||
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a></p>
|
||||
<div id="detailsQR" class="collapse">
|
||||
|
@ -101,7 +101,7 @@
|
|||
<script type="text/javascript">
|
||||
new QRCode(document.getElementById("qrCode"),
|
||||
{
|
||||
text: "@Html.Raw(Model.ServiceLink)",
|
||||
text: @Safe.Json(Model.ServiceLink),
|
||||
width: 200,
|
||||
height: 200,
|
||||
useSVG: true
|
||||
|
|
|
@ -128,14 +128,14 @@
|
|||
|
||||
@RenderSection("Scripts", required: false)
|
||||
|
||||
<script type="text/javascript">
|
||||
var expectedDomain = @Html.Raw(Json.Serialize(env.ExpectedHost));
|
||||
var expectedProtocol = @Html.Raw(Json.Serialize(env.ExpectedProtocol));
|
||||
<script type="text/javascript">
|
||||
var expectedDomain = @Safe.Json(env.ExpectedHost);
|
||||
var expectedProtocol = @Safe.Json(env.ExpectedProtocol);
|
||||
if (window.location.host != expectedDomain || window.location.protocol != expectedProtocol + ":") {
|
||||
document.getElementById("badUrl").style.display = "block";
|
||||
document.getElementById("browserScheme").innerText = window.location.protocol.substr(0, window.location.protocol.length -1);
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
}
|
||||
@if (!string.IsNullOrEmpty(parsedModel.Html))
|
||||
{
|
||||
@Html.Raw(parsedModel.Html)
|
||||
@Safe.Raw(parsedModel.Html)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
|
||||
@section Scripts {
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Html.Raw(Json.Serialize(Model));
|
||||
var srvModel = @Safe.Json(Model);
|
||||
|
||||
var payButtonCtrl = new Vue({
|
||||
el: '#payButtonCtrl',
|
||||
|
|
|
@ -171,6 +171,6 @@
|
|||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script type="text/javascript">var defaultScript = @Html.Raw(Json.Serialize(Model.DefaultScript));</script>
|
||||
<script type="text/javascript">var defaultScript = @Safe.Json(Model.DefaultScript);</script>
|
||||
@await Html.PartialAsync("_ValidationScriptsPartial")
|
||||
}
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
@using BTCPayServer.Models.InvoicingModels
|
||||
@using BTCPayServer.Models.ManageViewModels
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
@inject BTCPayServer.Services.Safe Safe
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
|
@ -47,5 +47,5 @@
|
|||
"Pay with CoinSwitch": "CoinSwitchでのお支払い",
|
||||
"Pay with Changelly": "Changellyでのお支払い",
|
||||
"Close": "閉じる",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
"NotPaid_ExtraTransaction": "請求金額の全額が支払われていません。未払い分の別のトランザクションをお送りください。"
|
||||
}
|
Loading…
Add table
Reference in a new issue