diff --git a/Elsa.sln b/Elsa.sln index 3333b9f37..7ce63c59f 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{7D ProjectSection(SolutionItems) = preProject README.md = README.md docker-compose.yml = docker-compose.yml + common.props = common.props + configureawait.props = configureawait.props EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{0354F050-3992-4DD4-B0EE-5FBA04AC72B6}" @@ -78,7 +80,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AllInOne.Web", "src\bu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.WorkflowServer.Web", "src\bundles\Elsa.WorkflowServer.Web\Elsa.WorkflowServer.Web.csproj", "{3C2752A7-EEBC-4ED4-B1BF-0FCF6E071BC2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Persistence.Abstractions", "src\common\Elsa.Persistence.Abstractions\Elsa.Persistence.Abstractions.csproj", "{6D590FA1-898B-429B-AE85-DE16BE691246}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Persistence.Common", "src\common\Elsa.Persistence.Common\Elsa.Persistence.Common.csproj", "{6D590FA1-898B-429B-AE85-DE16BE691246}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Persistence.EntityFrameworkCore.Common", "src\common\Elsa.Persistence.EntityFrameworkCore.Common\Elsa.Persistence.EntityFrameworkCore.Common.csproj", "{B962750E-C2B1-4F5A-B3C5-6C64CAF1ED2E}" EndProject @@ -100,8 +102,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Features", "src\common EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MemoryCache", "src\modules\Elsa.MemoryCache\Elsa.MemoryCache.csproj", "{2570418D-1674-4DAE-9A24-9146D522450C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AspNetCore", "src\modules\Elsa.AspNetCore\Elsa.AspNetCore.csproj", "{2CFF3041-BB6A-45EA-9716-7BA531BA6479}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions", "src\modules\Elsa.Expressions\Elsa.Expressions.csproj", "{80529478-A383-4FEA-B744-C71264969E9A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Mediator", "src\modules\Elsa.Mediator\Elsa.Mediator.csproj", "{40ED82D8-A7BB-4D37-9157-3176EDA3E119}" @@ -132,6 +132,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "worker", "worker", "{389D40 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.Worker1", "src\samples\Elsa.Samples.Worker1\Elsa.Samples.Worker1.csproj", "{197223FB-2472-442C-BD10-2E1F931285BC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Models.Common", "src\common\Elsa.Models.Common\Elsa.Models.Common.csproj", "{81BDD2FB-810E-4526-8290-80BA2F4FC473}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -290,10 +292,6 @@ Global {2570418D-1674-4DAE-9A24-9146D522450C}.Debug|Any CPU.Build.0 = Debug|Any CPU {2570418D-1674-4DAE-9A24-9146D522450C}.Release|Any CPU.ActiveCfg = Release|Any CPU {2570418D-1674-4DAE-9A24-9146D522450C}.Release|Any CPU.Build.0 = Release|Any CPU - {2CFF3041-BB6A-45EA-9716-7BA531BA6479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2CFF3041-BB6A-45EA-9716-7BA531BA6479}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2CFF3041-BB6A-45EA-9716-7BA531BA6479}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2CFF3041-BB6A-45EA-9716-7BA531BA6479}.Release|Any CPU.Build.0 = Release|Any CPU {80529478-A383-4FEA-B744-C71264969E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80529478-A383-4FEA-B744-C71264969E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU {80529478-A383-4FEA-B744-C71264969E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -342,6 +340,10 @@ Global {517B703A-7653-4036-AAB5-7B4293D39D0F}.Debug|Any CPU.Build.0 = Debug|Any CPU {197223FB-2472-442C-BD10-2E1F931285BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {197223FB-2472-442C-BD10-2E1F931285BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81BDD2FB-810E-4526-8290-80BA2F4FC473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81BDD2FB-810E-4526-8290-80BA2F4FC473}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81BDD2FB-810E-4526-8290-80BA2F4FC473}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81BDD2FB-810E-4526-8290-80BA2F4FC473}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F} @@ -385,7 +387,6 @@ Global {8A050229-DB79-4E0B-9AFF-7565E87F2954} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {C237BA1A-3A7D-4AB2-BE09-2696F3C082A4} = {C6658DE0-2B2F-47F0-BB61-2CA66D435C09} {2570418D-1674-4DAE-9A24-9146D522450C} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} - {2CFF3041-BB6A-45EA-9716-7BA531BA6479} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {80529478-A383-4FEA-B744-C71264969E9A} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {40ED82D8-A7BB-4D37-9157-3176EDA3E119} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {80FF5821-E831-450D-AA0C-C76D07D878F4} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} @@ -402,5 +403,6 @@ Global {517B703A-7653-4036-AAB5-7B4293D39D0F} = {873BFC3E-63C2-4495-A503-5EC05DCD84E4} {F599E891-598E-402F-A9B9-95D0B1C661F6} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {26087ED2-9249-4FF3-8869-C11C405E441A} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} + {81BDD2FB-810E-4526-8290-80BA2F4FC473} = {C6658DE0-2B2F-47F0-BB61-2CA66D435C09} EndGlobalSection EndGlobal diff --git a/common.props b/common.props new file mode 100644 index 000000000..5c1d5687e --- /dev/null +++ b/common.props @@ -0,0 +1,30 @@ + + + latest + Elsa Contributors + 2022 + https://github.com/elsa-workflows/elsa-core + https://github.com/elsa-workflows/elsa-core + git + enable + enable + MIT + https://elsaworkflows.io/nuget-icon.png + + true + Default + latest + + + true + snupkg + true + + + + + all + runtime; build; native; contentfiles; analyzers + + + \ No newline at end of file diff --git a/configureawait.props b/configureawait.props new file mode 100644 index 000000000..2792f54a7 --- /dev/null +++ b/configureawait.props @@ -0,0 +1,9 @@ + + + + + All + runtime; build; native; contentfiles; analyzers + + + \ No newline at end of file diff --git a/src/bundles/Elsa.AllInOne.Web/Elsa.AllInOne.Web.csproj b/src/bundles/Elsa.AllInOne.Web/Elsa.AllInOne.Web.csproj index 34ab90a19..77b17ce9e 100644 --- a/src/bundles/Elsa.AllInOne.Web/Elsa.AllInOne.Web.csproj +++ b/src/bundles/Elsa.AllInOne.Web/Elsa.AllInOne.Web.csproj @@ -1,5 +1,5 @@ - + net6.0 enable diff --git a/src/bundles/Elsa.AllInOne.Web/Program.cs b/src/bundles/Elsa.AllInOne.Web/Program.cs index 2c093c996..17f3fee18 100644 --- a/src/bundles/Elsa.AllInOne.Web/Program.cs +++ b/src/bundles/Elsa.AllInOne.Web/Program.cs @@ -1,5 +1,4 @@ using Elsa.Workflows.Api.Extensions; -using Elsa.AspNetCore.Extensions; using Elsa.Extensions; using Elsa.Jobs.Extensions; using Elsa.Http; @@ -46,7 +45,6 @@ services .UseLiquid() .UseHttp() .UseCustomActivities() - .UseMvc() ); // Register serialization configurator for configuring what types to allow to be serialized. diff --git a/src/bundles/Elsa.AllInOne.Web/README b/src/bundles/Elsa.AllInOne.Web/README new file mode 100644 index 000000000..99ccbf321 --- /dev/null +++ b/src/bundles/Elsa.AllInOne.Web/README @@ -0,0 +1,3 @@ +# All In One + +This project represents an Elsa application that hosts both the workflow server as well as the dashboard. \ No newline at end of file diff --git a/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj b/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj index 576b16841..ba1b05d8d 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj +++ b/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + Linux diff --git a/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomAccessTokenIssuer.cs b/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomAccessTokenIssuer.cs deleted file mode 100644 index 83a33f039..000000000 --- a/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomAccessTokenIssuer.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Elsa.Api.Common; -using Elsa.Api.Common.Options; -using Elsa.Api.Common.Services; -using Elsa.WorkflowServer.Web.Models; -using FastEndpoints.Security; -using Microsoft.Extensions.Options; - -namespace Elsa.WorkflowServer.Web.Implementations; - -public class CustomAccessTokenIssuer : IAccessTokenIssuer -{ - private readonly AccessTokenOptions _options; - - public CustomAccessTokenIssuer(IOptions options) - { - _options = options.Value; - } - - public ValueTask CreateTokenAsync(IDictionary credentials, object? context, CancellationToken cancellationToken = default) - { - var user = context as User; - var fullName = user!.FullName; - - var jwtToken = JWTBearer.CreateToken( - signingKey: _options.SigningKey, - roles: new[] { RoleNames.Admin }, - permissions: new[] { PermissionNames.Everything }, - claims: new[] { new Claim(JwtRegisteredClaimNames.Name, fullName) } - ); - - return new(jwtToken); - } -} \ No newline at end of file diff --git a/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomCredentialsValidator.cs b/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomCredentialsValidator.cs deleted file mode 100644 index f496e7ac8..000000000 --- a/src/bundles/Elsa.WorkflowServer.Web/Implementations/CustomCredentialsValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Elsa.Api.Common.Models; -using Elsa.Api.Common.Services; -using Elsa.WorkflowServer.Web.Models; - -namespace Elsa.WorkflowServer.Web.Implementations; - -public class CustomCredentialsValidator : ICredentialsValidator -{ - public ValueTask ValidateCredentialsAsync(IDictionary credentials, CancellationToken cancellationToken = default) - { - var isValid = credentials.TryGetValue("user", out var user) && user == "admin" && credentials.TryGetValue("password", out var password) && password == "admin"; - - return !isValid - ? new(ValidateCredentialsResult.Invalid()) - : new(ValidateCredentialsResult.Valid(new User("Superman"))); - } -} \ No newline at end of file diff --git a/src/bundles/Elsa.WorkflowServer.Web/Program.cs b/src/bundles/Elsa.WorkflowServer.Web/Program.cs index 815619f24..a4d6f03fb 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Program.cs +++ b/src/bundles/Elsa.WorkflowServer.Web/Program.cs @@ -2,10 +2,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.ActivityDefinitions.EntityFrameworkCore.Extensions; using Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite; -using Elsa.Api.Common; -using Elsa.Api.Common.Features; -using Elsa.Api.Common.Options; -using Elsa.AspNetCore.Extensions; using Elsa.Extensions; using Elsa.Features.Extensions; using Elsa.Http; @@ -32,24 +28,12 @@ using Elsa.Workflows.Persistence.EntityFrameworkCore.Extensions; using Elsa.Workflows.Persistence.EntityFrameworkCore.Sqlite; using Elsa.Workflows.Persistence.Extensions; using Elsa.Workflows.Runtime.Extensions; -using Elsa.WorkflowServer.Web.Implementations; using Elsa.WorkflowServer.Web.Jobs; using FastEndpoints; using FastEndpoints.Security; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; -var configuration = builder.Configuration; -var accessTokenOptions = new AccessTokenOptions(); -configuration.GetSection("AccessTokens").Bind(accessTokenOptions); - -// Global control over Elsa API endpoints security. -ApiSecurityOptions.AllowAnonymous = !builder.Environment.IsProduction(); -ApiSecurityOptions.ValidateRoles = builder.Environment.IsProduction(); - -// Add application-specific services. -services.AddSingleton(); -services.AddSingleton(); // Add Elsa services. services @@ -70,12 +54,6 @@ services .AddActivity() .AddActivity() ) - .Use(feature => - { - feature.TokenSigningKey = accessTokenOptions.SigningKey; - feature.CredentialsValidator = sp => sp.GetRequiredService(); - feature.AccessTokenIssuer = sp => sp.GetRequiredService(); - }) .UseJobActivities() .UseScheduling() .UseWorkflowPersistence(p => p.UseEntityFrameworkCore(ef => ef.UseSqlite())) @@ -85,11 +63,9 @@ services .UseLabels(labels => labels.UseEntityFrameworkCore(ef => ef.UseSqlite())) .UseCustomActivities(feature => feature.UseEntityFrameworkCore(ef => ef.UseSqlite())) .UseHttp() - .UseMvc() ); services.AddFastEndpoints(); -services.AddAuthenticationJWTBearer(accessTokenOptions.SigningKey); services.AddHealthChecks(); services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin())); @@ -161,9 +137,9 @@ Task SerializeRequestAsync(HttpResponse httpResponse, object dto, string content app.UseFastEndpoints(config => { - config.RoutingOptions = routing => routing.Prefix = "elsa/api"; - config.RequestDeserializer = DeserializeRequestAsync; - config.ResponseSerializer = SerializeRequestAsync; + config.Endpoints.RoutePrefix = "elsa/api"; + config.Serializer.RequestDeserializer = DeserializeRequestAsync; + config.Serializer.ResponseSerializer = SerializeRequestAsync; }); // Register Elsa middleware. diff --git a/src/bundles/Elsa.WorkflowServer.Web/README b/src/bundles/Elsa.WorkflowServer.Web/README new file mode 100644 index 000000000..f10864488 --- /dev/null +++ b/src/bundles/Elsa.WorkflowServer.Web/README @@ -0,0 +1,3 @@ +# Server + +This project represents an Elsa application that hosts workflows and exposes API endpoints to manage & execute workflows. \ No newline at end of file diff --git a/src/bundles/Elsa.WorkflowServer.Web/appsettings.json b/src/bundles/Elsa.WorkflowServer.Web/appsettings.json index e3defe4e6..006192806 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/appsettings.json +++ b/src/bundles/Elsa.WorkflowServer.Web/appsettings.json @@ -6,8 +6,5 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*", - "AccessTokens": { - "SigningKey": "ultra-secure-key" - } + "AllowedHosts": "*" } diff --git a/src/bundles/Elsa/Elsa.csproj b/src/bundles/Elsa/Elsa.csproj index fb2af3f26..6222a719e 100644 --- a/src/bundles/Elsa/Elsa.csproj +++ b/src/bundles/Elsa/Elsa.csproj @@ -1,10 +1,15 @@ + + + net6.0 - enable + + Bundles the most commonly-used packages when building an Elsa workflows application. + Elsa - latest + elsa diff --git a/src/bundles/Elsa/Extensions/DependencyInjectionExtensions.cs b/src/bundles/Elsa/Extensions/DependencyInjectionExtensions.cs index 186eb19a1..487cf94c7 100644 --- a/src/bundles/Elsa/Extensions/DependencyInjectionExtensions.cs +++ b/src/bundles/Elsa/Extensions/DependencyInjectionExtensions.cs @@ -1,4 +1,3 @@ -using System; using Elsa.Features; using Elsa.Features.Extensions; using Elsa.Features.Services; @@ -6,21 +5,20 @@ using Microsoft.Extensions.DependencyInjection; namespace Elsa.Extensions; +/// +/// Provides extension methods to . +/// public static class DependencyInjectionExtensions { + /// + /// Creates a new Elsa module and adds the to it. + /// public static IServiceCollection AddElsa(this IServiceCollection services, Action? configure = default) - { - var serviceConfiguration = services.ConfigureElsa(); - configure?.Invoke(serviceConfiguration); - serviceConfiguration.Apply(); - return services; - } - - public static IModule ConfigureElsa(this IServiceCollection services) { var module = services.CreateModule(); module.Configure(); - - return module; + configure?.Invoke(module); + module.Apply(); + return services; } } \ No newline at end of file diff --git a/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs b/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs index 353a02845..2c96cf461 100644 --- a/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs +++ b/src/bundles/Elsa/Extensions/ServiceProviderExtensions.cs @@ -1,11 +1,16 @@ -using System; using Elsa.Workflows.Core.Services; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Extensions; +/// +/// Provides extension methods to the . +/// public static class ServiceProviderExtensions { + /// + /// Configure the default activity execution pipeline. + /// public static IServiceProvider ConfigureDefaultActivityExecutionPipeline(this IServiceProvider services, Action setup) { var pipeline = services.GetRequiredService(); @@ -13,6 +18,9 @@ public static class ServiceProviderExtensions return services; } + /// + /// Configure the default workflow execution pipeline. + /// public static IServiceProvider ConfigureDefaultWorkflowExecutionPipeline(this IServiceProvider services, Action setup) { var pipeline = services.GetRequiredService(); diff --git a/src/bundles/Elsa/Features/ElsaFeature.cs b/src/bundles/Elsa/Features/ElsaFeature.cs index 53aa19303..50dd5a6b4 100644 --- a/src/bundles/Elsa/Features/ElsaFeature.cs +++ b/src/bundles/Elsa/Features/ElsaFeature.cs @@ -1,4 +1,3 @@ -using Elsa.Api.Common.Features; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; @@ -10,15 +9,18 @@ using Elsa.Workflows.Runtime.Features; namespace Elsa.Features; +/// +/// Represents Elsa as a feature of the system. +/// [DependsOn(typeof(MediatorFeature))] [DependsOn(typeof(WorkflowsFeature))] [DependsOn(typeof(FlowchartFeature))] [DependsOn(typeof(WorkflowPersistenceFeature))] [DependsOn(typeof(WorkflowRuntimeFeature))] [DependsOn(typeof(WorkflowManagementFeature))] -[DependsOn(typeof(CommonApiFeature))] public class ElsaFeature : FeatureBase { + /// public ElsaFeature(IModule module) : base(module) { } diff --git a/src/common/Elsa.Api.Common/ApiSecurityOptions.cs b/src/common/Elsa.Api.Common/ApiSecurityOptions.cs deleted file mode 100644 index c6c6d1533..000000000 --- a/src/common/Elsa.Api.Common/ApiSecurityOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Elsa.Api.Common; - -public static class ApiSecurityOptions -{ - public static bool AllowAnonymous = true; - public static bool ValidatePermissions = false; - public static bool ValidatePolicies = false; - public static bool ValidateRoles = false; -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Constants.cs b/src/common/Elsa.Api.Common/Constants.cs deleted file mode 100644 index 598451b89..000000000 --- a/src/common/Elsa.Api.Common/Constants.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Elsa.Api.Common; - -public static class PermissionNames -{ - /// - /// Allow access to all API endpoints. - /// - public const string Everything = "Everything"; -} - -public static class PolicyNames -{ - public const string Admin = "Admin"; -} - -public static class RoleNames -{ - public const string Admin = "Admin"; -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Elsa.Api.Common.csproj b/src/common/Elsa.Api.Common/Elsa.Api.Common.csproj index aa4c9af6b..8716b2568 100644 --- a/src/common/Elsa.Api.Common/Elsa.Api.Common.csproj +++ b/src/common/Elsa.Api.Common/Elsa.Api.Common.csproj @@ -1,20 +1,26 @@ + + + net6.0 - enable - enable + + Provides common features to modules that expose API endpoints. + + Elsa + elsa, api - - - + + + - + diff --git a/src/common/Elsa.Api.Common/Features/CommonApiFeature.cs b/src/common/Elsa.Api.Common/Features/CommonApiFeature.cs deleted file mode 100644 index 3d676b85e..000000000 --- a/src/common/Elsa.Api.Common/Features/CommonApiFeature.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Elsa.Api.Common.Implementations; -using Elsa.Api.Common.Options; -using Elsa.Api.Common.Services; -using Elsa.Features.Abstractions; -using Elsa.Features.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.Api.Common.Features; - -public class CommonApiFeature : FeatureBase -{ - public CommonApiFeature(IModule module) : base(module) - { - } - - public string TokenSigningKey { get; set; } = default!; - public Func CredentialsValidator { get; set; } = ActivatorUtilities.GetServiceOrCreateInstance; - public Func AccessTokenIssuer { get; set; } = ActivatorUtilities.GetServiceOrCreateInstance; - - public override void Apply() - { - Services.Configure(options => options.SigningKey = TokenSigningKey); - Services.AddSingleton(sp => CredentialsValidator(sp)); - Services.AddSingleton(sp => AccessTokenIssuer(sp)); - } -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Implementations/AdminAccessTokenIssuer.cs b/src/common/Elsa.Api.Common/Implementations/AdminAccessTokenIssuer.cs deleted file mode 100644 index 6882d3ab9..000000000 --- a/src/common/Elsa.Api.Common/Implementations/AdminAccessTokenIssuer.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Elsa.Api.Common.Options; -using Elsa.Api.Common.Services; -using FastEndpoints.Security; -using Microsoft.Extensions.Options; - -namespace Elsa.Api.Common.Implementations; - -/// -/// Creates access tokens that grant full access to all Elsa API endpoints by means of the Admin role and Everything permissions. -/// -public class AdminAccessTokenIssuer : IAccessTokenIssuer -{ - private readonly AccessTokenOptions _options; - - public AdminAccessTokenIssuer(IOptions options) - { - _options = options.Value; - } - - public ValueTask CreateTokenAsync(IDictionary credentials, object? context, CancellationToken cancellationToken = default) - { - var jwtToken = JWTBearer.CreateToken( - signingKey: _options.SigningKey, - roles: new[] { RoleNames.Admin }, - permissions: new[] { PermissionNames.Everything }); - - return new(jwtToken); - } -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Implementations/AllowAnyCredentialsValidator.cs b/src/common/Elsa.Api.Common/Implementations/AllowAnyCredentialsValidator.cs deleted file mode 100644 index 77533fc85..000000000 --- a/src/common/Elsa.Api.Common/Implementations/AllowAnyCredentialsValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Elsa.Api.Common.Models; -using Elsa.Api.Common.Services; - -namespace Elsa.Api.Common.Implementations; - -public class AllowAnyCredentialsValidator : ICredentialsValidator -{ - public ValueTask ValidateCredentialsAsync(IDictionary credentials, CancellationToken cancellationToken = default) => new(ValidateCredentialsResult.Valid()); -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Models/EndpointConfiguration.cs b/src/common/Elsa.Api.Common/Models/EndpointConfiguration.cs deleted file mode 100644 index 53beca488..000000000 --- a/src/common/Elsa.Api.Common/Models/EndpointConfiguration.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Elsa.Api.Common.Models; - -public class EndpointConfiguration -{ - public ICollection Policies { get; } = new List(); -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Models/PagedListResponse.cs b/src/common/Elsa.Api.Common/Models/PagedListResponse.cs index e65d37155..c3ee1e296 100644 --- a/src/common/Elsa.Api.Common/Models/PagedListResponse.cs +++ b/src/common/Elsa.Api.Common/Models/PagedListResponse.cs @@ -1,6 +1,4 @@ -using Elsa.Persistence.Common.Models; - -namespace Elsa.Api.Common.Models; +namespace Elsa.Models; public class PagedListResponse { diff --git a/src/common/Elsa.Api.Common/Models/ValidateCredentialsResult.cs b/src/common/Elsa.Api.Common/Models/ValidateCredentialsResult.cs index 586bfaf18..d03565677 100644 --- a/src/common/Elsa.Api.Common/Models/ValidateCredentialsResult.cs +++ b/src/common/Elsa.Api.Common/Models/ValidateCredentialsResult.cs @@ -1,4 +1,4 @@ -namespace Elsa.Api.Common.Models; +namespace Elsa.Models; public record ValidateCredentialsResult(bool IsValid, object? Context = null) { diff --git a/src/common/Elsa.Api.Common/Options/AccessTokenOptions.cs b/src/common/Elsa.Api.Common/Options/AccessTokenOptions.cs deleted file mode 100644 index e0c4441fa..000000000 --- a/src/common/Elsa.Api.Common/Options/AccessTokenOptions.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Elsa.Api.Common.Options; - -public class AccessTokenOptions -{ - public string SigningKey { get; set; } = default!; -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/ProtectedEndpoint.cs b/src/common/Elsa.Api.Common/ProtectedEndpoint.cs deleted file mode 100644 index 693719c05..000000000 --- a/src/common/Elsa.Api.Common/ProtectedEndpoint.cs +++ /dev/null @@ -1,45 +0,0 @@ -using FastEndpoints; - -namespace Elsa.Api.Common; - -public class ProtectedEndpoint : Endpoint where TRequest : notnull, new() where TResponse : notnull, new() -{ - protected void ConfigureSecurity(IEnumerable permissions, IEnumerable policies, IEnumerable roles) - { - if (ApiSecurityOptions.AllowAnonymous) - { - AllowAnonymous(); - return; - } - - if (ApiSecurityOptions.ValidatePermissions) - Permissions(new[] { PermissionNames.Everything }.Concat(permissions).ToArray()); - - if (ApiSecurityOptions.ValidatePolicies) - Policies(new[] { PolicyNames.Admin }.Concat(policies).ToArray()); - - if (ApiSecurityOptions.ValidateRoles) - Roles(new[] { RoleNames.Admin }.Concat(roles).ToArray()); - } -} - -public class ProtectedEndpoint : Endpoint where TRequest : notnull, new() -{ - protected void ConfigureSecurity(IEnumerable permissions, IEnumerable policies, IEnumerable roles) - { - if (ApiSecurityOptions.AllowAnonymous) - { - AllowAnonymous(); - return; - } - - if (ApiSecurityOptions.ValidatePermissions) - Permissions(new[] { PermissionNames.Everything }.Concat(permissions).ToArray()); - - if (ApiSecurityOptions.ValidatePolicies) - Policies(new[] { PolicyNames.Admin }.Concat(policies).ToArray()); - - if (ApiSecurityOptions.ValidateRoles) - Roles(new[] { RoleNames.Admin }.Concat(roles).ToArray()); - } -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Services/IAccessTokenIssuer.cs b/src/common/Elsa.Api.Common/Services/IAccessTokenIssuer.cs deleted file mode 100644 index bf4aff29c..000000000 --- a/src/common/Elsa.Api.Common/Services/IAccessTokenIssuer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Elsa.Api.Common.Services; - -/// -/// Implement this to issue new security tokens based on the specified credentials. -/// -public interface IAccessTokenIssuer -{ - ValueTask CreateTokenAsync(IDictionary credentials, object? context, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/src/common/Elsa.Api.Common/Services/ICredentialsValidator.cs b/src/common/Elsa.Api.Common/Services/ICredentialsValidator.cs deleted file mode 100644 index e1c2d09d8..000000000 --- a/src/common/Elsa.Api.Common/Services/ICredentialsValidator.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Elsa.Api.Common.Models; - -namespace Elsa.Api.Common.Services; - -public interface ICredentialsValidator -{ - ValueTask ValidateCredentialsAsync(IDictionary credentials, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/src/common/Elsa.Features/Abstractions/FeatureBase.cs b/src/common/Elsa.Features/Abstractions/FeatureBase.cs index ffcd53056..df354e23f 100644 --- a/src/common/Elsa.Features/Abstractions/FeatureBase.cs +++ b/src/common/Elsa.Features/Abstractions/FeatureBase.cs @@ -3,24 +3,46 @@ using Microsoft.Extensions.DependencyInjection; namespace Elsa.Features.Abstractions; +/// +/// Base type for classes that represent a feature. +/// public abstract class FeatureBase : IFeature { + /// + /// Constructor. + /// protected FeatureBase(IModule module) { Module = module; } + /// + /// The module this feature is a part of. + /// public IModule Module { get; } + + /// + /// A reference to the to which services can be added. + /// public IServiceCollection Services => Module.Services; + /// + /// Override this method to configure your feature. + /// public virtual void Configure() { } + /// + /// Override this method to register any hosted services provided by your feature. + /// public virtual void ConfigureHostedServices() { } + /// + /// Override this to register services with . + /// public virtual void Apply() { } diff --git a/src/common/Elsa.Features/Elsa.Features.csproj b/src/common/Elsa.Features/Elsa.Features.csproj index edf7aaa8c..b7a7df0a0 100644 --- a/src/common/Elsa.Features/Elsa.Features.csproj +++ b/src/common/Elsa.Features/Elsa.Features.csproj @@ -1,9 +1,14 @@ + + + net6.0 - enable - enable + + Provides utilities to turn your class library into a module that provides features. + + elsa, common diff --git a/src/common/Elsa.Formatting/Elsa.Formatting.csproj b/src/common/Elsa.Formatting/Elsa.Formatting.csproj index eb2460e91..ca6d7ad9c 100644 --- a/src/common/Elsa.Formatting/Elsa.Formatting.csproj +++ b/src/common/Elsa.Formatting/Elsa.Formatting.csproj @@ -1,9 +1,14 @@ + + + net6.0 - enable - enable + + A small utility library for formatting objects from and to strings. + + elsa, common diff --git a/src/common/Elsa.Models.Common/Elsa.Models.Common.csproj b/src/common/Elsa.Models.Common/Elsa.Models.Common.csproj new file mode 100644 index 000000000..f1394c12d --- /dev/null +++ b/src/common/Elsa.Models.Common/Elsa.Models.Common.csproj @@ -0,0 +1,15 @@ + + + + + + + net6.0 + + Provides common models used by various modules. + + Elsa + elsa, common + + + diff --git a/src/common/Elsa.Persistence.Abstractions/Models/Page.cs b/src/common/Elsa.Models.Common/Models/Page.cs similarity index 81% rename from src/common/Elsa.Persistence.Abstractions/Models/Page.cs rename to src/common/Elsa.Models.Common/Models/Page.cs index 44aab82f4..a0aacc483 100644 --- a/src/common/Elsa.Persistence.Abstractions/Models/Page.cs +++ b/src/common/Elsa.Models.Common/Models/Page.cs @@ -1,4 +1,4 @@ -namespace Elsa.Persistence.Common.Models; +namespace Elsa.Models; public record Page(ICollection Items, long TotalCount); diff --git a/src/common/Elsa.Persistence.Abstractions/Models/PageArgs.cs b/src/common/Elsa.Models.Common/Models/PageArgs.cs similarity index 75% rename from src/common/Elsa.Persistence.Abstractions/Models/PageArgs.cs rename to src/common/Elsa.Models.Common/Models/PageArgs.cs index 62c36fe7e..c5950ef02 100644 --- a/src/common/Elsa.Persistence.Abstractions/Models/PageArgs.cs +++ b/src/common/Elsa.Models.Common/Models/PageArgs.cs @@ -1,4 +1,4 @@ -namespace Elsa.Persistence.Common.Models; +namespace Elsa.Models; public record PageArgs(int? Page, int? PageSize) { diff --git a/src/common/Elsa.Persistence.Abstractions/Models/VersionOptions.cs b/src/common/Elsa.Models.Common/Models/VersionOptions.cs similarity index 97% rename from src/common/Elsa.Persistence.Abstractions/Models/VersionOptions.cs rename to src/common/Elsa.Models.Common/Models/VersionOptions.cs index cac446c86..0c3238b73 100644 --- a/src/common/Elsa.Persistence.Abstractions/Models/VersionOptions.cs +++ b/src/common/Elsa.Models.Common/Models/VersionOptions.cs @@ -1,7 +1,7 @@ using System.ComponentModel; -using Elsa.Persistence.Common.TypeConverters; +using Elsa.TypeConverters; -namespace Elsa.Persistence.Common.Models; +namespace Elsa.Models; [TypeConverter(typeof(VersionOptionsTypeConverter))] public struct VersionOptions diff --git a/src/common/Elsa.Persistence.Abstractions/TypeConverters/VersionOptionsTypeConverter.cs b/src/common/Elsa.Models.Common/TypeConverters/VersionOptionsTypeConverter.cs similarity index 85% rename from src/common/Elsa.Persistence.Abstractions/TypeConverters/VersionOptionsTypeConverter.cs rename to src/common/Elsa.Models.Common/TypeConverters/VersionOptionsTypeConverter.cs index 0126c0830..82a04a4de 100644 --- a/src/common/Elsa.Persistence.Abstractions/TypeConverters/VersionOptionsTypeConverter.cs +++ b/src/common/Elsa.Models.Common/TypeConverters/VersionOptionsTypeConverter.cs @@ -1,8 +1,8 @@ using System.ComponentModel; using System.Globalization; -using Elsa.Persistence.Common.Models; +using Elsa.Models; -namespace Elsa.Persistence.Common.TypeConverters +namespace Elsa.TypeConverters { public class VersionOptionsTypeConverter : TypeConverter { diff --git a/src/common/Elsa.Persistence.Abstractions/Elsa.Persistence.Abstractions.csproj b/src/common/Elsa.Persistence.Abstractions/Elsa.Persistence.Abstractions.csproj deleted file mode 100644 index 71df591ff..000000000 --- a/src/common/Elsa.Persistence.Abstractions/Elsa.Persistence.Abstractions.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net6.0 - enable - enable - Elsa.Persistence.Common - - - - - - - - diff --git a/src/common/Elsa.Persistence.Common/Elsa.Persistence.Common.csproj b/src/common/Elsa.Persistence.Common/Elsa.Persistence.Common.csproj new file mode 100644 index 000000000..e4c88cccd --- /dev/null +++ b/src/common/Elsa.Persistence.Common/Elsa.Persistence.Common.csproj @@ -0,0 +1,23 @@ + + + + + + + net6.0 + + Provides common features that can be used by persistence modules. + + elsa, common, persistence + + + + + + + + + + + + diff --git a/src/common/Elsa.Persistence.Abstractions/Entities/Entity.cs b/src/common/Elsa.Persistence.Common/Entities/Entity.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Entities/Entity.cs rename to src/common/Elsa.Persistence.Common/Entities/Entity.cs diff --git a/src/common/Elsa.Persistence.Abstractions/Entities/OrderBy.cs b/src/common/Elsa.Persistence.Common/Entities/OrderBy.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Entities/OrderBy.cs rename to src/common/Elsa.Persistence.Common/Entities/OrderBy.cs diff --git a/src/common/Elsa.Persistence.Abstractions/Entities/OrderDirection.cs b/src/common/Elsa.Persistence.Common/Entities/OrderDirection.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Entities/OrderDirection.cs rename to src/common/Elsa.Persistence.Common/Entities/OrderDirection.cs diff --git a/src/common/Elsa.Persistence.Abstractions/Entities/VersionedEntity.cs b/src/common/Elsa.Persistence.Common/Entities/VersionedEntity.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Entities/VersionedEntity.cs rename to src/common/Elsa.Persistence.Common/Entities/VersionedEntity.cs diff --git a/src/common/Elsa.Persistence.Abstractions/Extensions/DependencyInjectionExtensions.cs b/src/common/Elsa.Persistence.Common/Extensions/DependencyInjectionExtensions.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Extensions/DependencyInjectionExtensions.cs rename to src/common/Elsa.Persistence.Common/Extensions/DependencyInjectionExtensions.cs diff --git a/src/common/Elsa.Persistence.Abstractions/Extensions/EnumerableExtensions.cs b/src/common/Elsa.Persistence.Common/Extensions/EnumerableExtensions.cs similarity index 96% rename from src/common/Elsa.Persistence.Abstractions/Extensions/EnumerableExtensions.cs rename to src/common/Elsa.Persistence.Common/Extensions/EnumerableExtensions.cs index 204ef46b7..7d4221728 100644 --- a/src/common/Elsa.Persistence.Abstractions/Extensions/EnumerableExtensions.cs +++ b/src/common/Elsa.Persistence.Common/Extensions/EnumerableExtensions.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.Persistence.Common.Extensions; diff --git a/src/common/Elsa.Persistence.Abstractions/Extensions/QueryableExtensions.cs b/src/common/Elsa.Persistence.Common/Extensions/QueryableExtensions.cs similarity index 96% rename from src/common/Elsa.Persistence.Abstractions/Extensions/QueryableExtensions.cs rename to src/common/Elsa.Persistence.Common/Extensions/QueryableExtensions.cs index fe4ae8e36..e2421371a 100644 --- a/src/common/Elsa.Persistence.Abstractions/Extensions/QueryableExtensions.cs +++ b/src/common/Elsa.Persistence.Common/Extensions/QueryableExtensions.cs @@ -1,5 +1,5 @@ using System.Linq.Expressions; -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.Persistence.Common.Extensions; diff --git a/src/common/Elsa.Persistence.Abstractions/Extensions/VersionedEntityExtensions.cs b/src/common/Elsa.Persistence.Common/Extensions/VersionedEntityExtensions.cs similarity index 98% rename from src/common/Elsa.Persistence.Abstractions/Extensions/VersionedEntityExtensions.cs rename to src/common/Elsa.Persistence.Common/Extensions/VersionedEntityExtensions.cs index 73850c67c..bcbdb20e2 100644 --- a/src/common/Elsa.Persistence.Abstractions/Extensions/VersionedEntityExtensions.cs +++ b/src/common/Elsa.Persistence.Common/Extensions/VersionedEntityExtensions.cs @@ -1,6 +1,6 @@ using System.Linq.Expressions; +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using LinqKit; namespace Elsa.Persistence.Common.Extensions; diff --git a/src/common/Elsa.Persistence.Abstractions/Implementations/MemoryStore.cs b/src/common/Elsa.Persistence.Common/Implementations/MemoryStore.cs similarity index 100% rename from src/common/Elsa.Persistence.Abstractions/Implementations/MemoryStore.cs rename to src/common/Elsa.Persistence.Common/Implementations/MemoryStore.cs diff --git a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Elsa.Persistence.EntityFrameworkCore.Common.csproj b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Elsa.Persistence.EntityFrameworkCore.Common.csproj index f7706a01f..d7bab8d5a 100644 --- a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Elsa.Persistence.EntityFrameworkCore.Common.csproj +++ b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Elsa.Persistence.EntityFrameworkCore.Common.csproj @@ -1,9 +1,14 @@ + + + net6.0 - enable - enable + + Provides common features that can be used by persistence modules using Entity Framework Core. + + elsa @@ -23,7 +28,7 @@ - + diff --git a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Extensions/QueryableExtensions.cs b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Extensions/QueryableExtensions.cs index 6626e8b8d..db71df573 100644 --- a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Extensions/QueryableExtensions.cs +++ b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Extensions/QueryableExtensions.cs @@ -1,6 +1,6 @@ using System.Linq.Expressions; using EFCore.BulkExtensions; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Microsoft.EntityFrameworkCore; namespace Elsa.Persistence.EntityFrameworkCore.Common.Extensions; diff --git a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Implementations/EFCoreStore.cs b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Implementations/EFCoreStore.cs index 61f31f926..d30a99181 100644 --- a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Implementations/EFCoreStore.cs +++ b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Implementations/EFCoreStore.cs @@ -1,7 +1,7 @@ using System.Linq.Expressions; using EFCore.BulkExtensions; +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Extensions; using Elsa.Persistence.EntityFrameworkCore.Common.Services; using Microsoft.EntityFrameworkCore; diff --git a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Services/IStore.cs b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Services/IStore.cs index b6829b75c..0c4e9d956 100644 --- a/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Services/IStore.cs +++ b/src/common/Elsa.Persistence.EntityFrameworkCore.Common/Services/IStore.cs @@ -1,6 +1,6 @@ using System.Linq.Expressions; +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; namespace Elsa.Persistence.EntityFrameworkCore.Common.Services; diff --git a/src/common/Elsa.ServiceBus.Abstractions/Elsa.ServiceBus.Abstractions.csproj b/src/common/Elsa.ServiceBus.Abstractions/Elsa.ServiceBus.Abstractions.csproj index 168c16fd2..dfad98f4d 100644 --- a/src/common/Elsa.ServiceBus.Abstractions/Elsa.ServiceBus.Abstractions.csproj +++ b/src/common/Elsa.ServiceBus.Abstractions/Elsa.ServiceBus.Abstractions.csproj @@ -1,9 +1,15 @@ + + + net6.0 - enable - enable + + Provides abstractions representing a service bus that can be used by other Elsa modules. + Concrete implementations are provided by different packages such as Elsa.MassTransit. + + elsa, common, service bus diff --git a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.csproj b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.csproj index 20218b587..7f431b16f 100644 --- a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.csproj +++ b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite/Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.csproj @@ -1,13 +1,18 @@ + + + net6.0 - enable - enable + + Provides migrations specific to SQLite for the Entity Framework Core implementation. + + elsa, module, efcore, sqlite - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Elsa.ActivityDefinitions.EntityFrameworkCore.csproj b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Elsa.ActivityDefinitions.EntityFrameworkCore.csproj index 9d7403b41..0bd1e7f3f 100644 --- a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Elsa.ActivityDefinitions.EntityFrameworkCore.csproj +++ b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Elsa.ActivityDefinitions.EntityFrameworkCore.csproj @@ -1,13 +1,18 @@ + + + net6.0 - enable - enable + + Provides an Entity Framework Core implementation of the persistence abstractions provided by Elsa.ActivityDefinitions. + + elsa, module, efcore - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Implementations/EFCoreActivityDefinitionStore.cs b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Implementations/EFCoreActivityDefinitionStore.cs index 7dd7f3c25..cb90479fc 100644 --- a/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Implementations/EFCoreActivityDefinitionStore.cs +++ b/src/modules/Elsa.ActivityDefinitions.EntityFrameworkCore/Implementations/EFCoreActivityDefinitionStore.cs @@ -2,8 +2,8 @@ using System.Linq.Expressions; using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Models; using Elsa.ActivityDefinitions.Services; +using Elsa.Models; using Elsa.Persistence.Common.Extensions; -using Elsa.Persistence.Common.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Extensions; using Elsa.Persistence.EntityFrameworkCore.Common.Services; diff --git a/src/modules/Elsa.ActivityDefinitions/Elsa.ActivityDefinitions.csproj b/src/modules/Elsa.ActivityDefinitions/Elsa.ActivityDefinitions.csproj index b2e01abbb..17b137113 100644 --- a/src/modules/Elsa.ActivityDefinitions/Elsa.ActivityDefinitions.csproj +++ b/src/modules/Elsa.ActivityDefinitions/Elsa.ActivityDefinitions.csproj @@ -1,9 +1,15 @@ + + + net6.0 - enable - enable + + Activity Definitions allow you to manage custom activity definitions that can be created using the workflow designer. + Think reusable mini workflows that can be used as composite activities. + + elsa, module @@ -17,7 +23,7 @@ - + diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Constants.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Constants.cs index afd779498..c0be13e24 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Constants.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Constants.cs @@ -1,8 +1,12 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.BulkDelete; -public static class SecurityConstants +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants { - public static readonly string[] Policies = { "DeleteActivityDefinitions" }; - public static readonly string[] Permissions = { "DeleteActivityDefinitions" }; - public static readonly string[] Roles = { "DefinitionsDeleter" }; + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "BulkDeleteActivityDefinitions"; } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Endpoint.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Endpoint.cs index 4c5b940a5..e19ea5423 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Endpoint.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Endpoint.cs @@ -1,23 +1,29 @@ using Elsa.ActivityDefinitions.Services; -using Elsa.Api.Common; +using FastEndpoints; namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.BulkDelete; -public class BulkDelete : ProtectedEndpoint +/// +/// An endpoint that bulk-deletes activity definitions. +/// +public class BulkDelete : Endpoint { private readonly IActivityDefinitionStore _activityDefinitionStore; + /// public BulkDelete(IActivityDefinitionStore activityDefinitionStore) { _activityDefinitionStore = activityDefinitionStore; } + /// public override void Configure() { Post("/bulk-actions/delete/activity-definitions/by-definition-id"); - ConfigureSecurity(SecurityConstants.Permissions, SecurityConstants.Policies, SecurityConstants.Roles); + Policies(Constants.PolicyName); } + /// public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) { var deleted = await _activityDefinitionStore.DeleteByDefinitionIdsAsync(request.DefinitionIds, cancellationToken); diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Models.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Models.cs index f53d9109b..7d0b27f9c 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Models.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/BulkDelete/Models.cs @@ -1,11 +1,23 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.BulkDelete; +/// +/// Represents a bulk-delete activity definitions request. +/// public class Request { + /// + /// The activity definition IDs to delete. + /// public ICollection DefinitionIds { get; set; } = default!; } +/// +/// Represents a bulk-delete response. +/// public class Response { + /// + /// The number of records that were actually deleted. + /// public int Deleted { get; set; } } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Constants.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Constants.cs index c0399fd92..1a0c8b651 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Constants.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Constants.cs @@ -1,8 +1,12 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Delete; -public static class SecurityConstants +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants { - public static readonly string[] Policies = { "DeleteActivityDefinitions" }; - public static readonly string[] Permissions = { "DeleteActivityDefinitions" }; - public static readonly string[] Roles = { "DefinitionsDeleter" }; + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "DeleteActivityDefinition"; } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Endpoint.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Endpoint.cs index 23dba200b..1fef27ea9 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Endpoint.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Delete/Endpoint.cs @@ -1,23 +1,29 @@ using Elsa.ActivityDefinitions.Services; -using Elsa.Api.Common; +using FastEndpoints; namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Delete; -public class Delete : ProtectedEndpoint +/// +/// An endpoint that deletes a specific activity definition by ID. +/// +public class Delete : Endpoint { private readonly IActivityDefinitionStore _activityDefinitionStore; + /// public Delete(IActivityDefinitionStore activityDefinitionStore) { _activityDefinitionStore = activityDefinitionStore; } + /// public override void Configure() { Delete("/activity-definitions/{definitionId}"); - ConfigureSecurity(SecurityConstants.Permissions, SecurityConstants.Policies, SecurityConstants.Roles); + Policies(Constants.PolicyName); } + /// public override async Task HandleAsync(Request request, CancellationToken cancellationToken) { await _activityDefinitionStore.DeleteByDefinitionIdAsync(request.DefinitionId, cancellationToken); diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Constants.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Constants.cs index 84e3cee33..85d6298a0 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Constants.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Constants.cs @@ -1,8 +1,12 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Get; -public static class SecurityConstants +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants { - public static readonly string[] Policies = { "ReadActivityDefinitions" }; - public static readonly string[] Permissions = { "ReadActivityDefinitions" }; - public static readonly string[] Roles = { "ActivityDefinitionsReader" }; + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "ReadActivityDefinitions"; } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Endpoint.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Endpoint.cs index a0a7174eb..ab5535d2f 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Endpoint.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Get/Endpoint.cs @@ -1,20 +1,26 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.Json; +using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Models; using Elsa.ActivityDefinitions.Services; -using Elsa.Api.Common; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Mappers; +using FastEndpoints; namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Get; -public class Get : ProtectedEndpoint +/// +/// An endpoint that returns the specified by ID. +/// +public class Get : Endpoint { private readonly IActivityDefinitionStore _activityDefinitionStore; private readonly VariableDefinitionMapper _variableDefinitionMapper; private readonly SerializerOptionsProvider _serializerOptionsProvider; + /// public Get(IActivityDefinitionStore activityDefinitionStore, VariableDefinitionMapper variableDefinitionMapper, SerializerOptionsProvider serializerOptionsProvider) { _activityDefinitionStore = activityDefinitionStore; @@ -22,12 +28,14 @@ public class Get : ProtectedEndpoint _serializerOptionsProvider = serializerOptionsProvider; } + /// public override void Configure() { Get("/activity-definitions/{definitionId}"); - ConfigureSecurity(SecurityConstants.Permissions, SecurityConstants.Policies, SecurityConstants.Roles); + Policies(Constants.PolicyName); } + /// public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) { var parsedVersionOptions = request.VersionOptions != null ? VersionOptions.FromString(request.VersionOptions) : VersionOptions.Latest; diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Constants.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Constants.cs index 64e229c41..d9dd55719 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Constants.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Constants.cs @@ -1,8 +1,12 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.List; -public static class SecurityConstants +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants { - public static readonly string[] Policies = { "ListActivityDefinitions" }; - public static readonly string[] Permissions = { "ListActivityDefinitions" }; - public static readonly string[] Roles = { "ActivityDefinitionsViewer" }; + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "ListActivityDefinitions"; } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Endpoint.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Endpoint.cs index f2b519e7c..e8699bc80 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Endpoint.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/List/Endpoint.cs @@ -1,26 +1,31 @@ using Elsa.ActivityDefinitions.Models; using Elsa.ActivityDefinitions.Services; -using Elsa.Api.Common; -using Elsa.Api.Common.Models; -using Elsa.Persistence.Common.Models; +using Elsa.Models; +using FastEndpoints; namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.List; -public class List : ProtectedEndpoint> +/// +/// An endpoint that returns a page of objects. +/// +public class List : Endpoint> { private readonly IActivityDefinitionStore _store; + /// public List(IActivityDefinitionStore store) { _store = store; } + /// public override void Configure() { Get("/activity-definitions"); - ConfigureSecurity(SecurityConstants.Permissions, SecurityConstants.Policies, SecurityConstants.Roles); + Policies(Constants.PolicyName); } + /// public override async Task> ExecuteAsync(Request req, CancellationToken ct) { var parsedVersionOptions = req.VersionOptions != null ? VersionOptions.FromString(req.VersionOptions) : VersionOptions.Published; diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Constants.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Constants.cs index 7fb2882d1..11e202006 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Constants.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Constants.cs @@ -1,8 +1,12 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Post; -public static class SecurityConstants +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants { - public static readonly string[] Policies = { "CreateActivityDefinitions", "UpdateActivityDefinitions" }; - public static readonly string[] Permissions = { "CreateActivityDefinitions", "UpdateActivityDefinitions" }; - public static readonly string[] Roles = { "ActivityDefinitionsCreator", "ActivityDefinitionsUpdater" }; + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "CreateOrUpdateActivityDefinition"; } \ No newline at end of file diff --git a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Endpoint.cs b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Endpoint.cs index af53ef6e4..3a62c6b3b 100644 --- a/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Endpoint.cs +++ b/src/modules/Elsa.ActivityDefinitions/Endpoints/ActivityDefinitions/Post/Endpoint.cs @@ -1,19 +1,24 @@ using System.Text.Json; +using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Services; -using Elsa.Api.Common; using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Models; +using FastEndpoints; namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Post; -public class Post : ProtectedEndpoint +/// +/// An endpoint that creates or updates objects. +/// +public class Post : Endpoint { private readonly SerializerOptionsProvider _serializerOptionsProvider; private readonly IActivityDefinitionPublisher _activityDefinitionPublisher; private readonly VariableDefinitionMapper _variableDefinitionMapper; + /// public Post( SerializerOptionsProvider serializerOptionsProvider, IActivityDefinitionPublisher activityDefinitionPublisher, @@ -24,12 +29,14 @@ public class Post : ProtectedEndpoint _variableDefinitionMapper = variableDefinitionMapper; } + /// public override void Configure() { Post("/activity-definitions"); - ConfigureSecurity(List.SecurityConstants.Permissions, List.SecurityConstants.Policies, List.SecurityConstants.Roles); + Policies(Constants.PolicyName); } + /// public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) { var definitionId = request.DefinitionId; diff --git a/src/modules/Elsa.ActivityDefinitions/Extensions/ActivityDefinitionStoreExtensions.cs b/src/modules/Elsa.ActivityDefinitions/Extensions/ActivityDefinitionStoreExtensions.cs index a3c65c1bd..906927246 100644 --- a/src/modules/Elsa.ActivityDefinitions/Extensions/ActivityDefinitionStoreExtensions.cs +++ b/src/modules/Elsa.ActivityDefinitions/Extensions/ActivityDefinitionStoreExtensions.cs @@ -1,6 +1,6 @@ using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.ActivityDefinitions.Extensions; diff --git a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionActivityProvider.cs b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionActivityProvider.cs index e136abc49..b10898db3 100644 --- a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionActivityProvider.cs +++ b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionActivityProvider.cs @@ -2,7 +2,7 @@ using Elsa.ActivityDefinitions.Activities; using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Extensions; using Elsa.ActivityDefinitions.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionMaterializer.cs b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionMaterializer.cs index 73a492bdf..d025d34df 100644 --- a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionMaterializer.cs +++ b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionMaterializer.cs @@ -1,7 +1,6 @@ using System.Text.Json; using Elsa.ActivityDefinitions.Activities; using Elsa.ActivityDefinitions.Services; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Core; using Elsa.Workflows.Core.Activities; using Elsa.Workflows.Core.Serialization; diff --git a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionPublisher.cs b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionPublisher.cs index 61e2f3b07..a64894d9f 100644 --- a/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionPublisher.cs +++ b/src/modules/Elsa.ActivityDefinitions/Implementations/ActivityDefinitionPublisher.cs @@ -4,7 +4,7 @@ using Elsa.ActivityDefinitions.Notifications; using Elsa.ActivityDefinitions.Services; using Elsa.Common.Services; using Elsa.Mediator.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; diff --git a/src/modules/Elsa.ActivityDefinitions/Implementations/MemoryActivityDefinitionStore.cs b/src/modules/Elsa.ActivityDefinitions/Implementations/MemoryActivityDefinitionStore.cs index 4fb9a9e14..b48be955b 100644 --- a/src/modules/Elsa.ActivityDefinitions/Implementations/MemoryActivityDefinitionStore.cs +++ b/src/modules/Elsa.ActivityDefinitions/Implementations/MemoryActivityDefinitionStore.cs @@ -1,9 +1,9 @@ using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Models; using Elsa.ActivityDefinitions.Services; +using Elsa.Models; using Elsa.Persistence.Common.Extensions; using Elsa.Persistence.Common.Implementations; -using Elsa.Persistence.Common.Models; namespace Elsa.ActivityDefinitions.Implementations; diff --git a/src/modules/Elsa.ActivityDefinitions/Services/IActivityDefinitionStore.cs b/src/modules/Elsa.ActivityDefinitions/Services/IActivityDefinitionStore.cs index fb309d2fb..fd01d259e 100644 --- a/src/modules/Elsa.ActivityDefinitions/Services/IActivityDefinitionStore.cs +++ b/src/modules/Elsa.ActivityDefinitions/Services/IActivityDefinitionStore.cs @@ -1,6 +1,6 @@ using Elsa.ActivityDefinitions.Entities; using Elsa.ActivityDefinitions.Models; -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.ActivityDefinitions.Services; diff --git a/src/modules/Elsa.AspNetCore/Attributes/ApiEndpointAttribute.cs b/src/modules/Elsa.AspNetCore/Attributes/ApiEndpointAttribute.cs deleted file mode 100644 index eb4493e89..000000000 --- a/src/modules/Elsa.AspNetCore/Attributes/ApiEndpointAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Elsa.AspNetCore.Attributes; - -/// -/// Apply this to a controller that models an API endpoint, where the controller contains a single action. -/// -[AttributeUsage(AttributeTargets.Class)] -public class ApiEndpointAttribute : Attribute -{ - public string ControllerName { get; } - public string ActionName { get; } - - public ApiEndpointAttribute(string controllerName, string actionName) - { - ControllerName = controllerName; - ActionName = actionName; - } -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Conventions/ApiEndpointAttributeConvention.cs b/src/modules/Elsa.AspNetCore/Conventions/ApiEndpointAttributeConvention.cs deleted file mode 100644 index 3c473351d..000000000 --- a/src/modules/Elsa.AspNetCore/Conventions/ApiEndpointAttributeConvention.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Microsoft.AspNetCore.Mvc.ApplicationModels; - -namespace Elsa.AspNetCore.Conventions; - -/// -/// A custom controller model convention that applies a controller & action name based on the values provided via . -/// -public class ApiEndpointAttributeConvention : IControllerModelConvention -{ - public void Apply(ControllerModel controller) - { - var controllerNameAttribute = controller.Attributes.OfType().SingleOrDefault(); - - if (controllerNameAttribute != null) - { - controller.ControllerName = controllerNameAttribute.ControllerName; - var actionModel = controller.Actions.FirstOrDefault(); - - if (actionModel != null) - actionModel.ActionName = controllerNameAttribute.ActionName; - } - } -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Elsa.AspNetCore.csproj b/src/modules/Elsa.AspNetCore/Elsa.AspNetCore.csproj deleted file mode 100644 index ed4926d92..000000000 --- a/src/modules/Elsa.AspNetCore/Elsa.AspNetCore.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - - - diff --git a/src/modules/Elsa.AspNetCore/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa.AspNetCore/Extensions/DependencyInjectionExtensions.cs deleted file mode 100644 index 352550c6a..000000000 --- a/src/modules/Elsa.AspNetCore/Extensions/DependencyInjectionExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Elsa.AspNetCore.Features; -using Elsa.Features.Services; - -namespace Elsa.AspNetCore.Extensions; - -public static class DependencyInjectionExtensions -{ - public static IModule UseMvc(this IModule configuration, Action? configure = default) - { - configuration.Configure(configure); - return configuration; - } -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Extensions/MvcBuilderExtensions.cs b/src/modules/Elsa.AspNetCore/Extensions/MvcBuilderExtensions.cs deleted file mode 100644 index da6bd57ca..000000000 --- a/src/modules/Elsa.AspNetCore/Extensions/MvcBuilderExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Elsa.AspNetCore.Parts; -using Microsoft.AspNetCore.Mvc.ApplicationParts; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.AspNetCore.Extensions; - -public static class MvcBuilderExtensions -{ - /// - /// Remove all application parts. This allows for manually controlling what controllers to add. - /// - public static IMvcBuilder ClearApplicationParts(this IMvcBuilder mvcBuilder) => - mvcBuilder.ConfigureApplicationPartManager(partManager => - partManager.ApplicationParts.Clear()); - - /// - /// Add application parts from the assembly containing the specified type. - /// - public static IMvcBuilder AddApplicationPartsFrom(this IMvcBuilder mvcBuilder) => - mvcBuilder.ConfigureApplicationPartManager(partManager => - partManager.ApplicationParts.Add(new AssemblyPart(typeof(T).Assembly))); - - /// - /// Add the specified controller types. - /// - public static IMvcBuilder AddControllerTypes(this IMvcBuilder mvcBuilder, params Type[] controllerTypes) => - mvcBuilder.ConfigureApplicationPartManager(partManager => - partManager.ApplicationParts.Add(new TypesPart(controllerTypes))); -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Features/MvcFeature.cs b/src/modules/Elsa.AspNetCore/Features/MvcFeature.cs deleted file mode 100644 index f63c92d52..000000000 --- a/src/modules/Elsa.AspNetCore/Features/MvcFeature.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Elsa.AspNetCore.Conventions; -using Elsa.Features.Abstractions; -using Elsa.Features.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.AspNetCore.Features; - -public class MvcFeature : FeatureBase -{ - public MvcFeature(IModule module) : base(module) - { - } - - public override void Configure() - { - Services.AddMvc(mvc => mvc.Conventions.Add(new ApiEndpointAttributeConvention())); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Models/ListModel.cs b/src/modules/Elsa.AspNetCore/Models/ListModel.cs deleted file mode 100644 index c0d35b736..000000000 --- a/src/modules/Elsa.AspNetCore/Models/ListModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Elsa.AspNetCore.Models; - -public record ListModel(ICollection Items); - -public static class ListModel -{ - public static ListModel Of(ICollection items) => new(items); - public static ListModel Of(IEnumerable items) => new(items.ToList()); -} \ No newline at end of file diff --git a/src/modules/Elsa.AspNetCore/Parts/TypesPart.cs b/src/modules/Elsa.AspNetCore/Parts/TypesPart.cs deleted file mode 100644 index d3c557ea4..000000000 --- a/src/modules/Elsa.AspNetCore/Parts/TypesPart.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using Microsoft.AspNetCore.Mvc.ApplicationParts; - -namespace Elsa.AspNetCore.Parts; - -/// -/// A custom that controls what types will be provided to the system. -/// Use this to control what controllers should be made available from other libraries. -/// -public class TypesPart : ApplicationPart, IApplicationPartTypeProvider -{ - public TypesPart(params Type[] types) - { - Types = types.Select(t => t.GetTypeInfo()); - } - - public override string Name => string.Join(", ", Types.Select(t => t.FullName)); - - public IEnumerable Types { get; } -} \ No newline at end of file diff --git a/src/modules/Elsa.Labels.EntityFrameworkCore/Implementations/EFCoreLabelStore.cs b/src/modules/Elsa.Labels.EntityFrameworkCore/Implementations/EFCoreLabelStore.cs index 93c5ff8e4..8a274a70b 100644 --- a/src/modules/Elsa.Labels.EntityFrameworkCore/Implementations/EFCoreLabelStore.cs +++ b/src/modules/Elsa.Labels.EntityFrameworkCore/Implementations/EFCoreLabelStore.cs @@ -1,6 +1,6 @@ using Elsa.Labels.Entities; using Elsa.Labels.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Extensions; using Elsa.Persistence.EntityFrameworkCore.Common.Services; diff --git a/src/modules/Elsa.Labels/Elsa.Labels.csproj b/src/modules/Elsa.Labels/Elsa.Labels.csproj index e36a72d0f..a7700e68d 100644 --- a/src/modules/Elsa.Labels/Elsa.Labels.csproj +++ b/src/modules/Elsa.Labels/Elsa.Labels.csproj @@ -6,18 +6,15 @@ enable - - - - + - + diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Create.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Create.cs deleted file mode 100644 index 6cbee5321..000000000 --- a/src/modules/Elsa.Labels/Endpoints/Labels/Create.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Elsa.Labels.Entities; -using Elsa.Labels.Services; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Core.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Labels.Endpoints.Labels; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.Labels, "Create")] -[ProducesResponseType(typeof(Label), StatusCodes.Status201Created)] -public class Create : Controller -{ - private readonly ILabelStore _store; - private readonly IIdentityGenerator _identityGenerator; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - // ReSharper disable once ClassNeverInstantiated.Local - private record LabelModel(string Name, string? Description, string? Color); - - public Create(ILabelStore store, IIdentityGenerator identityGenerator, SerializerOptionsProvider serializerOptionsProvider) - { - _store = store; - _identityGenerator = identityGenerator; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = (await Request.ReadFromJsonAsync(serializerOptions, cancellationToken))!; - - var label = new Label - { - Id = _identityGenerator.GenerateId(), - Name = model.Name.Trim(), - Description = model.Description?.Trim(), - Color = model.Color?.Trim() - }; - - await _store.SaveAsync(label, cancellationToken); - - return CreatedAtRoute("Elsa.Labels.Get", new { Id = label.Id }, label); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Delete.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Delete.cs deleted file mode 100644 index 1e800decc..000000000 --- a/src/modules/Elsa.Labels/Endpoints/Labels/Delete.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Elsa.Labels.Entities; -using Elsa.Labels.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Labels.Endpoints.Labels; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.Labels, "Delete")] -[ProducesResponseType(typeof(Label), StatusCodes.Status204NoContent)] -[ProducesResponseType(StatusCodes.Status404NotFound)] -public class Delete : Controller -{ - private readonly ILabelStore _store; - - public Delete(ILabelStore store) => _store = store; - - [HttpDelete] - public async Task HandleAsync(string id, CancellationToken cancellationToken) - { - var deleted = await _store.DeleteAsync(id, cancellationToken); - return deleted ? NoContent() : NotFound(); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Constants.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Constants.cs new file mode 100644 index 000000000..e93c370d8 --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Constants.cs @@ -0,0 +1,12 @@ +namespace Elsa.Labels.Endpoints.Labels.Delete; + +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants +{ + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "DeleteLabel"; +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Endpoint.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Endpoint.cs new file mode 100644 index 000000000..30f30301e --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Endpoint.cs @@ -0,0 +1,27 @@ +using Elsa.Labels.Services; +using FastEndpoints; + +namespace Elsa.Labels.Endpoints.Labels.Delete; + +public class Delete : Endpoint +{ + private readonly ILabelStore _store; + + public Delete(ILabelStore store) => _store = store; + + public override void Configure() + { + Delete("/labels/{id}"); + Policies(Constants.PolicyName); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var deleted = await _store.DeleteAsync(request.Id, cancellationToken); + + if (deleted) + await SendNoContentAsync(cancellationToken); + else + await SendNotFoundAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Models.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Models.cs new file mode 100644 index 000000000..38f0a0064 --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Delete/Models.cs @@ -0,0 +1,6 @@ +namespace Elsa.Labels.Endpoints.Labels.Delete; + +public class Request +{ + public string Id { get; init; } = default!; +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Get.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Get.cs deleted file mode 100644 index 0d08ad923..000000000 --- a/src/modules/Elsa.Labels/Endpoints/Labels/Get.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Elsa.Labels.Entities; -using Elsa.Labels.Services; -using Elsa.Workflows.Core.Serialization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Labels.Endpoints.Labels; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.Labels, "Get")] -[ProducesResponseType(typeof(Label), StatusCodes.Status200OK)] -[ProducesResponseType(StatusCodes.Status404NotFound)] -public class Get : Controller -{ - private readonly ILabelStore _store; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public Get(ILabelStore store, SerializerOptionsProvider serializerOptionsProvider) - { - _store = store; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpGet] - public async Task HandleAsync(string id, CancellationToken cancellationToken) - { - var label = await _store.FindByIdAsync(id, cancellationToken); - return label == null ? NotFound() : Json(label, _serializerOptionsProvider.CreateApiOptions()); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Get/Constants.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Constants.cs new file mode 100644 index 000000000..7b75082e6 --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Constants.cs @@ -0,0 +1,12 @@ +namespace Elsa.Labels.Endpoints.Labels.Get; + +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants +{ + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "GetLabel"; +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Get/Endpoint.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Endpoint.cs new file mode 100644 index 000000000..76f7b9806 --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Endpoint.cs @@ -0,0 +1,33 @@ +using Elsa.Labels.Services; +using FastEndpoints; + +namespace Elsa.Labels.Endpoints.Labels.Get; + +public class Get : Endpoint +{ + private readonly ILabelStore _store; + + public Get(ILabelStore store) + { + _store = store; + } + + public override void Configure() + { + Get("/labels/{id}"); + Policies(Constants.PolicyName); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var label = await _store.FindByIdAsync(request.Id, cancellationToken); + + if (label == null) + await SendNotFoundAsync(cancellationToken); + else + { + var response = await Map.FromEntityAsync(label); + await SendOkAsync(response, cancellationToken); + } + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Get/Mappers.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Mappers.cs new file mode 100644 index 000000000..a23b20bda --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Mappers.cs @@ -0,0 +1,16 @@ +using Elsa.Labels.Entities; +using Elsa.Workflows.Core.Services; +using FastEndpoints; + +namespace Elsa.Labels.Endpoints.Labels.Get; + +public class LabelMapper : Mapper +{ + public override Task FromEntityAsync(Label e) => Task.FromResult(new Response + { + Id = e.Id, + Color = e.Color, + Description = e.Description, + NormalizedName = e.NormalizedName + }); +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/Get/Models.cs b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Models.cs new file mode 100644 index 000000000..496ea3525 --- /dev/null +++ b/src/modules/Elsa.Labels/Endpoints/Labels/Get/Models.cs @@ -0,0 +1,14 @@ +namespace Elsa.Labels.Endpoints.Labels.Get; + +public class Request +{ + public string Id { get; set; } = default!; +} + +public class Response +{ + public string Id { get; set; } = default!; + public string NormalizedName { get; set; } = default!; + public string? Description { get; set; } + public string? Color { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Labels/Endpoints/Labels/List.cs b/src/modules/Elsa.Labels/Endpoints/Labels/List.cs deleted file mode 100644 index 263c12c6f..000000000 --- a/src/modules/Elsa.Labels/Endpoints/Labels/List.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Elsa.Labels.Entities; -using Elsa.Labels.Services; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Labels.Endpoints.Labels; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.Labels, "List")] -[ProducesResponseType(typeof(Page - + diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs deleted file mode 100644 index 8cfa91526..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; -using Elsa.AspNetCore.Attributes; -using Elsa.AspNetCore.Models; -using Elsa.Workflows.Core.Models; -using Elsa.Workflows.Core.Serialization.Converters; -using Elsa.Workflows.Core.Services; -using Elsa.Workflows.Management.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptors; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.ActivityDescriptors, "List")] -[ProducesResponseType(typeof(ActivityDescriptors), StatusCodes.Status200OK, "application/json")] -public class List : Controller -{ - private readonly IActivityRegistry _registry; - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; - - public List(IActivityRegistry registry, IWellKnownTypeRegistry wellKnownTypeRegistry) - { - _registry = registry; - _wellKnownTypeRegistry = wellKnownTypeRegistry; - } - - [HttpGet] - public IActionResult Handle() - { - var descriptors = _registry.ListAll().ToList(); - - var model = new - { - ActivityDescriptors = descriptors - }; - - var serializerOptions = new JsonSerializerOptions - { - Converters = - { - new JsonStringEnumConverter(), - new TypeJsonConverter(_wellKnownTypeRegistry) - }, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - - return Json(model, serializerOptions); - } -} - -public record ActivityDescriptors(ICollection Items) : ListModel(Items); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Constants.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Constants.cs new file mode 100644 index 000000000..fb00fd5f5 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Constants.cs @@ -0,0 +1,13 @@ + +namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptors.List; + +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants +{ + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "ListActivityDescriptors"; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Endpoint.cs new file mode 100644 index 000000000..991ed2071 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Endpoint.cs @@ -0,0 +1,33 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Workflows.Core.Services; +using Elsa.Workflows.Management.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptors.List; + +public class List : EndpointWithoutRequest +{ + private readonly IActivityRegistry _registry; + + public List(IActivityRegistry registry, IWellKnownTypeRegistry wellKnownTypeRegistry) + { + _registry = registry; + } + + public override void Configure() + { + Policies(Constants.PolicyName); + Roles("Admin"); + Permissions("all", "list:activity-descriptors"); + } + + public override Task ExecuteAsync(CancellationToken cancellationToken) + { + var descriptors = _registry.ListAll().ToList(); + var response = new Response(descriptors); + + return Task.FromResult(response); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs new file mode 100644 index 000000000..55c0a4392 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Elsa.Workflows.Core.Models; + +namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptors.List; + +public class Response +{ + public Response(ICollection items) + { + Items = items; + } + + public ICollection Items { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger.cs deleted file mode 100644 index 2faea638b..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Elsa.AspNetCore.Attributes; -using Elsa.Workflows.Api.ApiResults; -using Elsa.Workflows.Api.Models; -using Elsa.Workflows.Core.Activities; -using Elsa.Workflows.Core.Helpers; -using Elsa.Workflows.Core.Models; -using Elsa.Workflows.Core.Services; -using Elsa.Workflows.Runtime.Models; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.Events; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.Events, "Trigger")] -[ProducesResponseType(typeof(ProcessStimulusResults), StatusCodes.Status200OK, "application/json")] -public class Trigger : Controller -{ - private readonly IHasher _hasher; - - public Trigger(IHasher hasher) - { - _hasher = hasher; - } - - [HttpPost] - public IActionResult Handle(string eventName) - { - var eventBookmark = new EventBookmarkData(eventName); - var hash = _hasher.Hash(eventBookmark); - var stimulus = Stimulus.Standard(ActivityTypeNameHelper.GenerateTypeName(), hash); - return new ProcessStimulusResult(stimulus); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Constants.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Constants.cs new file mode 100644 index 000000000..524b941cc --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Constants.cs @@ -0,0 +1,13 @@ + +namespace Elsa.Workflows.Api.Endpoints.Events.Trigger; + +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants +{ + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "TriggerEvent"; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Endpoint.cs new file mode 100644 index 000000000..42372c65e --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Endpoint.cs @@ -0,0 +1,49 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Helpers; +using Elsa.Workflows.Core.Models; +using Elsa.Workflows.Core.Services; +using Elsa.Workflows.Runtime.Models; +using Elsa.Workflows.Runtime.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.Events.Trigger; + +public class Trigger : Endpoint +{ + private readonly IHasher _hasher; + private readonly IStimulusInterpreter _stimulusInterpreter; + private readonly IWorkflowInstructionExecutor _workflowInstructionExecutor; + + public Trigger(IHasher hasher, IStimulusInterpreter stimulusInterpreter, IWorkflowInstructionExecutor workflowInstructionExecutor) + { + _hasher = hasher; + _stimulusInterpreter = stimulusInterpreter; + _workflowInstructionExecutor = workflowInstructionExecutor; + } + + public override void Configure() + { + Post("/events/{eventName}/trigger"); + Policies(Constants.PolicyName); + Permissions("all", "trigger:event"); + Roles("Admin"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var eventBookmark = new EventBookmarkData(request.EventName); + var hash = _hasher.Hash(eventBookmark); + var stimulus = Stimulus.Standard(ActivityTypeNameHelper.GenerateTypeName(), hash); + var instructions = await _stimulusInterpreter.GetExecutionInstructionsAsync(stimulus, cancellationToken); + var executionResults = (await _workflowInstructionExecutor.ExecuteInstructionsAsync(instructions, CancellationToken.None)).ToList(); + + if (!HttpContext.Response.HasStarted) + { + var response = new Response(executionResults); + await SendOkAsync(response, cancellationToken); + } + } +} diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Models.cs new file mode 100644 index 000000000..ebad5c7ca --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/Events/Trigger/Models.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Elsa.Workflows.Runtime.Models; + +namespace Elsa.Workflows.Api.Endpoints.Events.Trigger; + +public class Request +{ + public string EventName { get; set; } +} + +public class Response +{ + public Response(ICollection items) + { + Items = items; + } + + public ICollection Items { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List.cs b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List.cs deleted file mode 100644 index 1b2f5ff4d..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Elsa.AspNetCore.Attributes; -using Elsa.AspNetCore.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Core.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -// ReSharper disable NotAccessedPositionalProperty.Global - -namespace Elsa.Workflows.Api.Endpoints.StorageDrivers; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.StorageDrivers, "List")] -[ProducesResponseType(typeof(StorageDrivers), StatusCodes.Status200OK, "application/json")] -public class List : Controller -{ - private readonly IStorageDriverManager _registry; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public List(IStorageDriverManager registry, SerializerOptionsProvider serializerOptionsProvider) - { - _registry = registry; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpGet] - public IActionResult Handle() - { - var drivers = _registry.List(); - var descriptors = drivers.Select(x => new StorageDriverDescriptor(x.Id, x.DisplayName)).ToList(); - var model = new StorageDrivers(descriptors); - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - - return Json(model, serializerOptions); - } -} - -public record StorageDrivers(ICollection Items) : ListModel(Items); - -public record StorageDriverDescriptor(string Id, string DisplayName); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Constants.cs b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Constants.cs new file mode 100644 index 000000000..2fd170cda --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Constants.cs @@ -0,0 +1,13 @@ + +namespace Elsa.Workflows.Api.Endpoints.StorageDrivers.List; + +/// +/// Provides policy names accepted by the endpoint. +/// +public static class Constants +{ + /// + /// The policy name accepted by this endpoint. + /// + public const string PolicyName = "ListStorageDrivers"; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Endpoint.cs new file mode 100644 index 000000000..5ef6333a0 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Endpoint.cs @@ -0,0 +1,33 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Workflows.Core.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.StorageDrivers.List; + +public class List : EndpointWithoutRequest +{ + private readonly IStorageDriverManager _registry; + + public List(IStorageDriverManager registry) + { + _registry = registry; + } + + public override void Configure() + { + Get("/descriptors/activities"); + Policies(Constants.PolicyName); + Permissions("all", "read:storage-drivers"); + } + + public override Task ExecuteAsync(CancellationToken ct) + { + var drivers = _registry.List(); + var descriptors = drivers.Select(x => new StorageDriverDescriptor(x.Id, x.DisplayName)).ToList(); + var response = new Response(descriptors); + + return Task.FromResult(response); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Models.cs new file mode 100644 index 000000000..49774fcea --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/StorageDrivers/List/Models.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Elsa.Workflows.Api.Endpoints.StorageDrivers.List; + +public class Response +{ + public Response(ICollection items) + { + Items = items; + } + + public ICollection Items { get; set; } +} + +public record StorageDriverDescriptor(string Id, string DisplayName); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete.cs deleted file mode 100644 index 8fb7c668b..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Management.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "BulkDelete")] -public class BulkDelete : Controller -{ - private readonly IWorkflowDefinitionManager _workflowDefinitionManager; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public BulkDelete(IWorkflowDefinitionManager workflowDefinitionManager, SerializerOptionsProvider serializerOptionsProvider) - { - _workflowDefinitionManager = workflowDefinitionManager; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = await Request.ReadFromJsonAsync(serializerOptions, cancellationToken); - var count = await _workflowDefinitionManager.BulkDeleteByDefinitionIdsAsync(model!.DefinitionIds, cancellationToken); - - return Json(new BulkDeleteWorkflowDefinitionsResponse(count), serializerOptions); - } - - public record BulkDeleteWorkflowDefinitionsRequest(ICollection DefinitionIds); - - public record BulkDeleteWorkflowDefinitionsResponse([property: JsonPropertyName("deleted")] int DeletedCount); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Endpoint.cs new file mode 100644 index 000000000..395dc8160 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Endpoint.cs @@ -0,0 +1,28 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Workflows.Core.Serialization; +using Elsa.Workflows.Management.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkDelete; + +public class BulkDelete : Endpoint +{ + private readonly IWorkflowDefinitionManager _workflowDefinitionManager; + + public BulkDelete(IWorkflowDefinitionManager workflowDefinitionManager, SerializerOptionsProvider serializerOptionsProvider) + { + _workflowDefinitionManager = workflowDefinitionManager; + } + + public override void Configure() + { + Post("/bulk-actions/delete/workflow-definitions/by-definition-id"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) + { + var count = await _workflowDefinitionManager.BulkDeleteByDefinitionIdsAsync(request!.DefinitionIds, cancellationToken); + return new Response(count); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Models.cs new file mode 100644 index 000000000..8b534d186 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkDelete/Models.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkDelete; + +public class Request +{ + public ICollection DefinitionIds { get; set; } = default!; +} + +public class Response +{ + public Response(int deletedCount) + { + DeletedCount = deletedCount; + } + + [JsonPropertyName("deleted")] public int DeletedCount { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Endpoint.cs similarity index 52% rename from src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish.cs rename to src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Endpoint.cs index af34db6bb..988d2386e 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Endpoint.cs @@ -1,41 +1,37 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +using FastEndpoints; -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkPublish; -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "BulkPublish")] -public class BulkPublish : Controller +public class BulkPublish : Endpoint { private readonly IWorkflowDefinitionStore _store; private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; - private readonly SerializerOptionsProvider _serializerOptionsProvider; public BulkPublish(IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher, SerializerOptionsProvider serializerOptionsProvider) { _store = store; _workflowDefinitionPublisher = workflowDefinitionPublisher; - _serializerOptionsProvider = serializerOptionsProvider; } - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) + public override void Configure() + { + Post("/bulk-actions/publish/workflow-definitions/by-definition-id"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = (await Request.ReadFromJsonAsync(serializerOptions, cancellationToken))!; var published = new List(); var notFound = new List(); var alreadyPublished = new List(); - foreach (var definitionId in model.DefinitionIds) + foreach (var definitionId in request.DefinitionIds) { var definition = await _store.FindByDefinitionIdAsync(definitionId, VersionOptions.Latest, cancellationToken); @@ -55,10 +51,6 @@ public class BulkPublish : Controller published.Add(definitionId); } - return Json(new BulkPublishWorkflowDefinitionsResponse(published, alreadyPublished, notFound), serializerOptions); + return new Response(published, alreadyPublished, notFound); } - - public record BulkPublishWorkflowDefinitionsRequest(ICollection DefinitionIds); - - public record BulkPublishWorkflowDefinitionsResponse(ICollection Published, ICollection AlreadyPublished, ICollection NotFound); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Models.cs new file mode 100644 index 000000000..7245a5ec6 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkPublish/Models.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkPublish; + +public class Request +{ + public ICollection DefinitionIds { get; set; } = default!; +} + +public class Response +{ + public Response(ICollection published, ICollection alreadyPublished, ICollection notFound) + { + Published = published; + AlreadyPublished = alreadyPublished; + NotFound = notFound; + } + + public ICollection Published { get; } + public ICollection AlreadyPublished { get; } + public ICollection NotFound { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract.cs deleted file mode 100644 index f6cb402d9..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Management.Services; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "BulkRetract")] -public class BulkRetract : Controller -{ - private readonly IWorkflowDefinitionStore _store; - private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public BulkRetract(IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher, SerializerOptionsProvider serializerOptionsProvider) - { - _store = store; - _workflowDefinitionPublisher = workflowDefinitionPublisher; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = (await Request.ReadFromJsonAsync(serializerOptions, cancellationToken))!; - var retracted = new List(); - var notFound = new List(); - var notPublished = new List(); - - foreach (var definitionId in model.DefinitionIds) - { - var definition = await _store.FindByDefinitionIdAsync(definitionId, VersionOptions.Latest, cancellationToken); - - if (definition == null) - { - notFound.Add(definitionId); - continue; - } - - if (!definition.IsPublished) - { - notPublished.Add(definitionId); - continue; - } - - await _workflowDefinitionPublisher.RetractAsync(definition, cancellationToken); - retracted.Add(definitionId); - } - - return Json(new BulkRetractWorkflowDefinitionsResponse(retracted, notPublished, notFound), serializerOptions); - } - - public record BulkRetractWorkflowDefinitionsRequest(ICollection DefinitionIds); - - public record BulkRetractWorkflowDefinitionsResponse(ICollection Retracted, ICollection NotPublished, ICollection NotFound); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Endpoint.cs new file mode 100644 index 000000000..2ce8d49f3 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Endpoint.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Management.Services; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkRetract; + +public class BulkRetract : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; + + public BulkRetract(IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher) + { + _store = store; + _workflowDefinitionPublisher = workflowDefinitionPublisher; + } + + public override void Configure() + { + Post("/bulk-actions/retract/workflow-definitions/by-definition-id"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) + { + var retracted = new List(); + var notFound = new List(); + var notPublished = new List(); + + foreach (var definitionId in request.DefinitionIds) + { + var definition = await _store.FindByDefinitionIdAsync(definitionId, VersionOptions.Latest, cancellationToken); + + if (definition == null) + { + notFound.Add(definitionId); + continue; + } + + if (!definition.IsPublished) + { + notPublished.Add(definitionId); + continue; + } + + await _workflowDefinitionPublisher.RetractAsync(definition, cancellationToken); + retracted.Add(definitionId); + } + + return new Response(retracted, notPublished, notFound); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Models.cs new file mode 100644 index 000000000..f661a5e1e --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/BulkRetract/Models.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.BulkRetract; + +public class Request +{ + public ICollection DefinitionIds { get; set; } = default!; +} + +public class Response +{ + public Response(ICollection retracted, ICollection notPublished, ICollection notFound) + { + Retracted = retracted; + NotPublished = notPublished; + NotFound = notFound; + } + + public ICollection Retracted { get; } + public ICollection NotPublished { get; } + public ICollection NotFound { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete.cs deleted file mode 100644 index 6c0804336..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Workflows.Management.Services; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Delete")] -public class Delete : Controller -{ - private readonly IWorkflowDefinitionManager _workflowDefinitionManager; - public Delete(IWorkflowDefinitionManager workflowDefinitionManager) - { - _workflowDefinitionManager = workflowDefinitionManager; - } - - [HttpDelete] - public async Task HandleAsync(string definitionId, CancellationToken cancellationToken) - { - var result = await _workflowDefinitionManager.DeleteByDefinitionIdAsync(definitionId, cancellationToken); - return result == 0 ? NotFound() : NoContent(); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Endpoint.cs new file mode 100644 index 000000000..7ba29896d --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Endpoint.cs @@ -0,0 +1,32 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Workflows.Management.Services; +using FastEndpoints; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Delete; + +public class Delete : Endpoint +{ + private readonly IWorkflowDefinitionManager _workflowDefinitionManager; + + public Delete(IWorkflowDefinitionManager workflowDefinitionManager) + { + _workflowDefinitionManager = workflowDefinitionManager; + } + + public override void Configure() + { + Delete("/workflow-definitions/{definitionId}"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var result = await _workflowDefinitionManager.DeleteByDefinitionIdAsync(request.DefinitionId, cancellationToken); + + if (result == 0) + await SendNotFoundAsync(cancellationToken); + else + await SendNoContentAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Models.cs new file mode 100644 index 000000000..8c9f9615c --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Delete/Models.cs @@ -0,0 +1,6 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Delete; + +public class Request +{ + public string DefinitionId { get; set; } = default!; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch.cs deleted file mode 100644 index 8fdb21035..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Api.ApiResults; -using Elsa.Workflows.Persistence.Services; -using Elsa.Workflows.Runtime.Models; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Dispatch")] -[ProducesResponseType(typeof(DispatchWorkflowDefinitionResponse), StatusCodes.Status200OK)] -public class Dispatch : Controller -{ - private readonly IWorkflowDefinitionStore _store; - public Dispatch(IWorkflowDefinitionStore store) => _store = store; - - [HttpPost] - public async Task DispatchAsync(string definitionId, string? correlationId = default, CancellationToken cancellationToken = default) - { - var exists = await _store.GetExistsAsync(definitionId, VersionOptions.Published, cancellationToken); - return exists ? new DispatchWorkflowDefinitionResult(definitionId, correlationId) : NotFound(); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs new file mode 100644 index 000000000..05cd8defa --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs @@ -0,0 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Persistence.Services; +using Elsa.Workflows.Runtime.Models; +using Elsa.Workflows.Runtime.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Dispatch; + +public class Endpoint : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + private readonly IWorkflowDispatcher _workflowDispatcher; + + public Endpoint(IWorkflowDefinitionStore store, IWorkflowDispatcher workflowDispatcher) + { + _store = store; + _workflowDispatcher = workflowDispatcher; + } + + public override void Configure() + { + Post("/workflow-definitions/{definitionId}/dispatch"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var exists = await _store.GetExistsAsync(request.DefinitionId, VersionOptions.Published, cancellationToken); + + if (!exists) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + var result = await _workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest( + request.DefinitionId, + VersionOptions.Published, + CorrelationId: request.CorrelationId), + cancellationToken); + + await SendOkAsync(new Response(), cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs new file mode 100644 index 000000000..06eb8fee9 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs @@ -0,0 +1,11 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Dispatch; + +public class Request +{ + public string DefinitionId { get; set; } = default!; + public string? CorrelationId { get; set; } +} + +public class Response +{ +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute.cs deleted file mode 100644 index 26f3125e9..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Api.ApiResults; -using Elsa.Workflows.Core.Models; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Execute")] -[ProducesResponseType(typeof(RunWorkflowResult), StatusCodes.Status200OK)] -public class Execute : Controller -{ - private readonly IWorkflowDefinitionStore _store; - public Execute(IWorkflowDefinitionStore store) => _store = store; - - [HttpPost] - public async Task ExecuteAsync(string definitionId, string? correlationId = default, CancellationToken cancellationToken = default) - { - var exists = await _store.GetExistsAsync(definitionId, VersionOptions.Published, cancellationToken); - return exists ? new ExecuteWorkflowDefinitionResult(definitionId, correlationId) : NotFound(); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Endpoint.cs new file mode 100644 index 000000000..227efaf25 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Endpoint.cs @@ -0,0 +1,43 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Persistence.Services; +using Elsa.Workflows.Runtime.Models; +using Elsa.Workflows.Runtime.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Execute; + +public class Execute : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + private readonly IWorkflowInvoker _workflowInvoker; + + public Execute(IWorkflowDefinitionStore store, IWorkflowInvoker workflowInvoker) + { + _store = store; + _workflowInvoker = workflowInvoker; + } + + public override void Configure() + { + Post("/workflow-definitions/{definitionId}/execute"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var exists = await _store.GetExistsAsync(request.DefinitionId, VersionOptions.Published, cancellationToken); + + if (!exists) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + var executeRequest = new InvokeWorkflowDefinitionRequest(request.DefinitionId, VersionOptions.Published, CorrelationId: request.CorrelationId); + var result = await _workflowInvoker.InvokeAsync(executeRequest, CancellationToken.None); + + if (!HttpContext.Response.HasStarted) + await SendOkAsync(new Response(result.WorkflowState, result.Bookmarks), cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Models.cs new file mode 100644 index 000000000..d757ccfd3 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Execute/Models.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Elsa.Workflows.Core.Models; +using Elsa.Workflows.Core.State; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Execute; + +public class Request +{ + public string DefinitionId { get; set; } = default!; + public string? CorrelationId { get; set; } +} + +public class Response +{ + public Response(WorkflowState workflowState, IReadOnlyCollection bookmarks) + { + WorkflowState = workflowState; + Bookmarks = bookmarks; + } + + public WorkflowState WorkflowState { get; } + public IReadOnlyCollection Bookmarks { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Endpoint.cs similarity index 68% rename from src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export.cs rename to src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Endpoint.cs index 663d536bc..c96e1c40b 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Endpoint.cs @@ -1,24 +1,19 @@ using System.Linq; -using System.Net.Mime; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Api.Models; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Persistence.Services; using Elsa.Workflows.Runtime.Services; +using FastEndpoints; using Humanizer; -using Microsoft.AspNetCore.Mvc; -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Export; -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Export")] -[Produces("application/json")] -public class Export : Controller +public class Export : Endpoint { private readonly IWorkflowDefinitionStore _store; private readonly IWorkflowDefinitionService _workflowDefinitionService; @@ -26,8 +21,8 @@ public class Export : Controller private readonly VariableDefinitionMapper _variableDefinitionMapper; public Export( - IWorkflowDefinitionStore store, - IWorkflowDefinitionService workflowDefinitionService, + IWorkflowDefinitionStore store, + IWorkflowDefinitionService workflowDefinitionService, SerializerOptionsProvider serializerOptionsProvider, VariableDefinitionMapper variableDefinitionMapper) { @@ -37,22 +32,26 @@ public class Export : Controller _variableDefinitionMapper = variableDefinitionMapper; } - [HttpGet] - public async Task HandleAsync( - CancellationToken cancellationToken, - [FromRoute] string definitionId, - [FromQuery] string? versionOptions = default) + public override void Configure() + { + Get("/workflow-definitions/{definitionId}/export"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) { var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var parsedVersionOptions = versionOptions != null ? VersionOptions.FromString(versionOptions) : VersionOptions.Latest; - var definition = await _store.FindByDefinitionIdAsync(definitionId, parsedVersionOptions, cancellationToken); + var versionOptions = request.VersionOptions != null ? VersionOptions.FromString(request.VersionOptions) : VersionOptions.Latest; + var definition = await _store.FindByDefinitionIdAsync(request.DefinitionId, versionOptions, cancellationToken); if (definition == null) - return NotFound(); - + { + await SendNotFoundAsync(cancellationToken); + return; + } + var workflow = await _workflowDefinitionService.MaterializeWorkflowAsync(definition, cancellationToken); var variables = _variableDefinitionMapper.Map(workflow.Variables).ToList(); - + var model = new WorkflowDefinitionModel( definition.Id, definition.DefinitionId, @@ -66,15 +65,15 @@ public class Export : Controller definition.IsLatest, definition.IsPublished, workflow.Root); - + var binaryJson = JsonSerializer.SerializeToUtf8Bytes(model, serializerOptions); var hasWorkflowName = !string.IsNullOrWhiteSpace(definition.Name); var workflowName = hasWorkflowName ? definition.Name!.Trim() : definition.DefinitionId; - + var fileName = hasWorkflowName ? $"{workflowName.Underscore().Dasherize().ToLowerInvariant()}.json" : $"workflow-definition-{workflowName.Underscore().Dasherize().ToLowerInvariant()}.json"; - return File(binaryJson, MediaTypeNames.Application.Json, fileName); + await SendBytesAsync(binaryJson, fileName, cancellation: cancellationToken); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Models.cs new file mode 100644 index 000000000..6e9c1300d --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Export/Models.cs @@ -0,0 +1,7 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Export; + +public class Request +{ + public string DefinitionId { get; set; } = default!; + public string? VersionOptions { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get.cs deleted file mode 100644 index 85d2b3263..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Api.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Management.Mappers; -using Elsa.Workflows.Persistence.Services; -using Elsa.Workflows.Runtime.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Get")] -[ProducesResponseType(typeof(WorkflowDefinitionModel), StatusCodes.Status200OK)] -public class Get : Controller -{ - private readonly IWorkflowDefinitionStore _store; - private readonly IWorkflowDefinitionService _workflowDefinitionService; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - private readonly VariableDefinitionMapper _variableDefinitionMapper; - - public Get( - IWorkflowDefinitionStore store, - IWorkflowDefinitionService workflowDefinitionService, - SerializerOptionsProvider serializerOptionsProvider, - VariableDefinitionMapper variableDefinitionMapper) - { - _store = store; - _workflowDefinitionService = workflowDefinitionService; - _serializerOptionsProvider = serializerOptionsProvider; - _variableDefinitionMapper = variableDefinitionMapper; - } - - [HttpGet] - public async Task HandleAsync( - CancellationToken cancellationToken, - [FromRoute] string definitionId, - [FromQuery] string? versionOptions = default) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var parsedVersionOptions = versionOptions != null ? VersionOptions.FromString(versionOptions) : VersionOptions.Latest; - var definition = await _store.FindByDefinitionIdAsync(definitionId, parsedVersionOptions, cancellationToken); - - if (definition == null) - return NotFound(); - - var workflow = await _workflowDefinitionService.MaterializeWorkflowAsync(definition, cancellationToken); - var variables = _variableDefinitionMapper.Map(workflow.Variables).ToList(); - - var model = new WorkflowDefinitionModel( - definition.Id, - definition.DefinitionId, - definition.Name, - definition.Description, - definition.CreatedAt, - definition.Version, - variables, - definition.Metadata, - definition.ApplicationProperties, - definition.IsLatest, - definition.IsPublished, - workflow.Root); - - return Json(model, serializerOptions); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Endpoint.cs new file mode 100644 index 000000000..e9a0bb80f --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Endpoint.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Api.Mappers; +using Elsa.Workflows.Api.Models; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Get; + +public class Get : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + + public Get(IWorkflowDefinitionStore store) + { + _store = store; + } + + public override void Configure() + { + Get("/workflow-definitions/{definitionId}"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var versionOptions = request.VersionOptions != null ? VersionOptions.FromString(request.VersionOptions) : VersionOptions.Latest; + var definition = await _store.FindByDefinitionIdAsync(request.DefinitionId, versionOptions, cancellationToken); + + if (definition == null) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + var response = await Map.FromEntityAsync(definition); + await SendOkAsync(response, cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Models.cs new file mode 100644 index 000000000..b8a0af0a9 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Get/Models.cs @@ -0,0 +1,7 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Get; + +public class Request +{ + public string DefinitionId { get; set; } = default!; + public string? VersionOptions { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import/Endpoint.cs similarity index 63% rename from src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import.cs rename to src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import/Endpoint.cs index 34b38b3ee..e1cf3570c 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Import/Endpoint.cs @@ -2,24 +2,17 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; using Elsa.Workflows.Api.Models; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Materializers; using Elsa.Workflows.Management.Services; -using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Runtime.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +using FastEndpoints; -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Import; -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Import")] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status200OK)] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status201Created)] -public class Import : Controller +public class Import : Endpoint { private readonly SerializerOptionsProvider _serializerOptionsProvider; private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; @@ -38,11 +31,14 @@ public class Import : Controller _variableDefinitionMapper = variableDefinitionMapper; } - [HttpPost] - public async Task HandleAsync(string? definitionId, bool publish, CancellationToken cancellationToken) + public override void Configure() { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = (await Request.ReadFromJsonAsync(serializerOptions, cancellationToken))!; + Post("workflow-definitions/import", "workflow-definitions/{definitionId}/import"); + } + + public override async Task HandleAsync(WorkflowDefinitionRequest request, CancellationToken cancellationToken) + { + var definitionId = request.DefinitionId; // Get a workflow draft version. var draft = !string.IsNullOrWhiteSpace(definitionId) @@ -61,39 +57,40 @@ public class Import : Controller } // Update the draft with the received model. - var root = model.Root; + var root = request.Root; + var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); var stringData = JsonSerializer.Serialize(root, serializerOptions); - var variables = _variableDefinitionMapper.Map(model.Variables).ToList(); + var variables = _variableDefinitionMapper.Map(request.Variables).ToList(); draft!.StringData = stringData; draft.MaterializerName = JsonWorkflowMaterializer.MaterializerName; - draft.Name = model.Name?.Trim(); - draft.Description = model.Description?.Trim(); - draft.Metadata = model.Metadata; + draft.Name = request.Name?.Trim(); + draft.Description = request.Description?.Trim(); + draft.Metadata = request.Metadata; draft.Variables = variables; - draft.ApplicationProperties = model.ApplicationProperties; - draft = publish ? await _workflowDefinitionPublisher.PublishAsync(draft, cancellationToken) : await _workflowDefinitionPublisher.SaveDraftAsync(draft, cancellationToken); + draft.ApplicationProperties = request.ApplicationProperties; + draft = request.Publish ? await _workflowDefinitionPublisher.PublishAsync(draft, cancellationToken) : await _workflowDefinitionPublisher.SaveDraftAsync(draft, cancellationToken); // Materialize the workflow definition for serialization. var workflow = await _workflowDefinitionService.MaterializeWorkflowAsync(draft, cancellationToken); - var workflowModel = new WorkflowDefinitionModel( + var response = new WorkflowDefinitionResponse( draft.Id, draft.DefinitionId, draft.Name, draft.Description, draft.CreatedAt, draft.Version, - model.Variables, + request.Variables, draft.Metadata, draft.ApplicationProperties, draft.IsLatest, draft.IsPublished, workflow.Root); - var result = Json(workflowModel, serializerOptions); - result.StatusCode = isNew ? StatusCodes.Status201Created : StatusCodes.Status200OK; - - return result; + if (isNew) + await SendCreatedAtAsync(new { DefinitionId = definitionId }, response, cancellation: cancellationToken); + else + await SendOkAsync(response, cancellationToken); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List.cs deleted file mode 100644 index 74082690f..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Persistence.Models; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Open.Linq.AsyncExtensions; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "List")] -[ProducesResponseType(typeof(Page), StatusCodes.Status200OK)] -public class List : Controller -{ - private readonly IWorkflowDefinitionStore _store; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public List(IWorkflowDefinitionStore store, SerializerOptionsProvider serializerOptionsProvider) - { - _store = store; - _serializerOptionsProvider = serializerOptionsProvider; - } - - public async Task HandleAsync( - CancellationToken cancellationToken, - [FromQuery] string? versionOptions = default, - [FromQuery] string? definitionIds = default, - [FromQuery(Name = "materializer")] string? materializerName = default, - //[FromQuery(Name = "label")] string[]? labels = default, - [FromQuery] int? page = default, - [FromQuery] int? pageSize = default) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var pageArgs = new PageArgs(page, pageSize); - var parsedVersionOptions = versionOptions != null ? VersionOptions.FromString(versionOptions) : default(VersionOptions?); - var splitIds = definitionIds?.Split(',', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty(); - - if (splitIds.Any()) - { - var summaries = await _store.FindManySummariesAsync(splitIds, parsedVersionOptions, cancellationToken).ToList(); - var pageOfSummaries = new Page(summaries, summaries.Count); - - return Json(pageOfSummaries, serializerOptions); - } - else - { - var pageOfSummaries = await _store.ListSummariesAsync(parsedVersionOptions, materializerName, pageArgs, cancellationToken); - return Json(pageOfSummaries, serializerOptions); - } - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Endpoint.cs new file mode 100644 index 000000000..4f9de410a --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Endpoint.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; +using Open.Linq.AsyncExtensions; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.List; + +public class List : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + + public List(IWorkflowDefinitionStore store) + { + _store = store; + } + + public override void Configure() + { + Get("/workflow-definitions"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) + { + var pageArgs = new PageArgs(request.Page, request.PageSize); + var versionOptions = request.VersionOptions != null ? VersionOptions.FromString(request.VersionOptions) : default(VersionOptions?); + var splitIds = request.DefinitionIds ?? Array.Empty(); + + if (splitIds.Any()) + { + var summaries = await _store.FindManySummariesAsync(splitIds, versionOptions, cancellationToken).ToList(); + return new Response(summaries, summaries.Count); + } + else + { + var summaries = await _store.ListSummariesAsync(versionOptions, request.MaterializerName, pageArgs, cancellationToken); + return new Response(summaries.Items, summaries.TotalCount); + } + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Models.cs new file mode 100644 index 000000000..4baae78a7 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/List/Models.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Elsa.Workflows.Persistence.Models; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.List; + +public class Request +{ + public string? VersionOptions { get; set; } + public string[]? DefinitionIds { get; set; } + [BindFrom("materializer")] public string? MaterializerName { get; set; } + [BindFrom("label")] public string[]? Labels { get; set; } + public int? Page { get; set; } + public int? PageSize { get; set; } +} + +public class Response +{ + public Response(ICollection items, long totalCount) + { + Items = items; + TotalCount = totalCount; + } + + public ICollection Items { get; set; } + public long TotalCount { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs similarity index 51% rename from src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post.cs rename to src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs index 1feb1b9ad..62662cf5e 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs @@ -3,34 +3,26 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; using Elsa.Workflows.Api.Models; using Elsa.Workflows.Core.Activities; using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Materializers; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Services; -using Elsa.Workflows.Persistence.Entities; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +using FastEndpoints; -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Post; -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Post")] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status200OK)] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status201Created)] -public class Post : Controller +public class Post : Endpoint { private readonly SerializerOptionsProvider _serializerOptionsProvider; private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; private readonly VariableDefinitionMapper _variableDefinitionMapper; public Post( - SerializerOptionsProvider serializerOptionsProvider, - IWorkflowDefinitionPublisher workflowDefinitionPublisher, + SerializerOptionsProvider serializerOptionsProvider, + IWorkflowDefinitionPublisher workflowDefinitionPublisher, VariableDefinitionMapper variableDefinitionMapper) { _serializerOptionsProvider = serializerOptionsProvider; @@ -38,22 +30,14 @@ public class Post : Controller _variableDefinitionMapper = variableDefinitionMapper; } - public record SaveWorkflowDefinitionRequest( - string? DefinitionId, - string? Name, - string? Description, - IActivity? Root, - ICollection? Variables, - IDictionary? Metadata, - IDictionary? ApplicationProperties, - bool Publish); - - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) + public override void Configure() { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = (await Request.ReadFromJsonAsync(serializerOptions, cancellationToken))!; - var definitionId = model.DefinitionId; + Post("/workflow-definitions"); + } + + public override async Task HandleAsync(WorkflowDefinitionRequest request, CancellationToken cancellationToken) + { + var definitionId = request.DefinitionId; // Get a workflow draft version. var draft = !string.IsNullOrWhiteSpace(definitionId) @@ -72,36 +56,37 @@ public class Post : Controller } // Update the draft with the received model. - var root = model.Root ?? new Sequence(); + var root = request.Root ?? new Sequence(); + var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); var stringData = JsonSerializer.Serialize(root, serializerOptions); - var variables = _variableDefinitionMapper.Map(model.Variables).ToList(); + var variables = _variableDefinitionMapper.Map(request.Variables).ToList(); draft!.StringData = stringData; draft.MaterializerName = JsonWorkflowMaterializer.MaterializerName; - draft.Name = model.Name?.Trim(); - draft.Description = model.Description?.Trim(); - draft.Metadata = model.Metadata ?? new Dictionary(); + draft.Name = request.Name?.Trim(); + draft.Description = request.Description?.Trim(); + draft.Metadata = request.Metadata ?? new Dictionary(); draft.Variables = variables; - draft.ApplicationProperties = model.ApplicationProperties ?? new Dictionary(); - draft = model.Publish ? await _workflowDefinitionPublisher.PublishAsync(draft, cancellationToken) : await _workflowDefinitionPublisher.SaveDraftAsync(draft, cancellationToken); + draft.ApplicationProperties = request.ApplicationProperties ?? new Dictionary(); + draft = request.Publish ? await _workflowDefinitionPublisher.PublishAsync(draft, cancellationToken) : await _workflowDefinitionPublisher.SaveDraftAsync(draft, cancellationToken); - var draftModel = new WorkflowDefinitionModel( + var response = new WorkflowDefinitionResponse( draft.Id, draft.DefinitionId, draft.Name, draft.Description, draft.CreatedAt, draft.Version, - model.Variables ?? new List(), + request.Variables ?? new List(), draft.Metadata, draft.ApplicationProperties, draft.IsLatest, draft.IsPublished, root); - var result = Json(draftModel, serializerOptions); - result.StatusCode = isNew ? StatusCodes.Status201Created : StatusCodes.Status200OK; - - return result; + if (isNew) + await SendCreatedAtAsync(new { definitionId = definitionId }, response, cancellation: cancellationToken); + else + await SendOkAsync(response, cancellationToken); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish.cs deleted file mode 100644 index eeac84c1c..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Management.Services; -using Elsa.Workflows.Persistence.Entities; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Publish")] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status200OK)] -public class Publish : Controller -{ - private readonly SerializerOptionsProvider _serializerOptionsProvider; - private readonly IWorkflowDefinitionStore _store; - private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; - - public Publish(SerializerOptionsProvider serializerOptionsProvider, IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher) - { - _serializerOptionsProvider = serializerOptionsProvider; - _store = store; - _workflowDefinitionPublisher = workflowDefinitionPublisher; - } - - public async Task HandleAsync(string definitionId, CancellationToken cancellationToken) - { - var definition = await _store.FindByDefinitionIdAsync(definitionId, VersionOptions.Latest, cancellationToken); - - if (definition == null) - return NotFound(); - - if (definition.IsPublished) - return BadRequest(new - { - Message = $"Workflow with id {definitionId} is already published" - }); - - await _workflowDefinitionPublisher.PublishAsync(definition, cancellationToken); - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - - return Json(definition, serializerOptions); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Endpoint.cs new file mode 100644 index 000000000..28d2d62b4 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Endpoint.cs @@ -0,0 +1,54 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Api.Mappers; +using Elsa.Workflows.Api.Models; +using Elsa.Workflows.Core.Serialization; +using Elsa.Workflows.Management.Services; +using Elsa.Workflows.Persistence.Entities; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Publish; + +public class Publish : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; + + public Publish(IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher) + { + _store = store; + _workflowDefinitionPublisher = workflowDefinitionPublisher; + } + + public override void Configure() + { + Post("/workflow-definitions/{definitionId}/publish"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var definition = await _store.FindByDefinitionIdAsync(request.DefinitionId, VersionOptions.Latest, cancellationToken); + + if (definition == null) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + if (definition.IsPublished) + { + AddError($"Workflow with id {request.DefinitionId} is already published"); + await SendErrorsAsync(cancellation: cancellationToken); + return; + } + + await _workflowDefinitionPublisher.PublishAsync(definition, cancellationToken); + + var response = await Map.FromEntityAsync(definition); + await SendOkAsync(response, cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Models.cs new file mode 100644 index 000000000..3b85be489 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Publish/Models.cs @@ -0,0 +1,6 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Publish; + +public class Request +{ + public string DefinitionId { get; set; } = default!; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract.cs deleted file mode 100644 index 37c37fc78..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Management.Services; -using Elsa.Workflows.Persistence.Entities; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowDefinitions, "Retract")] -[ProducesResponseType(typeof(WorkflowDefinition), StatusCodes.Status200OK)] -public class Retract : Controller -{ - private readonly SerializerOptionsProvider _serializerOptionsProvider; - private readonly IWorkflowDefinitionStore _store; - private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; - - public Retract( - SerializerOptionsProvider serializerOptionsProvider, - IWorkflowDefinitionStore store, - IWorkflowDefinitionPublisher workflowDefinitionPublisher) - { - _serializerOptionsProvider = serializerOptionsProvider; - _store = store; - _workflowDefinitionPublisher = workflowDefinitionPublisher; - } - - public async Task HandleAsync(string definitionId, CancellationToken cancellationToken) - { - var definition = await _store.FindByDefinitionIdAsync(definitionId, VersionOptions.LatestOrPublished, cancellationToken); - - if (definition == null) - return NotFound(); - - if (!definition.IsPublished) - return BadRequest(new - { - Message = $"Workflow with id {definitionId} is not published" - }); - - await _workflowDefinitionPublisher.RetractAsync(definition, cancellationToken); - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - - return Json(definition, serializerOptions); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Endpoint.cs new file mode 100644 index 000000000..33eb9f276 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Endpoint.cs @@ -0,0 +1,49 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Api.Mappers; +using Elsa.Workflows.Api.Models; +using Elsa.Workflows.Management.Services; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Retract; + +public class Retract : Endpoint +{ + private readonly IWorkflowDefinitionStore _store; + private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher; + + public Retract(IWorkflowDefinitionStore store, IWorkflowDefinitionPublisher workflowDefinitionPublisher) + { + _store = store; + _workflowDefinitionPublisher = workflowDefinitionPublisher; + } + + public override void Configure() + { + Post("/workflow-definitions/{definitionId}/retract"); + } + + public override async Task HandleAsync(Request request, CancellationToken cancellationToken) + { + var definition = await _store.FindByDefinitionIdAsync(request.DefinitionId, VersionOptions.LatestOrPublished, cancellationToken); + + if (definition == null) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + if (!definition.IsPublished) + { + AddError($"Workflow with id {request.DefinitionId} is not published"); + await SendErrorsAsync(cancellation: cancellationToken); + return; + } + + await _workflowDefinitionPublisher.RetractAsync(definition, cancellationToken); + var response = await Map.FromEntityAsync(definition); + await SendOkAsync(response, cancellationToken); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Models.cs new file mode 100644 index 000000000..47c506537 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Retract/Models.cs @@ -0,0 +1,6 @@ +namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Retract; + +public class Request +{ + public string DefinitionId { get; set; } = default!; +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel.cs deleted file mode 100644 index 421c2b72b..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Workflows.Core.Serialization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowInstances, "BulkCancel")] -public class BulkCancel : Controller -{ - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public BulkCancel(SerializerOptionsProvider serializerOptionsProvider) - { - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpPost] - public async Task HandleAsync(CancellationToken cancellationToken) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = await Request.ReadFromJsonAsync(serializerOptions, cancellationToken); - // TODO: Implement workflow cancellation. - var count = -1; - - return Json(new BulkCancelWorkflowInstancesResponse(count), serializerOptions); - } - - public record BulkCancelWorkflowInstancesRequest(ICollection Ids); - - public record BulkCancelWorkflowInstancesResponse([property: JsonPropertyName("cancelled")] int CancelledCount); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Endpoint.cs new file mode 100644 index 000000000..44b73f610 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Endpoint.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.BulkCancel; + +public class Endpoint : Endpoint +{ + public override void Configure() + { + Post("/bulk-actions/cancel/workflow-instances/by-id"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) + { + // TODO: Implement workflow cancellation. + var count = -1; + + return new(count); + } + + public record BulkCancelWorkflowInstancesRequest(ICollection Ids); + + public record BulkCancelWorkflowInstancesResponse([property: JsonPropertyName("cancelled")] int CancelledCount); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Models.cs new file mode 100644 index 000000000..cc799afb5 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkCancel/Models.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.BulkCancel; + +public class Request +{ + public ICollection Ids { get; set; } = default!; +} + +public class Response +{ + public Response(int cancelledCount) + { + CancelledCount = cancelledCount; + } + + [JsonPropertyName("cancelled")] public int CancelledCount { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete/Endpoint.cs similarity index 56% rename from src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete.cs rename to src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete/Endpoint.cs index f2988a456..c3c8784c4 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/BulkDelete/Endpoint.cs @@ -2,17 +2,15 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Persistence.Services; +using FastEndpoints; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances; +namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.BulkDelete; -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowInstances, "BulkDelete")] -public class BulkDelete : Controller +public class BulkDelete : Endpoint { private readonly IWorkflowInstanceStore _store; private readonly SerializerOptionsProvider _serializerOptionsProvider; @@ -23,17 +21,33 @@ public class BulkDelete : Controller _serializerOptionsProvider = serializerOptionsProvider; } - [HttpPost] + public override void Configure() + { + Post(""); + } + + [Microsoft.AspNetCore.Mvc.HttpPost] public async Task HandleAsync(CancellationToken cancellationToken) { var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var model = await Request.ReadFromJsonAsync(serializerOptions, cancellationToken); + var model = await Request.ReadFromJsonAsync(serializerOptions, cancellationToken); var count = await _store.DeleteManyAsync(model!.Ids, cancellationToken); - return Json(new BulkDeleteWorkflowInstancesResponse(count), serializerOptions); + return Json(new Response(count), serializerOptions); + } +} + +public class Request +{ + public ICollection Ids { get; set; } = default!; +} + +public class Response +{ + public Response(int deletedCount) + { + DeletedCount = deletedCount; } - public record BulkDeleteWorkflowInstancesRequest(ICollection Ids); - - public record BulkDeleteWorkflowInstancesResponse([property: JsonPropertyName("deleted")] int DeletedCount); + [JsonPropertyName("deleted")] public int DeletedCount { get; init; } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get.cs deleted file mode 100644 index 734faaf30..000000000 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Elsa.AspNetCore.Attributes; -using Elsa.Persistence.Common.Models; -using Elsa.Workflows.Core.Serialization; -using Elsa.Workflows.Persistence.Services; -using Microsoft.AspNetCore.Mvc; - -// ReSharper disable NotAccessedPositionalProperty.Global - -namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.Journal; - -[Area(AreaNames.Elsa)] -[ApiEndpoint(ControllerNames.WorkflowJournal, "Get")] -public class Get : Controller -{ - private readonly IWorkflowExecutionLogStore _store; - private readonly SerializerOptionsProvider _serializerOptionsProvider; - - public Get(IWorkflowExecutionLogStore store, SerializerOptionsProvider serializerOptionsProvider) - { - _store = store; - _serializerOptionsProvider = serializerOptionsProvider; - } - - [HttpGet] - public async Task HandleAsync( - [FromRoute(Name = "id")] string workflowInstanceId, - [FromQuery] int? page, - [FromQuery] int? pageSize, - CancellationToken cancellationToken) - { - var serializerOptions = _serializerOptionsProvider.CreateApiOptions(); - var pageArgs = new PageArgs(page, pageSize); - var pageOfRecords = await _store.FindManyByWorkflowInstanceIdAsync(workflowInstanceId, pageArgs, cancellationToken); - - var models = pageOfRecords.Items.Select(x => - new WorkflowExecutionLogRecordModel( - x.Id, - x.ActivityInstanceId, - x.ParentActivityInstanceId, - x.ActivityId, - x.ActivityType, - x.Timestamp, - x.EventName, - x.Message, - x.Source, - x.Payload)) - .ToList(); - - var pageOfModels = Page.Of(models, pageOfRecords.TotalCount); - - return Json(pageOfModels, serializerOptions); - } - - public record WorkflowExecutionLogRecordModel( - string Id, - string ActivityInstanceId, - string? ParentActivityInstanceId, - string ActivityId, - string ActivityType, - DateTimeOffset Timestamp, - string? EventName, - string? Message, - string? Source, - object? Payload); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Endpoint.cs new file mode 100644 index 000000000..886519c4f --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Endpoint.cs @@ -0,0 +1,45 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Workflows.Persistence.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.Journal.Get; + +public class Get : Endpoint +{ + private readonly IWorkflowExecutionLogStore _store; + + public Get(IWorkflowExecutionLogStore store) + { + _store = store; + } + + public override void Configure() + { + Get("/workflow-instances/{id}/journal"); + } + + public override async Task ExecuteAsync(Request request, CancellationToken cancellationToken) + { + var pageArgs = new PageArgs(request.Page, request.PageSize); + var pageOfRecords = await _store.FindManyByWorkflowInstanceIdAsync(request.WorkflowInstanceId, pageArgs, cancellationToken); + + var models = pageOfRecords.Items.Select(x => + new ExecutionLogRecord( + x.Id, + x.ActivityInstanceId, + x.ParentActivityInstanceId, + x.ActivityId, + x.ActivityType, + x.Timestamp, + x.EventName, + x.Message, + x.Source, + x.Payload)) + .ToList(); + + return new(models, pageOfRecords.TotalCount); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Models.cs new file mode 100644 index 000000000..789d41a27 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/Get/Models.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using FastEndpoints; + +// ReSharper disable NotAccessedPositionalProperty.Global + +namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.Journal.Get; + +public class Request +{ + [BindFrom("id")] public string WorkflowInstanceId { get; set; } = default!; + public int? Page { get; set; } + public int? PageSize { get; set; } +} + +public class Response +{ + public Response(ICollection items, long totalCount) + { + Items = items; + TotalCount = totalCount; + } + + public ICollection Items { get; } + public long TotalCount { get; } +} + +public record ExecutionLogRecord( + string Id, + string ActivityInstanceId, + string? ParentActivityInstanceId, + string ActivityId, + string ActivityType, + DateTimeOffset Timestamp, + string? EventName, + string? Message, + string? Source, + object? Payload); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/List.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/List.cs index f6d07f499..d2d0bd7cc 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/List.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/List.cs @@ -1,8 +1,8 @@ using System.Threading; using System.Threading.Tasks; using Elsa.AspNetCore.Attributes; +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Api/Extensions/MvcBuilderExtensions.cs b/src/modules/Elsa.Workflows.Api/Extensions/MvcBuilderExtensions.cs index be05db2c6..dd51ddb59 100644 --- a/src/modules/Elsa.Workflows.Api/Extensions/MvcBuilderExtensions.cs +++ b/src/modules/Elsa.Workflows.Api/Extensions/MvcBuilderExtensions.cs @@ -1,4 +1,5 @@ using Elsa.Workflows.Api.Endpoints.ActivityDescriptors; +using Elsa.Workflows.Api.Endpoints.ActivityDescriptors.List; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.Workflows.Api/Mappers/WorkflowDefinitionMapper.cs b/src/modules/Elsa.Workflows.Api/Mappers/WorkflowDefinitionMapper.cs new file mode 100644 index 000000000..43911d573 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Mappers/WorkflowDefinitionMapper.cs @@ -0,0 +1,34 @@ +using System.Linq; +using System.Threading.Tasks; +using Elsa.Workflows.Api.Models; +using Elsa.Workflows.Management.Mappers; +using Elsa.Workflows.Persistence.Entities; +using Elsa.Workflows.Runtime.Services; +using FastEndpoints; + +namespace Elsa.Workflows.Api.Mappers; + +public class WorkflowDefinitionMapper : ResponseMapper +{ + public override async Task FromEntityAsync(WorkflowDefinition entity) + { + var workflowDefinitionService = Resolve(); + var variableDefinitionMapper = Resolve(); + var workflow = await workflowDefinitionService.MaterializeWorkflowAsync(entity); + var variables = variableDefinitionMapper.Map(workflow.Variables).ToList(); + + return new ( + entity.Id, + entity.DefinitionId, + entity.Name, + entity.Description, + entity.CreatedAt, + entity.Version, + variables, + entity.Metadata, + entity.ApplicationProperties, + entity.IsLatest, + entity.IsPublished, + workflow.Root); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Models/ProcessStimulusResults.cs b/src/modules/Elsa.Workflows.Api/Models/ProcessStimulusResults.cs deleted file mode 100644 index fe4bc0c71..000000000 --- a/src/modules/Elsa.Workflows.Api/Models/ProcessStimulusResults.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.Collections.Generic; -using Elsa.AspNetCore.Models; -using Elsa.Workflows.Runtime.Models; - -namespace Elsa.Workflows.Api.Models; - -public record ProcessStimulusResults(ICollection Items) : ListModel(Items); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionRequest.cs b/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionRequest.cs new file mode 100644 index 000000000..067ded7f4 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionRequest.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Elsa.Workflows.Core.Services; +using Elsa.Workflows.Management.Models; + +namespace Elsa.Workflows.Api.Models; + +public class WorkflowDefinitionRequest +{ + public string? DefinitionId { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } = default!; + public ICollection? Variables { get; set; } = default!; + public IDictionary? Metadata { get; set; } = default!; + public IDictionary? ApplicationProperties { get; set; } = default!; + public IActivity? Root { get; set; } = default!; + public bool Publish { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionResponse.cs b/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionResponse.cs new file mode 100644 index 000000000..5691f6024 --- /dev/null +++ b/src/modules/Elsa.Workflows.Api/Models/WorkflowDefinitionResponse.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Elsa.Workflows.Core.Services; +using Elsa.Workflows.Management.Models; + +namespace Elsa.Workflows.Api.Models; + +public class WorkflowDefinitionResponse +{ + public WorkflowDefinitionResponse( + string id, + string definitionId, + string? name, + string? description, + DateTimeOffset createdAt, + int version, + ICollection variables, + IDictionary metadata, + IDictionary applicationProperties, + bool isLatest, + bool isPublished, + IActivity root) + { + Id = id; + DefinitionId = definitionId; + Name = name; + Description = description; + CreatedAt = createdAt; + Version = version; + Variables = variables; + Metadata = metadata; + ApplicationProperties = applicationProperties; + IsLatest = isLatest; + IsPublished = isPublished; + Root = root; + } + + public string Id { get; } + public string DefinitionId { get; } + public string? Name { get; } + public string? Description { get; } + public DateTimeOffset CreatedAt { get; } + public int Version { get; } + public ICollection Variables { get; } + public IDictionary Metadata { get; } + public IDictionary ApplicationProperties { get; } + public bool IsLatest { get; } + public bool IsPublished { get; } + public IActivity Root { get; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Implementations/WorkflowDefinitionPublisher.cs b/src/modules/Elsa.Workflows.Management/Implementations/WorkflowDefinitionPublisher.cs index 4907c4b18..34c402452 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/WorkflowDefinitionPublisher.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/WorkflowDefinitionPublisher.cs @@ -1,7 +1,7 @@ using System.Text.Json; using Elsa.Common.Services; using Elsa.Mediator.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Activities; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; diff --git a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowDefinitionStore.cs b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowDefinitionStore.cs index deacdc851..97936da66 100644 --- a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowDefinitionStore.cs @@ -1,6 +1,6 @@ using System.Linq.Expressions; +using Elsa.Models; using Elsa.Persistence.Common.Extensions; -using Elsa.Persistence.Common.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Extensions; using Elsa.Persistence.EntityFrameworkCore.Common.Services; using Elsa.Workflows.Persistence.Entities; diff --git a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowExecutionLogStore.cs b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowExecutionLogStore.cs index 25116a480..dd7870ff9 100644 --- a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowExecutionLogStore.cs @@ -1,5 +1,5 @@ +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Services; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowInstanceStore.cs b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowInstanceStore.cs index 4a3d72dcc..6d414e5e2 100644 --- a/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowInstanceStore.cs +++ b/src/modules/Elsa.Workflows.Persistence.EntityFrameworkCore/Implementations/EFCoreWorkflowInstanceStore.cs @@ -1,5 +1,5 @@ +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using Elsa.Persistence.EntityFrameworkCore.Common.Extensions; using Elsa.Persistence.EntityFrameworkCore.Common.Services; using Elsa.Workflows.Persistence.Entities; diff --git a/src/modules/Elsa.Workflows.Persistence/Elsa.Workflows.Persistence.csproj b/src/modules/Elsa.Workflows.Persistence/Elsa.Workflows.Persistence.csproj index 45a5eb12e..71ea14acb 100644 --- a/src/modules/Elsa.Workflows.Persistence/Elsa.Workflows.Persistence.csproj +++ b/src/modules/Elsa.Workflows.Persistence/Elsa.Workflows.Persistence.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/modules/Elsa.Workflows.Persistence/Extensions/WorkflowExtensions.cs b/src/modules/Elsa.Workflows.Persistence/Extensions/WorkflowExtensions.cs index 039c38577..9cbeaa655 100644 --- a/src/modules/Elsa.Workflows.Persistence/Extensions/WorkflowExtensions.cs +++ b/src/modules/Elsa.Workflows.Persistence/Extensions/WorkflowExtensions.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; namespace Elsa.Workflows.Persistence.Extensions; diff --git a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowDefinitionStore.cs b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowDefinitionStore.cs index b896a05a4..6aa5e25e3 100644 --- a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowDefinitionStore.cs @@ -1,6 +1,6 @@ +using Elsa.Models; using Elsa.Persistence.Common.Extensions; using Elsa.Persistence.Common.Implementations; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Models; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowExecutionLogStore.cs b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowExecutionLogStore.cs index 56e7096d4..ee4cb7952 100644 --- a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowExecutionLogStore.cs @@ -1,6 +1,6 @@ +using Elsa.Models; using Elsa.Persistence.Common.Extensions; using Elsa.Persistence.Common.Implementations; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowInstanceStore.cs b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowInstanceStore.cs index c8f9ad5e8..f8efeb02b 100644 --- a/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowInstanceStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Implementations/MemoryWorkflowInstanceStore.cs @@ -1,6 +1,6 @@ +using Elsa.Models; using Elsa.Persistence.Common.Entities; using Elsa.Persistence.Common.Implementations; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Models; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowDefinitionStore.cs b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowDefinitionStore.cs index 850dc7cc8..eaa13f78f 100644 --- a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowDefinitionStore.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Models; diff --git a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowExecutionLogStore.cs b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowExecutionLogStore.cs index 238250ca1..9aa9a0c26 100644 --- a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowExecutionLogStore.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Persistence.Entities; namespace Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowInstanceStore.cs b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowInstanceStore.cs index fb24a34a4..1b9437696 100644 --- a/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowInstanceStore.cs +++ b/src/modules/Elsa.Workflows.Persistence/Services/IWorkflowInstanceStore.cs @@ -1,5 +1,5 @@ +using Elsa.Models; using Elsa.Persistence.Common.Entities; -using Elsa.Persistence.Common.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Models; diff --git a/src/modules/Elsa.Workflows.Runtime/Activities/DispatchWorkflow.cs b/src/modules/Elsa.Workflows.Runtime/Activities/DispatchWorkflow.cs index b02cde09f..000f98504 100644 --- a/src/modules/Elsa.Workflows.Runtime/Activities/DispatchWorkflow.cs +++ b/src/modules/Elsa.Workflows.Runtime/Activities/DispatchWorkflow.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core; using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Models; diff --git a/src/modules/Elsa.Workflows.Runtime/HostedServices/PopulateWorkflowDefinitionStore.cs b/src/modules/Elsa.Workflows.Runtime/HostedServices/PopulateWorkflowDefinitionStore.cs index d9d0b6ba9..f60a1fe5f 100644 --- a/src/modules/Elsa.Workflows.Runtime/HostedServices/PopulateWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Workflows.Runtime/HostedServices/PopulateWorkflowDefinitionStore.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Services; diff --git a/src/modules/Elsa.Workflows.Runtime/Implementations/DefaultWorkflowInvoker.cs b/src/modules/Elsa.Workflows.Runtime/Implementations/DefaultWorkflowInvoker.cs index fb6d48289..fff20bc80 100644 --- a/src/modules/Elsa.Workflows.Runtime/Implementations/DefaultWorkflowInvoker.cs +++ b/src/modules/Elsa.Workflows.Runtime/Implementations/DefaultWorkflowInvoker.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Core.State; diff --git a/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowInstanceFactory.cs b/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowInstanceFactory.cs index 3b3a6c4f9..2ba965380 100644 --- a/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowInstanceFactory.cs +++ b/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowInstanceFactory.cs @@ -1,5 +1,5 @@ using Elsa.Common.Services; -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Core.State; diff --git a/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowService.cs b/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowService.cs index 3faf4773e..770c3c707 100644 --- a/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowService.cs +++ b/src/modules/Elsa.Workflows.Runtime/Implementations/WorkflowService.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Runtime.Models; diff --git a/src/modules/Elsa.Workflows.Runtime/Interpreters/ResumeWorkflowInstructionInterpreter.cs b/src/modules/Elsa.Workflows.Runtime/Interpreters/ResumeWorkflowInstructionInterpreter.cs index ee11c6523..c66786dfa 100644 --- a/src/modules/Elsa.Workflows.Runtime/Interpreters/ResumeWorkflowInstructionInterpreter.cs +++ b/src/modules/Elsa.Workflows.Runtime/Interpreters/ResumeWorkflowInstructionInterpreter.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Persistence.Entities; diff --git a/src/modules/Elsa.Workflows.Runtime/Interpreters/TriggerWorkflowInstructionInterpreter.cs b/src/modules/Elsa.Workflows.Runtime/Interpreters/TriggerWorkflowInstructionInterpreter.cs index ad1f4f61f..4fbd26e7f 100644 --- a/src/modules/Elsa.Workflows.Runtime/Interpreters/TriggerWorkflowInstructionInterpreter.cs +++ b/src/modules/Elsa.Workflows.Runtime/Interpreters/TriggerWorkflowInstructionInterpreter.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Services; using Elsa.Workflows.Runtime.Abstractions; diff --git a/src/modules/Elsa.Workflows.Runtime/Models/DispatchWorkflowDefinitionRequest.cs b/src/modules/Elsa.Workflows.Runtime/Models/DispatchWorkflowDefinitionRequest.cs index 37f3de809..b8a77faa1 100644 --- a/src/modules/Elsa.Workflows.Runtime/Models/DispatchWorkflowDefinitionRequest.cs +++ b/src/modules/Elsa.Workflows.Runtime/Models/DispatchWorkflowDefinitionRequest.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.Workflows.Runtime.Models; diff --git a/src/modules/Elsa.Workflows.Runtime/Models/InvokeWorkflowDefinitionRequest.cs b/src/modules/Elsa.Workflows.Runtime/Models/InvokeWorkflowDefinitionRequest.cs index 8213d4a3c..7edd178bd 100644 --- a/src/modules/Elsa.Workflows.Runtime/Models/InvokeWorkflowDefinitionRequest.cs +++ b/src/modules/Elsa.Workflows.Runtime/Models/InvokeWorkflowDefinitionRequest.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; namespace Elsa.Workflows.Runtime.Models; diff --git a/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowInstanceFactory.cs b/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowInstanceFactory.cs index 7b01982ad..07e73f2b9 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowInstanceFactory.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowInstanceFactory.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Persistence.Entities; diff --git a/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowService.cs b/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowService.cs index 23292cd64..ec8ccbf1c 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowService.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/IWorkflowService.cs @@ -1,4 +1,4 @@ -using Elsa.Persistence.Common.Models; +using Elsa.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Runtime.Models; diff --git a/test/Elsa.IntegrationTests/Elsa.IntegrationTests.csproj b/test/Elsa.IntegrationTests/Elsa.IntegrationTests.csproj index 267249a8b..d38ca5401 100644 --- a/test/Elsa.IntegrationTests/Elsa.IntegrationTests.csproj +++ b/test/Elsa.IntegrationTests/Elsa.IntegrationTests.csproj @@ -22,7 +22,7 @@ - +