public AuditLoggingFilterTests() { _fhirResult = new FhirResult(new Patient() { Name = { new HumanName() { Text = "TestPatient" } } }); _executedContext = new ResultExecutedContext( new ActionContext(new DefaultHttpContext(), new RouteData(), new ControllerActionDescriptor() { DisplayName = "Executed Context Test Descriptor" }), new List <IFilterMetadata>(), _fhirResult, FilterTestsHelper.CreateMockFhirController()); _executedContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Created; _fhirResult.StatusCode = HttpStatusCode.Created; _fhirRequestContext.RequestType.Returns(new Coding("System", "TestRequestType")); _fhirRequestContext.RequestSubType = new Coding("System", "TestRequestSubType"); _fhirRequestContext.Uri.Returns(new Uri("https://fhirtest/fhir?count=100")); _fhirRequestContextAccessor.FhirRequestContext.Returns(_fhirRequestContext); _fhirRequestContextAccessor.FhirRequestContext.Principal.Returns(_claimsPrincipal); _securityConfiguration.LastModifiedClaims.Returns(new HashSet <string> { "claim1" }); _securityOptions.Value.Returns(_securityConfiguration); _claimsPrincipal.Claims.Returns(new List <System.Security.Claims.Claim> { Claim1 }); _claims = new KeyValuePair <string, string>[] { KeyValuePair.Create("claim", "value"), }; _claimsIndexer = Substitute.For <IClaimsIndexer>(); _claimsIndexer.Extract().Returns(_claims); _filter = new AuditLoggingFilterAttribute( _auditLogger, _fhirRequestContextAccessor, _claimsIndexer); }
public IActionResult CustomError(int?statusCode = null) { HttpStatusCode returnCode; OperationOutcome.IssueType issueType; string diagnosticInfo; switch (statusCode) { case (int)HttpStatusCode.Unauthorized: issueType = OperationOutcome.IssueType.Login; returnCode = HttpStatusCode.Unauthorized; diagnosticInfo = Resources.Unauthorized; break; case (int)HttpStatusCode.Forbidden: issueType = OperationOutcome.IssueType.Forbidden; returnCode = HttpStatusCode.Forbidden; diagnosticInfo = Resources.Forbidden; break; case (int)HttpStatusCode.NotFound: issueType = OperationOutcome.IssueType.NotFound; returnCode = HttpStatusCode.NotFound; diagnosticInfo = Resources.NotFoundException; break; default: issueType = OperationOutcome.IssueType.Exception; returnCode = HttpStatusCode.InternalServerError; diagnosticInfo = Resources.GeneralInternalError; break; } return(FhirResult.Create( new OperationOutcome { Id = _fhirRequestContextAccessor.FhirRequestContext.CorrelationId, Issue = new List <OperationOutcome.IssueComponent> { new OperationOutcome.IssueComponent { Severity = OperationOutcome.IssueSeverity.Error, Code = issueType, Diagnostics = diagnosticInfo, }, }, }.ToResourceElement(), returnCode)); }
public async Task <IActionResult> CreateReindexJob([FromBody] Parameters inputParams) { CheckIfReindexIsEnabledAndRespond(); ValidateParams(inputParams); ushort?maximumConcurrency = ReadNumericParameter(inputParams, JobRecordProperties.MaximumConcurrency); string scope = ReadStringParameter(inputParams, JobRecordProperties.Scope); ResourceElement response = await _mediator.CreateReindexJobAsync(maximumConcurrency, scope, HttpContext.RequestAborted); return(FhirResult.Create(response, HttpStatusCode.Created) .SetETagHeader() .SetLastModifiedHeader()); }
public static FhirResult SetLocationHeader(this FhirResult fhirResult, IUrlResolver urlResolver) { var resource = fhirResult.Resource; if (!string.IsNullOrEmpty(resource.Id) && !string.IsNullOrWhiteSpace(resource.Meta.VersionId)) { var url = urlResolver.ResolveResourceUrl(resource, true); if (url.IsAbsoluteUri) { fhirResult.Headers.Add(HeaderNames.Location, url.AbsoluteUri); } } return(fhirResult); }
public void GivenAController_WhenExecutedAction_ThenAuditLogShouldBeLogged() { const HttpStatusCode expectedStatusCode = HttpStatusCode.Created; var fhirResult = new FhirResult(new Patient() { Name = { new HumanName() { Text = "TestPatient" } } }); SetupExecutedAction(expectedStatusCode, fhirResult); _auditHelper.Received(1).LogExecuted(ControllerName, ActionName, expectedStatusCode, "Patient"); }
public async Task <IActionResult> CreateReindexJob([FromBody] Parameters inputParams) { CheckIfReindexIsEnabledAndRespond(); ValidateParams(inputParams); ushort?maximumConcurrency = ReadNumericParameter(inputParams, JobRecordProperties.MaximumConcurrency); ResourceElement response = await _mediator.CreateReindexJobAsync(maximumConcurrency, HttpContext.RequestAborted); var result = FhirResult.Create(response, HttpStatusCode.Created) .SetETagHeader() .SetLastModifiedHeader(); result.SetContentLocationHeader(_urlResolver, OperationsConstants.Reindex, response.Id); return(result); }
private IActionResult ToSaveOutcomeResult(SaveOutcome saveOutcome) { switch (saveOutcome.Outcome) { case SaveOutcomeType.Created: return FhirResult.Create(saveOutcome.RawResourceElement, HttpStatusCode.Created) .SetETagHeader() .SetLastModifiedHeader() .SetLocationHeader(_urlResolver); case SaveOutcomeType.Updated: return FhirResult.Create(saveOutcome.RawResourceElement, HttpStatusCode.OK) .SetETagHeader() .SetLastModifiedHeader(); } return FhirResult.Create(saveOutcome.RawResourceElement, HttpStatusCode.BadRequest); }
public async Task <IActionResult> Delete(string typeParameter, string idParameter, [FromQuery] bool hardDelete) { string policy = PolicyNames.WritePolicy; if (hardDelete) { policy = PolicyNames.HardDeletePolicy; } AuthorizationResult authorizationResult = await _authorizationService.AuthorizeAsync(User, policy); if (!authorizationResult.Succeeded) { return(Forbid()); } DeleteResourceResponse response = await _mediator.DeleteResourceAsync(new ResourceKey(typeParameter, idParameter), hardDelete, HttpContext.RequestAborted); return(FhirResult.NoContent().SetETagHeader(response.WeakETag)); }
public async Task <IActionResult> ConditionalCreate([FromBody] Resource resource) { StringValues conditionalCreateHeader = HttpContext.Request.Headers[KnownFhirHeaders.IfNoneExist]; Tuple <string, string>[] conditionalParameters = QueryHelpers.ParseQuery(conditionalCreateHeader) .SelectMany(query => query.Value, (query, value) => Tuple.Create(query.Key, value)).ToArray(); UpsertResourceResponse createResponse = await _mediator.Send <UpsertResourceResponse>(new ConditionalCreateResourceRequest(resource.ToResourceElement(), conditionalParameters), HttpContext.RequestAborted); if (createResponse == null) { return(Ok()); } ResourceElement response = createResponse.Outcome.Resource; return(FhirResult.Create(response, HttpStatusCode.Created) .SetETagHeader() .SetLastModifiedHeader() .SetLocationHeader(_urlResolver)); }
public void GivenAController_WhenExecutedAction_ThenAuditLogShouldBeLogged() { var fhirResult = new FhirResult(new Patient() { Name = { new HumanName() { Text = "TestPatient" } } }.ToResourceElement()); var resultExecutedContext = new ResultExecutedContext( new ActionContext(_httpContext, new RouteData(), new ControllerActionDescriptor() { DisplayName = "Executed Context Test Descriptor" }), new List <IFilterMetadata>(), fhirResult, FilterTestsHelper.CreateMockFhirController()); _filter.OnResultExecuted(resultExecutedContext); _auditHelper.Received(1).LogExecuted(_httpContext, _claimsExtractor); }
public void WhenSettingALastModifiedHeader_ThenFhirResultHasALastModifierHeader() { var fhirResult = FhirResult.Create(_mockResource).SetLastModifiedHeader(); Assert.Equal(_mockResource.LastUpdated?.ToString("r", CultureInfo.InvariantCulture), fhirResult.Headers[HeaderNames.LastModified]); }
public async Task <IActionResult> Metadata(bool system = false) { ResourceElement response = await _mediator.GetCapabilitiesAsync(system, HttpContext.RequestAborted); return(FhirResult.Create(response)); }
private async Task <IActionResult> PerformSearch(string type, IReadOnlyList <Tuple <string, string> > queries) { ResourceElement response = await _mediator.SearchResourceAsync(type, queries, HttpContext.RequestAborted); return(FhirResult.Create(response)); }
public async Task <IActionResult> BatchAndTransactions([FromBody] Resource bundle) { ResourceElement bundleResponse = await _mediator.PostBundle(bundle.ToResourceElement()); return(FhirResult.Create(bundleResponse)); }
public async Task <IActionResult> Delete(string typeParameter, string idParameter, [FromQuery] bool hardDelete) { DeleteResourceResponse response = await _mediator.DeleteResourceAsync(new ResourceKey(typeParameter, idParameter), hardDelete, HttpContext.RequestAborted); return(FhirResult.NoContent().SetETagHeader(response.WeakETag)); }
private async Task <IActionResult> PerformSearch(string type, IReadOnlyList <Tuple <string, string> > queries) { var response = await _mediator.Send(new SearchResourceRequest(type, queries), HttpContext.RequestAborted); return(FhirResult.Create(response.Bundle)); }
private async Task<IActionResult> PerformCompartmentSearch(string compartmentType, string compartmentId, string resourceType, IReadOnlyList<Tuple<string, string>> queries) { ResourceElement response = await _mediator.SearchResourceCompartmentAsync(compartmentType, compartmentId, resourceType, queries, HttpContext.RequestAborted); return FhirResult.Create(response); }
public void WhenAddingSameHeaderTwice_ThenOnlyOneHeaderIsPresent() { Assert.Throws <ArgumentException>(() => FhirResult.Create(_mockResource) .SetLastModifiedHeader() .SetLastModifiedHeader()); }
public void WhenCreatingAFhirResultAndNotSettingHeaders_ThenThereIsNoHeaders() { var fhirResult = FhirResult.Create(_mockResource); Assert.Empty(fhirResult.Headers); }
public async Task Invoke(HttpContext context) { try { await _next(context); } catch (Exception exception) { if (context.Response.HasStarted) { _logger.LogWarning("The response has already started, the base exception middleware will not be executed."); throw; } var localCorrelationId = _fhirRequestContextAccessor.FhirRequestContext?.CorrelationId; if (string.IsNullOrWhiteSpace(localCorrelationId)) { localCorrelationId = _correlationIdProvider.Invoke(); _logger.LogError($"No correlation id available in exception middleware. Setting to {localCorrelationId}"); } context.Response.Clear(); var diagnostics = Resources.GeneralInternalError; // If any of these exceptions are encountered, show a more specific diagnostic message if (exception.Message.StartsWith("IDX10803: Unable to obtain configuration from:", StringComparison.OrdinalIgnoreCase)) { diagnostics = Resources.UnableToObtainOpenIdConfiguration; } else if (exception.Message.StartsWith("The MetadataAddress or Authority must use HTTPS", StringComparison.OrdinalIgnoreCase)) { diagnostics = Resources.RequireHttpsMetadataError; } var operationOutcome = new OperationOutcome { Id = localCorrelationId, Issue = new List <OperationOutcome.IssueComponent> { new OperationOutcome.IssueComponent { Severity = OperationOutcome.IssueSeverity.Fatal, Code = OperationOutcome.IssueType.Exception, Diagnostics = diagnostics, }, }, }; try { await _contentTypeService.CheckRequestedContentTypeAsync(context); } catch (UnsupportedMediaTypeException) { context.Response.ContentType = ContentType.JSON_CONTENT_HEADER; } var result = FhirResult.Create(operationOutcome, HttpStatusCode.InternalServerError); await ExecuteResultAsync(context, result); } }
public void WhenAddingStringEtag_ThenStringETagIsReturned() { var fhirResult = FhirResult.Create(_mockResource).SetETagHeader("etag"); Assert.Equal("etag", fhirResult.Headers[HeaderNames.ETag]); }
public async Task <IActionResult> PurgeHistory(string typeParameter, string idParameter) { DeleteResourceResponse response = await _mediator.DeleteResourceAsync(new ResourceKey(typeParameter, idParameter), DeleteOperation.PurgeHistory, HttpContext.RequestAborted); return(FhirResult.NoContent().SetETagHeader(response.WeakETag)); }
public void WhenAddingTwoHeaders_ThenFhirResultHasAtLeastTwoHeaders() { var fhirResult = FhirResult.Create(_mockResource).SetLastModifiedHeader().SetETagHeader(); Assert.Equal(2, fhirResult.Headers.Count); }
public override void OnActionExecuted(ActionExecutedContext context) { EnsureArg.IsNotNull(context, nameof(context)); if (context?.Exception is FhirException fhirException) { FhirResult fhirResult = FhirResult.Create( new OperationOutcome { Id = _fhirRequestContextAccessor.FhirRequestContext.CorrelationId, Issue = fhirException.Issues.ToList(), }, HttpStatusCode.BadRequest); switch (fhirException) { case ResourceGoneException resourceGoneException: fhirResult.StatusCode = HttpStatusCode.Gone; if (!string.IsNullOrEmpty(resourceGoneException.DeletedResource?.VersionId)) { fhirResult.SetETagHeader(WeakETag.FromVersionId(resourceGoneException.DeletedResource.VersionId)); } break; case ResourceNotFoundException _: fhirResult.StatusCode = HttpStatusCode.NotFound; break; case MethodNotAllowedException _: fhirResult.StatusCode = HttpStatusCode.MethodNotAllowed; break; case ServiceUnavailableException _: case OpenIdConfigurationException _: fhirResult.StatusCode = HttpStatusCode.ServiceUnavailable; break; case ResourceNotValidException _: case BadRequestException _: fhirResult.StatusCode = HttpStatusCode.BadRequest; break; case ResourceConflictException _: fhirResult.StatusCode = HttpStatusCode.Conflict; break; case UnsupportedMediaTypeException _: fhirResult.StatusCode = HttpStatusCode.UnsupportedMediaType; break; case PreconditionFailedException _: fhirResult.StatusCode = HttpStatusCode.PreconditionFailed; break; case InvalidSearchOperationException _: case SearchOperationNotSupportedException _: fhirResult.StatusCode = HttpStatusCode.Forbidden; break; case UnsupportedConfigurationException _: fhirResult.StatusCode = HttpStatusCode.InternalServerError; break; case RequestRateExceededException ex: fhirResult.StatusCode = HttpStatusCode.TooManyRequests; if (ex.RetryAfter != null) { fhirResult.Headers.Add( RetryAfterHeaderName, ex.RetryAfter.Value.TotalMilliseconds.ToString(CultureInfo.InvariantCulture)); } break; } context.Result = fhirResult; context.ExceptionHandled = true; } }
public void WhenAddingStringEtag_ThenStringETagIsReturned() { var fhirResult = FhirResult.Create(_mockResource).SetETagHeader(WeakETag.FromVersionId("etag")); Assert.Equal("W/\"etag\"", fhirResult.Headers[HeaderNames.ETag]); }
private async Task <IActionResult> PerformCompartmentSearch(string compartmentType, string compartmentId, string resourceType, IReadOnlyList <Tuple <string, string> > queries) { var response = await _mediator.Send(new CompartmentResourceRequest(compartmentType, compartmentId, resourceType, queries), HttpContext.RequestAborted); return(FhirResult.Create(response.Bundle)); }