using System.Collections.Generic; using System.Dynamic; using System.Threading; using System.Threading.Tasks; using Elsa.Models; using Elsa.Scripting.Liquid.Helpers; using Elsa.Scripting.Liquid.Messages; using Elsa.Services.Models; using Fluid; using Fluid.Values; using MediatR; using Microsoft.Extensions.Configuration; using Newtonsoft.Json.Linq; namespace Elsa.Scripting.Liquid.Handlers { public class ConfigureLiquidEngine : INotificationHandler { private readonly IConfiguration _configuration; public ConfigureLiquidEngine(IConfiguration configuration) { _configuration = configuration; } public Task Handle(EvaluatingLiquidExpression notification, CancellationToken cancellationToken) { var context = notification.TemplateContext; var options = context.Options; options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register(o => o.Value); options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register((x, name) => x.GetValueAsync(name)); options.MemberAccessStrategy.Register("Input", x => ToFluidValue(x.Input, options)); options.MemberAccessStrategy.Register("WorkflowInstanceId", x => ToFluidValue(x.WorkflowInstance.Id, options)); options.MemberAccessStrategy.Register("CorrelationId", x => ToFluidValue(x.CorrelationId, options)); options.MemberAccessStrategy.Register("WorkflowDefinitionId", x => ToFluidValue(x.WorkflowInstance.DefinitionId, options)); options.MemberAccessStrategy.Register("WorkflowDefinitionVersion", x => ToFluidValue(x.WorkflowInstance.Version, options)); options.MemberAccessStrategy.Register("Variables", x => new LiquidPropertyAccessor(name => ToFluidValue(x.WorkflowExecutionContext.GetMergedVariables(), name, options))); options.MemberAccessStrategy.Register("Activities", x => new LiquidPropertyAccessor(name => ToFluidValue(GetActivityModelAsync(x, name), options)!)); options.MemberAccessStrategy.Register("Output", GetActivityOutput); options.MemberAccessStrategy.Register, object>((x, name) => x.GetValueAsync(name)); options.MemberAccessStrategy.Register((x, name) => ((IDictionary) x)[name]); options.MemberAccessStrategy.Register((source, name) => source[name]); options.MemberAccessStrategy.Register("Configuration", x => new LiquidPropertyAccessor(name => ToFluidValue(GetConfigurationValue(name), options)!)); options.MemberAccessStrategy.Register((source, name) => source.GetSection(name)); return Task.CompletedTask; } private ConfigurationSectionWrapper GetConfigurationValue(string name) => new(_configuration.GetSection(name)); private Task ToFluidValue(object? input, TemplateOptions options) => Task.FromResult(FluidValue.Create(input, options)); private Task ToFluidValue(Variables dictionary, string key, TemplateOptions options) => Task.FromResult(!dictionary.Has(key) ? default : FluidValue.Create(dictionary.Get(key), options)); private LiquidActivityModel GetActivityModelAsync(ActivityExecutionContext context, string name) => new(context, name); private Task GetActivityOutput(LiquidActivityModel activityModel) { var output = activityModel.ActivityExecutionContext.GetOutputFrom(activityModel.ActivityName); return Task.FromResult(output); } } }