예제 #1
0
        public async Task ValidateAsync(object?value, ValidationContext context, AddError addError)
        {
            var count = context.Path.Count();

            if (value != null && (count == 0 || (count == 2 && context.Path.Last() == InvariantPartitioning.Key)))
            {
                FilterNode <ClrValue>?filter = null;

                if (value is string s)
                {
                    filter = ClrFilter.Eq(Path(context), s);
                }
                else if (value is double d)
                {
                    filter = ClrFilter.Eq(Path(context), d);
                }

                if (filter != null)
                {
                    var found = await checkUniqueness(filter);

                    if (found.Any(x => x.Id != context.ContentId))
                    {
                        addError(context.Path, T.Get("contents.validation.unique"));
                    }
                }
            }
        }
예제 #2
0
        public async ValueTask ValidateAsync(object value, ValidationContext context, AddError addError)
        {
            if (value is ContentData data)
            {
                var validateableFields = context.Schema.Fields.Where(IsValidateableField);

                var filters = new List <FilterNode <ClrValue> >();

                foreach (var field in validateableFields)
                {
                    var fieldValue = TryGetValue(field, data);

                    if (fieldValue != null)
                    {
                        filters.Add(ClrFilter.Eq($"data.{field.Name}.iv", fieldValue));
                    }
                }

                if (filters.Count > 0)
                {
                    var filter = ClrFilter.And(filters);

                    var found = await contentRepository.QueryIdsAsync(context.AppId.Id, context.SchemaId.Id, filter);

                    if (found.Any(x => x.Id != context.ContentId))
                    {
                        addError(Enumerable.Empty <string>(), "A content with the same values already exist.");
                    }
                }
            }
        }
예제 #3
0
        public async Task ValidateAsync(object?value, ValidationContext context, AddError addError)
        {
            if (context.Mode == ValidationMode.Optimized)
            {
                return;
            }

            var count = context.Path.Count();

            if (value != null && (count == 0 || (count == 2 && context.Path.Last() == InvariantPartitioning.Key)))
            {
                FilterNode <ClrValue>?filter = null;

                if (value is string s)
                {
                    filter = ClrFilter.Eq(Path(context), s);
                }
                else if (value is double d)
                {
                    filter = ClrFilter.Eq(Path(context), d);
                }

                if (filter != null)
                {
                    var found = await checkUniqueness(filter);

                    if (found.Any(x => x.Id != context.ContentId))
                    {
                        addError(context.Path, "Another content with the same value exists.");
                    }
                }
            }
        }
예제 #4
0
        public async Task ValidateAsync(object value, ValidationContext context, AddError addError)
        {
            var count = context.Path.Count();

            if (value != null && (count == 0 || (count == 2 && context.Path.Last() == InvariantPartitioning.Key)))
            {
                FilterNode <ClrValue> filter = null;

                if (value is string s)
                {
                    filter = ClrFilter.Eq(Path(context), s);
                }
                else if (value is double d)
                {
                    filter = ClrFilter.Eq(Path(context), d);
                }

                if (filter != null)
                {
                    var found = await context.GetContentIdsAsync(context.SchemaId, filter);

                    if (found.Any(x => x != context.ContentId))
                    {
                        addError(context.Path, "Another content with the same value exists.");
                    }
                }
            }
        }
예제 #5
0
        public void Should_not_normalize_other_field()
        {
            var source = ClrFilter.Eq("other", "value");
            var result = FilterTagTransformer.Transform(source, appId, tagService);

            Assert.Equal("other == 'value'", result.ToString());

            A.CallTo(() => tagService.GetTagIdsAsync(appId, A <string> .Ignored, A <HashSet <string> > .Ignored))
            .MustNotHaveHappened();
        }
예제 #6
0
        public void Should_not_fail_when_tags_not_found()
        {
            A.CallTo(() => tagService.GetTagIdsAsync(appId, TagGroups.Assets, A <HashSet <string> > .That.Contains("name1")))
            .Returns(new Dictionary <string, string>());

            var source = ClrFilter.Eq("tags", "name1");
            var result = FilterTagTransformer.Transform(source, appId, tagService);

            Assert.Equal("tags == 'name1'", result.ToString());
        }
예제 #7
0
        public void Should_not_normalize_non_data_field()
        {
            var source = ClrFilter.Eq("no.data", "value");

            var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService);

            Assert.Equal("no.data == 'value'", result !.ToString());

            A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A <string> ._, A <HashSet <string> > ._))
            .MustNotHaveHappened();
        }
예제 #8
0
        public void Should_normalize_tags()
        {
            A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, TagGroups.Schemas(schemaId.Id), A <HashSet <string> > .That.Contains("name1")))
            .Returns(new Dictionary <string, string> {
                ["name1"] = "id1"
            });

            var source = ClrFilter.Eq("data.tags2.iv", "name1");
            var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService);

            Assert.Equal("data.tags2.iv == 'id1'", result.ToString());
        }
        public async Task Should_normalize_tags()
        {
            A.CallTo(() => tagService.GetTagIdsAsync(appId, TagGroups.Assets, A <HashSet <string> > .That.Contains("name1")))
            .Returns(new Dictionary <string, string> {
                ["name1"] = "id1"
            });

            var source = ClrFilter.Eq("tags", "name1");

            var result = await FilterTagTransformer.TransformAsync(source, appId, tagService);

            Assert.Equal("tags == 'id1'", result !.ToString());
        }
예제 #10
0
        public override async ValueTask <FilterNode <ClrValue>?> Visit(CompareFilter <ClrValue> nodeIn, Args args)
        {
            if (nodeIn.Value.Value is FilterSphere sphere)
            {
                var field = string.Join(".", nodeIn.Path.Skip(1));

                var searchQuery = new GeoQuery(args.Schema.Id, field, sphere.Latitude, sphere.Longitude, sphere.Radius, 1000);
                var searchScope = args.Context.Scope();

                var ids = await args.TextIndex.SearchAsync(args.Context.App, searchQuery, searchScope);

                if (ids == null || ids.Count == 0)
                {
                    return(ClrFilter.Eq("id", "__notfound__"));
                }

                return(ClrFilter.In("id", ids.Select(x => x.ToString()).ToList()));
            }

            return(nodeIn);
        }
예제 #11
0
        private async Task TransformFilterAsync(ClrQuery query, Context context, ISchemaEntity?schema)
        {
            if (query.Filter != null && schema != null)
            {
                query.Filter = await GeoQueryTransformer.TransformAsync(query.Filter, context, schema, textIndex);
            }

            if (!string.IsNullOrWhiteSpace(query.FullText))
            {
                if (schema == null)
                {
                    throw new InvalidOperationException();
                }

                var textQuery = new TextQuery(query.FullText, 1000)
                {
                    PreferredSchemaId = schema.Id
                };

                var fullTextIds = await textIndex.SearchAsync(context.App, textQuery, context.Scope());

                var fullTextFilter = ClrFilter.Eq("id", "__notfound__");

                if (fullTextIds?.Any() == true)
                {
                    fullTextFilter = ClrFilter.In("id", fullTextIds.Select(x => x.ToString()).ToList());
                }

                if (query.Filter != null)
                {
                    query.Filter = ClrFilter.And(query.Filter, fullTextFilter);
                }
                else
                {
                    query.Filter = fullTextFilter;
                }

                query.FullText = null;
            }
        }
예제 #12
0
        public override FilterNode <ClrValue> Visit(BinaryOperatorNode nodeIn)
        {
            if (nodeIn.OperatorKind == BinaryOperatorKind.And)
            {
                return(ClrFilter.And(nodeIn.Left.Accept(this), nodeIn.Right.Accept(this)));
            }

            if (nodeIn.OperatorKind == BinaryOperatorKind.Or)
            {
                return(ClrFilter.Or(nodeIn.Left.Accept(this), nodeIn.Right.Accept(this)));
            }

            if (nodeIn.Left is SingleValueFunctionCallNode functionNode)
            {
                if (string.Equals(functionNode.Name, "geo.distance", StringComparison.OrdinalIgnoreCase) && nodeIn.OperatorKind == BinaryOperatorKind.LessThan)
                {
                    var valueDistance = (double)ConstantWithTypeVisitor.Visit(nodeIn.Right).Value !;

                    if (functionNode.Parameters.ElementAt(1) is not ConstantNode constantNode)
                    {
                        throw new NotSupportedException();
                    }

                    if (constantNode.Value is not GeographyPoint geographyPoint)
                    {
                        throw new NotSupportedException();
                    }

                    var property = PropertyPathVisitor.Visit(functionNode.Parameters.ElementAt(0));

                    return(ClrFilter.Lt(property, new FilterSphere(geographyPoint.Longitude, geographyPoint.Latitude, valueDistance)));
                }
                else
                {
                    var regexFilter = Visit(functionNode);

                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    if (value.ValueType == ClrValueType.Boolean && value.Value is bool booleanRight)
                    {
                        if ((nodeIn.OperatorKind == BinaryOperatorKind.Equal && !booleanRight) ||
                            (nodeIn.OperatorKind == BinaryOperatorKind.NotEqual && booleanRight))
                        {
                            regexFilter = ClrFilter.Not(regexFilter);
                        }

                        return(regexFilter);
                    }
                }
            }
            else
            {
                if (nodeIn.OperatorKind == BinaryOperatorKind.NotEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Ne(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.Equal)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Eq(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.LessThan)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Lt(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.LessThanOrEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Le(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.GreaterThan)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Gt(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.GreaterThanOrEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Ge(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }
            }

            throw new NotSupportedException();
        }
예제 #13
0
        public override FilterNode <ClrValue> Visit(BinaryOperatorNode nodeIn)
        {
            if (nodeIn.OperatorKind == BinaryOperatorKind.And)
            {
                return(ClrFilter.And(nodeIn.Left.Accept(this), nodeIn.Right.Accept(this)));
            }

            if (nodeIn.OperatorKind == BinaryOperatorKind.Or)
            {
                return(ClrFilter.Or(nodeIn.Left.Accept(this), nodeIn.Right.Accept(this)));
            }

            if (nodeIn.Left is SingleValueFunctionCallNode functionNode)
            {
                var regexFilter = Visit(functionNode);

                var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                if (value.ValueType == ClrValueType.Boolean && value.Value is bool booleanRight)
                {
                    if ((nodeIn.OperatorKind == BinaryOperatorKind.Equal && !booleanRight) ||
                        (nodeIn.OperatorKind == BinaryOperatorKind.NotEqual && booleanRight))
                    {
                        regexFilter = ClrFilter.Not(regexFilter);
                    }

                    return(regexFilter);
                }
            }
            else
            {
                if (nodeIn.OperatorKind == BinaryOperatorKind.NotEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Ne(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.Equal)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Eq(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.LessThan)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Lt(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.LessThanOrEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Le(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.GreaterThan)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Gt(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }

                if (nodeIn.OperatorKind == BinaryOperatorKind.GreaterThanOrEqual)
                {
                    var value = ConstantWithTypeVisitor.Visit(nodeIn.Right);

                    return(ClrFilter.Ge(PropertyPathVisitor.Visit(nodeIn.Left), value));
                }
            }

            throw new NotSupportedException();
        }