diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs index 82436cf29..740f92b2d 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs @@ -1,4 +1,4 @@ -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -6,6 +6,7 @@ // ========================================================================== using Jint; +using Jint.Native; using Squidex.Infrastructure; using Squidex.Infrastructure.Translations; using Squidex.Infrastructure.Validation; @@ -16,18 +17,50 @@ internal static class ScriptOperations { private delegate void MessageDelegate(string? message); - private static readonly MessageDelegate Disallow = message => + private delegate void MessageJsonDelegate(string? message); + + private static readonly Action Disallow = message => { message = !string.IsNullOrWhiteSpace(message) ? message : T.Get("common.jsNotAllowed"); throw new DomainForbiddenException(message); }; - private static readonly MessageDelegate Reject = message => + private static readonly Action Reject = message => { - message = !string.IsNullOrWhiteSpace(message) ? message : T.Get("common.jsRejected"); + var errors = new List(); + + void AddError(JsString message) + { + var text = message.ToString(); + + if (!string.IsNullOrWhiteSpace(text)) + { + errors.Add(new ValidationError(text)); + } + } + + if (message is JsString typed) + { + AddError(typed); + } + else if (message is JsArray jsArray) + { + foreach (var item in jsArray) + { + if (item is JsString typedItem) + { + AddError(typedItem); + } + } + } + + if (errors.Count == 0) + { + errors.Add(new ValidationError(T.Get("common.jsRejected"))); + } - throw new ValidationException(message); + throw new ValidationException(errors); }; public static Engine AddDisallow(this Engine engine) diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs index 7e0711537..9725103a6 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs @@ -279,12 +279,33 @@ public class JintScriptEngineHelperTests : IClassFixture }; const string script = @" - reject('Not valid') + reject('Error1') "; var ex = await Assert.ThrowsAsync(() => sut.ExecuteAsync(vars, script, options)); - Assert.Equal("Not valid", ex.Errors.Single().Message); + Assert.Equal(new[] { "Error1" }, ex.Errors.Select(x => x.Message).ToArray()); + } + + [Fact] + public async Task Should_throw_validation_exception_if_calling_reject_with_messages() + { + var options = new ScriptOptions + { + CanReject = true + }; + + var vars = new ScriptVars + { + }; + + const string script = @" + reject(['Error1', 'Error2']) + "; + + var ex = await Assert.ThrowsAsync(() => sut.ExecuteAsync(vars, script, options)); + + Assert.Equal(new[] { "Error1", "Error2" }, ex.Errors.Select(x => x.Message).ToArray()); } [Fact]