using Elsa.Extensions; using Elsa.Http.Bookmarks; using Elsa.Mediator.Contracts; using Elsa.Workflows.Helpers; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Requests; using Elsa.Workflows.Management.Responses; using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; namespace Elsa.Http.Handlers; /// /// A handler that validates a workflow path and return any errors. /// [UsedImplicitly] public class ValidateWorkflowRequestHandler : IRequestHandler { private readonly ITriggerStore _triggerStore; private readonly ITriggerIndexer _triggerIndexer; /// /// Constructor. /// public ValidateWorkflowRequestHandler(ITriggerStore triggerStore, ITriggerIndexer triggerIndexer) { _triggerStore = triggerStore; _triggerIndexer = triggerIndexer; } /// public async Task HandleAsync(ValidateWorkflowRequest request, CancellationToken cancellationToken) { var workflow = request.Workflow; var httpEndpointTriggers = (await _triggerIndexer.GetTriggersAsync(workflow, cancellationToken)).Where(x => x.Payload is HttpEndpointBookmarkPayload).ToList(); var publishedWorkflowsTriggers = (await _triggerStore.FindManyAsync(new TriggerFilter { Name = ActivityTypeNameHelper.GenerateTypeName(typeof(HttpEndpoint)) }, cancellationToken)).ToList(); var validationErrors = new List(); foreach (var httpEndpointTrigger in httpEndpointTriggers) { var triggerPayload = httpEndpointTrigger.GetPayload(); var otherWorkflowsWithSamePath = publishedWorkflowsTriggers .Where(x => x.WorkflowDefinitionId != workflow.Identity.DefinitionId && x.Payload is HttpEndpointBookmarkPayload payload && payload.Path == triggerPayload.Path && payload.Method == triggerPayload.Method) .ToList(); if (!otherWorkflowsWithSamePath.Any()) continue; var message = $"The {triggerPayload.Path} path and {triggerPayload.Method} method are already in use by another workflow!"; validationErrors.Add(new WorkflowValidationError(message, httpEndpointTrigger.ActivityId)); } return new ValidateWorkflowResponse(validationErrors); } }