public void Parse_ValidSelection_CanParse()
        {
            // Arrange
            const string type        = "articles";
            const string attrName    = "someField";
            var          attribute   = new AttrAttribute(attrName);
            var          idAttribute = new AttrAttribute("id");

            var query = new KeyValuePair <string, StringValues>("fields", new StringValues(attrName));

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act
            service.Parse(query);
            var result = service.Get();

            // Assert
            Assert.NotEmpty(result);
            Assert.Equal(idAttribute, result.First());
            Assert.Equal(attribute, result[1]);
        }
 private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue)
 {
     return(OmitNullValuedAttribute(attr, attributeValue) == false &&
            ((_jsonApiContext.QuerySet == null ||
              _jsonApiContext.QuerySet.Fields.Count == 0) ||
             _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName)));
 }
Beispiel #3
0
        public void Parse_ValidSelection_CanParse()
        {
            // Arrange
            const string type      = "articles";
            const string attrName  = "name";
            var          attribute = new AttrAttribute(attrName)
            {
                PropertyInfo = typeof(Article).GetProperty(nameof(Article.Name))
            };
            var idAttribute = new AttrAttribute("id")
            {
                PropertyInfo = typeof(Article).GetProperty(nameof(Article.Id))
            };

            var query = new KeyValuePair <string, StringValues>("fields", attrName);

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act
            service.Parse(query.Key, query.Value);
            var result = service.Get();

            // Assert
            Assert.NotEmpty(result);
            Assert.Contains(idAttribute, result);
            Assert.Contains(attribute, result);
        }
Beispiel #4
0
        public void Parse_DeeplyNestedSelection_ThrowsJsonApiException()
        {
            // Arrange
            const string type               = "articles";
            const string relationship       = "author.employer";
            const string attrName           = "someField";
            var          attribute          = new AttrAttribute(attrName);
            var          idAttribute        = new AttrAttribute("id");
            var          queryParameterName = $"fields[{relationship}]";

            var query = new KeyValuePair <string, StringValues>(queryParameterName, attrName);

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act, assert
            var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value));

            Assert.Equal(queryParameterName, exception.QueryParameterName);
            Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode);
            Assert.Equal("Deeply nested sparse field selection is currently not supported.", exception.Error.Title);
            Assert.Equal($"Parameter fields[{relationship}] is currently not supported.", exception.Error.Detail);
            Assert.Equal(queryParameterName, exception.Error.Source.Parameter);
        }
Beispiel #5
0
        public void Parse_InvalidField_ThrowsJsonApiException()
        {
            // Arrange
            const string type        = "articles";
            const string attrName    = "dne";
            var          idAttribute = new AttrAttribute("id")
            {
                PropertyInfo = typeof(Article).GetProperty(nameof(Article.Id))
            };

            var query = new KeyValuePair <string, StringValues>("fields", attrName);

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };

            var service = GetService(resourceContext);

            // Act, assert
            var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value));

            Assert.Equal("fields", exception.QueryParameterName);
            Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode);
            Assert.Equal("The specified field does not exist on the requested resource.", exception.Error.Title);
            Assert.Equal($"The field '{attrName}' does not exist on resource '{type}'.", exception.Error.Detail);
            Assert.Equal("fields", exception.Error.Source.Parameter);
        }
Beispiel #6
0
        /// <inheritdoc />
        public QueryLayer ComposeForHasMany <TId>(HasManyAttribute hasManyRelationship, TId leftId, ICollection <IIdentifiable> rightResourceIds)
        {
            ArgumentGuard.NotNull(hasManyRelationship, nameof(hasManyRelationship));
            ArgumentGuard.NotNull(rightResourceIds, nameof(rightResourceIds));

            ResourceContext leftResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.LeftType);
            AttrAttribute   leftIdAttribute     = GetIdAttribute(leftResourceContext);

            ResourceContext rightResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.RightType);
            AttrAttribute   rightIdAttribute     = GetIdAttribute(rightResourceContext);

            object[] rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray();

            FilterExpression leftFilter  = CreateFilterByIds(leftId.AsArray(), leftIdAttribute, null);
            FilterExpression rightFilter = CreateFilterByIds(rightTypedIds, rightIdAttribute, null);

            return(new QueryLayer(leftResourceContext)
            {
                Include = new IncludeExpression(new IncludeElementExpression(hasManyRelationship).AsArray()),
                Filter = leftFilter,
                Projection = new Dictionary <ResourceFieldAttribute, QueryLayer>
                {
                    [hasManyRelationship] = new QueryLayer(rightResourceContext)
                    {
                        Filter = rightFilter,
                        Projection = new Dictionary <ResourceFieldAttribute, QueryLayer>
                        {
                            [rightIdAttribute] = null
                        }
                    },
                    [leftIdAttribute] = null
                }
            });
        }
Beispiel #7
0
        /// <inheritdoc />
        public QueryLayer WrapLayerForSecondaryEndpoint <TId>(QueryLayer secondaryLayer, ResourceContext primaryResourceContext, TId primaryId,
                                                              RelationshipAttribute secondaryRelationship)
        {
            ArgumentGuard.NotNull(secondaryLayer, nameof(secondaryLayer));
            ArgumentGuard.NotNull(primaryResourceContext, nameof(primaryResourceContext));
            ArgumentGuard.NotNull(secondaryRelationship, nameof(secondaryRelationship));

            IncludeExpression innerInclude = secondaryLayer.Include;

            secondaryLayer.Include = null;

            IReadOnlyCollection <AttrAttribute> primaryAttributeSet = _sparseFieldSetCache.GetIdAttributeSetForRelationshipQuery(primaryResourceContext);

            Dictionary <ResourceFieldAttribute, QueryLayer> primaryProjection =
                primaryAttributeSet.ToDictionary(key => (ResourceFieldAttribute)key, _ => (QueryLayer)null);

            primaryProjection[secondaryRelationship] = secondaryLayer;

            FilterExpression primaryFilter      = GetFilter(Array.Empty <QueryExpression>(), primaryResourceContext);
            AttrAttribute    primaryIdAttribute = GetIdAttribute(primaryResourceContext);

            return(new QueryLayer(primaryResourceContext)
            {
                Include = RewriteIncludeForSecondaryEndpoint(innerInclude, secondaryRelationship),
                Filter = CreateFilterByIds(primaryId.AsArray(), primaryIdAttribute, primaryFilter),
                Projection = primaryProjection
            });
        }
Beispiel #8
0
        /// <inheritdoc />
        public QueryLayer ComposeForGetById <TId>(TId id, ResourceContext resourceContext, TopFieldSelection fieldSelection)
        {
            ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));

            AttrAttribute idAttribute = GetIdAttribute(resourceContext);

            QueryLayer queryLayer = ComposeFromConstraints(resourceContext);

            queryLayer.Sort       = null;
            queryLayer.Pagination = null;
            queryLayer.Filter     = CreateFilterByIds(id.AsArray(), idAttribute, queryLayer.Filter);

            if (fieldSelection == TopFieldSelection.OnlyIdAttribute)
            {
                queryLayer.Projection = new Dictionary <ResourceFieldAttribute, QueryLayer>
                {
                    [idAttribute] = null
                };
            }
            else if (fieldSelection == TopFieldSelection.WithAllAttributes && queryLayer.Projection != null)
            {
                // Discard any top-level ?fields[]= or attribute exclusions from resource definition, because we need the full database row.
                while (queryLayer.Projection.Any(pair => pair.Key is AttrAttribute))
                {
                    queryLayer.Projection.Remove(queryLayer.Projection.First(pair => pair.Key is AttrAttribute));
                }
            }

            return(queryLayer);
        }
Beispiel #9
0
        public void Parse_InvalidRelationship_ThrowsJsonApiException()
        {
            // Arrange
            const string type               = "articles";
            var          attrName           = "someField";
            var          attribute          = new AttrAttribute(attrName);
            var          idAttribute        = new AttrAttribute("id");
            var          queryParameterName = "fields[missing]";

            var query = new KeyValuePair <string, StringValues>(queryParameterName, attrName);

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act, assert
            var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value));

            Assert.Equal(queryParameterName, exception.QueryParameterName);
            Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode);
            Assert.Equal("Sparse field navigation path refers to an invalid relationship.", exception.Error.Title);
            Assert.Equal("'missing' in 'fields[missing]' is not a valid relationship of articles.", exception.Error.Detail);
            Assert.Equal(queryParameterName, exception.Error.Source.Parameter);
        }
        public void Parse_DeeplyNestedSelection_Throws400ErrorWithDeeplyNestedMessage()
        {
            // Arrange
            const string type         = "articles";
            const string relationship = "author.employer";
            const string attrName     = "someField";
            var          attribute    = new AttrAttribute(attrName);
            var          idAttribute  = new AttrAttribute("id");

            var query = new KeyValuePair <string, StringValues>($"fields[{relationship}]", new StringValues(attrName));

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act, assert
            var ex = Assert.Throws <JsonApiException>(() => service.Parse(query));

            Assert.Contains("deeply nested", ex.Message);
        }
        public void Parse_TypeNameAsNavigation_Throws400ErrorWithRelationshipsOnlyMessage()
        {
            // Arrange
            const string type             = "articles";
            const string attrName         = "someField";
            const string internalAttrName = "SomeField";
            var          attribute        = new AttrAttribute(attrName)
            {
                InternalAttributeName = internalAttrName
            };
            var idAttribute = new AttrAttribute("id")
            {
                InternalAttributeName = "Id"
            };

            var query = new KeyValuePair <string, StringValues>($"fields[{type}]", new StringValues(attrName));

            var resourceContext = new ResourceContext
            {
                ResourceName = type,
                Attributes   = new List <AttrAttribute> {
                    attribute, idAttribute
                },
                Relationships = new List <RelationshipAttribute>()
            };
            var service = GetService(resourceContext);

            // Act, assert
            var ex = Assert.Throws <JsonApiException>(() => service.Parse(query));

            Assert.Contains("relationships only", ex.Message);
        }
        public void AttrAttribute_Equals_Returns_True_When_Same_Name()
        {
            var a = new AttrAttribute("test");
            var b = new AttrAttribute("test");

            Assert.Equal(a, b);
        }
Beispiel #13
0
        public override async Task <IActionResult> PatchAsync(int id, [FromBody] PatientVitals patientVital)
        {
            //var attrToUpdate = _jsonApiContext.AttributesToUpdate;
            //var patientVitalOld = _dbContextResolver.GetDbSet<PatientVitals>().Where(m => m.Id == id).FirstOrDefault();

            //CommonMethods commonMethods = new CommonMethods();
            //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientVitalOld, patientVital, "PatientVitals", attrToUpdate)
            //    //.Where(i => attrToUpdate.Keys.Any(a1 => a1.InternalAttributeName == i.PropertyName))
            //    .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName }).ToList();
            //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs);
            AttrAttribute BMI = new AttrAttribute(AttrToUpdate.BMI.ToString(), AttrToUpdate.BMI.ToString());

            _jsonApiContext.AttributesToUpdate.Remove(BMI);

            patientVital = calculateBmi(patientVital);
            _jsonApiContext.AttributesToUpdate.Add(BMI, patientVital.BMI);
            //return await base.PatchAsync(id, patientVital);

            //var patientVitalInfo = await base.PatchAsync(id, patientVital);

            //int eventID = _dbContextResolver.GetDbSet<Event>().LastOrDefault().Id + 1;
            //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientVitalOld, patientVital, "PatientVitals", attrToUpdate)
            //    //.Where(i => attrToUpdate.Keys.Any(a1 => a1.InternalAttributeName == i.PropertyName))
            //    .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName, EventID = eventID }).ToList();
            //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs);
            return(await base.PatchAsync(id, patientVital));
        }
        public async Task UpdateAsync_Updates_Attributes_In_AttributesToUpdate()
        {
            // arrange
            var todoItemUpdates = new TodoItem
            {
                Id          = _todoItem.Id,
                Description = Guid.NewGuid().ToString()
            };

            var descAttr = new AttrAttribute("description", "Description");

            descAttr.PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description));

            _attrsToUpdate = new Dictionary <AttrAttribute, object>
            {
                {
                    descAttr,
                    null //todoItemUpdates.Description
                }
            };

            var repository = GetRepository();

            // act
            var updatedItem = await repository.UpdateAsync(todoItemUpdates);

            // assert
            Assert.NotNull(updatedItem);
            Assert.Equal(_todoItem.Ordinal, updatedItem.Ordinal);
            Assert.Equal(todoItemUpdates.Description, updatedItem.Description);
        }
Beispiel #15
0
        private FilterExpression CreateFilterByIds <TId>(ICollection <TId> ids, AttrAttribute idAttribute, FilterExpression existingFilter)
        {
            var idChain = new ResourceFieldChainExpression(idAttribute);

            FilterExpression filter = null;

            if (ids.Count == 1)
            {
                var constant = new LiteralConstantExpression(ids.Single().ToString());
                filter = new ComparisonExpression(ComparisonOperator.Equals, idChain, constant);
            }
            else if (ids.Count > 1)
            {
                var constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToList();
                filter = new EqualsAnyOfExpression(idChain, constants);
            }

            // @formatter:keep_existing_linebreaks true

            return(filter == null
                ? existingFilter
                : existingFilter == null
                    ? filter
                    : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(filter, existingFilter)));

            // @formatter:keep_existing_linebreaks restore
        }
Beispiel #16
0
        protected virtual List <AttrAttribute> GetAttributes(Type entityType)
        {
            var attributes = new List <AttrAttribute>();

            var properties = entityType.GetProperties();

            foreach (var prop in properties)
            {
                // todo: investigate why this is added in the exposed attributes list
                // because it is not really defined attribute considered from the json:api
                // spec point of view.
                if (prop.Name == nameof(Identifiable.Id))
                {
                    var idAttr = new AttrAttribute
                    {
                        PublicAttributeName = FormatPropertyName(prop),
                        PropertyInfo        = prop
                    };
                    attributes.Add(idAttr);
                    continue;
                }

                var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute));
                if (attribute == null)
                {
                    continue;
                }

                attribute.PublicAttributeName ??= FormatPropertyName(prop);
                attribute.PropertyInfo = prop;

                attributes.Add(attribute);
            }
            return(attributes);
        }
        protected virtual List <AttrAttribute> GetAttributes(Type entityType)
        {
            var attributes = new List <AttrAttribute>();

            var properties = entityType.GetProperties();

            foreach (var prop in properties)
            {
                if (prop.Name == nameof(Identifiable.Id))
                {
                    var idAttr = new AttrAttribute()
                    {
                        PublicAttributeName   = JsonApiOptions.ResourceNameFormatter.FormatPropertyName(prop),
                        PropertyInfo          = prop,
                        InternalAttributeName = prop.Name
                    };
                    attributes.Add(idAttr);
                    continue;
                }

                var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute));
                if (attribute == null)
                {
                    continue;
                }

                attribute.PublicAttributeName   = attribute.PublicAttributeName ?? JsonApiOptions.ResourceNameFormatter.FormatPropertyName(prop);
                attribute.InternalAttributeName = prop.Name;
                attribute.PropertyInfo          = prop;

                attributes.Add(attribute);
            }
            return(attributes);
        }
Beispiel #18
0
        public override async Task <IActionResult> PatchAsync(int id, [FromBody] Patients patientInfo)
        {
            // var attrToUpdate= _jsonApiContext.AttributesToUpdate;
            //var patientInfoOld =  _dbContextResolver.GetDbSet<Patients>().Where(m => m.Id == id).FirstOrDefault();

            CommonMethods commonMethods      = new CommonMethods();
            AttrAttribute photoPath          = new AttrAttribute(AttrToUpdate.PhotoPath.ToString(), AttrToUpdate.PhotoPath.ToString());
            AttrAttribute photoThumbnailPath = new AttrAttribute(AttrToUpdate.PhotoThumbnailPath.ToString(), AttrToUpdate.PhotoThumbnailPath.ToString());

            if (!string.IsNullOrEmpty(patientInfo.PhotoBase64))
            {
                _jsonApiContext.AttributesToUpdate.Remove(photoPath);
                _jsonApiContext.AttributesToUpdate.Remove(photoThumbnailPath);

                patientInfo = ConvertBase64ToImage(patientInfo, commonMethods);

                if (!string.IsNullOrEmpty(patientInfo.PhotoPath) && !string.IsNullOrEmpty(patientInfo.PhotoThumbnailPath))
                {
                    _jsonApiContext.AttributesToUpdate.Add(photoPath, patientInfo.PhotoPath);
                    _jsonApiContext.AttributesToUpdate.Add(photoThumbnailPath, patientInfo.PhotoThumbnailPath);
                }
            }
            //var patientDetails = await base.PatchAsync(id, patientInfo);

            //int eventID = _dbContextResolver.GetDbSet<Event>().AsQueryable().OrderByDescending(p => p.Id).FirstOrDefault().Id + 1;
            //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientInfoOld, patientInfo, "Patients", attrToUpdate)
            //    //.Where(i=> attrToUpdate.Keys.Any(a1 =>  a1.InternalAttributeName == i.PropertyName))
            //    .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName, EventID = eventID }).ToList();
            //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs);
            return(await base.PatchAsync(id, patientInfo));
        }
        public void AttrAttribute_Equals_Returns_False_When_Different_Name()
        {
            var a = new AttrAttribute("test");
            var b = new AttrAttribute("test2");

            Assert.NotEqual(a, b);
        }
        public async Task UpdateAsync_AttributesUpdated_ShouldHaveSpecificallyThoseAttributesUpdated()
        {
            // Arrange
            var itemId = 213;
            var seed   = Guid.NewGuid();

            var databaseResource = new TodoItem
            {
                Id          = itemId,
                Description = "Before"
            };

            var todoItemUpdates = new TodoItem
            {
                Id          = itemId,
                Description = "After"
            };

            await using (var arrangeDbContext = GetDbContext(seed))
            {
                var(repository, targetedFields, _) = Setup(arrangeDbContext);
                arrangeDbContext.Add(databaseResource);
                await arrangeDbContext.SaveChangesAsync();

                var descAttr = new AttrAttribute
                {
                    PublicName = "description",
                    Property   = typeof(TodoItem).GetProperty(nameof(TodoItem.Description))
                };
                targetedFields.Setup(m => m.Attributes).Returns(new List <AttrAttribute> {
                    descAttr
                });
                targetedFields.Setup(m => m.Relationships).Returns(new List <RelationshipAttribute>());

                // Act
                await repository.UpdateAsync(todoItemUpdates, databaseResource);
            }

            // Assert - in different context
            await using (var assertDbContext = GetDbContext(seed))
            {
                var(repository, _, resourceGraph) = Setup(assertDbContext);

                var resourceContext = resourceGraph.GetResourceContext <TodoItem>();
                var idAttribute     = resourceContext.Attributes.Single(a => a.Property.Name == nameof(Identifiable.Id));

                var resources = await repository.GetAsync(new QueryLayer(resourceContext)
                {
                    Filter = new ComparisonExpression(ComparisonOperator.Equals,
                                                      new ResourceFieldChainExpression(idAttribute),
                                                      new LiteralConstantExpression(itemId.ToString()))
                });

                var fetchedTodo = resources.First();
                Assert.NotNull(fetchedTodo);
                Assert.Equal(databaseResource.Ordinal, fetchedTodo.Ordinal);
                Assert.Equal(todoItemUpdates.Description, fetchedTodo.Description);
            }
        }
Beispiel #21
0
        public CarExpressionRewriter(IResourceContextProvider resourceContextProvider)
        {
            ResourceContext carResourceContext = resourceContextProvider.GetResourceContext <Car>();

            _regionIdAttribute = carResourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Car.RegionId));

            _licensePlateAttribute = carResourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Car.LicensePlate));
        }
 private void ValidateSingleAttribute(AttrAttribute attribute, ResourceContext resourceContext, string path)
 {
     if (!attribute.Capabilities.HasFlag(AttrCapabilities.AllowView))
     {
         throw new InvalidQueryStringParameterException(_lastParameterName, "Retrieving the requested attribute is not allowed.",
                                                        $"Retrieving the attribute '{attribute.PublicName}' is not allowed.");
     }
 }
Beispiel #23
0
 private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue, RelationshipAttribute relationship = null)
 {
     return(OmitNullValuedAttribute(attr, attributeValue) == false &&
            attr.InternalAttributeName != nameof(Identifiable.Id) &&
            ((_jsonApiContext.QuerySet == null ||
              _jsonApiContext.QuerySet.Fields.Count == 0) ||
             _jsonApiContext.QuerySet.Fields.Contains(relationship != null ?
                                                      $"{relationship.InternalRelationshipName}.{attr.InternalAttributeName}" :
                                                      attr.InternalAttributeName)));
 }
Beispiel #24
0
        private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, ResourceContext resourceContext)
        {
            SparseFieldSetExpression sparseFieldSet = _sparseFieldSetParser.Parse(parameterValue, resourceContext);

            if (sparseFieldSet == null)
            {
                // We add ID on an incoming empty fieldset, so that callers can distinguish between no fieldset and an empty one.
                AttrAttribute idAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Identifiable.Id));
                return(new SparseFieldSetExpression(ArrayFactory.Create(idAttribute)));
            }

            return(sparseFieldSet);
        }
        public void AttrAttribute_Equals_Returns_False_When_Different_Name()
        {
            var attribute1 = new AttrAttribute
            {
                PublicName = "test"
            };

            var attribute2 = new AttrAttribute
            {
                PublicName = "test2"
            };

            Assert.NotEqual(attribute1, attribute2);
        }
        public void AttrAttribute_Equals_Returns_True_When_Same_Name()
        {
            var attribute1 = new AttrAttribute
            {
                PublicName = "test"
            };

            var attribute2 = new AttrAttribute
            {
                PublicName = "test"
            };

            Assert.Equal(attribute1, attribute2);
        }
        public override FilterExpression OnApplyFilter(FilterExpression existingFilter)
        {
            ResourceContext resourceContext = _resourceGraph.GetResourceContext <TResource>();

            AttrAttribute isSoftDeletedAttribute =
                resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(ISoftDeletable.IsSoftDeleted));

            var isNotSoftDeleted = new ComparisonExpression(ComparisonOperator.Equals, new ResourceFieldChainExpression(isSoftDeletedAttribute),
                                                            new LiteralConstantExpression("false"));

            return(existingFilter == null
                ? (FilterExpression)isNotSoftDeleted
                : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(isNotSoftDeleted, existingFilter)));
        }
        public override FilterExpression OnApplyFilter(FilterExpression existingFilter)
        {
            // Use case: automatically exclude deleted resources for all requests.

            ResourceContext resourceContext    = ResourceGraph.GetResourceContext <CallableResource>();
            AttrAttribute   isDeletedAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(CallableResource.IsDeleted));

            var isNotDeleted = new ComparisonExpression(ComparisonOperator.Equals, new ResourceFieldChainExpression(isDeletedAttribute),
                                                        new LiteralConstantExpression(bool.FalseString));

            return(existingFilter == null
                ? (FilterExpression)isNotDeleted
                : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(isNotDeleted, existingFilter)));
        }
Beispiel #29
0
        private static FilterExpression CreateFilterByIds <TId>(IReadOnlyCollection <TId> ids, ResourceContext resourceContext)
        {
            AttrAttribute idAttribute = resourceContext.Attributes.Single(attr => attr.Property.Name == nameof(Identifiable.Id));
            var           idChain     = new ResourceFieldChainExpression(idAttribute);

            if (ids.Count == 1)
            {
                var constant = new LiteralConstantExpression(ids.Single().ToString());
                return(new ComparisonExpression(ComparisonOperator.Equals, idChain, constant));
            }

            List <LiteralConstantExpression> constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToList();

            return(new EqualsAnyOfExpression(idChain, constants));
        }
        public async Task UpdateAsync_AttributesUpdated_ShouldHaveSpecificallyThoseAttributesUpdated()
        {
            // Arrange
            var itemId = 213;
            var seed   = Guid.NewGuid();

            var databaseEntity = new TodoItem
            {
                Id          = itemId,
                Description = "Before"
            };

            var todoItemUpdates = new TodoItem
            {
                Id          = itemId,
                Description = "After"
            };

            await using (var arrangeContext = GetContext(seed))
            {
                var(repository, targetedFields) = Setup(arrangeContext);
                arrangeContext.Add(databaseEntity);
                arrangeContext.SaveChanges();

                var descAttr = new AttrAttribute("description")
                {
                    PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description))
                };
                targetedFields.Setup(m => m.Attributes).Returns(new List <AttrAttribute> {
                    descAttr
                });
                targetedFields.Setup(m => m.Relationships).Returns(new List <RelationshipAttribute>());

                // Act
                await repository.UpdateAsync(todoItemUpdates, databaseEntity);
            }

            // Assert - in different context
            await using var assertContext = GetContext(seed);
            {
                var(repository, _) = Setup(assertContext);

                var fetchedTodo = repository.Get(itemId).First();
                Assert.NotNull(fetchedTodo);
                Assert.Equal(databaseEntity.Ordinal, fetchedTodo.Ordinal);
                Assert.Equal(todoItemUpdates.Description, fetchedTodo.Description);
            }
        }