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);
}
}