< Summary

Information
Class: Program
Assembly: Elsa.Server.Web
File(s): /home/runner/work/elsa-core/elsa-core/src/apps/Elsa.Server.Web/Program.cs
Line coverage
100%
Covered lines: 128
Uncovered lines: 0
Coverable lines: 128
Total lines: 218
Line coverage: 100%
Branch coverage
96%
Covered branches: 27
Total branches: 28
Branch coverage: 96.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
<Main>$()96.42%2828100%
get_ConfigureForTest()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/apps/Elsa.Server.Web/Program.cs

#LineLine coverage
 1using System.Text.Encodings.Web;
 2using Elsa.Caching.Options;
 3using Elsa.Common.RecurringTasks;
 4using Elsa.Expressions.Helpers;
 5using Elsa.Extensions;
 6using Elsa.Features.Services;
 7using Elsa.Identity.Multitenancy;
 8using Elsa.Persistence.EFCore.Extensions;
 9using Elsa.Persistence.EFCore.Modules.Management;
 10using Elsa.Persistence.EFCore.Modules.Runtime;
 11using Elsa.Server.Web.Activities;
 12using Elsa.Server.Web.ActivityHosts;
 13using Elsa.Server.Web.Filters;
 14using Elsa.Tenants;
 15using Elsa.Tenants.AspNetCore;
 16using Elsa.Tenants.Extensions;
 17using Elsa.WorkflowProviders.BlobStorage.ElsaScript.Extensions;
 18using Elsa.Workflows;
 19using Elsa.Workflows.Activities.Flowchart.Extensions;
 20using Elsa.Workflows.Api;
 21using Elsa.Workflows.CommitStates.Strategies;
 22using Elsa.Workflows.IncidentStrategies;
 23using Elsa.Workflows.LogPersistence;
 24using Elsa.Workflows.Options;
 25using Elsa.Workflows.Runtime.Distributed.Extensions;
 26using Elsa.Workflows.Runtime.Options;
 27using Elsa.Workflows.Runtime.Tasks;
 28using JetBrains.Annotations;
 29using Microsoft.Extensions.Options;
 30
 31// ReSharper disable RedundantAssignment
 32const bool useReadOnlyMode = false;
 33const bool useSignalR = false; // Disabled until Elsa Studio sends authenticated requests.
 34const bool useMultitenancy = true;
 35const bool disableVariableWrappers = false;
 36
 737ObjectConverter.StrictMode = true;
 38
 739var builder = WebApplication.CreateBuilder(args);
 740var services = builder.Services;
 741var configuration = builder.Configuration;
 742var identitySection = configuration.GetSection("Identity");
 743var identityTokenSection = identitySection.GetSection("Tokens");
 44
 45// Add Elsa services.
 746services
 747    .AddElsa(elsa =>
 748    {
 749        elsa
 750            .AddActivitiesFrom<Program>()
 751            .AddActivityHost<Penguin>()
 752            .AddWorkflowsFrom<Program>()
 753            .UseIdentity(identity =>
 754            {
 755                identity.TokenOptions += options => identityTokenSection.Bind(options);
 756                identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options));
 757                identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options));
 758                identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
 759            })
 760            .UseDefaultAuthentication()
 761            .UseWorkflows(workflows =>
 762            {
 763                workflows.UseCommitStrategies(strategies =>
 764                {
 765                    strategies.AddStandardStrategies();
 766                    strategies.Add("Every 10 seconds", new PeriodicWorkflowStrategy(TimeSpan.FromSeconds(10)));
 1467                });
 768            })
 769            .UseFlowchart(flowchart => flowchart.UseTokenBasedExecution())
 770            .UseWorkflowManagement(management =>
 771            {
 1472                management.UseEntityFrameworkCore(ef => ef.UseSqlite());
 773                management.SetDefaultLogPersistenceMode(LogPersistenceMode.Inherit);
 774                management.UseCache();
 775                management.UseReadOnlyMode(useReadOnlyMode);
 776            })
 777            .UseWorkflowRuntime(runtime =>
 778            {
 1479                runtime.UseEntityFrameworkCore(ef => ef.UseSqlite());
 780                runtime.UseCache();
 781                runtime.UseDistributedRuntime();
 782            })
 783            .UseWorkflowsApi()
 784            .UseFluentStorageProvider()
 785            .UseElsaScriptBlobStorage()
 786            .UseScheduling()
 787            .UseCSharp(options =>
 788            {
 789                options.DisableWrappers = disableVariableWrappers;
 790                options.AppendScript("string Greet(string name) => $\"Hello {name}!\";");
 791                options.AppendScript("string SayHelloWorld() => Greet(\"World\");");
 792            })
 793            .UseJavaScript(options =>
 794            {
 795                options.AllowClrAccess = true;
 796                options.ConfigureEngine(engine =>
 797                {
 2398                    engine.Execute("function greet(name) { return `Hello ${name}!`; }");
 2399                    engine.Execute("function sayHelloWorld() { return greet('World'); }");
 30100                });
 7101            })
 7102            .UsePython(python =>
 7103            {
 7104                python.PythonOptions += options =>
 7105                {
 7106                    // Make sure to configure the path to the python DLL. E.g. /opt/homebrew/Cellar/python@3.11/3.11.6_1
 7107                    // alternatively, you can set the PYTHONNET_PYDLL environment variable.
 7108                    configuration.GetSection("Scripting:Python").Bind(options);
 7109
 7110                    options.AddScript(sb =>
 7111                    {
 7112                        sb.AppendLine("def greet():");
 7113                        sb.AppendLine("    return \"Hello, welcome to Python!\"");
 14114                    });
 14115                };
 7116            })
 14117            .UseLiquid(liquid => liquid.FluidOptions = options => options.Encoder = HtmlEncoder.Default)
 7118            .UseHttp(http =>
 7119            {
 14120                http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options);
 7121                http.UseCache();
 14122            });
 7123
 7124        if(useMultitenancy)
 7125        {
 7126            elsa.UseTenants(tenants =>
 7127            {
 7128                tenants.UseConfigurationBasedTenantsProvider(options => configuration.GetSection("Multitenancy").Bind(op
 8129                tenants.ConfigureMultitenancy(options => options.TenantResolverPipelineBuilder = new TenantResolverPipel
 8130                    .Append<CurrentUserTenantResolver>());
 14131            });
 7132        }
 7133
 7134        ConfigureForTest?.Invoke(elsa);
 14135    });
 136
 137// Obfuscate HTTP request headers.
 7138services.AddActivityStateFilter<HttpRequestAuthenticationHeaderFilter>();
 139
 140// Optionally configure recurring tasks using alternative schedules.
 7141services.Configure<RecurringTaskOptions>(options =>
 7142{
 7143    options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(300));
 7144    options.Schedule.ConfigureTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(300));
 7145    options.Schedule.ConfigureTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromSeconds(15));
 14146});
 147
 21148services.Configure<RuntimeOptions>(options => { options.InactivityThreshold = TimeSpan.FromSeconds(15); });
 14149services.Configure<BookmarkQueuePurgeOptions>(options => options.Ttl = TimeSpan.FromSeconds(3600));
 14150services.Configure<CachingOptions>(options => options.CacheDuration = TimeSpan.FromDays(1));
 8151services.Configure<IncidentOptions>(options => options.DefaultIncidentStrategy = typeof(ContinueWithIncidentsStrategy));
 7152services.AddHealthChecks();
 7153services.AddControllers();
 21154services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().WithE
 155
 156// Build the web application.
 7157var app = builder.Build();
 158
 159
 160// Configure the pipeline.
 7161if (app.Environment.IsDevelopment())
 7162    app.UseDeveloperExceptionPage();
 163
 164// CORS.
 7165app.UseCors();
 166
 167// Health checks.
 7168app.MapHealthChecks("/");
 169
 170// Routing used for SignalR.
 7171app.UseRouting();
 172
 173// Security.
 7174app.UseAuthentication();
 7175app.UseAuthorization();
 176
 177// Multitenancy.
 178if (useMultitenancy)
 7179    app.UseTenants();
 180
 181// Elsa API endpoints for designer.
 7182var routePrefix = app.Services.GetRequiredService<IOptions<ApiEndpointOptions>>().Value.RoutePrefix;
 7183app.UseWorkflowsApi(routePrefix);
 184
 185// Captures unhandled exceptions and returns a JSON response.
 7186app.UseJsonSerializationErrorHandler();
 187
 188// Elsa HTTP Endpoint activities.
 7189app.UseWorkflows();
 190
 7191app.MapControllers();
 192
 193// Swagger API documentation.
 7194if (app.Environment.IsDevelopment())
 195{
 7196    app.UseSwaggerUI();
 197}
 198
 199// SignalR.
 200if (useSignalR)
 201{
 202    app.UseWorkflowsSignalRHubs();
 203}
 204
 205// Run.
 7206await app.RunAsync();
 207
 208/// <summary>
 209/// The main entry point for the application made public for end to end testing.
 210/// </summary>
 211[UsedImplicitly]
 212public partial class Program
 213{
 214    /// <summary>
 215    /// Set by the test runner to configure the module for testing.
 216    /// </summary>
 15217    public static Action<IModule>? ConfigureForTest { get; set; }
 218}

Methods/Properties

<Main>$()
get_ConfigureForTest()