Example #1
0
        public async Task WhenUpdatingAResource_GivenAUserWithNoWritePermissions_TheServerShouldReturnForbidden()
        {
            await Client.RunAsUser(TestUsers.WriteOnlyUser, TestApplications.NativeClient);

            Observation createdResource = await Client.CreateAsync(Samples.GetDefaultObservation());

            await Client.RunAsUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await Client.UpdateAsync(createdResource));

            Assert.Equal(ForbiddenMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Forbidden, fhirException.StatusCode);
        }
Example #2
0
        public async Task GivenADeletedIdAndVersionId_WhenGettingAResource_TheServerShouldReturnAGoneStatus()
        {
            Observation createdResource = await _client.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            using FhirResponse deleteResponse = await _client.DeleteAsync(createdResource);

            var deletedVersion = WeakETag.FromWeakETag(deleteResponse.Headers.ETag.ToString()).VersionId;

            using FhirException ex = await Assert.ThrowsAsync <FhirException>(
                      () => _client.VReadAsync <Observation>(ResourceType.Observation, createdResource.Id, deletedVersion));

            Assert.Equal(System.Net.HttpStatusCode.Gone, ex.StatusCode);
        }
Example #3
0
        public async Task GivenAResource_WhenHardDeleting_ThenServerShouldDeleteAllRelatedResourcesSuccessfully()
        {
            List <string> versionIds = new List <string>();

            using FhirResponse <Observation> response1 = await _client.CreateAsync(Samples.GetDefaultObservation ().ToPoco <Observation>());

            Observation observation = response1.Resource;
            string      resourceId  = observation.Id;

            versionIds.Add(observation.Meta.VersionId);

            // Update the observation.
            observation.Status = ObservationStatus.EnteredInError;

            using FhirResponse <Observation> response2 = await _client.UpdateAsync(observation);

            versionIds.Add(response2.Resource.Meta.VersionId);

            // Delete the observation
            await _client.DeleteAsync(observation);

            // Update the observation to resurrect the resource.
            observation.Status  = ObservationStatus.Final;
            observation.Subject = new ResourceReference("Patient/123");

            using FhirResponse <Observation> response3 = await _client.UpdateAsync(observation);

            versionIds.Add(response3.Resource.Meta.VersionId);

            // Hard-delete the resource.
            await _client.HardDeleteAsync(observation);

            // Getting the resource should result in NotFound.
            await ExecuteAndValidateNotFoundStatus(() => _client.ReadAsync <Observation>(ResourceType.Observation, resourceId));

            // Each version read should also result in NotFound.
            foreach (string versionId in versionIds)
            {
                await ExecuteAndValidateNotFoundStatus(() => _client.VReadAsync <Observation>(ResourceType.Observation, resourceId, versionId));
            }

            // History API should return NotFound.
            await ExecuteAndValidateNotFoundStatus(() => _client.SearchAsync($"Observation/{resourceId}/_history"));

            async Task ExecuteAndValidateNotFoundStatus(Func <Task> action)
            {
                using FhirException exception = await Assert.ThrowsAsync <FhirException>(action);

                Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);
            }
        }
Example #4
0
        public async Task GivenPatientWithReplacedByLink_WhenRunningPatientEverythingWithPreferHeaderSetToStrictHandling_ThenMovedPermanentlyIsReturned()
        {
            string searchUrl = $"Patient/{Fixture.PatientWithReplacedByLink.Id}/$everything";

            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => Client.SearchAsync(searchUrl, Tuple.Create(KnownHeaders.Prefer, "handling=strict")));

            // Confirm header location contains url for the correct request
            string id  = Fixture.PatientReferencedByReplacedByLink.Id;
            string uri = $"/{KnownResourceTypes.Patient}/{id}/$everything";

            Assert.Contains(uri, ex.Content.Headers.GetValues(HeaderNames.ContentLocation).First());
            Assert.Equal(HttpStatusCode.MovedPermanently, ex.StatusCode);
            Assert.Contains(string.Format(Core.Resources.EverythingOperationResourceIrrelevant, Fixture.PatientWithReplacedByLink.Id, Fixture.PatientReferencedByReplacedByLink.Id), ex.Message);
        }
Example #5
0
        public async Task GivenAUserWithNoConvertDataPermissions_WhenConvertData_TheServerShouldReturnForbidden()
        {
            if (!_convertDataEnabled)
            {
                return;
            }

            TestFhirClient tempClient = _client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            var           parameters    = Samples.GetDefaultConvertDataParameter().ToPoco <Parameters>();
            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.ConvertDataAsync(parameters));

            Assert.Equal(ForbiddenMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Forbidden, fhirException.StatusCode);
        }
Example #6
0
        public async Task GivenListOfResources_WhenSearchedWithInvalidTotalType_ThenExceptionShouldBeThrown(string key, string val)
        {
            Patient[] patients = await Client.CreateResourcesAsync <Patient>(3);

            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => Client.SearchAsync($"Patient?{key}={val}"));

            var expectedStatusCode = HttpStatusCode.BadRequest;

            Assert.Equal(expectedStatusCode, ex.StatusCode);

            var supportedTotalTypes  = new string($"'{TotalType.Accurate}', '{TotalType.None}'").ToLower(CultureInfo.CurrentCulture);
            var expectedErrorMessage = $"{expectedStatusCode}: " + string.Format(Core.Resources.InvalidTotalParameter, val, supportedTotalTypes);

            Assert.Equal(expectedErrorMessage, ex.Message);
        }
Example #7
0
        public async Task GivenAnIncorrectETagHeader_WhenUpdatingAResource_TheServerShouldReturnAnError()
        {
            Observation createdResource = await _client.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            // Specify a version that is one off from the version of the existing resource
            var incorrectVersionId = int.Parse(createdResource.Meta.VersionId) + 1;
            var weakETag           = $"W/\"{incorrectVersionId.ToString()}\"";

            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.UpdateAsync(createdResource, weakETag));

#if Stu3
            Assert.Equal(HttpStatusCode.Conflict, ex.StatusCode);
#else
            Assert.Equal(HttpStatusCode.PreconditionFailed, ex.StatusCode);
#endif
        }
Example #8
0
        public async Task GivenImportOperationEnabled_WhenImportInvalidResourceUrl_ThenBadRequestShouldBeReturned()
        {
            _metricHandler?.ResetCount();
            var request = new ImportRequest()
            {
                InputFormat   = "application/fhir+ndjson",
                InputSource   = new Uri("https://other-server.example.org"),
                StorageDetail = new ImportRequestStorageDetail()
                {
                    Type = "azure-blob"
                },
                Input = new List <InputResource>()
                {
                    new InputResource()
                    {
                        Url  = new Uri("https://fhirtest-invalid.com"),
                        Type = "Patient",
                    },
                },
            };

            Uri checkLocation = await ImportTestHelper.CreateImportTaskAsync(_client, request);

            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(
                async() =>
            {
                HttpResponseMessage response;
                while ((response = await _client.CheckImportAsync(checkLocation, CancellationToken.None)).StatusCode == System.Net.HttpStatusCode.Accepted)
                {
                    await Task.Delay(TimeSpan.FromSeconds(5));
                }
            });

            Assert.Equal(HttpStatusCode.BadRequest, fhirException.StatusCode);

            // Only check metric for local tests
            if (_fixture.IsUsingInProcTestServer)
            {
                var notificationList = _metricHandler.NotificationMapping[typeof(ImportTaskMetricsNotification)];
                Assert.Single(notificationList);
                var notification = notificationList.First() as ImportTaskMetricsNotification;
                Assert.Equal(TaskResult.Fail.ToString(), notification.Status);
                Assert.Null(notification.DataSize);
                Assert.Null(notification.SucceedCount);
                Assert.Null(notification.FailedCount);
            }
        }
Example #9
0
        private async Task GivenExecuteAndValidateNotFoundStatus(Func <Task> action)
        {
            FhirException exception = null;

            do
            {
                if (exception?.StatusCode == (HttpStatusCode)429)
                {
                    // Wait for a little bit before retrying if we are geting throttled.
                    await Task.Delay(500);
                }

                exception = await Assert.ThrowsAsync <FhirException>(action);
            }while (exception.StatusCode == (HttpStatusCode)429);

            Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);

            exception.Dispose();
        }
Example #10
0
        public async Task GivenListOfResources_WhenSearchedWithTotalTypeEstimate_ThenExceptionShouldBeThrown()
        {
            const int numberOfResources = 5;

            var tag = new Coding(string.Empty, Guid.NewGuid().ToString());

            Patient patient = Samples.GetDefaultPatient().ToPoco <Patient>();

            for (int i = 0; i < numberOfResources; i++)
            {
                patient.Meta = new Meta();
                patient.Meta.Tag.Add(tag);

                await Client.CreateAsync(patient);
            }

            FhirException ex = await Assert.ThrowsAsync <FhirException>(() => Client.SearchAsync($"Patient?_total=estimate"));

            Assert.Equal(HttpStatusCode.Forbidden, ex.StatusCode);
        }
Example #11
0
        public async Task GivenImportOperationEnabled_WhenImportOperationTriggeredBeforePreviousTaskCompleted_ThenConflictShouldBeReturned()
        {
            string patientNdJsonResource = Samples.GetNdJson("Import-Patient");

            patientNdJsonResource       = Regex.Replace(patientNdJsonResource, "##PatientID##", m => Guid.NewGuid().ToString("N"));
            (Uri location, string etag) = await ImportTestHelper.UploadFileAsync(patientNdJsonResource, _fixture.CloudStorageAccount);

            var request = new ImportRequest()
            {
                InputFormat   = "application/fhir+ndjson",
                InputSource   = new Uri("https://other-server.example.org"),
                StorageDetail = new ImportRequestStorageDetail()
                {
                    Type = "azure-blob"
                },
                Input = new List <InputResource>()
                {
                    new InputResource()
                    {
                        Url  = location,
                        Etag = etag,
                        Type = "Patient",
                    },
                },
            };

            request.Mode  = ImportConstants.InitialLoadMode;
            request.Force = true;
            Uri checkLocation = await ImportTestHelper.CreateImportTaskAsync(_client, request);

            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await _client.ImportAsync(request.ToParameters(), CancellationToken.None));

            Assert.Equal(HttpStatusCode.Conflict, fhirException.StatusCode);

            HttpResponseMessage response;

            while ((response = await _client.CheckImportAsync(checkLocation, CancellationToken.None)).StatusCode == System.Net.HttpStatusCode.Accepted)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
            }
        }
        private Task R4FhirExceptionProcessing(HttpContext context, FhirException FhirException, FhirFormatType AcceptFormatType)
        {
            R4Model.OperationOutcome?R4OperationOutcomeResult;
            if (FhirException is FhirFatalException FatalExec)
            {
                R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetFatal(FatalExec.MessageList);
            }
            else if (FhirException is FhirErrorException ErrorExec)
            {
                R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetError(ErrorExec.MessageList);
            }
            else if (FhirException is FhirWarnException WarnExec)
            {
                R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetWarning(WarnExec.MessageList);
            }
            else if (FhirException is FhirInfoException InfoExec)
            {
                R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetInformation(InfoExec.MessageList);
            }
            else
            {
                R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetFatal(new string[] { $"Unexpected FhirException type encountered of : {FhirException.GetType().FullName}" });
            }

            context.Response.StatusCode  = (int)FhirException.HttpStatusCode;
            context.Response.ContentType = Bug.Api.ContentFormatters.FhirMediaType.GetMediaTypeHeaderValue(R4OperationOutcomeResult.GetType(), AcceptFormatType).Value;
            if (AcceptFormatType == FhirFormatType.xml)
            {
                return(context.Response.WriteAsync(IR4SerializationToXml.SerializeToXml(R4OperationOutcomeResult)));
            }
            else if (AcceptFormatType == FhirFormatType.json)
            {
                return(context.Response.WriteAsync(IR4SerializationToJson.SerializeToJson(R4OperationOutcomeResult)));
            }
            else
            {
                string msg = $"Unexpected FhirFormatType type encountered of : {AcceptFormatType.GetType().FullName}";
                _logger.LogError(msg);
                throw new ApplicationException(msg);
            }
        }
Example #13
0
        public async Task GivenAUserWithHardDeletePermissions_WhenHardDeletingAResource_TheServerShouldReturnSuccess()
        {
            TestFhirClient tempClient      = _client.CreateClientForUser(TestUsers.ReadWriteUser, TestApplications.NativeClient);
            Observation    createdResource = await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            tempClient = _client.CreateClientForUser(TestUsers.AdminUser, TestApplications.NativeClient);

            // Hard-delete the resource.
            await tempClient.HardDeleteAsync(createdResource);

            tempClient = _client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            // Getting the resource should result in NotFound.
            await ExecuteAndValidateNotFoundStatus(() => tempClient.ReadAsync <Observation>(ResourceType.Observation, createdResource.Id));

            async Task <FhirException> ExecuteAndValidateNotFoundStatus(Func <Task> action)
            {
                using FhirException exception = await Assert.ThrowsAsync <FhirException>(action);

                Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);
                return(exception);
            }
        }
Example #14
0
        public async Task GivenAResourceThatWasRenamed_WhenSearched_ThenExceptionShouldBeThrown()
        {
            FhirException exception = await Assert.ThrowsAsync <FhirException>(() => _client.SearchAsync("Sequence"));

            Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);
        }
Example #15
0
        public async Task GivenAnUnsupportedResourceType_WhenPostingToHttp_TheServerShouldRespondWithANotFoundResponse()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.CreateAsync("NotObservation", Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(HttpStatusCode.NotFound, ex.StatusCode);
        }
Example #16
0
        public async Task GivenBundleTypeIsMissing_WhenSubmittingABundle_ThenMethodNotAllowedExceptionIsReturned()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.PostBundleAsync(Samples.GetJsonSample("Bundle-TypeMissing").ToPoco <Bundle>()));

            ValidateOperationOutcome(ex.StatusCode.ToString(), ex.OperationOutcome, "MethodNotAllowed", "Bundle type is not present. Possible values are: transaction or batch", IssueType.Forbidden);
        }
Example #17
0
        public async Task GivenANonBundleResource_WhenSubmittingABatch_ThenBadRequestIsReturned()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.PostBundleAsync(Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(HttpStatusCode.BadRequest, ex.StatusCode);
        }
Example #18
0
        public async Task GivenInvalidPrettyParameter_WhenGettingMetadata_TheServerShouldReturnBadRequest(string value)
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(async () => await _client.ReadAsync <CapabilityStatement>($"metadata?_pretty={value}"));

            Assert.Equal(HttpStatusCode.BadRequest, ex.StatusCode);
        }
Example #19
0
        public async Task GivenInvalidFormatParameter_WhenGettingMetadata_TheServerShouldReturnNotAcceptable()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(async () => await _client.ReadAsync <CapabilityStatement>("metadata?_format=blah"));

            Assert.Equal(HttpStatusCode.NotAcceptable, ex.StatusCode);
        }
Example #20
0
        public async Task GivenAProperBundle_WhenSubmittingATransactionForCosmosDbDataStore_ThenNotSupportedIsReturned()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.PostBundleAsync(Samples.GetDefaultTransaction().ToPoco <Bundle>()));

            Assert.Equal(HttpStatusCode.MethodNotAllowed, ex.StatusCode);
        }
Example #21
0
        public async Task GivenAServerThatDoesNotSupportIt_WhenSubmittingAPatch_ThenMethodNotAllowedIsReturned()
        {
            using FhirException ex = await Assert.ThrowsAsync <FhirException>(() => _client.PatchAsync("Patient/1234", "patch content"));

            Assert.Equal(HttpStatusCode.MethodNotAllowed, ex.StatusCode);
        }
Example #22
0
        public async Task WhenSubmittingABatch_GivenAProperBundle_ThenNotSupportedIsReturned()
        {
            FhirException ex = await Assert.ThrowsAsync <FhirException>(() => Client.PostBundleAsync(Samples.GetDefaultBatch().ToPoco <Bundle>()));

            Assert.Equal(HttpStatusCode.MethodNotAllowed, ex.StatusCode);
        }