From 048dff7e9ecdfbf1ccf168af2c98b4c44f82336e Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Sat, 30 May 2020 09:59:09 +0900 Subject: [PATCH] Always use second based TimeSpan in Greenfield --- .../JsonConverters/TimeSpanJsonConverter.cs | 45 +++++++++++++++++++ BTCPayServer.Client/Models/StoreBaseData.cs | 14 ++++-- BTCPayServer.Tests/SeleniumTests.cs | 2 + .../GreenField/StoresController.cs | 12 ++--- .../swagger/v1/swagger.template.stores.json | 12 ++++- 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 BTCPayServer.Client/JsonConverters/TimeSpanJsonConverter.cs diff --git a/BTCPayServer.Client/JsonConverters/TimeSpanJsonConverter.cs b/BTCPayServer.Client/JsonConverters/TimeSpanJsonConverter.cs new file mode 100644 index 000000000..3947d334c --- /dev/null +++ b/BTCPayServer.Client/JsonConverters/TimeSpanJsonConverter.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NBitcoin.JsonConverters; +using Newtonsoft.Json; + +namespace BTCPayServer.Client.JsonConverters +{ + public class TimeSpanJsonConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return objectType == typeof(TimeSpan) || objectType == typeof(TimeSpan?); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + try + { + var nullable = objectType == typeof(TimeSpan?); + if (reader.TokenType == JsonToken.Null) + { + if (nullable) + return null; + return TimeSpan.Zero; + } + if (reader.TokenType != JsonToken.Integer) + throw new JsonObjectException("Invalid timespan, expected integer", reader); + return TimeSpan.FromSeconds((long)reader.Value); + } + catch + { + throw new JsonObjectException("Invalid locktime", reader); + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value is TimeSpan s) + { + writer.WriteValue((int)s.TotalSeconds); + } + } + } +} diff --git a/BTCPayServer.Client/Models/StoreBaseData.cs b/BTCPayServer.Client/Models/StoreBaseData.cs index 25caddbfa..517c7232b 100644 --- a/BTCPayServer.Client/Models/StoreBaseData.cs +++ b/BTCPayServer.Client/Models/StoreBaseData.cs @@ -1,3 +1,5 @@ +using System; +using System.ComponentModel; using BTCPayServer.Client.JsonConverters; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -12,9 +14,15 @@ namespace BTCPayServer.Client.Models public string Name { get; set; } public string Website { get; set; } - public int InvoiceExpiration { get; set; } = 15; - public int MonitoringExpiration { get; set; } = 60; - + + [JsonConverter(typeof(TimeSpanJsonConverter))] + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TimeSpan InvoiceExpiration { get; set; } = TimeSpan.FromMinutes(15); + + [JsonConverter(typeof(TimeSpanJsonConverter))] + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TimeSpan MonitoringExpiration { get; set; } = TimeSpan.FromMinutes(60); + [JsonConverter(typeof(StringEnumConverter))] public SpeedPolicy SpeedPolicy { get; set; } public string LightningDescriptionTemplate { get; set; } diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index d571c69c4..c680596cc 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -15,6 +15,8 @@ using BTCPayServer.Controllers; using BTCPayServer.Data; using BTCPayServer.Services.Wallets; using BTCPayServer.Views.Wallets; +using Newtonsoft.Json; +using BTCPayServer.Client.Models; namespace BTCPayServer.Tests { diff --git a/BTCPayServer/Controllers/GreenField/StoresController.cs b/BTCPayServer/Controllers/GreenField/StoresController.cs index 12215626b..a6c1636e4 100644 --- a/BTCPayServer/Controllers/GreenField/StoresController.cs +++ b/BTCPayServer/Controllers/GreenField/StoresController.cs @@ -122,8 +122,8 @@ namespace BTCPayServer.Controllers.GreenField ShowRecommendedFee = storeBlob.ShowRecommendedFee, RecommendedFeeBlockTarget = storeBlob.RecommendedFeeBlockTarget, DefaultLang = storeBlob.DefaultLang, - MonitoringExpiration = storeBlob.MonitoringExpiration, - InvoiceExpiration = storeBlob.InvoiceExpiration, + MonitoringExpiration = TimeSpan.FromMinutes(storeBlob.MonitoringExpiration), + InvoiceExpiration = TimeSpan.FromMinutes(storeBlob.InvoiceExpiration), LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi, CustomLogo = storeBlob.CustomLogo, CustomCSS = storeBlob.CustomCSS, @@ -158,8 +158,8 @@ namespace BTCPayServer.Controllers.GreenField blob.ShowRecommendedFee = restModel.ShowRecommendedFee; blob.RecommendedFeeBlockTarget = restModel.RecommendedFeeBlockTarget; blob.DefaultLang = restModel.DefaultLang; - blob.MonitoringExpiration = restModel.MonitoringExpiration; - blob.InvoiceExpiration = restModel.InvoiceExpiration; + blob.MonitoringExpiration = (int)restModel.MonitoringExpiration.TotalMinutes; + blob.InvoiceExpiration = (int)restModel.InvoiceExpiration.TotalMinutes; blob.LightningAmountInSatoshi = restModel.LightningAmountInSatoshi; blob.CustomLogo = restModel.CustomLogo; blob.CustomCSS = restModel.CustomCSS; @@ -188,9 +188,9 @@ namespace BTCPayServer.Controllers.GreenField { ModelState.AddModelError(nameof(request.Website), "Website is not a valid url"); } - if(request.InvoiceExpiration < 1 && request.InvoiceExpiration > 60 * 24 * 24) + if(request.InvoiceExpiration < TimeSpan.FromMinutes(1) && request.InvoiceExpiration > TimeSpan.FromMinutes(60 * 24 * 24)) ModelState.AddModelError(nameof(request.InvoiceExpiration), "InvoiceExpiration can only be between 1 and 34560 mins"); - if(request.MonitoringExpiration < 10 && request.MonitoringExpiration > 60 * 24 * 24) + if(request.MonitoringExpiration < TimeSpan.FromMinutes(10) && request.MonitoringExpiration > TimeSpan.FromMinutes(60 * 24 * 24)) ModelState.AddModelError(nameof(request.MonitoringExpiration), "InvoiceExpiration can only be between 10 and 34560 mins"); if(request.PaymentTolerance < 0 && request.PaymentTolerance > 100) ModelState.AddModelError(nameof(request.PaymentTolerance), "PaymentTolerance can only be between 0 and 100 percent"); diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores.json index 312e61b75..fa6e483b6 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores.json @@ -287,11 +287,19 @@ }, "invoiceExpiration": { "type": "integer", - "format": "int32" + "format": "int32", + "default": 900, + "minimum": 60, + "maximum": 2073600, + "description": "The time after which an invoice is considered expired if not paid. The value will be rounded down to a minute." }, "monitoringExpiration": { "type": "integer", - "format": "int32" + "format": "int32", + "default": 3600, + "minimum": 600, + "maximum": 2073600, + "description": "The time after which an invoice which has been paid but not confirmed will be considered invalid. The value will be rounded down to a minute." }, "speedPolicy": { "$ref": "#/components/schemas/SpeedPolicy"