public async Task GivenANewExportRequest_WhenCreatingExportJob_ThenGetsJobCreated()
        {
            var jobRecord = new ExportJobRecord(_exportRequest.RequestUri, _exportRequest.RequestType, ExportFormatTags.ResourceName, _exportRequest.ResourceType, null, "hash", rollingFileSizeInMB: 64);

            ExportJobOutcome outcome = await _operationDataStore.CreateExportJobAsync(jobRecord, CancellationToken.None);

            Assert.NotNull(outcome);
            Assert.NotNull(outcome.JobRecord);
            Assert.NotEmpty(outcome.JobRecord.Id);
            Assert.NotNull(outcome.ETag);
        }
Example #2
0
        public async Task GivenANewExportRequest_WhenCreatingExportJob_ThenGetsJobCreated()
        {
            var jobRecord = new ExportJobRecord(new Uri("http://localhost/ExportJob"), "hash");

            ExportJobOutcome outcome = await _operationDataStore.CreateExportJobAsync(jobRecord, CancellationToken.None);

            Assert.NotNull(outcome);
            Assert.NotNull(outcome.JobRecord);
            Assert.NotEmpty(outcome.JobRecord.Id);
            Assert.NotNull(outcome.ETag);
        }
Example #3
0
        public async Task <CreateExportResponse> Handle(CreateExportRequest request, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(request, nameof(request));

            if (await _authorizationService.CheckAccess(DataActions.Export) != DataActions.Export)
            {
                throw new UnauthorizedFhirActionException();
            }

            IReadOnlyCollection <KeyValuePair <string, string> > requestorClaims = _claimsExtractor.Extract()?
                                                                                   .OrderBy(claim => claim.Key, StringComparer.Ordinal).ToList();

            // Compute the hash of the job.
            var hashObject = new
            {
                request.RequestUri,
                RequestorClaims = requestorClaims,
            };

            string hash = JsonConvert.SerializeObject(hashObject).ComputeHash();

            // Check to see if a matching job exists or not. If a matching job exists, we will return that instead.
            // Otherwise, we will create a new export job. This will be a best effort since the likelihood of this happen should be small.
            ExportJobOutcome outcome = await _fhirOperationDataStore.GetExportJobByHashAsync(hash, cancellationToken);

            if (outcome == null)
            {
                var jobRecord = new ExportJobRecord(request.RequestUri, request.ResourceType, hash, requestorClaims, request.Since);

                outcome = await _fhirOperationDataStore.CreateExportJobAsync(jobRecord, cancellationToken);
            }

            return(new CreateExportResponse(outcome.JobRecord.Id));
        }
Example #4
0
        public async Task <CreateExportResponse> Handle(CreateExportRequest request, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(request, nameof(request));

            if (await _authorizationService.CheckAccess(DataActions.Export, cancellationToken) != DataActions.Export)
            {
                throw new UnauthorizedFhirActionException();
            }

            IReadOnlyCollection <KeyValuePair <string, string> > requestorClaims = _claimsExtractor.Extract()?
                                                                                   .OrderBy(claim => claim.Key, StringComparer.Ordinal).ToList();

            // Compute the hash of the job.
            var hashObject = new
            {
                request.RequestUri,
                RequestorClaims = requestorClaims,
            };

            string hash = JsonConvert.SerializeObject(hashObject).ComputeHash();

            string storageAccountConnectionHash = string.IsNullOrEmpty(_exportJobConfiguration.StorageAccountConnection) ?
                                                  string.Empty :
                                                  StringExtensions.ComputeHash(_exportJobConfiguration.StorageAccountConnection);

            // Check to see if a matching job exists or not. If a matching job exists, we will return that instead.
            // Otherwise, we will create a new export job. This will be a best effort since the likelihood of this happen should be small.
            ExportJobOutcome outcome = await _fhirOperationDataStore.GetExportJobByHashAsync(hash, cancellationToken);

            var filters = ParseFilter(request.Filters);

            ExportJobFormatConfiguration formatConfiguration = ParseFormat(request.FormatName, request.ContainerName != null);

            if (outcome == null)
            {
                var jobRecord = new ExportJobRecord(
                    request.RequestUri,
                    request.RequestType,
                    formatConfiguration.Format,
                    request.ResourceType,
                    filters,
                    hash,
                    _exportJobConfiguration.RollingFileSizeInMB,
                    requestorClaims,
                    request.Since,
                    request.GroupId,
                    storageAccountConnectionHash,
                    _exportJobConfiguration.StorageAccountUri,
                    request.AnonymizationConfigurationLocation,
                    request.AnonymizationConfigurationFileETag,
                    _exportJobConfiguration.MaximumNumberOfResourcesPerQuery,
                    _exportJobConfiguration.NumberOfPagesPerCommit,
                    request.ContainerName);

                outcome = await _fhirOperationDataStore.CreateExportJobAsync(jobRecord, cancellationToken);
            }

            return(new CreateExportResponse(outcome.JobRecord.Id));
        }
        public async Task <CreateExportResponse> Handle(CreateExportRequest request, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(request, nameof(request));

            IReadOnlyCollection <KeyValuePair <string, string> > requestorClaims = _claimsExtractor.Extract()?
                                                                                   .OrderBy(claim => claim.Key, StringComparer.Ordinal).ToList();

            // Compute the hash of the job.
            var hashObject = new
            {
                request.RequestUri,
                RequestorClaims = requestorClaims,
                request.DestinationInfo,
            };

            string hash = JsonConvert.SerializeObject(hashObject).ComputeHash();

            // Check to see if a matching job exists or not. If a matching job exists, we will return that instead.
            // Otherwise, we will create a new export job. This will be a best effort since the likelihood of this happen should be small.
            ExportJobOutcome outcome = await _fhirOperationDataStore.GetExportJobByHashAsync(hash, cancellationToken);

            if (outcome == null)
            {
                // Remove the connection settings from the request URI before we store it in the secret store.
                NameValueCollection queryParameters = HttpUtility.ParseQueryString(request.RequestUri.Query);

                queryParameters.Remove(KnownQueryParameterNames.DestinationType);
                queryParameters.Remove(KnownQueryParameterNames.DestinationConnectionSettings);

                var uriBuilder = new UriBuilder(request.RequestUri);
                uriBuilder.Query = queryParameters.ToString();

                var jobRecord = new ExportJobRecord(uriBuilder.Uri, request.ResourceType, hash, requestorClaims);

                // Store the destination secret.
                try
                {
                    await _secretStore.SetSecretAsync(jobRecord.SecretName, request.DestinationInfo.ToJson(), cancellationToken);
                }
                catch (SecretStoreException sse)
                {
                    throw new OperationFailedException(string.Format(Resources.OperationFailed, OperationsConstants.Export, sse.Message), sse.ResponseStatusCode);
                }

                outcome = await _fhirOperationDataStore.CreateExportJobAsync(jobRecord, cancellationToken);
            }

            return(new CreateExportResponse(outcome.JobRecord.Id));
        }
Example #6
0
        private async Task <ExportJobOutcome> CreateAndExecuteCreateExportJobAsync()
        {
            var jobRecord = new ExportJobRecord(new Uri("https://localhost/ExportJob"), "hash");

            return(await _fhirOperationDataStore.CreateExportJobAsync(jobRecord, CancellationToken.None));
        }
Example #7
0
        public async Task <CreateExportResponse> Handle(CreateExportRequest request, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(request, nameof(request));

            if (await _authorizationService.CheckAccess(DataActions.Export) != DataActions.Export)
            {
                throw new UnauthorizedFhirActionException();
            }

            IReadOnlyCollection <KeyValuePair <string, string> > requestorClaims = _claimsExtractor.Extract()?
                                                                                   .OrderBy(claim => claim.Key, StringComparer.Ordinal).ToList();

            // Compute the hash of the job.
            var hashObject = new
            {
                request.RequestUri,
                RequestorClaims = requestorClaims,
            };

            string hash = JsonConvert.SerializeObject(hashObject).ComputeHash();

            string storageAccountConnectionHash = string.IsNullOrEmpty(_exportJobConfiguration.StorageAccountConnection) ?
                                                  string.Empty :
                                                  Microsoft.Health.Core.Extensions.StringExtensions.ComputeHash(_exportJobConfiguration.StorageAccountConnection);

            // Check to see if a matching job exists or not. If a matching job exists, we will return that instead.
            // Otherwise, we will create a new export job. This will be a best effort since the likelihood of this happen should be small.
            ExportJobOutcome outcome = await _fhirOperationDataStore.GetExportJobByHashAsync(hash, cancellationToken);

            ExportJobFormatConfiguration formatConfiguration = null;

            if (request.FormatName != null)
            {
                formatConfiguration = _exportJobConfiguration.Formats?.FirstOrDefault(
                    (ExportJobFormatConfiguration formatConfig) => formatConfig.Name.Equals(request.FormatName, StringComparison.OrdinalIgnoreCase));

                if (formatConfiguration == null)
                {
                    throw new BadRequestException(Resources.ExportFormatNotFound);
                }
            }

            formatConfiguration ??= _exportJobConfiguration.Formats?.FirstOrDefault(
                (ExportJobFormatConfiguration formatConfig) => formatConfig.Default);

            formatConfiguration ??= new ExportJobFormatConfiguration()
            {
                Format = request.ContainerName == null ? ExportFormatTags.ResourceName : $"{ExportFormatTags.Timestamp}-{ExportFormatTags.Id}/{ExportFormatTags.ResourceName}",
            };

            if (outcome == null)
            {
                var jobRecord = new ExportJobRecord(
                    request.RequestUri,
                    request.RequestType,
                    formatConfiguration.Format,
                    request.ResourceType,
                    hash,
                    requestorClaims,
                    request.Since,
                    request.GroupId,
                    storageAccountConnectionHash,
                    _exportJobConfiguration.StorageAccountUri,
                    request.AnonymizationConfigurationLocation,
                    request.AnonymizationConfigurationFileETag,
                    _exportJobConfiguration.MaximumNumberOfResourcesPerQuery,
                    _exportJobConfiguration.NumberOfPagesPerCommit,
                    request.ContainerName);

                outcome = await _fhirOperationDataStore.CreateExportJobAsync(jobRecord, cancellationToken);
            }

            return(new CreateExportResponse(outcome.JobRecord.Id));
        }