예제 #1
0
 private async Task <Core.Models.Execution> ToExecutionAsync(ExecutionRequestContext <ExecutionRequestApiModel> erContext) =>
 new Core.Models.Execution
 {
     CreatedDateTimeUtc     = DateTime.UtcNow,
     ExecutionId            = erContext.ExtensionVersion.CreateNewExecutionId(userContext.Executor.TenantId),
     ExecutionModelName     = erContext.ExecutionProfile.ExecutionModelName,
     ExecutionProfileName   = erContext.ExecutionProfile.ProfileName,
     Executor               = userContext.Executor,
     ExtensionId            = erContext.Extension.ExtensionId,
     ExtensionVersionId     = erContext.ExtensionVersion.ExtensionVersionId,
     LastUpdatedDateTimeUtc = DateTime.UtcNow,
     ObjectProviderName     = erContext.ExecutionProfile.ObjectProviderName,
     Priority               = Enum.Parse <ExecutionPriority>(erContext.OriginalRequest.Priority),
     StatusUpdateKey        = Guid.NewGuid().ToString(),
     ValidateOnly           = erContext.OriginalRequest.ValidateOnly,
     InputObjects           = erContext.ExtensionVersion.InputObjects,
     OutputObjects          = erContext.ExtensionVersion.OutputObjects,
     RequestData            = erContext.OriginalRequest.RequestData,
     Mode = erContext.ExecutionProfile.ExecutionMode,
     SignatureRsaKeyXml = await extensionRsaKeyProvider.GetExtensionRsaKeyXmlAsync(erContext.Extension),
     ExecutorProperties = erContext.OriginalRequest.ExecutorProperties
 };
        public async Task <ExecutionRequestContext <ExecutionRequestApiModel> > BuildExecutionRequestContextAsync(ExecutionRequestApiModel apiExecRequest)
        {
            // Create a new execution request context...

            var erContext = new ExecutionRequestContext <ExecutionRequestApiModel>(apiExecRequest);

            // Did they provide an extension ID?

            if (string.IsNullOrEmpty(apiExecRequest.ExtensionId))
            {
                erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionIdNotProvided}]: [extensionId] is required.");
            }

            // Did they provide an extension version ID?

            if (string.IsNullOrEmpty(apiExecRequest.ExtensionVersionId))
            {
                erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionVersionIdNotProvided}]: [extensionVersionId] is required.");
            }

            // Is the execution priority that they provided valid?

            if (Enum.TryParse <ExecutionPriority>(apiExecRequest.Priority, out var execPriority) == false)
            {
                erContext.ValidationErrors.Add($"[{ErrorCodes.InvalidPriority}]: [{apiExecRequest.Priority}] is not a valid [priority]; " +
                                               $"valid priorities are [{ExecutionPriority.Low}], [{ExecutionPriority.Normal}], " +
                                               $"and [{ExecutionPriority.High}]; if no [priority] is explicitly provided, " +
                                               $"[{ExecutionPriority.Normal}] is automatically selected.");
            }

            if (string.IsNullOrEmpty(apiExecRequest.ExtensionId) == false)
            {
                // Get the extension information...

                erContext.Extension = await extensionRepository.GetExtensionAsync(apiExecRequest.ExtensionId);

                // Were we able to find the extension and is it active?

                if (erContext.Extension == null)
                {
                    erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionNotFound}]: Extension [{apiExecRequest.ExtensionId}] not found.");
                }
                else if (erContext.Extension.IsActive == false)
                {
                    erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionDisabled}]: Extension [{apiExecRequest.ExtensionId}] is currently unavailable.");
                }
                else if (string.IsNullOrEmpty(apiExecRequest.ExtensionVersionId) == false)
                {
                    // Get the extension version information...

                    erContext.ExtensionVersion = erContext.Extension.GetExtensionVersion(apiExecRequest.ExtensionVersionId);

                    // Were we able to find the extension version and is it active?

                    if (erContext.ExtensionVersion == null)
                    {
                        erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionVersionNotFound}]: Extension [{apiExecRequest.ExtensionId}] version " +
                                                       $"[{apiExecRequest.ExtensionVersionId}] not found.");
                    }
                    else if (erContext.ExtensionVersion.IsActive == false)
                    {
                        erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionVersionDisabled}]: Extension [{apiExecRequest.ExtensionId}] version " +
                                                       $"[{apiExecRequest.ExtensionVersionId}] is currently unavailable.");
                    }
                    else
                    {
                        // If the user has only requested validation (not execution), does the extension version support validation?

                        if (apiExecRequest.ValidateOnly && erContext.ExtensionVersion.SupportsValidation == false)
                        {
                            erContext.ValidationErrors.Add($"[{ErrorCodes.ExtensionVersionDoesNotSupportValidation}]: " +
                                                           $"Extension [{apiExecRequest.ExtensionId}] version " +
                                                           $"[{apiExecRequest.ExtensionVersionId}] does not support validation.");
                        }

                        // Get the execution profile information...

                        erContext.ExecutionProfile = erContext.ExtensionVersion.GetExecutionProfile(apiExecRequest.ProfileName);

                        // Were we able to find the execution profile information?

                        if (erContext.ExecutionProfile == null)
                        {
                            erContext.ValidationErrors.Add($"[{ErrorCodes.ExecutionProfileNotFound}]: " +
                                                           $"Execution profile [{apiExecRequest.ProfileName}] not found.");
                        }
                        else
                        {
                            // And, finally, is the specified priority supported by the execution profile?

                            if (erContext.ExecutionProfile.SupportedPriorities.HasFlag(execPriority) == false)
                            {
                                erContext.ValidationErrors.Add($"[{ErrorCodes.PriorityNotSupported}]: " +
                                                               $"Execution profile [{apiExecRequest.ProfileName}] does not support " +
                                                               $"[{execPriority}]-priority execution.");
                            }
                        }
                    }
                }
            }

            return(erContext);
        }
예제 #3
0
        public async Task <IActionResult> ContinueExecutionAsync([Required] string executionId,
                                                                 [Required, FromBody] ContinueExecutionApiModel continueApiModel)
        {
            // Build the execution request context so we can pick up where we left off...

            var erContext = new ExecutionRequestContext <ContinueExecutionApiModel>(continueApiModel)
            {
                Execution = await execRepository.GetExecutionAsync(executionId, userContext.Executor.TenantId)
            };

            // If we can't find the original execution, respond with [404 Not Found]...

            if (erContext.Execution == null)
            {
                return(NotFound($"[{ErrorCodes.ExecutionNotFound}]: Execution [{executionId}] not found."));
            }

            // If we found the execution but we're not expecting any input objects, respond with [400 Bad Request]...

            if (erContext.Execution.Status != ExecutionStatus.PendingInputObjects)
            {
                return(BadRequest($"[{ErrorCodes.UnableToContinue}]: Unable to continue; " +
                                  $"execution [{executionId}] is already [{erContext.Execution.Status}]."));
            }

            // Augment the execution request context with extension, extension version, and execution profile.
            // We're going to need all of this information to build and dispatch the core execution request...

            erContext.Extension = await extensionRepository.GetExtensionAsync(erContext.Execution.ExtensionId);

            erContext.ExtensionVersion = erContext.Extension.GetExtensionVersion(erContext.Execution.ExtensionVersionId);
            erContext.ExecutionProfile = erContext.ExtensionVersion.GetExecutionProfile(erContext.Execution.ExecutionProfileName);

            // Make sure that we have the right input objects and only the right input objects...

            erContext.Execution.ProvidedInputObjects.AddRange(erContext.OriginalRequest.ProvidedInputObjects.Where(pio =>
                                                                                                                   erContext.ExtensionVersion.InputObjects.Any(io => io.Name == pio) &&
                                                                                                                   erContext.Execution.ProvidedInputObjects.Contains(pio) == false));

            var unknownObjects = erContext.OriginalRequest.ProvidedInputObjects
                                 .Where(pio => erContext.Execution.InputObjects.Select(io => io.Name).Contains(pio) == false)
                                 .ToArray();

            var neededObjects = erContext.Execution.InputObjects
                                .Where(io => io.IsRequired && (erContext.OriginalRequest.ProvidedInputObjects.Contains(io.Name) == false))
                                .Select(io => io.Name)
                                .ToArray();

            // If we don't, respond with [400 Bad Request] + detailed error description...

            if (unknownObjects.Any() || neededObjects.Any())
            {
                var errorMessages = new List <string>();

                if (unknownObjects.Any())
                {
                    errorMessages.Add($"[{ErrorCodes.UnknownInputObjects}]: " +
                                      $"The following provided input objects are unknown: [{unknownObjects.ToCommaSeparatedString()}].");
                }

                if (neededObjects.Any())
                {
                    errorMessages.Add($"[{ErrorCodes.MissingInputObjects}]: " +
                                      $"The following input objects are missing: [{neededObjects.ToCommaSeparatedString()}].");
                }

                return(BadRequest(await CreateToContinueApiModelAsync(erContext, errorMessages.ToSpaceSeparatedString())));
            }
            else
            {
                // Otherwise, dispatch the execution request to the execution pipeline and respond back to the client appropriately.
                // For more information on the execution pipeline, see /doc/architecture/execution-pipeline.md.

                return(await ToExecutionRequestRoutedResultAsync(await ExecuteAsync(erContext)));
            }
        }