From b5a1ec3a09a8c7f2325f4f159aa89ca8429e6d2a Mon Sep 17 00:00:00 2001 From: leandro-cavalcante <162341380+leandro-cavalcante@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:12:00 +0200 Subject: [PATCH] fix: policy hub post get policy rules response structuring error value map (#201) Co-authored-by: Phil Schneider Reviewed-by: Phil Schneider --- .../BusinessLogic/PolicyHubBusinessLogic.cs | 31 +++++++++++++------ .../Controllers/PolicyHubController.cs | 5 ++- .../PolicyHubBusinessLogicTests.cs | 21 +++++++++++-- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs index 18f641ee..7d58fb48 100644 --- a/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs +++ b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs @@ -64,17 +64,30 @@ private static (object rightOperand, AdditionalAttributes? additionalAttribute) AttributeKeyId.DynamicValue => (value ?? "{dynamicValue}", null), AttributeKeyId.Regex => (GetRegexValue(attributes, value), null), _ => operatorId == OperatorId.Equals - ? rightOperands.Count() > 1 ? - ($"@{leftOperand}{(useCase != null ? - useCase.Value.ToString().Insert(0, ".") : - string.Empty)}-{attributes.Key}", - new AdditionalAttributes($"@{leftOperand}{(useCase != null ? - useCase.Value.ToString().Insert(0, ".") : - string.Empty)}-{attributes.Key}", rightOperands)) : - (rightOperands.Single(), null) + ? processEqualsOperator(attributes, rightOperands, value, leftOperand, useCase) : (rightOperands, null) }; + private static (object rightOperand, AdditionalAttributes? additionalAttribute) processEqualsOperator((AttributeKeyId? Key, IEnumerable Values) attributes, IEnumerable rightOperands, string? value, string leftOperand, UseCaseId? useCase) + { + if (value != null) + { + if (!rightOperands.Any(r => r == value)) + { + throw new ControllerArgumentException($"Invalid values [{value}] set for key {leftOperand}. Possible values [{string.Join(",", rightOperands)}]"); + } + rightOperands = rightOperands.Where(r => r.Equals(value)); + } + + var useCaseValue = useCase != null ? + useCase.Value.ToString().Insert(0, ".") : + string.Empty; + var rightOperand = $"@{leftOperand}{useCaseValue}-{attributes.Key}"; + return rightOperands.Count() > 1 ? + (rightOperand, new AdditionalAttributes(rightOperand, rightOperands)) : + (rightOperands.Single(), null); + } + private static object GetRegexValue((AttributeKeyId? Key, IEnumerable Values) attributes, string? value) { if (string.IsNullOrWhiteSpace(value)) @@ -163,7 +176,7 @@ public async Task GetPolicyContentAsync(PolicyContentRequest req if (invalidValues.Any()) { var x = missingValues.Where(x => invalidValues.Contains(x.TechnicalKey)).Select(x => - $"Key: {x.TechnicalKey}, invalid values: {string.Join(',', x.Values)}"); + $"Key: {x.TechnicalKey}, requested value[{string.Join(',', x.Values)}] Possible Values[{string.Join(',', attributeValuesForTechnicalKeys.Where(a => a.TechnicalKey.Equals(x.TechnicalKey)).Select(a => a.Values).First())}]"); throw new ControllerArgumentException($"Invalid values set for {string.Join(',', x)}"); } diff --git a/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs index cf67bb38..78a831c4 100644 --- a/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs +++ b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs @@ -23,6 +23,7 @@ using Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; using Org.Eclipse.TractusX.PolicyHub.Service.Extensions; using Org.Eclipse.TractusX.PolicyHub.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Web; using System.Diagnostics.CodeAnalysis; @@ -71,6 +72,7 @@ public static RouteGroupBuilder MapPolicyHubApi(this RouteGroupBuilder group) .RequireAuthorization() .WithDefaultResponses() .Produces(StatusCodes.Status200OK, typeof(PolicyResponse), Constants.JsonContentType) + .Produces(StatusCodes.Status400BadRequest, typeof(ErrorResponse), Constants.JsonContentType) .Produces(StatusCodes.Status404NotFound, typeof(ErrorResponse), Constants.JsonContentType); policyHub.MapPost("policy-content", ([FromBody] PolicyContentRequest requestData, IPolicyHubBusinessLogic logic) => logic.GetPolicyContentAsync(requestData)) @@ -80,7 +82,8 @@ public static RouteGroupBuilder MapPolicyHubApi(this RouteGroupBuilder group) .RequireAuthorization() .WithDefaultResponses() .Produces(StatusCodes.Status200OK, typeof(PolicyResponse), Constants.JsonContentType) - .Produces(StatusCodes.Status404NotFound, typeof(ErrorResponse), Constants.JsonContentType); + .Produces(StatusCodes.Status400BadRequest, typeof(ErrorResponse), Constants.JsonContentType) + .Produces(StatusCodes.Status404NotFound, typeof(ControllerArgumentException), Constants.JsonContentType); return group; } diff --git a/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs index fdc291d1..2d045706 100644 --- a/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs +++ b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs @@ -169,7 +169,7 @@ public async Task GetPolicyContentWithFiltersAsync_WithMultipleValues_ReturnsExp .Returns(new ValueTuple>, string?>(true, "multipleAdditionalValues", new ValueTuple>(AttributeKeyId.Static, new[] { "value1", "value2", "value3" }), null)); // Act - var result = await _sut.GetPolicyContentWithFiltersAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues", OperatorId.Equals, "test"); + var result = await _sut.GetPolicyContentWithFiltersAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues", OperatorId.Equals, null); // Assert result.Content.Id.Should().Be("...."); @@ -188,6 +188,23 @@ public async Task GetPolicyContentWithFiltersAsync_WithMultipleValues_ReturnsExp result.Content.Permission.Constraint.OrOperands.Should().BeNull(); } + [Fact] + public async Task GetPolicyContentWithFiltersAsync_WithInvalidValue_ExceptionExpected() + { + // Arrange + A.CallTo(() => _policyRepository.GetPolicyContentAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues")) + .Returns(new ValueTuple>, string?>(true, "multipleAdditionalValues", new ValueTuple>(AttributeKeyId.Static, new[] { "value1", "value2", "value3" }), null)); + + // Act + async Task Act() => await _sut.GetPolicyContentWithFiltersAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues", OperatorId.Equals, "test"); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("Invalid values [test] set for key multipleAdditionalValues. Possible values [value1,value2,value3]"); + } + #endregion #region GetPolicyContentAsync @@ -264,7 +281,7 @@ public async Task GetPolicyContentAsync_WithUnmatchingAttributeValues_ThrowsCont var ex = await Assert.ThrowsAsync(Act); // Assert - ex.Message.Should().Be("Invalid values set for Key: test, invalid values: abc"); + ex.Message.Should().Be("Invalid values set for Key: test, requested value[abc] Possible Values[test]"); } [Fact]