diff --git a/Elsa.sln b/Elsa.sln index 427134c39..b7a440269 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -138,10 +138,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54 docker\Dockerfile = docker\Dockerfile EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{26A89A29-FE67-4174-9809-7C63AAD6BD5D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElsaWorkflowsApp", "templates\elsa-workflow-app\ElsaWorkflowsApp\ElsaWorkflowsApp.csproj", "{15B2ABCB-7460-4E59-A991-10AD9190B1C9}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.WorkflowSinks", "src\samples\aspnet\Elsa.Samples.WorkflowSinks\Elsa.Samples.WorkflowSinks.csproj", "{536EFB55-EEA1-4761-9A72-D4EA84A6DB70}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.EntityFrameworkCore.PostgreSql", "src\modules\Elsa.EntityFrameworkCore.PostgreSql\Elsa.EntityFrameworkCore.PostgreSql.csproj", "{AA84DBF7-F70F-4673-8DC2-6EFBE3E9BF83}" @@ -352,10 +348,6 @@ Global {34FBB2D3-4E2B-4411-95F2-C6B56899826A}.Debug|Any CPU.Build.0 = Debug|Any CPU {34FBB2D3-4E2B-4411-95F2-C6B56899826A}.Release|Any CPU.ActiveCfg = Release|Any CPU {34FBB2D3-4E2B-4411-95F2-C6B56899826A}.Release|Any CPU.Build.0 = Release|Any CPU - {15B2ABCB-7460-4E59-A991-10AD9190B1C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15B2ABCB-7460-4E59-A991-10AD9190B1C9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15B2ABCB-7460-4E59-A991-10AD9190B1C9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15B2ABCB-7460-4E59-A991-10AD9190B1C9}.Release|Any CPU.Build.0 = Release|Any CPU {536EFB55-EEA1-4761-9A72-D4EA84A6DB70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {536EFB55-EEA1-4761-9A72-D4EA84A6DB70}.Debug|Any CPU.Build.0 = Debug|Any CPU {536EFB55-EEA1-4761-9A72-D4EA84A6DB70}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -423,7 +415,6 @@ Global {89157FB8-A25B-42EC-A91F-37DFEE274C8C} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} {812B3B34-D2DD-4A3B-BA2D-3D3C52E0C062} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} {34FBB2D3-4E2B-4411-95F2-C6B56899826A} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} - {15B2ABCB-7460-4E59-A991-10AD9190B1C9} = {26A89A29-FE67-4174-9809-7C63AAD6BD5D} {536EFB55-EEA1-4761-9A72-D4EA84A6DB70} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} {AA84DBF7-F70F-4673-8DC2-6EFBE3E9BF83} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} EndGlobalSection diff --git a/src/bundles/Elsa.AllInOne.Web/Program.cs b/src/bundles/Elsa.AllInOne.Web/Program.cs index f710d3e85..e1a1fda21 100644 --- a/src/bundles/Elsa.AllInOne.Web/Program.cs +++ b/src/bundles/Elsa.AllInOne.Web/Program.cs @@ -13,8 +13,11 @@ var services = builder.Services; var configuration = builder.Configuration; var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; var identityOptions = new IdentityOptions(); +var identityTokenOptions = new IdentityTokenOptions(); var identitySection = configuration.GetSection("Identity"); +var identityTokenSection = identitySection.GetSection("Tokens"); identitySection.Bind(identityOptions); +identityTokenSection.Bind(identityTokenOptions); // Add Elsa services. services @@ -23,8 +26,8 @@ services .UseWorkflowsApi() .UseIdentity(identity => { - identity.CreateDefaultUser = true; identity.IdentityOptions = identityOptions; + identity.TokenOptions = identityTokenOptions; }) .UseDefaultAuthentication() .UseWorkflowRuntime(runtime => { runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)); }) diff --git a/src/bundles/Elsa.AllInOne.Web/appsettings.json b/src/bundles/Elsa.AllInOne.Web/appsettings.json index 8886609ba..302283fcf 100644 --- a/src/bundles/Elsa.AllInOne.Web/appsettings.json +++ b/src/bundles/Elsa.AllInOne.Web/appsettings.json @@ -14,6 +14,9 @@ "BasePath": "" }, "Identity": { - "SigningKey": "secret-signing-key" + "CreateDefaultAdmin": true, + "Tokens": { + "SigningKey": "secret-signing-key" + } } } diff --git a/src/bundles/Elsa.WorkflowServer.Web/Program.cs b/src/bundles/Elsa.WorkflowServer.Web/Program.cs index 43a50f1b8..684effde6 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Program.cs +++ b/src/bundles/Elsa.WorkflowServer.Web/Program.cs @@ -1,11 +1,7 @@ using Elsa.EntityFrameworkCore.Extensions; using Elsa.Extensions; -using Elsa.Http; using Elsa.Identity; using Elsa.Identity.Options; -using Elsa.JavaScript.Activities; -using Elsa.Jobs.Activities.Implementations; -using Elsa.Jobs.Activities.Middleware.Activities; using Elsa.Jobs.Activities.Services; using Elsa.EntityFrameworkCore.Modules.ActivityDefinitions; using Elsa.EntityFrameworkCore.Modules.Labels; @@ -13,11 +9,6 @@ using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.MassTransit.Options; using Elsa.Requirements; -using Elsa.Scheduling.Activities; -using Elsa.Workflows.Core.Activities; -using Elsa.Workflows.Core.Middleware.Activities; -using Elsa.Workflows.Core.Middleware.Workflows; -using Elsa.Workflows.Management.Services; using Elsa.WorkflowServer.Web.Jobs; using Microsoft.AspNetCore.Authorization; @@ -26,32 +17,30 @@ var services = builder.Services; var configuration = builder.Configuration; var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; var identityOptions = new IdentityOptions(); +var identityTokenOptions = new IdentityTokenOptions(); var identitySection = configuration.GetSection("Identity"); +var identityTokenSection = identitySection.GetSection("Tokens"); identitySection.Bind(identityOptions); +identityTokenSection.Bind(identityTokenOptions); var rabbitMqOptions = new RabbitMqOptions(); configuration.GetSection(RabbitMqOptions.RabbitMq).Bind(rabbitMqOptions); // Add Elsa services. services .AddElsa(elsa => elsa - .UseWorkflowManagement(management => management - .UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)) - .AddActivitiesFrom() - .AddActivitiesFrom() - .AddActivitiesFrom() - .AddActivitiesFrom() - .AddActivitiesFrom() - ) + .AddActivitiesFrom() .UseIdentity(identity => { - identity.CreateDefaultUser = true; identity.IdentityOptions = identityOptions; + identity.TokenOptions = identityTokenOptions; }) .UseDefaultAuthentication() + .UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) .UseWorkflowRuntime(runtime => { //runtime.UseProtoActor(proto => proto.PersistenceProvider = _ => new SqliteProvider(new SqliteConnectionStringBuilder(sqliteConnectionString))); runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)); + runtime.UseAsyncWorkflowStateExporter(); }) .UseLabels(labels => labels.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) .UseActivityDefinitions(feature => feature.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) @@ -78,24 +67,6 @@ var serviceProvider = app.Services; var jobRegistry = serviceProvider.GetRequiredService(); jobRegistry.Add(typeof(IndexBlockchainJob)); -// Update activity providers. -var activityRegistryPopulator = serviceProvider.GetRequiredService(); -activityRegistryPopulator.PopulateRegistryAsync(typeof(JobActivityProvider)); - -// Configure workflow engine execution pipeline. -serviceProvider.ConfigureDefaultWorkflowExecutionPipeline(pipeline => - pipeline - .UsePersistentVariables() - .UseBookmarkPersistence() - .UseWorkflowContexts() - .UseDefaultActivityScheduler() -); - -// Configure activity execution pipeline to use the job-based activity invoker. -serviceProvider.ConfigureDefaultActivityExecutionPipeline(pipeline => pipeline - .UseExceptionHandling() - .UseJobBasedActivityInvoker()); - if (app.Environment.IsDevelopment()) app.UseDeveloperExceptionPage(); diff --git a/src/bundles/Elsa.WorkflowServer.Web/appsettings.json b/src/bundles/Elsa.WorkflowServer.Web/appsettings.json index 6fe1b1752..fc2628e5f 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/appsettings.json +++ b/src/bundles/Elsa.WorkflowServer.Web/appsettings.json @@ -12,7 +12,11 @@ "RabbitMq": "localhost" }, "Identity": { - "SigningKey": "secret-signing-key" + "CreateDefaultAdmin": true, + "Tokens": { + "SigningKey": "secret-signing-key", + "Lifetime": "8:00:00" + } }, "RabbitMq": { "Username": "guest", diff --git a/src/bundles/Elsa/Elsa.csproj b/src/bundles/Elsa/Elsa.csproj index 4ddbc89db..c6cd069c9 100644 --- a/src/bundles/Elsa/Elsa.csproj +++ b/src/bundles/Elsa/Elsa.csproj @@ -1,7 +1,7 @@ - - + + net6.0;net7.0 @@ -13,17 +13,18 @@ - - - + + + - - - - - + + + + + + diff --git a/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs b/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs index 2c96cf461..e5de32740 100644 --- a/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs +++ b/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs @@ -11,20 +11,11 @@ public static class ServiceProviderExtensions /// /// Configure the default activity execution pipeline. /// - public static IServiceProvider ConfigureDefaultActivityExecutionPipeline(this IServiceProvider services, Action setup) + public static IServiceProvider ConfigureDefaultActivityExecutionPipeline(this IServiceProvider services, Action setup) { var pipeline = services.GetRequiredService(); pipeline.Setup(setup); return services; } - - /// - /// Configure the default workflow execution pipeline. - /// - public static IServiceProvider ConfigureDefaultWorkflowExecutionPipeline(this IServiceProvider services, Action setup) - { - var pipeline = services.GetRequiredService(); - pipeline.Setup(setup); - return services; - } + } \ No newline at end of file diff --git a/src/bundles/Elsa/Features/ElsaFeature.cs b/src/bundles/Elsa/Features/ElsaFeature.cs index d0241e480..83cc04ce3 100644 --- a/src/bundles/Elsa/Features/ElsaFeature.cs +++ b/src/bundles/Elsa/Features/ElsaFeature.cs @@ -24,7 +24,7 @@ public class ElsaFeature : FeatureBase /// Set this to true to opt out of automatically registering activities from Elsa.Workflows.Core. /// public bool DisableAutomaticActivityRegistration { get; set; } - + /// public ElsaFeature(IModule module) : base(module) { @@ -33,6 +33,14 @@ public class ElsaFeature : FeatureBase /// public override void Configure() { - Module.UseWorkflowManagement(management => management.AddActivitiesFrom()); + Module + .UseWorkflows(workflows => workflows + .WithDefaultRuntimeWorkflowExecutionPipeline() + .WithJobBasedActivityExecutionPipeline()) + .UseWorkflowManagement(management => + { + if (!DisableAutomaticActivityRegistration) + management.AddActivitiesFrom(); + }); } } \ No newline at end of file diff --git a/src/designer/elsa-workflows-designer/src/components.d.ts b/src/designer/elsa-workflows-designer/src/components.d.ts index bbe4d212c..b7288eb1d 100644 --- a/src/designer/elsa-workflows-designer/src/components.d.ts +++ b/src/designer/elsa-workflows-designer/src/components.d.ts @@ -17,8 +17,8 @@ import { ActivityInputContext } from "./services/node-input-driver"; import { ContextMenuAnchorPoint, MenuItem, MenuItemGroup } from "./components/shared/context-menu/models"; import { DropdownButtonItem, DropdownButtonOrigin } from "./components/shared/dropdown-button/models"; import { Graph } from "@antv/x6"; +import { AddActivityArgs, FlowchartPathItem, LayoutDirection, RenameActivityArgs, UpdateActivityArgs } from "./modules/flowchart/models"; import { OutNode } from "@antv/layout"; -import { AddActivityArgs, FlowchartPathItem, RenameActivityArgs, UpdateActivityArgs } from "./modules/flowchart/models"; import { ActivityNodeShape } from "./modules/flowchart/shapes"; import { PanelActionClickArgs, PanelActionDefinition } from "./components/shared/form-panel/models"; import { ExpressionChangedArs } from "./components/designer/input-control-switch/input-control-switch"; @@ -99,6 +99,7 @@ export namespace Components { "items": Array; "origin": DropdownButtonOrigin; "text": string; + "theme": string; } interface ElsaDropdownInput { "inputContext": ActivityInputContext; @@ -108,7 +109,7 @@ export namespace Components { } interface ElsaFlowchart { "addActivity": (args: AddActivityArgs) => Promise; - "autoLayout": (direction: "TB" | "BT" | "LR" | "RL") => Promise; + "autoLayout": (direction: LayoutDirection) => Promise; "export": () => Promise; "getGraph": () => Promise; "interactiveMode": boolean; @@ -259,7 +260,6 @@ export namespace Components { "workflowDefinition"?: WorkflowDefinition; } interface ElsaWorkflowDefinitionEditorToolbar { - "autoLayout": (direction: "TB" | "BT" | "LR" | "RL") => Promise; "zoomToFit": () => Promise; } interface ElsaWorkflowDefinitionEditorToolbox { @@ -409,6 +409,10 @@ export interface ElsaWorkflowDefinitionEditorCustomEvent extends CustomEvent< detail: T; target: HTMLElsaWorkflowDefinitionEditorElement; } +export interface ElsaWorkflowDefinitionEditorToolbarCustomEvent extends CustomEvent { + detail: T; + target: HTMLElsaWorkflowDefinitionEditorToolbarElement; +} export interface ElsaWorkflowDefinitionPropertiesEditorCustomEvent extends CustomEvent { detail: T; target: HTMLElsaWorkflowDefinitionPropertiesEditorElement; @@ -916,6 +920,7 @@ declare namespace LocalJSX { "onItemSelected"?: (event: ElsaDropdownButtonCustomEvent) => void; "origin"?: DropdownButtonOrigin; "text"?: string; + "theme"?: string; } interface ElsaDropdownInput { "inputContext"?: ActivityInputContext; @@ -1078,7 +1083,7 @@ declare namespace LocalJSX { "workflowDefinition"?: WorkflowDefinition; } interface ElsaWorkflowDefinitionEditorToolbar { - "autoLayout"?: (direction: "TB" | "BT" | "LR" | "RL") => Promise; + "onAutoLayout"?: (event: ElsaWorkflowDefinitionEditorToolbarCustomEvent) => void; "zoomToFit"?: () => Promise; } interface ElsaWorkflowDefinitionEditorToolbox { diff --git a/src/designer/elsa-workflows-designer/src/components/shared/dropdown-button/dropdown-button.tsx b/src/designer/elsa-workflows-designer/src/components/shared/dropdown-button/dropdown-button.tsx index 49b55612a..91b202b7f 100644 --- a/src/designer/elsa-workflows-designer/src/components/shared/dropdown-button/dropdown-button.tsx +++ b/src/designer/elsa-workflows-designer/src/components/shared/dropdown-button/dropdown-button.tsx @@ -6,25 +6,29 @@ import {DropdownButtonItem, DropdownButtonOrigin} from "./models"; tag: 'elsa-dropdown-button', shadow: false, }) -export class ElsaContextMenu { +export class DropdownButton { @Prop() public text: string; @Prop() public icon?: any; @Prop() public origin: DropdownButtonOrigin = DropdownButtonOrigin.TopLeft; @Prop() public items: Array = []; + @Prop() public theme: string = 'Secondary'; @Event() public itemSelected: EventEmitter private contextMenu: HTMLElement; private element: HTMLElement; public render() { + const buttonClass = this.theme == 'Secondary' ? 'btn-secondary' : 'btn-primary'; + const arrowClass = this.theme == 'Secondary' ? 'text-gray-400' : 'text-white'; + return (
this.element = el}> @@ -83,6 +87,10 @@ export class ElsaContextMenu { private async onItemClick(e: Event, menuItem: DropdownButtonItem) { e.preventDefault(); + + if(!!menuItem.handler) + menuItem.handler(); + this.itemSelected.emit(menuItem); this.closeContextMenu(); } diff --git a/src/designer/elsa-workflows-designer/src/components/shared/modal-dialog/modal-dialog.tsx b/src/designer/elsa-workflows-designer/src/components/shared/modal-dialog/modal-dialog.tsx index c6236936e..1e47aa762 100644 --- a/src/designer/elsa-workflows-designer/src/components/shared/modal-dialog/modal-dialog.tsx +++ b/src/designer/elsa-workflows-designer/src/components/shared/modal-dialog/modal-dialog.tsx @@ -13,7 +13,7 @@ export class ModalDialog { @Prop() modalDialogInstance: ModalDialogInstance; @Prop() actions: Array = []; - @Prop() size: string = 'sm:max-w-6xl'; + @Prop() size: string = 'max-w-6xl'; @Prop() type: ModalType = ModalType.Default; @Prop() autoHide: boolean = true; @Prop() content: () => any = () =>
; @@ -68,12 +68,6 @@ export class ModalDialog { } } - componentWillRender() { - if (this.type == ModalType.Default) { - this.size += " sm:w-full"; - } - } - componentDidRender() { if (this.isVisible) { enter(this.overlay); diff --git a/src/designer/elsa-workflows-designer/src/models/core.ts b/src/designer/elsa-workflows-designer/src/models/core.ts index dc6b27fa0..48c2c8fbe 100644 --- a/src/designer/elsa-workflows-designer/src/models/core.ts +++ b/src/designer/elsa-workflows-designer/src/models/core.ts @@ -17,7 +17,7 @@ export interface Activity { metadata: any; canStartWorkflow?: boolean; runAsynchronously?: boolean; - applicationProperties: any; + customProperties: any; [name: string]: any; } @@ -30,6 +30,11 @@ export interface Container extends Activity { variables: Array; } +export interface Workflow extends Activity { + root: Activity; + variables: Array; +} + export interface Variable { name: string; typeName: string; diff --git a/src/designer/elsa-workflows-designer/src/modules/activity-definitions/plugin.tsx b/src/designer/elsa-workflows-designer/src/modules/activity-definitions/plugin.tsx index 0857693e3..4f188eeda 100644 --- a/src/designer/elsa-workflows-designer/src/modules/activity-definitions/plugin.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/activity-definitions/plugin.tsx @@ -72,7 +72,7 @@ export class ActivityDefinitionsPlugin implements Plugin { connections: [], id: newName, metadata: {}, - applicationProperties: {}, + customProperties: {}, variables: [] } as Flowchart; diff --git a/src/designer/elsa-workflows-designer/src/modules/flowchart/flowchart.tsx b/src/designer/elsa-workflows-designer/src/modules/flowchart/flowchart.tsx index ba0a736f9..f3813c552 100644 --- a/src/designer/elsa-workflows-designer/src/modules/flowchart/flowchart.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/flowchart/flowchart.tsx @@ -7,7 +7,7 @@ import './ports'; import {ActivityNodeShape} from './shapes'; import {Activity, ActivityDeletedArgs, ActivityDescriptor, ActivitySelectedArgs, ContainerSelectedArgs, EditChildActivityArgs, GraphUpdatedArgs, Port, WorkflowUpdatedArgs} from '../../models'; import {createGraph} from './graph-factory'; -import {AddActivityArgs, Connection, Flowchart, FlowchartModel, FlowchartNavigationItem, FlowchartPathItem, RenameActivityArgs, UpdateActivityArgs} from './models'; +import {AddActivityArgs, Connection, Flowchart, FlowchartModel, FlowchartNavigationItem, FlowchartPathItem, LayoutDirection, RenameActivityArgs, UpdateActivityArgs} from './models'; import {NodeFactory} from "./node-factory"; import {Container} from "typedi"; import {ActivityNode, createActivityLookup, EventBus, flatten, PortProviderRegistry, walkActivities} from "../../services"; @@ -23,7 +23,6 @@ import {DagreLayout, OutNode} from '@antv/layout'; import {adjustPortMarkupByNode, rebuildGraph} from '../../utils/graph'; import {WorkflowDefinition} from "../workflow-definitions/models/entities"; import FlowchartTunnel, {FlowchartState} from "./state"; -import {WorkflowDefinitionUpdatedArgs} from "../workflow-definitions/models/ui"; const FlowchartTypeName = 'Elsa.Flowchart'; @@ -115,7 +114,8 @@ export class FlowchartComponent { } @Method() - async autoLayout(direction: "TB" | "BT" | "LR" | "RL") { + async autoLayout(direction: LayoutDirection) { + debugger; const dagreLayout = new DagreLayout({ type: 'dagre', rankdir: direction, @@ -150,7 +150,8 @@ export class FlowchartComponent { this.updateActivity({id: activity.id, originalId: activity.id, activity: activity}); }); - //this.importInternal() + this.updateGraphInternal(flowchartModel.activities, flowchartModel.connections); + this.graphUpdated.emit({}); } @Method() @@ -166,7 +167,7 @@ export class FlowchartComponent { id: id, type: descriptor.typeName, version: descriptor.version, - applicationProperties: {}, + customProperties: {}, metadata: { designer: { position: { @@ -276,8 +277,11 @@ export class FlowchartComponent { await this.setupGraph(childFlowchart); } - async componentDidLoad() { + async componentWillLoad() { this.updateLookups(); + } + + async componentDidLoad() { await this.createAndInitializeGraph(); } @@ -296,7 +300,7 @@ export class FlowchartComponent { connections: [], metadata: {}, variables: [], - applicationProperties: {}, + customProperties: {}, canStartWorkflow: false }; } @@ -392,6 +396,11 @@ export class FlowchartComponent { private setupGraph = async (flowchart: Flowchart) => { const activities = flowchart.activities; const connections = flowchart.connections; + this.updateGraphInternal(activities, connections); + await this.scrollToStart(); + }; + + private updateGraphInternal = (activities: Array, connections: Array) => { const edges: Array = []; // Create an X6 node for each activity. @@ -416,8 +425,7 @@ export class FlowchartComponent { this.graph.unfreeze(); rebuildGraph(this.graph); - await this.scrollToStart(); - }; + } private getFlowchartModel = (): FlowchartModel => { const graph = this.graph; diff --git a/src/designer/elsa-workflows-designer/src/modules/flowchart/models.ts b/src/designer/elsa-workflows-designer/src/modules/flowchart/models.ts index db7c40c02..2c1bb7a04 100644 --- a/src/designer/elsa-workflows-designer/src/modules/flowchart/models.ts +++ b/src/designer/elsa-workflows-designer/src/modules/flowchart/models.ts @@ -47,3 +47,5 @@ export interface RenameActivityArgs { newId: string; activity: Activity; } + +export type LayoutDirection = 'LR' | 'TB' | 'RL' | 'BT'; diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/components/editor.tsx b/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/components/editor.tsx index 29a91e5dd..40d9e655f 100644 --- a/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/components/editor.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/components/editor.tsx @@ -15,6 +15,7 @@ import {ActivityPropertyChangedEventArgs, WorkflowDefinitionPropsUpdatedArgs, Wo import {WorkflowDefinition} from "../models/entities"; import {WorkflowDefinitionsApi} from "../services/api" import WorkflowDefinitionTunnel, {WorkflowDefinitionState} from "../../../state/workflow-definition-state"; +import {LayoutDirection} from "../../flowchart/models"; @Component({ tag: 'elsa-workflow-definition-editor', @@ -226,7 +227,10 @@ export class WorkflowDefinitionEditor { private onZoomToFit = async () => await this.flowchart.zoomToFit(); - private onAutoLayout = async (direction: "TB" | "BT" | "LR" | "RL") => await this.flowchart.autoLayout(direction); + private onAutoLayout = async (direction: LayoutDirection) => { + debugger; + await this.flowchart.autoLayout(direction); + }; private onActivityUpdated = async (e: CustomEvent) => { await this.flowchart.updateActivity({ @@ -279,7 +283,7 @@ export class WorkflowDefinitionEditor { return (
this.container = el}> - + ) => this.onAutoLayout(e.detail)}/> Promise; - @Prop() - public autoLayout: (direction: "TB" | "BT" | "LR" | "RL") => Promise; + @Event() + public autoLayout: EventEmitter; render() { + + const layoutButtons: Array = [{ + text: 'Horizontally', + handler: () => this.autoLayout.emit('LR') + },{ + text: 'Vertically', + handler: () => this.autoLayout.emit('TB') + }]; + return (
- - + diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/plugin.tsx b/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/plugin.tsx index ab979a7d9..0a6d71f8b 100644 --- a/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/plugin.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/workflow-definitions/plugin.tsx @@ -43,7 +43,7 @@ export class WorkflowDefinitionsPlugin implements Plugin { const newWorkflowDefinitionItem: MenuItem = { text: 'Workflow Definition', - clickHandler: this.onNewWorkflowDefinitionClick + clickHandler: this.onNewWorkflowDefinitionSelected } const importWorkflowDefinitionItem: MenuItem = { @@ -80,7 +80,7 @@ export class WorkflowDefinitionsPlugin implements Plugin { connections: [], id: newName, metadata: {}, - applicationProperties: {}, + customProperties: {}, variables: [] } as Flowchart; @@ -146,7 +146,7 @@ export class WorkflowDefinitionsPlugin implements Plugin { }); }; - private onNewWorkflowDefinitionClick = async () => { + private onNewWorkflowDefinitionSelected = async () => { await this.newWorkflow(); this.modalDialogService.hide(this.workflowDefinitionBrowserInstance); }; @@ -158,32 +158,16 @@ export class WorkflowDefinitionsPlugin implements Plugin { private onWorkflowUpdated = async (e: CustomEvent) => { const updatedWorkflowDefinition = e.detail.workflowDefinition; - await this.saveWorkflowDefinition(updatedWorkflowDefinition, false); - - // if (e.detail.latestVersionNumber == undefined) { - // await this.saveWorkflowDefinition(updatedWorkflowDefinition, false); - // return; - // } - - // if (updatedWorkflowDefinition.version == e.detail.latestVersionNumber || updatedWorkflowDefinition.isPublished) { - // const currentWorkflowDefinition = await this.api.get({definitionId: updatedWorkflowDefinition.definitionId, versionOptions: {version: updatedWorkflowDefinition.version}}); - // if (!isEqual(currentWorkflowDefinition.root.activities, updatedWorkflowDefinition.root.activities) || !isEqual(currentWorkflowDefinition.variables, updatedWorkflowDefinition.variables)) { - // if (updatedWorkflowDefinition.isPublished) - // updatedWorkflowDefinition.version = e.detail.latestVersionNumber; - // - // await this.saveWorkflowDefinition(updatedWorkflowDefinition, false); - // } - // } } private onBrowseWorkflowDefinitions = async () => { const closeAction = DefaultModalActions.Close(); - const newAction = DefaultModalActions.New(this.onNewWorkflowDefinitionClick); + const newAction = DefaultModalActions.New(this.onNewWorkflowDefinitionSelected); const actions = [closeAction, newAction]; this.workflowDefinitionBrowserInstance = this.modalDialogService.show(() => - , + , {actions}) } @@ -198,16 +182,10 @@ export class WorkflowDefinitionsPlugin implements Plugin { e.detail.begin(); const notification = NotificationService.createNotification({title: 'Publishing', id: uuid(), text: 'Workflow is being publishing. Please wait'}) const workflowDefinition = await this.workflowDefinitionEditorElement.getWorkflowDefinition(); - //await this.eventBus.emit(NotificationEventTypes.Add, this, {id: workflowDefinition.definitionId, message: `Starting publishing ${workflowDefinition.name}`}); await this.saveWorkflowDefinition(workflowDefinition, true); NotificationService.updateNotification(notification, {title: 'Workflow published', text: 'Published !'}) e.detail.complete(); - // setTimeout(async () => { - // await this.eventBus.emit(NotificationEventTypes.Update, this, {id: workflowDefinition.definitionId, message: `${workflowDefinition.name} publish finished`}); - // e.detail.complete(); - // }, 2000) - } private onExportClicked = async (e: CustomEvent) => { diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/browser.tsx b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/browser.tsx index 19924d162..402def0ca 100644 --- a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/browser.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/browser.tsx @@ -108,8 +108,6 @@ export class WorkflowInstanceBrowser { Status Created Finished - Executed - Faulted @@ -143,8 +141,6 @@ export class WorkflowInstanceBrowser { {formatTimestamp(workflowInstance.createdAt, '-')} {formatTimestamp(workflowInstance.finishedAt, '-')} - {formatTimestamp(workflowInstance.lastExecutedAt, '-')} - {formatTimestamp(workflowInstance.faultedAt, '-')} this.onWorkflowInstanceClick(e, workflowInstance), icon: }, diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/journal.tsx b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/journal.tsx index 1c2138d66..6d44478a4 100644 --- a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/journal.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/journal.tsx @@ -1,5 +1,5 @@ import {Component, h, Prop, State, Watch} from "@stencil/core"; -import {ActivityDescriptor, WorkflowExecutionLogRecord, WorkflowInstance} from "../../../models"; +import {ActivityDescriptor, Workflow, WorkflowExecutionLogRecord, WorkflowInstance} from "../../../models"; import {Container} from "typedi"; import {ActivityIconRegistry, ActivityNode, createActivityNodeMap, flatten, walkActivities} from "../../../services"; import {durationToString, formatTime, getDuration, Hash, isNullOrWhitespace} from "../../../utils"; @@ -115,7 +115,7 @@ export class Journal { const activityDisplayText = isNullOrWhitespace(activityMetadata.displayText) ? activity.id : activityMetadata.displayText; const duration = durationToString(block.duration); const status = block.completed ? 'Completed' : 'Started'; - const icon = iconRegistry.get(activity.type)({size: ActivityIconSize.Small}); + const icon = iconRegistry.getOrDefault(activity.type)({size: ActivityIconSize.Small}); const expanded = !!expandedBlocks.find(x => x == block); const toggleIcon = expanded @@ -166,7 +166,19 @@ export class Journal { if (!this.workflowInstance || !this.workflowDefinition) return; - this.nodes = flatten(walkActivities(this.workflowDefinition.root)); + const workflow: Workflow = { + type: 'Elsa.Workflow', + id: 'Workflow1', // Always 'Workflow1'. + version: this.workflowDefinition.version, + customProperties: this.workflowDefinition.customProperties, + canStartWorkflow: false, + runAsynchronously: false, + metadata: {}, + root: this.workflowDefinition.root, + variables: this.workflowDefinition.variables + }; + + this.nodes = flatten(walkActivities(workflow)); this.nodeMap = createActivityNodeMap(this.nodes); }; diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/workflow-instance-viewer.scss b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/viewer.scss similarity index 100% rename from src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/workflow-instance-viewer.scss rename to src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/viewer.scss diff --git a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/workflow-instance-viewer.tsx b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/viewer.tsx similarity index 95% rename from src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/workflow-instance-viewer.tsx rename to src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/viewer.tsx index 0e4149315..86330bc49 100644 --- a/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/workflow-instance-viewer.tsx +++ b/src/designer/elsa-workflows-designer/src/modules/workflow-instances/components/viewer.tsx @@ -15,7 +15,7 @@ import {WorkflowEditorEventTypes} from "../../workflow-definitions/models/ui"; @Component({ tag: 'elsa-workflow-instance-viewer', - styleUrl: 'workflow-instance-viewer.scss', + styleUrl: 'viewer.scss', }) export class WorkflowInstanceViewer { private readonly pluginRegistry: PluginRegistry; @@ -99,7 +99,12 @@ export class WorkflowInstanceViewer { public async importWorkflow(workflowDefinition: WorkflowDefinition, workflowInstance: WorkflowInstance): Promise { this.workflowInstanceState = workflowInstance; await this.updateWorkflowDefinition(workflowDefinition); - //await this.flowchartElement.import(workflowDefinition.root); + // Update the flowchart after state is updated. + window.requestAnimationFrame(async () => { + await this.flowchartElement.updateGraph(); + }); + + await this.eventBus.emit(WorkflowEditorEventTypes.WorkflowDefinition.Imported, this, {workflowDefinition}); } // Updates the workflow definition without importing it into the designer. @@ -165,6 +170,7 @@ export class WorkflowInstanceViewer { this.flowchartElement = el} + workflowDefinition={workflowDefinition} interactiveMode={false}/> , - {actions: actions, size: 'max-w-10xl'}) + {actions: actions, size: 'max-w-screen-2xl'}) } private onWorkflowInstanceSelected = async (e: CustomEvent) => { diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/Extensions.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/Extensions.cs index e18a05fbd..a5b462b93 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/Extensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/Extensions.cs @@ -1,13 +1,30 @@ using Elsa.Workflows.Runtime.Features; +using Elsa.Workflows.Runtime.Implementations; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.EntityFrameworkCore.Modules.Runtime { + /// + /// Provides extensions to the feature. + /// public static class Extensions { + /// + /// Configures the to use the . + /// public static WorkflowRuntimeFeature UseEntityFrameworkCore(this WorkflowRuntimeFeature feature, Action? configure = default) { feature.Module.Configure(configure); return feature; } + + /// + /// Configures the workflow runtime to send workflow state to the . + /// + public static WorkflowRuntimeFeature UseAsyncWorkflowStateExporter(this WorkflowRuntimeFeature feature) + { + feature.WorkflowStateExporter = sp => ActivatorUtilities.CreateInstance(sp); + return feature; + } } } \ No newline at end of file diff --git a/src/modules/Elsa.Identity/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Identity/Extensions/ModuleExtensions.cs index fbe631617..bd716a0b9 100644 --- a/src/modules/Elsa.Identity/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Identity/Extensions/ModuleExtensions.cs @@ -24,7 +24,7 @@ public static class ModuleExtensions /// public static IModule UseIdentity(this IModule module, string signingKey, string issuer = "http://elsa.api", string audience = "http://elsa.api", TimeSpan? tokenLifetime = default) { - module.UseIdentity(identity => identity.IdentityOptions = new IdentityOptions + module.UseIdentity(identity => identity.TokenOptions = new IdentityTokenOptions { Audience = audience, Issuer = issuer, diff --git a/src/modules/Elsa.Identity/Features/DefaultAuthenticationFeature.cs b/src/modules/Elsa.Identity/Features/DefaultAuthenticationFeature.cs index 6e2b83548..fb430f350 100644 --- a/src/modules/Elsa.Identity/Features/DefaultAuthenticationFeature.cs +++ b/src/modules/Elsa.Identity/Features/DefaultAuthenticationFeature.cs @@ -21,7 +21,7 @@ public class DefaultAuthenticationFeature : FeatureBase public override void Apply() { var identityFeature = Module.Configure(); - var identityOptions = identityFeature.IdentityOptions; + var identityOptions = identityFeature.TokenOptions; Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) diff --git a/src/modules/Elsa.Identity/Features/IdentityFeature.cs b/src/modules/Elsa.Identity/Features/IdentityFeature.cs index 0f8112ee1..4b9cc920c 100644 --- a/src/modules/Elsa.Identity/Features/IdentityFeature.cs +++ b/src/modules/Elsa.Identity/Features/IdentityFeature.cs @@ -23,16 +23,16 @@ public class IdentityFeature : FeatureBase { } - /// - /// A flag indicating whether a default user should be created. - /// - public bool CreateDefaultUser { get; set; } - /// /// A delegate to configure . /// public IdentityOptions IdentityOptions { get; set; } = new(); + /// + /// A delegate to configure . + /// + public IdentityTokenOptions TokenOptions { get; set; } = new(); + /// /// A delegate that creates an instance of an implementation of . /// @@ -52,14 +52,14 @@ public class IdentityFeature : FeatureBase /// public override void ConfigureHostedServices() { - if(CreateDefaultUser) + if(IdentityOptions.CreateDefaultAdmin) Module.ConfigureHostedService(); } /// public override void Apply() { - Services.Configure(options => options.CopyFrom(IdentityOptions)); + Services.Configure(options => options.CopyFrom(TokenOptions)); Services .AddMemoryStore() diff --git a/src/modules/Elsa.Identity/Implementations/DefaultAccessTokenIssuer.cs b/src/modules/Elsa.Identity/Implementations/DefaultAccessTokenIssuer.cs index 03c4dcf99..cdb32d91d 100644 --- a/src/modules/Elsa.Identity/Implementations/DefaultAccessTokenIssuer.cs +++ b/src/modules/Elsa.Identity/Implementations/DefaultAccessTokenIssuer.cs @@ -12,9 +12,9 @@ namespace Elsa.Identity.Implementations; public class DefaultAccessTokenIssuer : IAccessTokenIssuer { private readonly ISystemClock _systemClock; - private readonly IdentityOptions _identityOptions; + private readonly IdentityTokenOptions _identityOptions; - public DefaultAccessTokenIssuer(ISystemClock systemClock, IOptions identityOptions) + public DefaultAccessTokenIssuer(ISystemClock systemClock, IOptions identityOptions) { _systemClock = systemClock; _identityOptions = identityOptions.Value; diff --git a/src/modules/Elsa.Identity/Options/IdentityOptions.cs b/src/modules/Elsa.Identity/Options/IdentityOptions.cs index 25dcf4e02..3799edf0a 100644 --- a/src/modules/Elsa.Identity/Options/IdentityOptions.cs +++ b/src/modules/Elsa.Identity/Options/IdentityOptions.cs @@ -1,42 +1,6 @@ -using System.Text; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.IdentityModel.Tokens; - namespace Elsa.Identity.Options; public class IdentityOptions { - public string SigningKey { get; set; } - public string Issuer { get; set; } = "http://elsa.api"; - public string Audience { get; set; } = "http://elsa.api"; - public TimeSpan? Lifetime { get; set; } = TimeSpan.FromHours(1); - - public SecurityKey CreateSecurityKey() => new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SigningKey)); - - public void ConfigureJwtBearerOptions(JwtBearerOptions options) => - options.TokenValidationParameters = new TokenValidationParameters - { - IssuerSigningKey = CreateSecurityKey(), - ValidAudience = Audience, - ValidIssuer = Issuer - }; - - /// - /// Deconstructor. - /// - internal void Deconstruct(out string signingKey, out string issuer, out string audience, out TimeSpan? lifetime) - { - signingKey = SigningKey; - issuer = Issuer; - audience = Audience; - lifetime = Lifetime; - } - - internal void CopyFrom(IdentityOptions identityOptions) - { - SigningKey = identityOptions.SigningKey; - Audience = identityOptions.Audience; - Issuer = identityOptions.Issuer; - Lifetime = identityOptions.Lifetime; - } + public bool CreateDefaultAdmin { get; set; } } \ No newline at end of file diff --git a/src/modules/Elsa.Identity/Options/IdentityTokenOptions.cs b/src/modules/Elsa.Identity/Options/IdentityTokenOptions.cs new file mode 100644 index 000000000..7f1e076e1 --- /dev/null +++ b/src/modules/Elsa.Identity/Options/IdentityTokenOptions.cs @@ -0,0 +1,42 @@ +using System.Text; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; + +namespace Elsa.Identity.Options; + +public class IdentityTokenOptions +{ + public string SigningKey { get; set; } + public string Issuer { get; set; } = "http://elsa.api"; + public string Audience { get; set; } = "http://elsa.api"; + public TimeSpan? Lifetime { get; set; } = TimeSpan.FromHours(1); + + public SecurityKey CreateSecurityKey() => new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SigningKey)); + + public void ConfigureJwtBearerOptions(JwtBearerOptions options) => + options.TokenValidationParameters = new TokenValidationParameters + { + IssuerSigningKey = CreateSecurityKey(), + ValidAudience = Audience, + ValidIssuer = Issuer + }; + + /// + /// Deconstructor. + /// + internal void Deconstruct(out string signingKey, out string issuer, out string audience, out TimeSpan? lifetime) + { + signingKey = SigningKey; + issuer = Issuer; + audience = Audience; + lifetime = Lifetime; + } + + internal void CopyFrom(IdentityTokenOptions identityOptions) + { + SigningKey = identityOptions.SigningKey; + Audience = identityOptions.Audience; + Issuer = identityOptions.Issuer; + Lifetime = identityOptions.Lifetime; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Jobs.Activities/Extensions/JobBasedActivityInvokerMiddlewareExtensions.cs b/src/modules/Elsa.Jobs.Activities/Extensions/JobBasedActivityInvokerMiddlewareExtensions.cs new file mode 100644 index 000000000..be2cc20a1 --- /dev/null +++ b/src/modules/Elsa.Jobs.Activities/Extensions/JobBasedActivityInvokerMiddlewareExtensions.cs @@ -0,0 +1,17 @@ +using Elsa.Jobs.Activities.Middleware.Activities; +using Elsa.Workflows.Core.Pipelines.ActivityExecution; +using Elsa.Workflows.Core.Services; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Adds extensions to . +/// +public static class JobBasedActivityInvokerMiddlewareExtensions +{ + /// + /// Installs the . + /// + public static IActivityExecutionPipelineBuilder UseJobBasedActivityInvoker(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Jobs.Activities/Extensions/WorkflowsFeatureExtensions.cs b/src/modules/Elsa.Jobs.Activities/Extensions/WorkflowsFeatureExtensions.cs new file mode 100644 index 000000000..3916dbcc6 --- /dev/null +++ b/src/modules/Elsa.Jobs.Activities/Extensions/WorkflowsFeatureExtensions.cs @@ -0,0 +1,15 @@ +using Elsa.Workflows.Core.Features; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Adds an extension method to the that installs a default workflow runtime execution pipeline. +/// +public static class WorkflowsFeatureExtensions +{ + /// + /// Installs a default workflow runtime execution pipeline. + /// + public static WorkflowsFeature WithJobBasedActivityExecutionPipeline(this WorkflowsFeature workflowsFeature) => workflowsFeature.WithActivityExecutionPipeline(pipeline => pipeline.UseJobBasedActivityInvoker()); +} \ No newline at end of file diff --git a/src/modules/Elsa.Jobs.Activities/Middleware/Activities/JobBasedActivityInvokerMiddleware.cs b/src/modules/Elsa.Jobs.Activities/Middleware/Activities/JobBasedActivityInvokerMiddleware.cs index 80876986a..a2f91d34c 100644 --- a/src/modules/Elsa.Jobs.Activities/Middleware/Activities/JobBasedActivityInvokerMiddleware.cs +++ b/src/modules/Elsa.Jobs.Activities/Middleware/Activities/JobBasedActivityInvokerMiddleware.cs @@ -5,16 +5,10 @@ using Elsa.Jobs.Services; using Elsa.Workflows.Core.Middleware.Activities; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Pipelines.ActivityExecution; -using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Services; namespace Elsa.Jobs.Activities.Middleware.Activities; -public static class JobBasedActivityInvokerMiddlewareExtensions -{ - public static IActivityExecutionBuilder UseJobBasedActivityInvoker(this IActivityExecutionBuilder builder) => builder.UseMiddleware(); -} - /// /// Executes the current activity from a background job if the activity is of kind or /// @@ -26,6 +20,7 @@ public class JobBasedActivityInvokerMiddleware : DefaultActivityInvokerMiddlewar private readonly IJobFactory _jobFactory; private readonly IJobQueue _jobQueue; + /// public JobBasedActivityInvokerMiddleware( ActivityMiddlewareDelegate next, IActivityRegistry activityRegistry, @@ -39,6 +34,7 @@ public class JobBasedActivityInvokerMiddleware : DefaultActivityInvokerMiddlewar _jobQueue = jobQueue; } + /// protected override async ValueTask ExecuteActivityAsync(ActivityExecutionContext context) { var activity = context.Activity; diff --git a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs index fc9c19bda..ec84b8180 100644 --- a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs +++ b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs @@ -5,22 +5,30 @@ using Elsa.Features.Services; using Elsa.Scheduling.Handlers; using Elsa.Scheduling.Implementations; using Elsa.Scheduling.Services; +using Elsa.Workflows.Management.Features; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Scheduling.Features; +/// +/// Provides scheduling features to the system. +/// [DependsOn(typeof(SystemClockFeature))] public class SchedulingFeature : FeatureBase { + /// public SchedulingFeature(IModule module) : base(module) { } + /// public override void Apply() { Services .AddSingleton() .AddSingleton() .AddNotificationHandlersFrom(); + + Module.Configure(management => management.AddActivitiesFrom()); } } \ No newline at end of file diff --git a/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowExecutionBuilderExtensions.cs b/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowExecutionBuilderExtensions.cs index 4bc3fa09c..624e61b8c 100644 --- a/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowExecutionBuilderExtensions.cs +++ b/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowExecutionBuilderExtensions.cs @@ -11,10 +11,10 @@ public static class WorkflowExecutionBuilderExtensions /// /// Installs middleware that enables the use of workflow context. /// - public static IWorkflowExecutionBuilder UseWorkflowContexts(this IWorkflowExecutionBuilder builder) => builder.UseMiddleware(); + public static IWorkflowExecutionPipelineBuilder UseWorkflowContexts(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); /// /// Installs middleware that enables the use of workflow context. /// - public static IActivityExecutionBuilder UseWorkflowContexts(this IActivityExecutionBuilder builder) => builder.UseMiddleware(); + public static IActivityExecutionPipelineBuilder UseWorkflowContexts(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Mappers.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Mappers.cs index 9547dcb9c..b87ebb5c7 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Mappers.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Mappers.cs @@ -3,10 +3,15 @@ using FastEndpoints; namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.Get; +/// +/// Maps a to . +/// public class WorkflowInstanceMapper : ResponseMapper { + /// public override Response FromEntity(WorkflowInstance e) => new() { + Id = e.Id, DefinitionId = e.DefinitionId, DefinitionVersionId = e.DefinitionVersionId, Version = e.Version, diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs index 1eea7a266..1e9ce30fb 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs @@ -10,6 +10,7 @@ public class Request public class Response { + public string Id { get; set; } public string DefinitionId { get; init; } = default!; public string DefinitionVersionId { get; init; } = default!; public int Version { get; init; } diff --git a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs index 4468e29d5..b12eb0b28 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs @@ -41,7 +41,6 @@ public abstract class Composite : ActivityBase, IVariableContainer /// The activity to schedule when this activity executes. /// [Port] - [Browsable(false)] [JsonIgnore] // Composite activities' Root is intended to be constructed from code only. public IActivity Root { get; set; } = new Sequence(); diff --git a/src/modules/Elsa.Workflows.Core/Activities/NotFoundActivity.cs b/src/modules/Elsa.Workflows.Core/Activities/NotFoundActivity.cs index 21c381043..bf89e2a92 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/NotFoundActivity.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/NotFoundActivity.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Models; namespace Elsa.Workflows.Core.Activities; @@ -7,6 +8,7 @@ namespace Elsa.Workflows.Core.Activities; /// This activity is instantiated in case a workflow references an activity type that could not be found. /// [Browsable(false)] +[Activity("Elsa", "Workflows", "A placeholder activity that will be used in case a workflow definition references an activity type that cannot be found.")] public class NotFoundActivity : Activity { /// diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs index f65c706f7..3c26ec627 100644 --- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs @@ -10,9 +10,12 @@ using Elsa.Workflows.Core.ActivityNodeResolvers; using Elsa.Workflows.Core.Builders; using Elsa.Workflows.Core.Expressions; using Elsa.Workflows.Core.Implementations; +using Elsa.Workflows.Core.Middleware.Activities; +using Elsa.Workflows.Core.Middleware.Workflows; using Elsa.Workflows.Core.Pipelines.ActivityExecution; using Elsa.Workflows.Core.Pipelines.WorkflowExecution; using Elsa.Workflows.Core.Serialization; +using Elsa.Workflows.Core.Serialization.Converters; using Elsa.Workflows.Core.Services; using Microsoft.Extensions.DependencyInjection; @@ -40,6 +43,16 @@ public class WorkflowsFeature : FeatureBase /// public Func StandardOutStreamProvider { get; set; } = _ => new StandardOutStreamProvider(Console.Out); + /// + /// A delegate to configure the . + /// + public Action WorkflowExecutionPipeline { get; set; } = builder => builder.UseDefaultActivityScheduler(); + + /// + /// A delegate to configure the . + /// + public Action ActivityExecutionPipeline { get; set; } = builder => builder.UseDefaultActivityInvoker(); + /// /// Fluent method to set . /// @@ -58,6 +71,24 @@ public class WorkflowsFeature : FeatureBase return this; } + /// + /// Fluent method to configure the . + /// + public WorkflowsFeature WithWorkflowExecutionPipeline(Action setup) + { + WorkflowExecutionPipeline = setup; + return this; + } + + /// + /// Fluent method to configure the . + /// + public WorkflowsFeature WithActivityExecutionPipeline(Action setup) + { + ActivityExecutionPipeline = setup; + return this; + } + /// public override void Apply() { @@ -78,7 +109,7 @@ public class WorkflowsFeature : FeatureBase .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddTransient() @@ -89,7 +120,7 @@ public class WorkflowsFeature : FeatureBase // Pipelines. .AddSingleton() - .AddSingleton() + .AddSingleton(sp => new WorkflowExecutionPipeline(sp, WorkflowExecutionPipeline)) // Built-in activity services. .AddSingleton() diff --git a/src/modules/Elsa.Workflows.Core/Implementations/GuidIdentityGenerator.cs b/src/modules/Elsa.Workflows.Core/Implementations/GuidIdentityGenerator.cs new file mode 100644 index 000000000..eec3cacbc --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Implementations/GuidIdentityGenerator.cs @@ -0,0 +1,12 @@ +using Elsa.Workflows.Core.Services; + +namespace Elsa.Workflows.Core.Implementations; + +/// +/// Generates a unique identifier using . +/// +public class GuidIdentityGenerator : IIdentityGenerator +{ + /// + public string GenerateId() => Guid.NewGuid().ToString("N"); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Implementations/RandomIdentityGenerator.cs b/src/modules/Elsa.Workflows.Core/Implementations/RandomIdentityGenerator.cs deleted file mode 100644 index 4f0ccee6b..000000000 --- a/src/modules/Elsa.Workflows.Core/Implementations/RandomIdentityGenerator.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Elsa.Workflows.Core.Services; - -namespace Elsa.Workflows.Core.Implementations; - -public class RandomIdentityGenerator : IIdentityGenerator -{ - public string GenerateId() => Guid.NewGuid().ToString("N"); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Middleware/Activities/DefaultActivityInvokerMiddleware.cs b/src/modules/Elsa.Workflows.Core/Middleware/Activities/DefaultActivityInvokerMiddleware.cs index 3f4c4c841..d99f9b5c1 100644 --- a/src/modules/Elsa.Workflows.Core/Middleware/Activities/DefaultActivityInvokerMiddleware.cs +++ b/src/modules/Elsa.Workflows.Core/Middleware/Activities/DefaultActivityInvokerMiddleware.cs @@ -7,14 +7,14 @@ using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.Middleware.Activities; /// -/// Provides extension methods to . +/// Provides extension methods to . /// public static class ActivityInvokerMiddlewareExtensions { /// /// Adds the component to the pipeline. /// - public static IActivityExecutionBuilder UseDefaultActivityInvoker(this IActivityExecutionBuilder builder) => builder.UseMiddleware(); + public static IActivityExecutionPipelineBuilder UseDefaultActivityInvoker(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); } /// diff --git a/src/modules/Elsa.Workflows.Core/Middleware/Activities/ExceptionHandlingMiddleware.cs b/src/modules/Elsa.Workflows.Core/Middleware/Activities/ExceptionHandlingMiddleware.cs index f53931e45..8bf5ef4cf 100644 --- a/src/modules/Elsa.Workflows.Core/Middleware/Activities/ExceptionHandlingMiddleware.cs +++ b/src/modules/Elsa.Workflows.Core/Middleware/Activities/ExceptionHandlingMiddleware.cs @@ -13,7 +13,7 @@ public static class ExceptionHandlingMiddlewareExtensions /// /// Installs the component in the activity execution pipeline. /// - public static IActivityExecutionBuilder UseExceptionHandling(this IActivityExecutionBuilder builder) => builder.UseMiddleware(); + public static IActivityExecutionPipelineBuilder UseExceptionHandling(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); } /// diff --git a/src/modules/Elsa.Workflows.Core/Middleware/Activities/LoggingMiddleware.cs b/src/modules/Elsa.Workflows.Core/Middleware/Activities/LoggingMiddleware.cs index 8b1d12520..400619c4c 100644 --- a/src/modules/Elsa.Workflows.Core/Middleware/Activities/LoggingMiddleware.cs +++ b/src/modules/Elsa.Workflows.Core/Middleware/Activities/LoggingMiddleware.cs @@ -32,5 +32,5 @@ public class LoggingMiddleware : IActivityExecutionMiddleware public static class LoggingMiddlewareExtensions { - public static IActivityExecutionBuilder UseLogging(this IActivityExecutionBuilder builder) => builder.UseMiddleware(); + public static IActivityExecutionPipelineBuilder UseLogging(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Middleware/Workflows/DefaultActivitySchedulerMiddleware.cs b/src/modules/Elsa.Workflows.Core/Middleware/Workflows/DefaultActivitySchedulerMiddleware.cs index f4f84726e..67e83f1d6 100644 --- a/src/modules/Elsa.Workflows.Core/Middleware/Workflows/DefaultActivitySchedulerMiddleware.cs +++ b/src/modules/Elsa.Workflows.Core/Middleware/Workflows/DefaultActivitySchedulerMiddleware.cs @@ -9,7 +9,7 @@ public static class UseActivitySchedulerMiddlewareExtensions /// /// Installs middleware that executes scheduled work items (activities). /// - public static IWorkflowExecutionBuilder UseDefaultActivityScheduler(this IWorkflowExecutionBuilder builder) => builder.UseMiddleware(); + public static IWorkflowExecutionPipelineBuilder UseDefaultActivityScheduler(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); } public class DefaultActivitySchedulerMiddleware : WorkflowExecutionMiddleware diff --git a/src/modules/Elsa.Workflows.Core/Models/Workflow.cs b/src/modules/Elsa.Workflows.Core/Models/Workflow.cs index 098efcf05..132fb6b70 100644 --- a/src/modules/Elsa.Workflows.Core/Models/Workflow.cs +++ b/src/modules/Elsa.Workflows.Core/Models/Workflow.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Text.Json.Serialization; using Elsa.Expressions.Models; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.Models; @@ -10,6 +11,7 @@ namespace Elsa.Workflows.Core.Models; /// Represents an executable process. /// [Browsable(false)] +[Activity("Elsa", "Workflows", "A workflow is an activity that executes its Root activity.")] public class Workflow : Composite, ICloneable { /// diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionMiddlewareExtensions.cs b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionMiddlewareExtensions.cs index 66e95bc41..2af510a5a 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionMiddlewareExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionMiddlewareExtensions.cs @@ -5,15 +5,15 @@ namespace Elsa.Workflows.Core.Pipelines.ActivityExecution; public static class ActivityExecutionMiddlewareExtensions { - public static IActivityExecutionBuilder UseMiddleware(this IActivityExecutionBuilder builder, params object[] args) where TMiddleware : IActivityExecutionMiddleware + public static IActivityExecutionPipelineBuilder UseMiddleware(this IActivityExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IActivityExecutionMiddleware { var middleware = typeof(TMiddleware); - return builder.Use(next => + return pipelineBuilder.Use(next => { var invokeMethod = MiddlewareHelpers.GetInvokeMethod(middleware); var ctorArgs = new[] { next }.Concat(args).Select(x => x!).ToArray(); - var instance = ActivatorUtilities.CreateInstance(builder.ServiceProvider, middleware, ctorArgs); + var instance = ActivatorUtilities.CreateInstance(pipelineBuilder.ServiceProvider, middleware, ctorArgs); return (ActivityMiddlewareDelegate)invokeMethod.CreateDelegate(typeof(ActivityMiddlewareDelegate), instance); }); } diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipeline.cs b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipeline.cs index 98d1e2287..8916ce11d 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipeline.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipeline.cs @@ -19,9 +19,9 @@ public class ActivityExecutionPipeline : IActivityExecutionPipeline } /// - public ActivityMiddlewareDelegate Setup(Action setup) + public ActivityMiddlewareDelegate Setup(Action setup) { - var builder = new ActivityExecutionPipelineBuilder(_serviceProvider); + var builder = new ActivityExecutionPipelinePipelineBuilder(_serviceProvider); setup(builder); _pipeline = builder.Build(); return _pipeline; diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelineBuilder.cs b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelinePipelineBuilder.cs similarity index 71% rename from src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelineBuilder.cs rename to src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelinePipelineBuilder.cs index bd239ef74..7acc8f0e2 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelineBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/ActivityExecution/ActivityExecutionPipelinePipelineBuilder.cs @@ -2,18 +2,18 @@ using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.Pipelines.ActivityExecution; -public class ActivityExecutionPipelineBuilder : IActivityExecutionBuilder +public class ActivityExecutionPipelinePipelineBuilder : IActivityExecutionPipelineBuilder { private readonly IList> _components = new List>(); - public ActivityExecutionPipelineBuilder(IServiceProvider serviceProvider) + public ActivityExecutionPipelinePipelineBuilder(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; } public IServiceProvider ServiceProvider { get; } - public IActivityExecutionBuilder Use(Func middleware) + public IActivityExecutionPipelineBuilder Use(Func middleware) { _components.Add(middleware); return this; diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionMiddlewareExtensions.cs b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionMiddlewareExtensions.cs index f2f74266e..ceafe77eb 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionMiddlewareExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionMiddlewareExtensions.cs @@ -3,17 +3,23 @@ using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.Core.Pipelines.WorkflowExecution; +/// +/// Provides extensions to that adds support for installing components. +/// public static class WorkflowExecutionMiddlewareExtensions { - public static IWorkflowExecutionBuilder UseMiddleware(this IWorkflowExecutionBuilder builder, params object[] args) where TMiddleware: IWorkflowExecutionMiddleware + /// + /// Installs the specified middleware component into the pipeline being built. + /// + public static IWorkflowExecutionPipelineBuilder UseMiddleware(this IWorkflowExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware: IWorkflowExecutionMiddleware { var middleware = typeof(TMiddleware); - return builder.Use(next => + return pipelineBuilder.Use(next => { var invokeMethod = MiddlewareHelpers.GetInvokeMethod(middleware); - var ctorParams = new[] { next }.Concat(args).Select(x => x!).ToArray(); - var instance = ActivatorUtilities.CreateInstance(builder.ApplicationServices, middleware, ctorParams); + var ctorParams = new[] { next }.Concat(args).Select(x => x).ToArray(); + var instance = ActivatorUtilities.CreateInstance(pipelineBuilder.ServiceProvider, middleware, ctorParams); return (WorkflowMiddlewareDelegate)invokeMethod.CreateDelegate(typeof(WorkflowMiddlewareDelegate), instance); }); } diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipeline.cs b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipeline.cs index 9a45a9114..c890d7625 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipeline.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipeline.cs @@ -4,15 +4,26 @@ using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.Pipelines.WorkflowExecution; +/// public class WorkflowExecutionPipeline : IWorkflowExecutionPipeline { private readonly IServiceProvider _serviceProvider; private WorkflowMiddlewareDelegate? _pipeline; - public WorkflowExecutionPipeline(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + /// + /// Constructor. + /// + public WorkflowExecutionPipeline(IServiceProvider serviceProvider, Action pipelineBuilder) + { + _serviceProvider = serviceProvider; + Setup(pipelineBuilder); + } + + /// public WorkflowMiddlewareDelegate Pipeline => _pipeline ??= CreateDefaultPipeline(); - public WorkflowMiddlewareDelegate Setup(Action setup) + /// + public WorkflowMiddlewareDelegate Setup(Action setup) { var builder = new WorkflowExecutionPipelineBuilder(_serviceProvider); setup(builder); @@ -20,6 +31,7 @@ public class WorkflowExecutionPipeline : IWorkflowExecutionPipeline return _pipeline; } + /// public async Task ExecuteAsync(WorkflowExecutionContext context) => await Pipeline(context); private WorkflowMiddlewareDelegate CreateDefaultPipeline() => Setup(x => x.UseDefaultActivityScheduler()); diff --git a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipelineBuilder.cs b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipelineBuilder.cs index 4c7505376..c61b018ee 100644 --- a/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipelineBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Pipelines/WorkflowExecution/WorkflowExecutionPipelineBuilder.cs @@ -2,30 +2,38 @@ using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.Pipelines.WorkflowExecution; -public class WorkflowExecutionPipelineBuilder : IWorkflowExecutionBuilder +/// +public class WorkflowExecutionPipelineBuilder : IWorkflowExecutionPipelineBuilder { private const string ServicesKey = "workflow-execution.Services"; private readonly IList> _components = new List>(); + /// + /// Constructor. + /// public WorkflowExecutionPipelineBuilder(IServiceProvider serviceProvider) { - ApplicationServices = serviceProvider; + ServiceProvider = serviceProvider; } - public IDictionary Properties { get; } = new Dictionary(); + /// + public IDictionary Properties { get; } = new Dictionary(); - public IServiceProvider ApplicationServices + /// + public IServiceProvider ServiceProvider { get => GetProperty(ServicesKey)!; set => SetProperty(ServicesKey, value); } - public IWorkflowExecutionBuilder Use(Func middleware) + /// + public IWorkflowExecutionPipelineBuilder Use(Func middleware) { _components.Add(middleware); return this; } - + + /// public WorkflowMiddlewareDelegate Build() { WorkflowMiddlewareDelegate pipeline = _ => new ValueTask(); @@ -36,6 +44,13 @@ public class WorkflowExecutionPipelineBuilder : IWorkflowExecutionBuilder return pipeline; } + /// + public IWorkflowExecutionPipelineBuilder Reset() + { + _components.Clear(); + return this; + } + private T? GetProperty(string key) => Properties.TryGetValue(key, out var value) ? (T?)value : default(T); private void SetProperty(string key, T value) => Properties[key] = value; } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipeline.cs b/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipeline.cs index 17ffe456d..47bfe9faa 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipeline.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipeline.cs @@ -5,7 +5,7 @@ namespace Elsa.Workflows.Core.Services; public interface IActivityExecutionPipeline { - ActivityMiddlewareDelegate Setup(Action setup); + ActivityMiddlewareDelegate Setup(Action setup); ActivityMiddlewareDelegate Pipeline { get; } Task ExecuteAsync(ActivityExecutionContext context); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionBuilder.cs b/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipelineBuilder.cs similarity index 53% rename from src/modules/Elsa.Workflows.Core/Services/IActivityExecutionBuilder.cs rename to src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipelineBuilder.cs index 40457ac08..06b13bc69 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IActivityExecutionPipelineBuilder.cs @@ -2,9 +2,9 @@ using Elsa.Workflows.Core.Pipelines.ActivityExecution; namespace Elsa.Workflows.Core.Services; -public interface IActivityExecutionBuilder +public interface IActivityExecutionPipelineBuilder { IServiceProvider ServiceProvider { get; } - IActivityExecutionBuilder Use(Func middleware); + IActivityExecutionPipelineBuilder Use(Func middleware); public ActivityMiddlewareDelegate Build(); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IIdentityGenerator.cs b/src/modules/Elsa.Workflows.Core/Services/IIdentityGenerator.cs index ee7c6ef97..0b9640ea5 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IIdentityGenerator.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IIdentityGenerator.cs @@ -1,6 +1,12 @@ namespace Elsa.Workflows.Core.Services; +/// +/// Represents a unique identity generator. +/// public interface IIdentityGenerator { + /// + /// Generates a unique identifier. + /// string GenerateId(); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IWorkflowBuilder.cs b/src/modules/Elsa.Workflows.Core/Services/IWorkflowBuilder.cs index bd5e5bd49..26a31f47d 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IWorkflowBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IWorkflowBuilder.cs @@ -3,7 +3,7 @@ using Elsa.Workflows.Core.Models; namespace Elsa.Workflows.Core.Services; /// -/// A workflow builder collects information about a workflow to be built programmatically. +/// A workflow pipelineBuilder collects information about a workflow to be built programmatically. /// public interface IWorkflowBuilder { @@ -98,7 +98,7 @@ public interface IWorkflowBuilder IWorkflowBuilder WithActivationStrategyType() where T : IWorkflowActivationStrategy; /// - /// Build a new instance using the information collected in this builder. + /// Build a new instance using the information collected in this pipelineBuilder. /// Workflow BuildWorkflow(); diff --git a/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionBuilder.cs b/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionBuilder.cs deleted file mode 100644 index 10f5f1258..000000000 --- a/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionBuilder.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Elsa.Workflows.Core.Pipelines.WorkflowExecution; - -namespace Elsa.Workflows.Core.Services; - -public interface IWorkflowExecutionBuilder -{ - public IDictionary Properties { get; } - IServiceProvider ApplicationServices { get; } - IWorkflowExecutionBuilder Use(Func middleware); - public WorkflowMiddlewareDelegate Build(); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipeline.cs b/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipeline.cs index 38ea65f28..2431a2b3f 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipeline.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipeline.cs @@ -5,7 +5,7 @@ namespace Elsa.Workflows.Core.Services; public interface IWorkflowExecutionPipeline { - WorkflowMiddlewareDelegate Setup(Action setup); + WorkflowMiddlewareDelegate Setup(Action setup); WorkflowMiddlewareDelegate Pipeline { get; } Task ExecuteAsync(WorkflowExecutionContext context); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipelineBuilder.cs b/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipelineBuilder.cs new file mode 100644 index 000000000..2521f5e0e --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Services/IWorkflowExecutionPipelineBuilder.cs @@ -0,0 +1,34 @@ +using Elsa.Workflows.Core.Pipelines.WorkflowExecution; + +namespace Elsa.Workflows.Core.Services; + +/// +/// Used to build a workflow execution pipeline. +/// +public interface IWorkflowExecutionPipelineBuilder +{ + /// + /// A general-purpose dictionary of values that can be used by middleware components. + /// + public IDictionary Properties { get; } + + /// + /// The current service provider to resolve services from. + /// + IServiceProvider ServiceProvider { get; } + + /// + /// Installs the specified delegate as a middleware component. + /// + IWorkflowExecutionPipelineBuilder Use(Func middleware); + + /// + /// Constructs the final delegate that invokes each installed middleware component. + /// + public WorkflowMiddlewareDelegate Build(); + + /// + /// Clears the current pipeline. + /// + IWorkflowExecutionPipelineBuilder Reset(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowBase.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowBase.cs index c9ff9388d..6574fb335 100644 --- a/src/modules/Elsa.Workflows.Core/Services/WorkflowBase.cs +++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowBase.cs @@ -3,7 +3,7 @@ using Elsa.Workflows.Core.Models; namespace Elsa.Workflows.Core.Services; /// -/// A base class for implementing workflow definitions using the builder API. +/// A base class for implementing workflow definitions using the pipelineBuilder API. /// public abstract class WorkflowBase : IWorkflow { @@ -43,7 +43,7 @@ public abstract class WorkflowBase : IWorkflow } /// -/// A base class for implementing workflow definitions that can return a result using the builder API. +/// A base class for implementing workflow definitions that can return a result using the pipelineBuilder API. /// public abstract class WorkflowBase : WorkflowBase { diff --git a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs index e21a3f64e..ba8c4872a 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs @@ -1,5 +1,6 @@ using Elsa.Features.Services; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Features; // ReSharper disable once CheckNamespace @@ -22,4 +23,14 @@ public static class ModuleExtensions }); return module; } + + /// + /// Adds all types implementing to the system. + /// + public static IModule AddActivitiesFrom(this IModule module) => module.UseWorkflowManagement(management => management.AddActivitiesFrom()); + + /// + /// Adds the specified activity type to the system. + /// + public static IModule AddActivity(this IModule module) where T:IActivity => module.UseWorkflowManagement(management => management.AddActivity()); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs index 8dae7906c..dd771ba2d 100644 --- a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs @@ -89,12 +89,9 @@ public class WorkflowManagementFeature : FeatureBase /// public WorkflowManagementFeature AddActivitiesFrom() { - var activityTypes = typeof(TMarker).Assembly.GetExportedTypes().Where(x => - { - var browsableAttr = x.GetCustomAttribute(); - var isBrowsable = browsableAttr == null || browsableAttr.Browsable; - return typeof(IActivity).IsAssignableFrom(x) && !x.IsAbstract && !x.IsInterface && !x.IsGenericType && isBrowsable; - }).ToList(); + var activityTypes = typeof(TMarker).Assembly.GetExportedTypes() + .Where(x => typeof(IActivity).IsAssignableFrom(x) && !x.IsAbstract && !x.IsInterface && !x.IsGenericType) + .ToList(); return AddActivities(activityTypes); } diff --git a/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistryPopulator.cs b/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistryPopulator.cs index 7b1556134..568c87e08 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistryPopulator.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistryPopulator.cs @@ -10,12 +10,16 @@ public class ActivityRegistryPopulator : IActivityRegistryPopulator private readonly IEnumerable _providers; private readonly IActivityRegistry _registry; + /// + /// Constructor. + /// public ActivityRegistryPopulator(IEnumerable providers, IActivityRegistry registry) { _providers = providers; _registry = registry; } + /// public async Task PopulateRegistryAsync(CancellationToken cancellationToken) { _registry.Clear(); @@ -24,6 +28,7 @@ public class ActivityRegistryPopulator : IActivityRegistryPopulator await PopulateRegistryAsync(provider, cancellationToken); } + /// public async Task PopulateRegistryAsync(Type providerType, CancellationToken cancellationToken = default) { _registry.ClearProvider(providerType); diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/ModuleExtensions.cs index 43e189b37..2b3a50f06 100644 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/ModuleExtensions.cs @@ -4,8 +4,14 @@ using Elsa.Workflows.Runtime.Features; // ReSharper disable once CheckNamespace namespace Elsa.Extensions; +/// +/// Adds extensions to setup the feature. +/// public static class ModuleExtensions { + /// + /// Enables the feature. + /// public static IModule UseWorkflowRuntime(this IModule module, Action? configure = default) { module.Configure(configure); diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionBuilderExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionBuilderExtensions.cs deleted file mode 100644 index 034286271..000000000 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionBuilderExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Elsa.Workflows.Core.Pipelines.WorkflowExecution; -using Elsa.Workflows.Core.Services; -using Elsa.Workflows.Runtime.Middleware; - -// ReSharper disable once CheckNamespace -namespace Elsa.Extensions; - -public static class WorkflowExecutionPipelineBuilderExtensions -{ - /// - /// Installs middleware that persists the workflow instance before and after workflow execution. - /// - public static IWorkflowExecutionBuilder UsePersistentVariables(this IWorkflowExecutionBuilder builder) => builder.UseMiddleware(); - - /// - /// Installs middleware that persists bookmarks after workflow execution. - /// - public static IWorkflowExecutionBuilder UseBookmarkPersistence(this IWorkflowExecutionBuilder builder) => builder.UseMiddleware(); - - /// - /// Installs middleware that persist the workflow execution journal. - /// - public static IWorkflowExecutionBuilder UseWorkflowExecutionLogPersistence(this IWorkflowExecutionBuilder builder) => builder.UseMiddleware(); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionPipelineBuilderExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionPipelineBuilderExtensions.cs new file mode 100644 index 000000000..ee1a5405c --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowExecutionPipelineBuilderExtensions.cs @@ -0,0 +1,40 @@ +using Elsa.Features.Services; +using Elsa.Workflows.Core.Middleware.Workflows; +using Elsa.Workflows.Core.Pipelines.WorkflowExecution; +using Elsa.Workflows.Core.Services; +using Elsa.Workflows.Runtime.Middleware; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Provides extensions to that add various middleware components. +/// +public static class WorkflowExecutionPipelineBuilderExtensions +{ + /// + /// Configures the workflow execution pipeline with commonly used components. + /// + public static IWorkflowExecutionPipelineBuilder UseDefaultRuntimePipeline(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => + pipelineBuilder + .Reset() + .UsePersistentVariables() + .UseBookmarkPersistence() + .UseWorkflowExecutionLogPersistence() + .UseDefaultActivityScheduler(); + + /// + /// Installs middleware that persists the workflow instance before and after workflow execution. + /// + public static IWorkflowExecutionPipelineBuilder UsePersistentVariables(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); + + /// + /// Installs middleware that persists bookmarks after workflow execution. + /// + public static IWorkflowExecutionPipelineBuilder UseBookmarkPersistence(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); + + /// + /// Installs middleware that persist the workflow execution journal. + /// + public static IWorkflowExecutionPipelineBuilder UseWorkflowExecutionLogPersistence(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.UseMiddleware(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowsFeatureExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowsFeatureExtensions.cs new file mode 100644 index 000000000..1eadc04d9 --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowsFeatureExtensions.cs @@ -0,0 +1,15 @@ +using Elsa.Workflows.Core.Features; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Adds an extension method to the that installs a default workflow runtime execution pipeline. +/// +public static class WorkflowsFeatureExtensions +{ + /// + /// Installs a default workflow runtime execution pipeline. + /// + public static WorkflowsFeature WithDefaultRuntimeWorkflowExecutionPipeline(this WorkflowsFeature workflowsFeature) => workflowsFeature.WithWorkflowExecutionPipeline(pipeline => pipeline.UseDefaultRuntimePipeline()); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs index cd3f85f4a..45b47795c 100644 --- a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs +++ b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs @@ -55,9 +55,24 @@ public class WorkflowRuntimeFeature : FeatureBase /// public Func BookmarkStore { get; set; } = sp => sp.GetRequiredService(); + /// + /// A factory that instantiates an . + /// public Func WorkflowTriggerStore { get; set; } = sp => sp.GetRequiredService(); + + /// + /// A factory that instantiates an . + /// public Func WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequiredService(); + + /// + /// A factory that instantiates an . + /// public Func DistributedLockProvider { get; set; } = _ => new FileDistributedSynchronizationProvider(new DirectoryInfo( Path.Combine(Environment.CurrentDirectory, "App_Data/locks"))); + + /// + /// A factory that instantiates an . + /// public Func WorkflowStateExporter { get; set; } = sp => sp.GetRequiredService(); /// diff --git a/src/modules/Elsa.Workflows.Runtime/Implementations/AsyncWorkflowStateExporter.cs b/src/modules/Elsa.Workflows.Runtime/Implementations/AsyncWorkflowStateExporter.cs index 6939c0b24..259977a62 100644 --- a/src/modules/Elsa.Workflows.Runtime/Implementations/AsyncWorkflowStateExporter.cs +++ b/src/modules/Elsa.Workflows.Runtime/Implementations/AsyncWorkflowStateExporter.cs @@ -36,10 +36,12 @@ public class AsyncWorkflowStateExporter : IWorkflowStateExporter, ICommandHandle _workflowInstanceStore = workflowInstanceStore; _systemClock = systemClock; } - + + /// public async ValueTask ExportAsync(Workflow workflow, WorkflowState workflowState, CancellationToken cancellationToken) => await _backgroundCommandSender.SendAsync(new ExportWorkflowStateToDb(workflowState), cancellationToken); + /// public async Task HandleAsync(ExportWorkflowStateToDb command, CancellationToken cancellationToken) { var workflowState = command.WorkflowState; diff --git a/src/modules/Elsa.Workflows.Runtime/Middleware/PersistBookmarkMiddleware.cs b/src/modules/Elsa.Workflows.Runtime/Middleware/PersistBookmarkMiddleware.cs index 3704761cd..dd4ef8289 100644 --- a/src/modules/Elsa.Workflows.Runtime/Middleware/PersistBookmarkMiddleware.cs +++ b/src/modules/Elsa.Workflows.Runtime/Middleware/PersistBookmarkMiddleware.cs @@ -9,7 +9,7 @@ using Elsa.Workflows.Runtime.Services; namespace Elsa.Workflows.Runtime.Middleware; /// -/// Takes care of loading & persisting workflow variables. +/// Takes care of loading and persisting bookmarks. /// public class PersistBookmarkMiddleware : WorkflowExecutionMiddleware { diff --git a/src/modules/Elsa.Workflows.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs b/src/modules/Elsa.Workflows.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs index 0d092e0a9..46dd8e87d 100644 --- a/src/modules/Elsa.Workflows.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs +++ b/src/modules/Elsa.Workflows.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs @@ -14,12 +14,14 @@ public class PersistWorkflowExecutionLogMiddleware : WorkflowExecutionMiddleware private readonly IWorkflowExecutionLogStore _workflowExecutionLogStore; private readonly IIdentityGenerator _identityGenerator; + /// public PersistWorkflowExecutionLogMiddleware(WorkflowMiddlewareDelegate next, IWorkflowExecutionLogStore workflowExecutionLogStore, IIdentityGenerator identityGenerator) : base(next) { _workflowExecutionLogStore = workflowExecutionLogStore; _identityGenerator = identityGenerator; } + /// public override async ValueTask InvokeAsync(WorkflowExecutionContext context) { // Invoke next middleware. diff --git a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs index a5e6555ab..2bc99fc7f 100644 --- a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs @@ -22,8 +22,11 @@ var services = builder.Services; var configuration = builder.Configuration; var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; var identityOptions = new IdentityOptions(); +var identityTokenOptions = new IdentityTokenOptions(); var identitySection = configuration.GetSection("Identity"); +var identityTokenSection = identitySection.GetSection("Tokens"); identitySection.Bind(identityOptions); +identityTokenSection.Bind(identityTokenOptions); // Add Elsa services. services @@ -47,8 +50,8 @@ services ) .UseIdentity(identity => { - identity.CreateDefaultUser = true; identity.IdentityOptions = identityOptions; + identity.TokenOptions = identityTokenOptions; }) .UseWorkflowRuntime(runtime => { @@ -76,7 +79,7 @@ services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader() // Authentication & Authorization. services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, identityOptions.ConfigureJwtBearerOptions); + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, identityTokenOptions.ConfigureJwtBearerOptions); services.AddHttpContextAccessor(); services.AddSingleton(); @@ -88,15 +91,6 @@ services.AddAuthorization(options => options.AddPolicy(IdentityPolicyNames.Secur var app = builder.Build(); var serviceProvider = app.Services; -// Configure workflow engine execution pipeline. -serviceProvider.ConfigureDefaultWorkflowExecutionPipeline(pipeline => - pipeline - .UsePersistentVariables() - .UseBookmarkPersistence() - .UseWorkflowContexts() - .UseDefaultActivityScheduler() -); - // Configure activity execution pipeline to use the job-based activity invoker. serviceProvider.ConfigureDefaultActivityExecutionPipeline(pipeline => pipeline.UseJobBasedActivityInvoker()); diff --git a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/appsettings.json b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/appsettings.json index 82954dd48..66e22e0bb 100644 --- a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/appsettings.json +++ b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/appsettings.json @@ -11,7 +11,10 @@ "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;" }, "Identity": { - "SigningKey": "secret-signing-key" + "CreateDefaultAdmin": true, + "Tokens": { + "SigningKey": "secret-signing-key" + } }, "Telnyx": { "ApiKey": "", diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowServer/Program.cs b/src/samples/aspnet/Elsa.Samples.WorkflowServer/Program.cs index 45a1dd7f4..fc1427e25 100644 --- a/src/samples/aspnet/Elsa.Samples.WorkflowServer/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.WorkflowServer/Program.cs @@ -19,8 +19,8 @@ builder.Services.AddElsa(elsa => // Configure identity so that we can create a default admin user. elsa.UseIdentity(identity => { - identity.CreateDefaultUser = builder.Environment.IsDevelopment(); - identity.IdentityOptions.SigningKey = "secret-token-signing-key"; + identity.IdentityOptions.CreateDefaultAdmin = builder.Environment.IsDevelopment(); + identity.TokenOptions.SigningKey = "secret-token-signing-key"; }); // Use default authentication (JWT). diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowServerAndDesigner/Program.cs b/src/samples/aspnet/Elsa.Samples.WorkflowServerAndDesigner/Program.cs index a7be7b9b9..a7405c256 100644 --- a/src/samples/aspnet/Elsa.Samples.WorkflowServerAndDesigner/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.WorkflowServerAndDesigner/Program.cs @@ -19,8 +19,8 @@ builder.Services.AddElsa(elsa => // Configure identity so that we can create a default admin user. elsa.UseIdentity(identity => { - identity.CreateDefaultUser = builder.Environment.IsDevelopment(); - identity.IdentityOptions.SigningKey = "secret-token-signing-key"; + identity.IdentityOptions.CreateDefaultAdmin = builder.Environment.IsDevelopment(); + identity.TokenOptions.SigningKey = "secret-token-signing-key"; }); // Use default authentication (JWT). diff --git a/templates/elsa-workflow-app/ElsaWorkflowsApp/ElsaWorkflowsApp.csproj b/templates/elsa-workflow-app/ElsaWorkflowsApp/ElsaWorkflowsApp.csproj deleted file mode 100644 index 0529efe14..000000000 --- a/templates/elsa-workflow-app/ElsaWorkflowsApp/ElsaWorkflowsApp.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net6.0;net7.0 - enable - enable - Linux - false - - - - - - - - - - - - - diff --git a/templates/elsa-workflow-app/ElsaWorkflowsApp/Program.cs b/templates/elsa-workflow-app/ElsaWorkflowsApp/Program.cs deleted file mode 100644 index 50b7ca119..000000000 --- a/templates/elsa-workflow-app/ElsaWorkflowsApp/Program.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Elsa.EntityFrameworkCore.Extensions; -using Elsa.EntityFrameworkCore.Modules.ActivityDefinitions; -using Elsa.EntityFrameworkCore.Modules.Labels; -using Elsa.EntityFrameworkCore.Modules.Runtime; -using Elsa.Extensions; -using Elsa.Identity; -using Elsa.Identity.Options; -using Elsa.Requirements; -using Microsoft.AspNetCore.Authorization; - -var builder = WebApplication.CreateBuilder(args); -var services = builder.Services; -var configuration = builder.Configuration; -var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; -var identityOptions = new IdentityOptions(); -var identitySection = configuration.GetSection("Identity"); -identitySection.Bind(identityOptions); - -// Add Elsa services. -services - .AddElsa(elsa => elsa - .UseWorkflows() - .UseWorkflowsApi() - .UseIdentity(identity => - { - identity.CreateDefaultUser = true; - identity.IdentityOptions = identityOptions; - }) - .UseDefaultAuthentication() - .UseWorkflowRuntime(runtime => { runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)); }) - .UseLabels(labels => labels.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) - .UseActivityDefinitions(feature => feature.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) - .UseJavaScript() - .UseLiquid() - .UseHttp() - ); - -services.AddHealthChecks(); -services.AddHttpContextAccessor(); -services.AddSingleton(); -services.AddAuthorization(options => options.AddPolicy(IdentityPolicyNames.SecurityRoot, policy => policy.AddRequirements(new LocalHostRequirement()))); - -// Razor Pages. -services.AddRazorPages(); - -// Configure middleware pipeline. -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (!app.Environment.IsDevelopment()) -{ - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); -} - -app.UseHttpsRedirection(); -app.UseStaticFiles(); -app.UseRouting(); -app.UseAuthentication(); -app.UseAuthorization(); -app.UseWorkflowsApi(); -app.UseWorkflows(); - -app.UseEndpoints(endpoints => -{ - endpoints.MapFallbackToPage("/Index"); -}); - -app.MapRazorPages(); -app.Run(); \ No newline at end of file diff --git a/templates/elsa-workflow-app/ElsaWorkflowsApp/Properties/launchSettings.json b/templates/elsa-workflow-app/ElsaWorkflowsApp/Properties/launchSettings.json deleted file mode 100644 index bf356e78a..000000000 --- a/templates/elsa-workflow-app/ElsaWorkflowsApp/Properties/launchSettings.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:20241", - "sslPort": 44391 - } - }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5118", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7113;http://localhost:5118", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.Development.json b/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.json b/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/templates/elsa-workflow-app/ElsaWorkflowsApp/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -}