Fixes Invalid URL exception message response. (#3644)
* changed invalidurl exception status code to 400 insteadof 500 * Added Validation Filter for ResourceType and Id. Removed Argumentnull exception block from OperationoutcomeExceptionFilterAttribute class * Validation added to few other scenarios * Added unit test case for Filete validation and rename filter attribute to ValidateIdSegmentAttribute * E2E for VRead BadRequest * reverting test * decorated newly added test case class with Trait attribute --------- Co-authored-by: rajithaaluri <rajithaaluri@microsoft.com>
This commit is contained in:
Родитель
d4e58b9f41
Коммит
7e0f423774
|
@ -0,0 +1,108 @@
|
|||
// -------------------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Hl7.Fhir.Model;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Health.Fhir.Api.Features.Filters;
|
||||
using Microsoft.Health.Fhir.Api.Features.Routing;
|
||||
using Microsoft.Health.Fhir.Core.Features.Validation;
|
||||
using Microsoft.Health.Fhir.Core.Models;
|
||||
using Microsoft.Health.Fhir.Tests.Common;
|
||||
using Microsoft.Health.Test.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Health.Fhir.Api.UnitTests.Features.Filters
|
||||
{
|
||||
[Trait(Traits.OwningTeam, OwningTeam.Fhir)]
|
||||
[Trait(Traits.Category, Categories.Validate)]
|
||||
[Trait(Traits.Category, Categories.Web)]
|
||||
public class ValidateIdSegmentAttributeTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData(null)]
|
||||
public void GivenAPatientAction_WhenPuttingAPatinetObjectWithNullResourceId_ThenAResourceNotValidExceptionShouldBeThrown(string id)
|
||||
{
|
||||
var filter = new ValidateIdSegmentAttribute();
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
};
|
||||
|
||||
var context = CreateContext(patient, id);
|
||||
|
||||
Assert.Throws<ResourceNotValidException>(() => filter.OnActionExecuting(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenAPatientAction_WhenPuttingAPatinetObjectwithValidResourceId_ThenTheResultIsSuccessful()
|
||||
{
|
||||
var filter = new ValidateIdSegmentAttribute();
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
};
|
||||
var context = CreateContext(patient, patient.Id);
|
||||
|
||||
var exception = Record.Exception(() => filter.OnActionExecuting(context));
|
||||
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData(null)]
|
||||
public void GivenAPatinetAction_WhenPuttingAParametersPatientObjectwithNullResourceId_ThenAResourceNotValidExceptionShouldBeThrown(string id)
|
||||
{
|
||||
var filter = new ValidateIdSegmentAttribute(true);
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
};
|
||||
|
||||
var parameters = new Parameters();
|
||||
parameters.Add("resource", patient);
|
||||
var context = CreateContext(parameters, id);
|
||||
|
||||
Assert.Throws<ResourceNotValidException>(() => filter.OnActionExecuting(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenAPatientAction_WhenPuttingAParametersPatientObjectwithValidResourceId_ThenTheResultIsSuccessful()
|
||||
{
|
||||
var filter = new ValidateResourceIdFilterAttribute(true);
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
};
|
||||
|
||||
var parameters = new Parameters();
|
||||
parameters.Add("resource", patient);
|
||||
var context = CreateContext(parameters, patient.Id);
|
||||
|
||||
filter.OnActionExecuting(context);
|
||||
}
|
||||
|
||||
private static ActionExecutingContext CreateContext(Resource type, string id)
|
||||
{
|
||||
return new ActionExecutingContext(
|
||||
new ActionContext(new DefaultHttpContext(), new RouteData { Values = { [KnownActionParameterNames.ResourceType] = "Patient", [KnownActionParameterNames.Id] = id } }, new ActionDescriptor()),
|
||||
new List<IFilterMetadata>(),
|
||||
new Dictionary<string, object> { { "resource", type } },
|
||||
FilterTestsHelper.CreateMockFhirController());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\OperationOutcomeExceptionFilterTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateContentTypeFilterAttributeTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateExportRequestFilterAttributeTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateIdSegmentAttributeTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateResourceIdFilterTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateResourceTypeFilterTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\SearchParameterFilterAttributeTests.cs" />
|
||||
|
|
|
@ -267,6 +267,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="typeParameter">The type.</param>
|
||||
/// <param name="idParameter">The identifier.</param>
|
||||
[HttpGet]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.ResourceTypeById, Name = RouteNames.ReadResource)]
|
||||
[AuditEventType(AuditEventSubType.Read)]
|
||||
public async Task<IActionResult> Read(string typeParameter, string idParameter)
|
||||
|
@ -361,6 +362,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="idParameter">The identifier.</param>
|
||||
/// <param name="vidParameter">The versionId.</param>
|
||||
[HttpGet]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.ResourceTypeByIdAndVid, Name = RouteNames.ReadResourceWithVersionRoute)]
|
||||
[AuditEventType(AuditEventSubType.VRead)]
|
||||
public async Task<IActionResult> VRead(string typeParameter, string idParameter, string vidParameter)
|
||||
|
@ -381,6 +383,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="idParameter">The identifier.</param>
|
||||
/// <param name="hardDelete">A flag indicating whether to hard-delete the resource or not.</param>
|
||||
[HttpDelete]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.ResourceTypeById)]
|
||||
[AuditEventType(AuditEventSubType.Delete)]
|
||||
public async Task<IActionResult> Delete(string typeParameter, string idParameter, [FromQuery] bool hardDelete)
|
||||
|
@ -401,6 +404,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="typeParameter">The type.</param>
|
||||
/// <param name="idParameter">The identifier.</param>
|
||||
[HttpDelete]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.PurgeHistoryResourceTypeById)]
|
||||
[AuditEventType(AuditEventSubType.PurgeHistory)]
|
||||
public async Task<IActionResult> PurgeHistory(string typeParameter, string idParameter)
|
||||
|
@ -455,6 +459,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="patchDocument">The JSON patch document.</param>
|
||||
/// <param name="ifMatchHeader">Optional If-Match header.</param>
|
||||
[HttpPatch]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.ResourceTypeById)]
|
||||
[AuditEventType(AuditEventSubType.Patch)]
|
||||
[Consumes("application/json-patch+json")]
|
||||
|
@ -504,6 +509,7 @@ namespace Microsoft.Health.Fhir.Api.Controllers
|
|||
/// <param name="paramsResource">The JSON FHIR Parameters Resource.</param>
|
||||
/// <param name="ifMatchHeader">Optional If-Match header.</param>
|
||||
[HttpPatch]
|
||||
[ValidateIdSegmentAttribute]
|
||||
[Route(KnownRoutes.ResourceTypeById)]
|
||||
[AuditEventType(AuditEventSubType.Patch)]
|
||||
[Consumes("application/fhir+json")]
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// -------------------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using EnsureThat;
|
||||
using FluentValidation.Results;
|
||||
using Hl7.Fhir.Model;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Health.Fhir.Api.Features.Routing;
|
||||
using Microsoft.Health.Fhir.Core.Features.Validation;
|
||||
|
||||
namespace Microsoft.Health.Fhir.Api.Features.Filters
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
internal sealed class ValidateIdSegmentAttribute : ParameterCompatibleFilter
|
||||
{
|
||||
public ValidateIdSegmentAttribute(bool allowParametersResource = false)
|
||||
: base(allowParametersResource)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
EnsureArg.IsNotNull(context, nameof(context));
|
||||
|
||||
if (context.RouteData.Values.TryGetValue(KnownActionParameterNames.Id, out var resourceId))
|
||||
{
|
||||
ValidateId((string)resourceId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateId(string resourceId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(resourceId))
|
||||
{
|
||||
throw new ResourceNotValidException(new List<ValidationFailure>
|
||||
{
|
||||
new ValidationFailure("ResourceKey.Id", string.Format(Core.Resources.IdRequirements)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\OperationOutcomeExceptionFilterAttribute.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateResourceIdFilterAttribute.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateResourceTypeFilterAttribute.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\ValidateIdSegmentAttribute.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Filters\WeakETagBinder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Formatters\FhirJsonInputFormatter.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Features\Formatters\FhirJsonOutputFormatter.cs" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче