diff --git a/WalletWasabi.WabiSabiClientLibrary.Tests/IntegrationTests/TestVectors/GetAnonymityScores.json b/WalletWasabi.WabiSabiClientLibrary.Tests/IntegrationTests/TestVectors/GetAnonymityScores.json index a7803cbc66b..bea95ecf484 100644 --- a/WalletWasabi.WabiSabiClientLibrary.Tests/IntegrationTests/TestVectors/GetAnonymityScores.json +++ b/WalletWasabi.WabiSabiClientLibrary.Tests/IntegrationTests/TestVectors/GetAnonymityScores.json @@ -56,5 +56,56 @@ } ] } + }, + { + "name": "", + "request": { + "transactions": [ + { + "internalInputs": [ + { + "address": "bcrt1p0hghqgks9z83pwh3a3jzq3eldgzj8ezjrs247szks3w2nq7s7fhsqtqgg7", + "value": 20000000 + } + ], + "externalInputs": [], + "internalOutputs": [], + "externalOutputs": [] + } + ] + }, + "expectedStatusCode": 500, + "expectedResponse": { + "description": "There is an internal input that references a non-existing transaction." + } + }, + { + "name": "", + "request": {}, + "expectedStatusCode": 500, + "expectedResponse": { + "description": "The Transactions field is required." + } + }, + { + "name": "", + "request": { + "transactions": [ + { + "internalInputs": [ + { + "value": "" + } + ], + "externalInputs": [], + "internalOutputs": [], + "externalOutputs": [] + } + ] + }, + "expectedStatusCode": 500, + "expectedResponse": { + "description": "Unable to cast object of type 'System.String' to type 'System.Nullable`1[System.Int64]'." + } } ] diff --git a/WalletWasabi.WabiSabiClientLibrary/Controllers/Controller.cs b/WalletWasabi.WabiSabiClientLibrary/Controllers/Controller.cs index c27af847b69..bb861744a93 100644 --- a/WalletWasabi.WabiSabiClientLibrary/Controllers/Controller.cs +++ b/WalletWasabi.WabiSabiClientLibrary/Controllers/Controller.cs @@ -9,6 +9,7 @@ namespace WalletWasabi.WabiSabiClientLibrary.Controllers; [ApiController] [ExceptionTranslateFilter] +[ValidationFilter] [Produces("application/json")] public class Controller : ControllerBase, IDisposable { diff --git a/WalletWasabi.WabiSabiClientLibrary/Filters/ValidationFilter.cs b/WalletWasabi.WabiSabiClientLibrary/Filters/ValidationFilter.cs new file mode 100644 index 00000000000..dce4afb17ca --- /dev/null +++ b/WalletWasabi.WabiSabiClientLibrary/Filters/ValidationFilter.cs @@ -0,0 +1,19 @@ +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace WalletWasabi.WabiSabiClientLibrary.Filters; + +public class ValidationFilterAttribute : Attribute, IAsyncActionFilter +{ + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + if (!context.ModelState.IsValid) + { + string messages = string.Join("; ", context.ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage)); + throw new Exception(messages); + } + + await next(); + } +} diff --git a/WalletWasabi.WabiSabiClientLibrary/Program.cs b/WalletWasabi.WabiSabiClientLibrary/Program.cs index 4a2c403cd7b..cb3067604b7 100644 --- a/WalletWasabi.WabiSabiClientLibrary/Program.cs +++ b/WalletWasabi.WabiSabiClientLibrary/Program.cs @@ -40,6 +40,9 @@ public static async Task Main(string[] args) builder.Services.AddControllers().AddNewtonsoftJson(x => { x.SerializerSettings.Converters = JsonSerializationOptions.Default.Settings.Converters; + }).ConfigureApiBehaviorOptions(options => + { + options.SuppressModelStateInvalidFilter = true; }); builder.Services.AddSingleton(global); #if (DEBUG)