From 111fb56a533fc52115187c60f490d4d0ef42a36b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 29 Apr 2021 14:54:01 +0200 Subject: [PATCH] Fix regex search. --- .../Contents/ContentChangedTriggerHandler.cs | 46 ++++++++++--------- .../MongoDb/Queries/FilterVisitor.cs | 5 +- .../Queries/Json/JsonFilterVisitor.cs | 7 +++ .../ContentChangedTriggerHandlerTests.cs | 44 +++++++++++++++++- .../MongoDb/MongoQueryTests.cs | 24 ++++++++++ .../Queries/QueryFromJsonTests.cs | 8 ++++ 6 files changed, 110 insertions(+), 24 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs index e33a8ec75..8094f7346 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs @@ -106,25 +106,15 @@ namespace Squidex.Domain.Apps.Entities.Contents case ContentDeleted: result.Type = EnrichedContentEventType.Deleted; break; - - case ContentStatusChanged statusChanged: - { - switch (statusChanged.Change) - { - case StatusChange.Published: - result.Type = EnrichedContentEventType.Published; - break; - case StatusChange.Unpublished: - result.Type = EnrichedContentEventType.Unpublished; - break; - default: - result.Type = EnrichedContentEventType.StatusChanged; - break; - } - - break; - } - + case ContentStatusChanged e when e.Change == StatusChange.Published: + result.Type = EnrichedContentEventType.Published; + break; + case ContentStatusChanged e when e.Change == StatusChange.Unpublished: + result.Type = EnrichedContentEventType.Unpublished; + break; + case ContentStatusChanged e when e.Change == StatusChange.Change: + result.Type = EnrichedContentEventType.StatusChanged; + break; case ContentUpdated: { result.Type = EnrichedContentEventType.Updated; @@ -152,9 +142,23 @@ namespace Squidex.Domain.Apps.Entities.Contents public string? GetName(AppEvent @event) { - var contentEvent = (ContentEvent)@event; + switch (@event) + { + case ContentCreated e: + return $"{e.SchemaId.Name.ToPascalCase()}Created"; + case ContentDeleted e: + return $"{e.SchemaId.Name.ToPascalCase()}Deleted"; + case ContentStatusChanged e when e.Change == StatusChange.Published: + return $"{e.SchemaId.Name.ToPascalCase()}Published"; + case ContentStatusChanged e when e.Change == StatusChange.Unpublished: + return $"{e.SchemaId.Name.ToPascalCase()}Unpublished"; + case ContentStatusChanged e when e.Change == StatusChange.Change: + return $"{e.SchemaId.Name.ToPascalCase()}StatusChanged"; + case ContentUpdated e: + return $"{e.SchemaId.Name.ToPascalCase()}Updated"; + } - return $"{@event.GetType().Name}({contentEvent.SchemaId.Name.ToPascalCase()})"; + return null; } public bool Trigger(Envelope @event, RuleContext context) diff --git a/backend/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs b/backend/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs index 9238b909e..2ea715dc7 100644 --- a/backend/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs +++ b/backend/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs @@ -8,6 +8,7 @@ using System; using System.Collections; using System.Linq; +using System.Text.RegularExpressions; using MongoDB.Bson; using MongoDB.Driver; using Squidex.Infrastructure.Queries; @@ -116,7 +117,9 @@ namespace Squidex.Infrastructure.MongoDb.Queries private static BsonRegularExpression BuildRegex(CompareFilter node, Func formatter) { - return new BsonRegularExpression(formatter(node.Value.Value?.ToString() ?? "null"), "i"); + var value = formatter(Regex.Escape(node.Value.Value?.ToString() ?? "null")); + + return new BsonRegularExpression(value, "i"); } } } diff --git a/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterVisitor.cs b/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterVisitor.cs index e985981c8..594c42c83 100644 --- a/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterVisitor.cs +++ b/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterVisitor.cs @@ -7,8 +7,10 @@ using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using NJsonSchema; using Squidex.Infrastructure.Json.Objects; +using Squidex.Infrastructure.Validation; namespace Squidex.Infrastructure.Queries.Json { @@ -89,6 +91,11 @@ namespace Squidex.Infrastructure.Queries.Json args.Errors.Add($"Array value is not allowed for '{nodeIn.Operator}' operator and path '{nodeIn.Path}'."); } + if (nodeIn.Operator == CompareOperator.Matchs && value.Value?.ToString()?.IsValidRegex() != true) + { + args.Errors.Add($"{value} is not a valid regular expression."); + } + result = new CompareFilter(nodeIn.Path, nodeIn.Operator, value); } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs index 637d184b9..46291eb1b 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs @@ -77,11 +77,51 @@ namespace Squidex.Domain.Apps.Entities.Contents } [Fact] - public void Should_calculate_name() + public void Should_calculate_name_for_created() { var @event = new ContentCreated { SchemaId = schemaMatch }; - Assert.Equal("ContentCreated(MySchema1)", sut.GetName(@event)); + Assert.Equal("MySchema1Created", sut.GetName(@event)); + } + + [Fact] + public void Should_calculate_name_for_deleted() + { + var @event = new ContentDeleted { SchemaId = schemaMatch }; + + Assert.Equal("MySchema1Deleted", sut.GetName(@event)); + } + + [Fact] + public void Should_calculate_name_for_updated() + { + var @event = new ContentUpdated { SchemaId = schemaMatch }; + + Assert.Equal("MySchema1Updated", sut.GetName(@event)); + } + + [Fact] + public void Should_calculate_name_for_published() + { + var @event = new ContentStatusChanged { SchemaId = schemaMatch, Change = StatusChange.Published }; + + Assert.Equal("MySchema1Published", sut.GetName(@event)); + } + + [Fact] + public void Should_calculate_name_for_unpublished() + { + var @event = new ContentStatusChanged { SchemaId = schemaMatch, Change = StatusChange.Unpublished }; + + Assert.Equal("MySchema1Unpublished", sut.GetName(@event)); + } + + [Fact] + public void Should_calculate_name_for_status_change() + { + var @event = new ContentStatusChanged { SchemaId = schemaMatch, Change = StatusChange.Change }; + + Assert.Equal("MySchema1StatusChanged", sut.GetName(@event)); } [Fact] diff --git a/backend/tests/Squidex.Infrastructure.Tests/MongoDb/MongoQueryTests.cs b/backend/tests/Squidex.Infrastructure.Tests/MongoDb/MongoQueryTests.cs index cfc75052b..8f5e5b7ae 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/MongoDb/MongoQueryTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/MongoDb/MongoQueryTests.cs @@ -162,6 +162,14 @@ namespace Squidex.Infrastructure.MongoDb AssertQuery("{ 'Text' : /search/i }", filter); } + [Fact] + public void Should_make_query_with_contains_and_invalid_character() + { + var filter = ClrFilter.Contains("Text", "search("); + + AssertQuery("{ 'Text' : /search\\(/i }", filter); + } + [Fact] public void Should_make_query_with_endswith_and_null_value() { @@ -178,6 +186,14 @@ namespace Squidex.Infrastructure.MongoDb AssertQuery("{ 'Text' : /search$/i }", filter); } + [Fact] + public void Should_make_query_with_endswithand_invalid_character() + { + var filter = ClrFilter.EndsWith("Text", "search("); + + AssertQuery("{ 'Text' : /search\\($/i }", filter); + } + [Fact] public void Should_make_query_with_startswith_and_null_value() { @@ -194,6 +210,14 @@ namespace Squidex.Infrastructure.MongoDb AssertQuery("{ 'Text' : /^search/i }", filter); } + [Fact] + public void Should_make_query_with_startswith_and_invalid_character() + { + var filter = ClrFilter.StartsWith("Text", "search("); + + AssertQuery("{ 'Text' : /^search\\(/i }", filter); + } + [Fact] public void Should_make_query_with_matchs_and_null_value() { diff --git a/backend/tests/Squidex.Infrastructure.Tests/Queries/QueryFromJsonTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Queries/QueryFromJsonTests.cs index 5727a5cd3..dd6b943b5 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Queries/QueryFromJsonTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Queries/QueryFromJsonTests.cs @@ -223,6 +223,14 @@ namespace Squidex.Infrastructure.Queries AssertErrors(json, "Expected String for path 'string', but got Number."); } + [Fact] + public void Should_add_error_if_valid_is_not_a_valid_regex() + { + var json = new { path = "string", op = "matchs", value = "((" }; + + AssertErrors(json, "'((' is not a valid regular expression."); + } + [Fact] public void Should_parse_nested_string_filter() {