diff --git a/Directory.Packages.props b/Directory.Packages.props index 70abc011d0..452482edcc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,171 +1,171 @@ - - - true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Elsa.sln b/Elsa.sln index f03016a978..0cccd0d7a6 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.7.34003.232 @@ -277,6 +276,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.FileStorage", "src\mod EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "storage", "storage", "{B818988E-639C-4E6E-85C1-B231BCAD9DAB}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Tenants", "src\modules\Elsa.Tenants\Elsa.Tenants.csproj", "{29638A67-E79F-44FE-AC05-DA499EBA929E}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.CSharp", "src\modules\Elsa.CSharp\Elsa.CSharp.csproj", "{24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Python", "src\modules\Elsa.Python\Elsa.Python.csproj", "{790E94F2-5393-47DF-AC52-D9247F5B243A}" @@ -295,26 +296,26 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{99F2B1DA-2F69-4D70-A2A3-AC985AD91EC4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.BatchProcessing", "samples\aspnet\Elsa.Samples.AspNet.BatchProcessing\Elsa.Samples.AspNet.BatchProcessing.csproj", "{0AAF5EF6-02E5-44F9-B2CB-B1401FC5EF66}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.BatchProcessing", "samples\aspnet\Elsa.Samples.AspNet.BatchProcessing\Elsa.Samples.AspNet.BatchProcessing.csproj", "{0AAF5EF6-02E5-44F9-B2CB-B1401FC5EF66}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Web", "src\bundles\Elsa.Studio.Web\Elsa.Studio.Web.csproj", "{F0385327-CEDE-4CD4-88A5-B66E73E75B28}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Studio.Web", "src\bundles\Elsa.Studio.Web\Elsa.Studio.Web.csproj", "{F0385327-CEDE-4CD4-88A5-B66E73E75B28}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.CustomUIHandler", "samples\aspnet\Elsa.Samples.AspNet.CustomUIHandler\Elsa.Samples.AspNet.CustomUIHandler.csproj", "{E4BF9791-4086-41EB-8EF0-02686A5F3F65}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.CustomUIHandler", "samples\aspnet\Elsa.Samples.AspNet.CustomUIHandler\Elsa.Samples.AspNet.CustomUIHandler.csproj", "{E4BF9791-4086-41EB-8EF0-02686A5F3F65}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.Heartbeats", "samples\aspnet\Elsa.Samples.AspNet.Heartbeats\Elsa.Samples.AspNet.Heartbeats.csproj", "{73852FEC-9847-4C6C-B1F5-1BB014C50A79}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.Heartbeats", "samples\aspnet\Elsa.Samples.AspNet.Heartbeats\Elsa.Samples.AspNet.Heartbeats.csproj", "{73852FEC-9847-4C6C-B1F5-1BB014C50A79}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit.AzureServiceBus", "src\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj", "{AFEB799E-82C3-4D02-9D5C-766BB8DEF004}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.MassTransit.AzureServiceBus", "src\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj", "{AFEB799E-82C3-4D02-9D5C-766BB8DEF004}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "migrations", "migrations", "{C80C8231-D35C-4ACC-9ED6-9F3DB221535E}" ProjectSection(SolutionItems) = preProject - migrations\efcore-3.1.sh = migrations\efcore-3.1.sh - migrations\efcore-3.0.sh = migrations\efcore-3.0.sh - migrations\efcore-3.1-sql.sh = migrations\efcore-3.1-sql.sh migrations\README.md = migrations\README.md + migrations\efcore-3.1.sh = migrations\efcore-3.1.sh migrations\efcore-3.2.sh = migrations\efcore-3.2.sh + migrations\efcore-3.0.sh = migrations\efcore-3.0.sh + migrations\efcore-3.3.sh = migrations\efcore-3.3.sh EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Alterations.IntegrationTests", "test\integration\Elsa.Alterations.IntegrationTests\Elsa.Alterations.IntegrationTests.csproj", "{F50336DA-42D1-4DD1-A107-67AFEB8A33EE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Alterations.IntegrationTests", "test\integration\Elsa.Alterations.IntegrationTests\Elsa.Alterations.IntegrationTests.csproj", "{F50336DA-42D1-4DD1-A107-67AFEB8A33EE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hosting", "hosting", "{A516931E-EDBB-4FC3-BB94-1BB824D5BC61}" EndProject @@ -359,6 +360,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.JavaScript.Integration EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AzureServiceBus.ComponentTests", "test\component\Elsa.AzureServiceBus.ComponentTests\Elsa.AzureServiceBus.ComponentTests.csproj", "{7F5A304F-7DD9-4A64-8FCD-9B1FF06735B9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.Tenants", "samples\aspnet\Elsa.Samples.AspNet.Tenants\Elsa.Samples.AspNet.Tenants.csproj", "{9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.Tenants.External", "samples\aspnet\Elsa.Samples.AspNet.Tenants.External\Elsa.Samples.AspNet.Tenants.External.csproj", "{1B9E55EB-4379-4B95-9F84-EEEB5AA20987}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -745,6 +750,10 @@ Global {732BF088-6AD7-4C4D-9A48-8074253596D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {732BF088-6AD7-4C4D-9A48-8074253596D4}.Release|Any CPU.ActiveCfg = Release|Any CPU {732BF088-6AD7-4C4D-9A48-8074253596D4}.Release|Any CPU.Build.0 = Release|Any CPU + {29638A67-E79F-44FE-AC05-DA499EBA929E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29638A67-E79F-44FE-AC05-DA499EBA929E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29638A67-E79F-44FE-AC05-DA499EBA929E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29638A67-E79F-44FE-AC05-DA499EBA929E}.Release|Any CPU.Build.0 = Release|Any CPU {24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -757,6 +766,8 @@ Global {169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6}.Debug|Any CPU.Build.0 = Debug|Any CPU {169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6}.Release|Any CPU.ActiveCfg = Release|Any CPU {169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6}.Release|Any CPU.Build.0 = Release|Any CPU + {99F2B1DA-2F69-4D70-A2A3-AC985AD91EC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99F2B1DA-2F69-4D70-A2A3-AC985AD91EC4}.Release|Any CPU.ActiveCfg = Release|Any CPU {0AAF5EF6-02E5-44F9-B2CB-B1401FC5EF66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0AAF5EF6-02E5-44F9-B2CB-B1401FC5EF66}.Debug|Any CPU.Build.0 = Debug|Any CPU {0AAF5EF6-02E5-44F9-B2CB-B1401FC5EF66}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -781,8 +792,6 @@ Global {F50336DA-42D1-4DD1-A107-67AFEB8A33EE}.Debug|Any CPU.Build.0 = Debug|Any CPU {F50336DA-42D1-4DD1-A107-67AFEB8A33EE}.Release|Any CPU.ActiveCfg = Release|Any CPU {F50336DA-42D1-4DD1-A107-67AFEB8A33EE}.Release|Any CPU.Build.0 = Release|Any CPU - {99F2B1DA-2F69-4D70-A2A3-AC985AD91EC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99F2B1DA-2F69-4D70-A2A3-AC985AD91EC4}.Release|Any CPU.ActiveCfg = Release|Any CPU {BBCE36D1-6767-4ED1-B3E8-84D2567A962A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BBCE36D1-6767-4ED1-B3E8-84D2567A962A}.Debug|Any CPU.Build.0 = Debug|Any CPU {BBCE36D1-6767-4ED1-B3E8-84D2567A962A}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -855,6 +864,14 @@ Global {7F5A304F-7DD9-4A64-8FCD-9B1FF06735B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F5A304F-7DD9-4A64-8FCD-9B1FF06735B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F5A304F-7DD9-4A64-8FCD-9B1FF06735B9}.Release|Any CPU.Build.0 = Release|Any CPU + {9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D}.Release|Any CPU.Build.0 = Release|Any CPU + {1B9E55EB-4379-4B95-9F84-EEEB5AA20987}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B9E55EB-4379-4B95-9F84-EEEB5AA20987}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B9E55EB-4379-4B95-9F84-EEEB5AA20987}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B9E55EB-4379-4B95-9F84-EEEB5AA20987}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -974,6 +991,7 @@ Global {CCCCEF8C-7D96-4BEA-B9D0-E91EDF08E65D} = {AB797AF0-C12C-46DE-A157-7E25625C6200} {732BF088-6AD7-4C4D-9A48-8074253596D4} = {B818988E-639C-4E6E-85C1-B231BCAD9DAB} {B818988E-639C-4E6E-85C1-B231BCAD9DAB} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} + {29638A67-E79F-44FE-AC05-DA499EBA929E} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76} {790E94F2-5393-47DF-AC52-D9247F5B243A} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76} {169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6} = {DD089B8B-DA73-492A-9010-F772D1C178DA} @@ -1004,6 +1022,8 @@ Global {99B171E6-0248-4402-836D-98947CD63772} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} {4332A6BC-434A-4AF5-A075-F1BBCDD28F5D} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} {7F5A304F-7DD9-4A64-8FCD-9B1FF06735B9} = {08B41FFA-CEE3-46A7-B5C0-3EB65D37A16C} + {9A6395A7-9F82-4F82-BFCB-1EBC38F0A86D} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} + {1B9E55EB-4379-4B95-9F84-EEEB5AA20987} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E} diff --git a/generate-migrations-initial copy.sh b/generate-migrations-initial copy.sh deleted file mode 100644 index f5dacadae2..0000000000 --- a/generate-migrations-initial copy.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env zsh - -# Define the modules to update -mods=("Management") -# mods=("Alterations" "Runtime" "Management" "Identity" "Labels") - -# Define the list of providers -providers=("MySql" "SqlServer" "Sqlite" "PostgreSql") -# providers=("SqlServer") - -# Connection strings for each provider -typeset -A connStrings -connStrings=( - MySql "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;" - SqlServer "" - Sqlite "" - PostgreSql "" -) - -# Loop through each module -for module in "${mods[@]}"; do - # Loop through each provider - for provider in "${providers[@]}"; do - providerPath="./src/modules/Elsa.EntityFrameworkCore.$provider" - migrationsPath="Migrations/$module" - - echo "Updating migrations for $provider..." - echo "Provider path: ${providerPath:?}/${migrationsPath}" - echo "Migrations path: $migrationsPath" - echo "Connection string: ${connStrings[$provider]}" - - # 1. Delete the existing migrations folder - rm -rf "${providerPath:?}/${migrationsPath}" - - # 2. Run the migrations command - dotnet ef migrations add Initial -c "$module"ElsaDbContext -p "$providerPath" -o "$migrationsPath" -- --connectionString "${connStrings[$provider]}" - done -done diff --git a/migrations/efcore-3.0.sh b/migrations/efcore-3.0.sh index 420d714972..b2f25f01e6 100644 --- a/migrations/efcore-3.0.sh +++ b/migrations/efcore-3.0.sh @@ -1,12 +1,10 @@ #!/usr/bin/env zsh # Define the modules to update -mods=("Management") -# mods=("Alterations" "Runtime" "Management" "Identity" "Labels") +mods=("Alterations" "Runtime" "Management" "Identity" "Labels") # Define the list of providers providers=("MySql" "SqlServer" "Sqlite" "PostgreSql") -# providers=("SqlServer") # Connection strings for each provider typeset -A connStrings diff --git a/migrations/efcore-3.3.sh b/migrations/efcore-3.3.sh new file mode 100755 index 0000000000..4f43b0cd88 --- /dev/null +++ b/migrations/efcore-3.3.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Define the modules to update +mods=("Alterations" "Runtime" "Management" "Identity" "Labels") + +# Define the list of providers +providers=("MySql" "SqlServer" "Sqlite" "PostgreSql") + +# Loop through each module +for module in "${mods[@]}"; do + # Loop through each provider + for provider in "${providers[@]}"; do + providerPath="../src/modules/Elsa.EntityFrameworkCore.$provider" + migrationsPath="Migrations/$module" + + echo "Updating migrations for $provider..." + echo "Provider path: ${providerPath:?}/${migrationsPath}" + echo "Migrations path: $migrationsPath" + ef-migration-runtime-schema --interface Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema --efOptions "migrations add V3_3 -c ""$module""ElsaDbContext -p ""$providerPath"" -o ""$migrationsPath""" + done +done diff --git a/samples/aspnet/Elsa.Samples.AspNet.HangfireIntegration/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.HangfireIntegration/Program.cs index 12dd7010a8..f32d617067 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.HangfireIntegration/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.HangfireIntegration/Program.cs @@ -33,7 +33,6 @@ // Configure identity. elsa.UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs index 5a838ec321..88545bbaa7 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs @@ -36,7 +36,6 @@ .AddActivitiesFrom() .UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime/Program.cs index 6c5e720371..29e33eec54 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime/Program.cs @@ -19,7 +19,6 @@ .AddActivitiesFrom() .UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/samples/aspnet/Elsa.Samples.AspNet.QuartzIntegration/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.QuartzIntegration/Program.cs index 4f1738b9d5..52dbb5e9ed 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.QuartzIntegration/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.QuartzIntegration/Program.cs @@ -28,7 +28,6 @@ // Configure identity. elsa.UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/samples/aspnet/Elsa.Samples.AspNet.TelnyxIntegration/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.TelnyxIntegration/Program.cs index fab4ec6067..5b3dd0f735 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.TelnyxIntegration/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.TelnyxIntegration/Program.cs @@ -15,11 +15,9 @@ var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var configuration = builder.Configuration; -var identityOptions = new IdentityOptions(); var identityTokenOptions = new IdentityTokenOptions(); var identitySection = configuration.GetSection("Identity"); var identityTokenSection = identitySection.GetSection("Tokens"); -identitySection.Bind(identityOptions); identityTokenSection.Bind(identityTokenOptions); // Add Elsa services. diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Controllers/RunWorkflowController.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Controllers/RunWorkflowController.cs new file mode 100644 index 0000000000..cc8eb52233 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Controllers/RunWorkflowController.cs @@ -0,0 +1,26 @@ +using Elsa.Http; +using Elsa.Workflows.Contracts; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Samples.AspNet.Tenants; + +[ApiController] +[Route("run-workflow")] +public class RunWorkflowController : ControllerBase +{ + private readonly IWorkflowRunner _workflowRunner; + + public RunWorkflowController(IWorkflowRunner workflowRunner) + { + _workflowRunner = workflowRunner; + } + + [HttpGet] + public async Task Post() + { + await _workflowRunner.RunAsync(new WriteHttpResponse + { + Content = new("Hello ASP.NET world!") + }); + } +} \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Elsa.Samples.AspNet.Tenants.External.csproj b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Elsa.Samples.AspNet.Tenants.External.csproj new file mode 100644 index 0000000000..2005a848e7 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Elsa.Samples.AspNet.Tenants.External.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + + + + + + + + + + + + + + diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Program.cs new file mode 100644 index 0000000000..d05b27b444 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Program.cs @@ -0,0 +1,154 @@ +using System.Security.Claims; +using Elsa; +using Elsa.EntityFrameworkCore.Common; +using Elsa.EntityFrameworkCore.Extensions; +using Elsa.EntityFrameworkCore.Modules.Management; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.Extensions; +using Elsa.Identity.MultiTenancy; +using Elsa.Tenants.Extensions; +using FastEndpoints.Swagger; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using NSwag; +using NSwag.AspNetCore; +using NSwag.Generation.Processors.Security; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); +ConfigurationManager configuration = builder.Configuration; + +var identitySection = configuration.GetSection("Identity"); +var tenantsSection = configuration.GetSection("Multitenancy"); + +// Add services to the container. +builder.Services.AddControllers(); +builder.Services.AddElsa(elsa => +{ + var dbContextOptions = new ElsaDbContextOptions(); + string sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; + string schema = configuration.GetConnectionString("Schema")!; + + if (!string.IsNullOrEmpty(schema)) + { + dbContextOptions.SchemaName = schema; + dbContextOptions.MigrationsAssemblyName = typeof(Program).Assembly.GetName().Name; + } + + elsa.UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString, dbContextOptions))); + elsa.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString, dbContextOptions))); + elsa.UseIdentity(options => identitySection.Bind(options)); + elsa.UseTenants(tenantsFeature => + { + tenantsFeature.TenantsOptions = options => + { + tenantsSection.Bind(options); + options.TenantResolutionPipelineBuilder.Append(); + }; + tenantsFeature.UseConfigurationBasedTenantsProvider(); + }); + + elsa + .UseHttp(options => + { + options.ConfigureHttpOptions = httpOptions => + { + httpOptions.BaseUrl = new Uri("https://localhost:8765"); + httpOptions.BasePath = "/workflows-http-endpoints"; + }; + }) + .AddFastEndpointsAssembly() + .UseWorkflowsApi() + .UseScheduling() + .UseRealTimeWorkflows() + .UseJavaScript() + .UseLiquid(); +}); + +builder.Services + .AddAuthentication("Bearer") + .AddJwtBearer(options => + { + options.Authority = configuration.GetValue("Authentication:Authority"); + options.Audience = configuration.GetValue("Authentication:Audience"); + options.RequireHttpsMetadata = false; + + options.Events = new JwtBearerEvents + { + OnTokenValidated = (context) => + { + //Simplification of the Elsa permissions by granting access to everything + var identity = context.Principal.Identity as ClaimsIdentity; + identity?.AddClaim(new Claim("permissions", PermissionNames.All)); + return Task.CompletedTask; + } + }; + }); + +builder.Services.SwaggerDocument(options => +{ + options.DocumentSettings = documentSetting => + { + documentSetting.Title = "Elsa API"; + documentSetting.Version = "v1"; + + documentSetting.AddSecurity("bearer", Enumerable.Empty(), new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.OAuth2, + Description = "OIDC", + Flow = OpenApiOAuth2Flow.Implicit, + Flows = new OpenApiOAuthFlows() + { + AuthorizationCode = new OpenApiOAuthFlow() + { + AuthorizationUrl = $"{configuration.GetValue("Authentication:Authority")}/connect/authorize", + TokenUrl = $"{configuration.GetValue("Authentication:Authority")}/connect/token", + Scopes = new Dictionary + { + { + "workflows.*", "workflows.*" + }, + { + "openid", "OpenId" + }, + { + "profile", "Profile" + }, + }, + }, + } + }); + documentSetting.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("bearer")); + }; +}); + +builder.Services.AddCors(options => options.AddDefaultPolicy(policy => policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader())); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +app.UseHttpsRedirection(); +app.UseRouting(); +app.UseAuthorization(); +app.MapControllers(); +app.UseCors(); +app.UseWorkflows(); +app.UseWorkflowsApi("api"); +app.UseWorkflowsSignalRHubs(); + +if (!app.Environment.IsProduction()) +{ + app.UseOpenApi(options => options.PostProcess = (document, _) => document.Servers.Clear()); + app.UseSwaggerUi(options => + { + options.OAuth2Client = new OAuth2ClientSettings + { + ClientId = configuration.GetValue("Authentication:ClientId"), + ClientSecret = configuration.GetValue("Authentication:ClientSecret"), + AppName = configuration.GetValue("Authentication:Audience"), + UsePkceWithAuthorizationCodeGrant = true, + }; + options.OAuth2Client.Scopes.AddRange("workflows.*", "openid", "profile"); + }); + app.UseReDoc(); +} + +app.Run(); \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Properties/launchSettings.json b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Properties/launchSettings.json new file mode 100644 index 0000000000..114397e425 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Properties/launchSettings.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:8764", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:8765;http://localhost:8764", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Workflows/HelloWorldHttpWorkflow.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Workflows/HelloWorldHttpWorkflow.cs new file mode 100644 index 0000000000..4b736b64df --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/Workflows/HelloWorldHttpWorkflow.cs @@ -0,0 +1,28 @@ +using Elsa.Http; +using Elsa.Workflows; +using Elsa.Workflows.Activities; +using Elsa.Workflows.Contracts; + +namespace Elsa.Samples.AspNet.Tenants; + +public class HelloWorldHttpWorkflow : WorkflowBase +{ + protected override void Build(IWorkflowBuilder builder) + { + builder.Root = new Sequence + { + Activities = + { + new HttpEndpoint + { + Path = new("/hello-world"), + CanStartWorkflow = true + }, + new WriteHttpResponse + { + Content = new("Hello world of HTTP workflows!") + } + } + }; + } +} \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/appsettings.json b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/appsettings.json new file mode 100644 index 0000000000..ebbc7a7a71 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants.External/appsettings.json @@ -0,0 +1,59 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;" + }, + "Multitenancy": { + "TenantIdClaimsType": "instance_token", + "Tenants": [ + { + "TenantId": "19a5f2b0-75e4-45ad-b0ae-fe02d77867d0", + "Name": "DefaultTenant" + }, + { + "TenantId": "a8ad404f-2ac1-439f-8856-f225c928d811", + "Name": "Tenant1" + } + ] + }, + "Authentication": { + "Authority": "https://authorization-server.com", + "Audience": "Elsa", + "ClientId": "elsa.client", + "ClientSecret": "elsa.client-secret" + }, + "Identity": { + "Tokens": { + "SigningKey": "secret-signing-key", + "AccessTokenLifetime": "1:00:00:00", + "RefreshTokenLifetime": "7:00:00:00" + }, + "Roles": [ + { + "Id": "admin", + "Name": "Administrator", + "Permissions": [ + "*" + ] + } + ], + "Users": [ + { + "Id": "a2323f46-42db-4e15-af8b-94238717d817", + "Name": "admin", + "TenantId": "19a5f2b0-75e4-45ad-b0ae-fe02d77867d0", + "HashedPassword": "TfKzh9RLix6FPcCNeHLkGrysFu3bYxqzGqduNdi8v1U=", + "HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=", + "Roles": [ + "admin" + ] + } + ] + } +} diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/Controllers/RunWorkflowController.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Controllers/RunWorkflowController.cs new file mode 100644 index 0000000000..cc8eb52233 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Controllers/RunWorkflowController.cs @@ -0,0 +1,26 @@ +using Elsa.Http; +using Elsa.Workflows.Contracts; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Samples.AspNet.Tenants; + +[ApiController] +[Route("run-workflow")] +public class RunWorkflowController : ControllerBase +{ + private readonly IWorkflowRunner _workflowRunner; + + public RunWorkflowController(IWorkflowRunner workflowRunner) + { + _workflowRunner = workflowRunner; + } + + [HttpGet] + public async Task Post() + { + await _workflowRunner.RunAsync(new WriteHttpResponse + { + Content = new("Hello ASP.NET world!") + }); + } +} \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/Elsa.Samples.AspNet.Tenants.csproj b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Elsa.Samples.AspNet.Tenants.csproj new file mode 100644 index 0000000000..e3341cc477 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Elsa.Samples.AspNet.Tenants.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + + + + + + + + + + + + diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Program.cs new file mode 100644 index 0000000000..82b32b5603 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Program.cs @@ -0,0 +1,90 @@ +using Elsa; +using Elsa.EntityFrameworkCore.Common; +using Elsa.EntityFrameworkCore.Extensions; +using Elsa.EntityFrameworkCore.Modules.Management; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.Extensions; +using Elsa.Identity.MultiTenancy; +using Elsa.Tenants.Extensions; +using FastEndpoints.Swagger; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); +ConfigurationManager configuration = builder.Configuration; + +var identitySection = configuration.GetSection("Identity"); +var identityTokenSection = identitySection.GetSection("Tokens"); +var multiTenancySection = configuration.GetSection("Multitenancy"); + +// Add services to the container. +builder.Services.AddControllers(); +builder.Services.AddElsa(elsa => +{ + var dbContextOptions = new ElsaDbContextOptions(); + string sqliteConnectionString = configuration.GetConnectionString("Sqlite")!; + string schema = configuration.GetConnectionString("Schema")!; + + if (!string.IsNullOrEmpty(schema)) + { + dbContextOptions.SchemaName = schema; + dbContextOptions.MigrationsAssemblyName = typeof(Program).Assembly.GetName().Name; + } + + elsa.UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString, dbContextOptions))); + elsa.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString, dbContextOptions))); + + elsa.UseSasTokens() + .UseIdentity(identity => + { + identity.TokenOptions = options => identityTokenSection.Bind(options); + identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); + identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); + identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options)); + }) + .UseDefaultAuthentication(); + + elsa.UseTenants(tenantsFeature => + { + tenantsFeature.TenantsOptions = options => + { + multiTenancySection.Bind(options); + options.TenantResolutionPipelineBuilder.Append(); + }; + tenantsFeature.UseConfigurationBasedTenantsProvider(); + }); + + elsa + .UseHttp() + .AddFastEndpointsAssembly() + .UseWorkflowsApi(); + + elsa.AddWorkflowsFrom(); +}); + +builder.Services.SwaggerDocument(options => +{ + options.DocumentSettings = documentSetting => + { + documentSetting.Title = "Elsa API"; + documentSetting.Version = "v1"; + }; +}); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +app.UseHttpsRedirection(); +app.UseAuthorization(); +app.MapControllers(); +app.UseWorkflows(); +app.UseWorkflowsApi(); + +if (!app.Environment.IsProduction()) +{ + EndpointSecurityOptions.SecurityIsEnabled = false; + + app.UseOpenApi(); + app.UseSwaggerUi(); + app.UseReDoc(); +} + +app.Run(); diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/Properties/launchSettings.json b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Properties/launchSettings.json new file mode 100644 index 0000000000..01ac0b6cb3 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Properties/launchSettings.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5284", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7285;http://localhost:5284", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/Workflows/HelloWorldHttpWorkflow.cs b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Workflows/HelloWorldHttpWorkflow.cs new file mode 100644 index 0000000000..4b736b64df --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/Workflows/HelloWorldHttpWorkflow.cs @@ -0,0 +1,28 @@ +using Elsa.Http; +using Elsa.Workflows; +using Elsa.Workflows.Activities; +using Elsa.Workflows.Contracts; + +namespace Elsa.Samples.AspNet.Tenants; + +public class HelloWorldHttpWorkflow : WorkflowBase +{ + protected override void Build(IWorkflowBuilder builder) + { + builder.Root = new Sequence + { + Activities = + { + new HttpEndpoint + { + Path = new("/hello-world"), + CanStartWorkflow = true + }, + new WriteHttpResponse + { + Content = new("Hello world of HTTP workflows!") + } + } + }; + } +} \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.Tenants/appsettings.json b/samples/aspnet/Elsa.Samples.AspNet.Tenants/appsettings.json new file mode 100644 index 0000000000..bf47eb0c34 --- /dev/null +++ b/samples/aspnet/Elsa.Samples.AspNet.Tenants/appsettings.json @@ -0,0 +1,67 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;" + }, + "Identity": { + "Tokens": { + "SigningKey": "secret-signing-key", + "AccessTokenLifetime": "1:00:00:00", + "RefreshTokenLifetime": "7:00:00:00" + }, + "Roles": [ + { + "Id": "admin", + "Name": "Administrator", + "Permissions": [ + "*" + ] + } + ], + "Users": [ + { + "Id": "a2323f46-42db-4e15-af8b-94238717d817", + "Name": "admin", + "TenantId": "19a5f2b0-75e4-45ad-b0ae-fe02d77867d0", + "HashedPassword": "TfKzh9RLix6FPcCNeHLkGrysFu3bYxqzGqduNdi8v1U=", + "HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=", + "Roles": [ + "admin" + ] + } + ] + }, + "Multitenancy": { + "Tenants": [ + { + "TenantId": "19a5f2b0-75e4-45ad-b0ae-fe02d77867d0", + "Name": "DefaultTenant" + }, + { + "TenantId": "a8ad404f-2ac1-439f-8856-f225c928d811", + "Name": "Tenant1" + } + ] + }, + "Applications": [ + { + "id": "d57030226341448daff5a2935aba2d3f", + "name": "Postman", + "roles": [ + "admin" + ], + "clientId": "HXr0Vzdm9KCZbwsJ", + "clientSecret": "a<~QGGHTEA%u4;CU&'Wga5ED:_&Gd1C)", + "hashedApiKey": "Z5ClHs3mbzx8Pnw3+PxbMq8A/Y+VKMCCDTGYtax8JFM=", + "hashedApiKeySalt": "kBisa1X8FwBfN2zmyGMFRgIVVBleghhQAJ4WGyTkaD0=", + "hashedClientSecret": "jEv58d0SVbGQ3nBZM0lkzHghG4Y+lMKW80wipz+9vHk=", + "hashedClientSecretSalt": "xRKy14Ok1/tU3kLf/8V1fcbLIegy9vcM90Peu2tzohU=" + } + ] +} \ No newline at end of file diff --git a/samples/aspnet/Elsa.Samples.AspNet.WorkflowContexts/Program.cs b/samples/aspnet/Elsa.Samples.AspNet.WorkflowContexts/Program.cs index 3958692647..435ac79617 100644 --- a/samples/aspnet/Elsa.Samples.AspNet.WorkflowContexts/Program.cs +++ b/samples/aspnet/Elsa.Samples.AspNet.WorkflowContexts/Program.cs @@ -23,7 +23,6 @@ .AddWorkflow() .UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/samples/console/Elsa.Samples.ConsoleApp.JsonWorkflows/Program.cs b/samples/console/Elsa.Samples.ConsoleApp.JsonWorkflows/Program.cs index 20b986bd3a..88f328d977 100644 --- a/samples/console/Elsa.Samples.ConsoleApp.JsonWorkflows/Program.cs +++ b/samples/console/Elsa.Samples.ConsoleApp.JsonWorkflows/Program.cs @@ -1,7 +1,7 @@ using Elsa.Extensions; using Elsa.Testing.Shared; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Microsoft.Extensions.DependencyInjection; // Setup service container. diff --git a/src/bundles/Elsa.Server.Web/Endpoints/DynamicWorkflows/Post/Endpoint.cs b/src/bundles/Elsa.Server.Web/Endpoints/DynamicWorkflows/Post/Endpoint.cs index 300f494340..73ca592316 100644 --- a/src/bundles/Elsa.Server.Web/Endpoints/DynamicWorkflows/Post/Endpoint.cs +++ b/src/bundles/Elsa.Server.Web/Endpoints/DynamicWorkflows/Post/Endpoint.cs @@ -4,7 +4,6 @@ using Elsa.Workflows.Options; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Contracts; -using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Parameters; namespace Elsa.Server.Web.Endpoints.DynamicWorkflows.Post; diff --git a/src/bundles/Elsa.Server.Web/Enums/PersistenceProvider.cs b/src/bundles/Elsa.Server.Web/Enums/PersistenceProvider.cs new file mode 100644 index 0000000000..31e3e33b8d --- /dev/null +++ b/src/bundles/Elsa.Server.Web/Enums/PersistenceProvider.cs @@ -0,0 +1,9 @@ +namespace Elsa.Server.Web; + +public enum PersistenceProvider +{ + Memory, + EntityFrameworkCore, + MongoDb, + Dapper +} \ No newline at end of file diff --git a/src/bundles/Elsa.Server.Web/Enums/SqlDatabaseProvider.cs b/src/bundles/Elsa.Server.Web/Enums/SqlDatabaseProvider.cs new file mode 100644 index 0000000000..cc29880428 --- /dev/null +++ b/src/bundles/Elsa.Server.Web/Enums/SqlDatabaseProvider.cs @@ -0,0 +1,10 @@ +namespace Elsa.Server.Web; + +public enum SqlDatabaseProvider +{ + SqlServer, + Sqlite, + MySql, + PostgreSql, + CockroachDb +} \ No newline at end of file diff --git a/src/bundles/Elsa.Server.Web/Program.cs b/src/bundles/Elsa.Server.Web/Program.cs index d90f910a56..67562657de 100644 --- a/src/bundles/Elsa.Server.Web/Program.cs +++ b/src/bundles/Elsa.Server.Web/Program.cs @@ -13,8 +13,10 @@ using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; using Elsa.Features.Services; +using Elsa.Http.MultiTenancy; using Elsa.Http.Options; using Elsa.MassTransit.Extensions; +using Elsa.Identity.MultiTenancy; using Elsa.MongoDb.Extensions; using Elsa.MongoDb.Modules.Alterations; using Elsa.MongoDb.Modules.Identity; @@ -22,6 +24,7 @@ using Elsa.MongoDb.Modules.Runtime; using Elsa.Server.Web; using Elsa.Workflows; +using Elsa.Tenants.Extensions; using Elsa.Workflows.Management.Compression; using Elsa.Workflows.Management.Stores; using Elsa.Workflows.Runtime.Distributed.Extensions; @@ -35,23 +38,21 @@ using Proto.Persistence.Sqlite; using Proto.Persistence.SqlServer; -const bool useMongoDb = false; -const bool useSqlServer = false; -const bool usePostgres = false; -const bool useCockroachDb = false; -const bool useDapper = false; +const PersistenceProvider persistenceProvider = PersistenceProvider.EntityFrameworkCore; +const SqlDatabaseProvider sqlDatabaseProvider = SqlDatabaseProvider.Sqlite; const bool useHangfire = false; const bool useQuartz = true; const bool useMassTransit = true; const bool useZipCompression = false; const bool runEFCoreMigrations = true; const bool useMemoryStores = false; -const bool useCaching = true; +const bool useCaching = false; const bool useAzureServiceBusModule = false; const bool useReadOnlyMode = false; const WorkflowRuntime workflowRuntime = WorkflowRuntime.ProtoActor; const DistributedCachingTransport distributedCachingTransport = DistributedCachingTransport.MassTransit; const MassTransitBroker massTransitBroker = MassTransitBroker.Memory; +const bool useMultitenancy = false; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; @@ -73,22 +74,22 @@ services .AddElsa(elsa => { - if (useMongoDb) + if (persistenceProvider == PersistenceProvider.MongoDb) elsa.UseMongoDb(mongoDbConnectionString); - if (useDapper) + if (persistenceProvider == PersistenceProvider.Dapper) elsa.UseDapper(dapper => { dapper.UseMigrations(feature => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) feature.UseSqlServer(); else feature.UseSqlite(); }); dapper.DbConnectionProvider = sp => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) return new SqlServerDbConnectionProvider(sqlServerConnectionString!); else return new SqliteDbConnectionProvider(sqliteConnectionString); @@ -105,26 +106,25 @@ .UseFileStorage() .UseIdentity(identity => { - if (useMongoDb) + if (persistenceProvider == PersistenceProvider.MongoDb) identity.UseMongoDb(); - else if (useDapper) + else if (persistenceProvider == PersistenceProvider.Dapper) identity.UseDapper(); else identity.UseEntityFrameworkCore(ef => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString!); - else if (usePostgres) + else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString!); - else if (useCockroachDb) + else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else ef.UseSqlite(sqliteConnectionString); ef.RunMigrations = runEFCoreMigrations; }); - - identity.IdentityOptions = options => identitySection.Bind(options); + identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); @@ -133,18 +133,18 @@ .UseDefaultAuthentication() .UseWorkflowManagement(management => { - if (useMongoDb) + if (persistenceProvider == PersistenceProvider.MongoDb) management.UseMongoDb(); - else if (useDapper) + else if (persistenceProvider == PersistenceProvider.Dapper) management.UseDapper(); else management.UseEntityFrameworkCore(ef => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString!); - else if (usePostgres) + else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString!); - else if (useCockroachDb) + else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else ef.UseSqlite(sqliteConnectionString); @@ -169,18 +169,18 @@ }) .UseWorkflowRuntime(runtime => { - if (useMongoDb) + if (persistenceProvider == PersistenceProvider.MongoDb) runtime.UseMongoDb(); - else if (useDapper) + else if (persistenceProvider == PersistenceProvider.Dapper) runtime.UseDapper(); else runtime.UseEntityFrameworkCore(ef => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString!); - else if (usePostgres) + else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString!); - else if (useCockroachDb) + else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else ef.UseSqlite(sqliteConnectionString); @@ -197,7 +197,7 @@ { runtime.UseProtoActor(proto => proto.PersistenceProvider = _ => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) return new SqlServerProvider(sqlServerConnectionString!, true, "", "proto_actor"); else return new SqliteProvider(new SqliteConnectionStringBuilder(sqliteConnectionString)); @@ -220,7 +220,7 @@ runtime.UseCache(); runtime.DistributedLockingOptions = options => configuration.GetSection("Runtime:DistributedLocking").Bind(options); - + runtime.DistributedLockProvider = _ => { switch (distributedLockProviderName) @@ -293,11 +293,11 @@ .UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options)) .UseAlterations(alterations => { - if (useMongoDb) + if (persistenceProvider == PersistenceProvider.MongoDb) { alterations.UseMongoDb(); } - else if (useDapper) + else if (persistenceProvider == PersistenceProvider.Dapper) { // TODO: alterations.UseDapper(); } @@ -305,11 +305,11 @@ { alterations.UseEntityFrameworkCore(ef => { - if (useSqlServer) + if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString); - else if (usePostgres) + else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString); - else if (useCockroachDb) + else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else ef.UseSqlite(sqliteConnectionString); @@ -378,6 +378,20 @@ }); } + if (useMultitenancy) + elsa.UseTenants(tenants => + { + tenants.TenantsOptions = options => + { + configuration.GetSection("Multitenancy").Bind(options); + options.TenantResolutionPipelineBuilder + .Append() + .Append() + .Append(); + }; + tenants.UseConfigurationBasedTenantsProvider(); + }); + elsa.InstallDropIns(options => options.DropInRootDirectory = Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "DropIns")); elsa.AddSwagger(); elsa.AddFastEndpointsAssembly(); @@ -393,11 +407,6 @@ // Build the web application. var app = builder.Build(); -// app.UseSimulatedLatency( -// TimeSpan.FromMilliseconds(1000), -// TimeSpan.FromMilliseconds(3000) -// ); - // Configure the pipeline. if (app.Environment.IsDevelopment()) app.UseDeveloperExceptionPage(); diff --git a/src/bundles/Elsa.Server.Web/appsettings.json b/src/bundles/Elsa.Server.Web/appsettings.json index f1ffa3c3d7..94d3973f7c 100644 --- a/src/bundles/Elsa.Server.Web/appsettings.json +++ b/src/bundles/Elsa.Server.Web/appsettings.json @@ -27,6 +27,27 @@ "RabbitMq": "amqp://guest:guest@localhost:5672", "Redis": "localhost:6379,abortConnect=false" }, + "Multitenancy": { + "Tenants": [ + { + "Id": "default", + "Name": "Default" + }, + { + "Id": "tenant-1", + "Name": "Tenant 1" + }, + { + "Id": "tenant-2", + "Name": "Tenant 2" + }, + { + "Id": "tenant-2a", + "TenantId": "tenant-2", + "Name": "Tenant 2a" + } + ] + }, "Smtp": { "Host": "localhost", "Port": 2525, @@ -55,7 +76,8 @@ "Name": "Administrator", "Permissions": [ "*" - ] + ], + "TenantId": "default" } ], "Users": [ @@ -66,22 +88,24 @@ "HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=", "Roles": [ "admin" - ] + ], + "TenantId": "default" } ], "Applications": [ { - "id": "d57030226341448daff5a2935aba2d3f", - "name": "Postman", - "roles": [ + "Id": "d57030226341448daff5a2935aba2d3f", + "Name": "Postman", + "Roles": [ "admin" ], - "clientId": "HXr0Vzdm9KCZbwsJ", - "clientSecret": "a<~QGGHTEA%u4;CU&'Wga5ED:_&Gd1C)", - "hashedApiKey": "Z5ClHs3mbzx8Pnw3+PxbMq8A/Y+VKMCCDTGYtax8JFM=", - "hashedApiKeySalt": "kBisa1X8FwBfN2zmyGMFRgIVVBleghhQAJ4WGyTkaD0=", - "hashedClientSecret": "jEv58d0SVbGQ3nBZM0lkzHghG4Y+lMKW80wipz+9vHk=", - "hashedClientSecretSalt": "xRKy14Ok1/tU3kLf/8V1fcbLIegy9vcM90Peu2tzohU=" + "ClientId": "HXr0Vzdm9KCZbwsJ", + "ClientSecret": "a<~QGGHTEA%u4;CU&'Wga5ED:_&Gd1C)", + "HashedApiKey": "Z5ClHs3mbzx8Pnw3+PxbMq8A/Y+VKMCCDTGYtax8JFM=", + "HashedApiKeySalt": "kBisa1X8FwBfN2zmyGMFRgIVVBleghhQAJ4WGyTkaD0=", + "HashedClientSecret": "jEv58d0SVbGQ3nBZM0lkzHghG4Y+lMKW80wipz+9vHk=", + "HashedClientSecretSalt": "xRKy14Ok1/tU3kLf/8V1fcbLIegy9vcM90Peu2tzohU=", + "TenantId": "default" } ] }, diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Program.cs b/src/bundles/Elsa.ServerAndStudio.Web/Program.cs index 608947b9a8..adf2b52ed2 100644 --- a/src/bundles/Elsa.ServerAndStudio.Web/Program.cs +++ b/src/bundles/Elsa.ServerAndStudio.Web/Program.cs @@ -42,7 +42,6 @@ .UseSasTokens() .UseIdentity(identity => { - identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); diff --git a/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs b/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs index 10d509f0cc..b467581f91 100644 --- a/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs +++ b/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs @@ -65,10 +65,14 @@ await foreach (var notification in output.Reader.ReadAllAsync(cancellationToken) { await notificationSender.SendAsync(notification, NotificationStrategy.Sequential, cancellationToken); } + catch (OperationCanceledException e) + { + _logger.LogDebug(e, "An operation was cancelled while processing the queue"); + } catch (Exception e) { _logger.LogError(e, "An unhandled exception occured while processing the queue"); } } } -} +} \ No newline at end of file diff --git a/src/common/Elsa.Mediator/Middleware/Notification/Components/NotificationHandlerInvokerMiddleware.cs b/src/common/Elsa.Mediator/Middleware/Notification/Components/NotificationHandlerInvokerMiddleware.cs index 95e3d54ae6..c555a7f5f1 100644 --- a/src/common/Elsa.Mediator/Middleware/Notification/Components/NotificationHandlerInvokerMiddleware.cs +++ b/src/common/Elsa.Mediator/Middleware/Notification/Components/NotificationHandlerInvokerMiddleware.cs @@ -43,4 +43,4 @@ public async ValueTask InvokeAsync(NotificationContext context) // Invoke next middleware. await _next(context); } -} \ No newline at end of file +} diff --git a/src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj b/src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj index 2a79c24468..1989e696e9 100644 --- a/src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj +++ b/src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj @@ -20,12 +20,9 @@ + - - - - diff --git a/src/common/Elsa.Testing.Shared.Component/Services/TestTenantResolutionStrategy.cs b/src/common/Elsa.Testing.Shared.Component/Services/TestTenantResolutionStrategy.cs new file mode 100644 index 0000000000..5f9a88c897 --- /dev/null +++ b/src/common/Elsa.Testing.Shared.Component/Services/TestTenantResolutionStrategy.cs @@ -0,0 +1,13 @@ +using Elsa.Common.Abstractions; +using Elsa.Common.Contexts; +using Elsa.Common.Results; + +namespace Elsa.Workflows.ComponentTests.Helpers.Services; + +public class TestTenantResolutionStrategy : TenantResolutionStrategyBase +{ + protected override TenantResolutionResult Resolve(TenantResolutionContext context) + { + return AutoResolve("Tenant1"); + } +} \ No newline at end of file diff --git a/src/common/Elsa.Testing.Shared.Component/Services/TestTenantsProvider.cs b/src/common/Elsa.Testing.Shared.Component/Services/TestTenantsProvider.cs new file mode 100644 index 0000000000..64b3c256cd --- /dev/null +++ b/src/common/Elsa.Testing.Shared.Component/Services/TestTenantsProvider.cs @@ -0,0 +1,20 @@ +using Elsa.Common.Entities; +using Elsa.Tenants; +using Elsa.Tenants.Models; + +namespace Elsa.Testing.Shared.Services; + +public class TestTenantsProvider(params string[] tenantIds) : ITenantsProvider +{ + public ValueTask> ListAsync(CancellationToken cancellationToken = default) + { + var tenants = tenantIds.Select(id => new Tenant {Id = id, Name = id}); + return new(tenants); + } + + public async ValueTask FindAsync(TenantFilter filter, CancellationToken cancellationToken = default) + { + var query = (await ListAsync(cancellationToken)).AsQueryable(); + return filter.Apply(query).FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/common/Elsa.Testing.Shared.Integration/ServiceProviderExtensions.cs b/src/common/Elsa.Testing.Shared.Integration/ServiceProviderExtensions.cs index 33ad3a32ed..9b596906e3 100644 --- a/src/common/Elsa.Testing.Shared.Integration/ServiceProviderExtensions.cs +++ b/src/common/Elsa.Testing.Shared.Integration/ServiceProviderExtensions.cs @@ -1,7 +1,7 @@ using Elsa.Common.Models; using Elsa.Workflows; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Models; @@ -94,7 +94,7 @@ public static async Task ImportWorkflowDefinitionAsync(this { var runRequest = new RunWorkflowInstanceRequest { - BookmarkId = bookmark.BookmarkId + BookmarkId = bookmark.Id }; response = await workflowClient.RunInstanceAsync(runRequest); } diff --git a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs index 1c3c3245a2..96bbc9c85b 100644 --- a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs +++ b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs @@ -1,7 +1,7 @@ using Elsa.Alterations.Core.Contracts; using Elsa.Alterations.Core.Models; using Elsa.Workflows; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Contracts; diff --git a/src/modules/Elsa.Alterations/AlterationHandlers/MigrateHandler.cs b/src/modules/Elsa.Alterations/AlterationHandlers/MigrateHandler.cs index f5a9a0c158..25418edeee 100644 --- a/src/modules/Elsa.Alterations/AlterationHandlers/MigrateHandler.cs +++ b/src/modules/Elsa.Alterations/AlterationHandlers/MigrateHandler.cs @@ -2,7 +2,7 @@ using Elsa.Alterations.Core.Abstractions; using Elsa.Alterations.Core.Contexts; using Elsa.Common.Models; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.Alterations/Endpoints/Workflows/Retry/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Workflows/Retry/Endpoint.cs index 7d81f6084e..c690f65ab2 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Workflows/Retry/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Workflows/Retry/Endpoint.cs @@ -2,7 +2,7 @@ using Elsa.Alterations.AlterationTypes; using Elsa.Alterations.Core.Contracts; using Elsa.Alterations.Core.Results; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Runtime; diff --git a/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs b/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs index bd36698556..db753bdea7 100644 --- a/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs +++ b/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs @@ -4,7 +4,7 @@ using Elsa.Common.Contracts; using Elsa.Common.Models; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Requests; diff --git a/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs b/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs index d9f5105b05..cc52c3404b 100644 --- a/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs +++ b/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs @@ -5,7 +5,7 @@ using Elsa.Common.Contracts; using Elsa.Workflows; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Pipelines.WorkflowExecution; using Elsa.Workflows.Runtime; using Microsoft.Extensions.Logging; diff --git a/src/modules/Elsa.AzureServiceBus/Features/AzureServiceBusFeature.cs b/src/modules/Elsa.AzureServiceBus/Features/AzureServiceBusFeature.cs index 03c1ec0bba..ed4dbf8be6 100644 --- a/src/modules/Elsa.AzureServiceBus/Features/AzureServiceBusFeature.cs +++ b/src/modules/Elsa.AzureServiceBus/Features/AzureServiceBusFeature.cs @@ -26,7 +26,7 @@ public AzureServiceBusFeature(IModule module) : base(module) } /// - /// A value controlling whether or not queues, topics and subscriptions should be created automatically. + /// A value controlling whether queues, topics and subscriptions should be created automatically. /// public bool CreateQueuesTopicsAndSubscriptions { get; set; } = true; diff --git a/src/modules/Elsa.Common/Abstractions/TenantResolutionStrategyBase.cs b/src/modules/Elsa.Common/Abstractions/TenantResolutionStrategyBase.cs new file mode 100644 index 0000000000..4648789a9f --- /dev/null +++ b/src/modules/Elsa.Common/Abstractions/TenantResolutionStrategyBase.cs @@ -0,0 +1,48 @@ +using Elsa.Common.Contexts; +using Elsa.Common.Contracts; +using Elsa.Common.Results; + +namespace Elsa.Common.Abstractions; + +/// +/// Base class for implementing a tenant resolution strategy. +/// +public abstract class TenantResolutionStrategyBase : ITenantResolutionStrategy +{ + ValueTask ITenantResolutionStrategy.ResolveAsync(TenantResolutionContext context) + { + return ResolveAsync(context); + } + + /// + /// Implement this method to resolve the tenant. + /// + protected virtual ValueTask ResolveAsync(TenantResolutionContext context) + { + return new(Resolve(context)); + } + + /// + /// Implement this method to resolve the tenant. + /// + /// + protected virtual TenantResolutionResult Resolve(TenantResolutionContext context) + { + return Unresolved(); + } + + /// + /// Creates a new instance of representing a resolved tenant. + /// + protected TenantResolutionResult Resolved(string tenantId) => new(tenantId); + + /// + /// Creates a new instance of representing an unresolved tenant. + /// + protected TenantResolutionResult Unresolved() => new(null); + + /// + /// Automatically resolves the tenant if the tenant ID is not null. + /// + protected TenantResolutionResult AutoResolve(string? tenantId) => tenantId == null ? Unresolved() : Resolved(tenantId); +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Contexts/TenantResolutionContext.cs b/src/modules/Elsa.Common/Contexts/TenantResolutionContext.cs new file mode 100644 index 0000000000..8dc9ec2c34 --- /dev/null +++ b/src/modules/Elsa.Common/Contexts/TenantResolutionContext.cs @@ -0,0 +1,49 @@ +using Elsa.Common.Entities; + +namespace Elsa.Common.Contexts; + +/// +/// Represents the context for resolving a tenant in a tenant resolution strategy pipeline. +/// +/// +/// This class provides the necessary information for resolving a tenant, including a cancellation token +/// to allow for cancelling the resolution process. +/// +public class TenantResolutionContext +{ + private readonly IDictionary _tenantsDictionary; + + /// + /// Initializes a new instance of the class. + /// + public TenantResolutionContext(IDictionary tenants, CancellationToken cancellationToken) + { + CancellationToken = cancellationToken; + _tenantsDictionary = tenants; + } + + /// + /// Gets the cancellation token. + /// + public CancellationToken CancellationToken { get; } = default; + + /// + /// Finds a tenant based on the provided tenant ID. + /// + /// The tenant ID. + /// The found tenant or null if no tenant with the provided ID exists. + public Tenant? FindTenant(string tenantId) + { + return _tenantsDictionary.TryGetValue(tenantId, out var tenant) ? tenant : null; + } + + /// + /// Finds a tenant based on the provided predicate. + /// + /// The predicate used to filter the tenants. + /// The found tenant or null if no tenant satisfies the predicate. + public Tenant? FindTenant(Func predicate) + { + return _tenantsDictionary.Values.FirstOrDefault(predicate); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Contracts/ITenantResolutionStrategy.cs b/src/modules/Elsa.Common/Contracts/ITenantResolutionStrategy.cs new file mode 100644 index 0000000000..7ba3bb5c82 --- /dev/null +++ b/src/modules/Elsa.Common/Contracts/ITenantResolutionStrategy.cs @@ -0,0 +1,15 @@ +using Elsa.Common.Contexts; +using Elsa.Common.Results; + +namespace Elsa.Common.Contracts; + +/// +/// A tenant resolver strategy in a pipeline of tenant resolvers. +/// +public interface ITenantResolutionStrategy +{ + /// + /// Resolves the tenant. + /// + ValueTask ResolveAsync(TenantResolutionContext context); +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Contracts/ITenantResolver.cs b/src/modules/Elsa.Common/Contracts/ITenantResolver.cs new file mode 100644 index 0000000000..fe7da6f58e --- /dev/null +++ b/src/modules/Elsa.Common/Contracts/ITenantResolver.cs @@ -0,0 +1,15 @@ +using Elsa.Common.Entities; + +namespace Elsa.Common.Contracts; + +/// +/// Provides access to the current tenant ID. +/// +public interface ITenantResolver +{ + /// + /// Get the current . + /// + /// Current tenant or null. + Task GetTenantAsync(CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Entities/Entity.cs b/src/modules/Elsa.Common/Entities/Entity.cs index 550be9d65f..2a3d2cd6e9 100644 --- a/src/modules/Elsa.Common/Entities/Entity.cs +++ b/src/modules/Elsa.Common/Entities/Entity.cs @@ -9,4 +9,9 @@ public abstract class Entity /// Gets or sets the ID of this entity. /// public string Id { get; set; } = default!; + + /// + /// Gets or sets the ID of the tenant that own this entity. + /// + public string? TenantId { get; set; } } \ No newline at end of file diff --git a/src/modules/Elsa.Common/Entities/Tenant.cs b/src/modules/Elsa.Common/Entities/Tenant.cs new file mode 100644 index 0000000000..315b14282a --- /dev/null +++ b/src/modules/Elsa.Common/Entities/Tenant.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; + +namespace Elsa.Common.Entities; + +/// +/// Represents a tenant. +/// +[UsedImplicitly] +public class Tenant : Entity +{ + /// + /// Gets or sets the name. + /// + public string Name { get; set; } = default!; +} diff --git a/src/modules/Elsa.Common/Features/SystemClockFeature.cs b/src/modules/Elsa.Common/Features/SystemClockFeature.cs index 027319e11a..76ebc55f3f 100644 --- a/src/modules/Elsa.Common/Features/SystemClockFeature.cs +++ b/src/modules/Elsa.Common/Features/SystemClockFeature.cs @@ -19,6 +19,6 @@ public SystemClockFeature(IModule module) : base(module) /// public override void Apply() { - Services.AddScoped(); + Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/modules/Elsa.Common/Features/TenantResolverFeature.cs b/src/modules/Elsa.Common/Features/TenantResolverFeature.cs new file mode 100644 index 0000000000..cb5e869931 --- /dev/null +++ b/src/modules/Elsa.Common/Features/TenantResolverFeature.cs @@ -0,0 +1,18 @@ +using Elsa.Common.Contracts; +using Elsa.Common.Services; +using Elsa.Features.Abstractions; +using Elsa.Features.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Common.Features; + +public class TenantResolverFeature(IModule module) : FeatureBase(module) +{ + public Func TenantResolver { get; set; } = sp => sp.GetRequiredService(); + + public override void Apply() + { + Services.AddTransient(); + Services.AddScoped(TenantResolver); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Results/TenantResolutionResult.cs b/src/modules/Elsa.Common/Results/TenantResolutionResult.cs new file mode 100644 index 0000000000..68bfa7188d --- /dev/null +++ b/src/modules/Elsa.Common/Results/TenantResolutionResult.cs @@ -0,0 +1,26 @@ +namespace Elsa.Common.Results; + +/// +/// Represents the result of a tenant resolution. +/// +/// The resolved tenant. +public record TenantResolutionResult(string? TenantId) +{ + /// + /// Creates a new instance of representing a resolved tenant. + /// + /// The resolved tenant. + /// A new instance of representing a resolved tenant. + public static TenantResolutionResult Resolved(string tenantId) => new(tenantId); + + /// + /// Creates a new instance of representing an unresolved tenant. + /// + /// A new instance of representing an unresolved tenant. + public static TenantResolutionResult Unresolved() => new(default(string?)); + + /// + /// Gets a value indicating whether the tenant has been resolved. + /// + public bool IsResolved => TenantId != null; +} \ No newline at end of file diff --git a/src/modules/Elsa.Common/Services/DefaultTenantResolver.cs b/src/modules/Elsa.Common/Services/DefaultTenantResolver.cs new file mode 100644 index 0000000000..eb99456cc5 --- /dev/null +++ b/src/modules/Elsa.Common/Services/DefaultTenantResolver.cs @@ -0,0 +1,21 @@ +using Elsa.Common.Contracts; +using Elsa.Common.Entities; + +namespace Elsa.Common.Services; + +/// +/// An implementation of that always returns the default tenant. +/// +public class DefaultTenantResolver : ITenantResolver +{ + private readonly Tenant _defaultTenant = new() + { + Id = null!, + Name = "Default" + }; + + public Task GetTenantAsync(CancellationToken cancellationToken = default) + { + return Task.FromResult(_defaultTenant); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Identity/Initial.cs b/src/modules/Elsa.Dapper.Migrations/Identity/Initial.cs index a01fd1cc49..aea88eae57 100644 --- a/src/modules/Elsa.Dapper.Migrations/Identity/Initial.cs +++ b/src/modules/Elsa.Dapper.Migrations/Identity/Initial.cs @@ -5,7 +5,7 @@ namespace Elsa.Dapper.Migrations.Identity; /// -[Migration(30001, "Elsa:Identity:Initial")] +[Migration(30001, "Elsa:Identity:V3.0")] [PublicAPI] public class Initial : Migration { diff --git a/src/modules/Elsa.Dapper.Migrations/Identity/V3_1.cs b/src/modules/Elsa.Dapper.Migrations/Identity/V3_1.cs new file mode 100644 index 0000000000..75d8ab191f --- /dev/null +++ b/src/modules/Elsa.Dapper.Migrations/Identity/V3_1.cs @@ -0,0 +1,24 @@ +using System.Diagnostics.CodeAnalysis; +using FluentMigrator; +using JetBrains.Annotations; + +namespace Elsa.Dapper.Migrations.Identity; + +/// +[Migration(30002, "Elsa:Identity:V3.1")] +[PublicAPI] +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class V3_1 : Migration +{ + /// + public override void Up() + { + // No changes + } + + /// + public override void Down() + { + // No changes + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Identity/V3_2.cs b/src/modules/Elsa.Dapper.Migrations/Identity/V3_2.cs new file mode 100644 index 0000000000..45488fd581 --- /dev/null +++ b/src/modules/Elsa.Dapper.Migrations/Identity/V3_2.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using FluentMigrator; +using JetBrains.Annotations; + +namespace Elsa.Dapper.Migrations.Identity; + +/// +[Migration(30003, "Elsa:Identity:V3.2")] +[PublicAPI] +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class V3_2 : Migration +{ + /// + public override void Up() + { + Alter.Table("Users").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("Roles").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("Applications").AddColumn("TenantId").AsString().Nullable(); + } + + /// + public override void Down() + { + Delete.Column("TenantId").FromTable("Users"); + Delete.Column("TenantId").FromTable("Roles"); + Delete.Column("TenantId").FromTable("Applications"); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Management/Initial.cs b/src/modules/Elsa.Dapper.Migrations/Management/Initial.cs index b7aa69db99..4fbad50447 100644 --- a/src/modules/Elsa.Dapper.Migrations/Management/Initial.cs +++ b/src/modules/Elsa.Dapper.Migrations/Management/Initial.cs @@ -5,7 +5,7 @@ namespace Elsa.Dapper.Migrations.Management; /// -[Migration(10001, "Elsa:Management:Initial")] +[Migration(10001, "Elsa:Management:V3.0")] [PublicAPI] public class Initial : Migration { diff --git a/src/modules/Elsa.Dapper.Migrations/Management/V3_1.cs b/src/modules/Elsa.Dapper.Migrations/Management/V3_1.cs index 3c54331d1d..bac4582666 100644 --- a/src/modules/Elsa.Dapper.Migrations/Management/V3_1.cs +++ b/src/modules/Elsa.Dapper.Migrations/Management/V3_1.cs @@ -5,7 +5,7 @@ namespace Elsa.Dapper.Migrations.Management; /// -[Migration(10002, "Elsa:Runtime:V3.1")] +[Migration(10002, "Elsa:Management:V3.1")] [PublicAPI] [SuppressMessage("ReSharper", "InconsistentNaming")] public class V3_1 : Migration @@ -25,7 +25,7 @@ public override void Up() /// public override void Down() { - Delete.Column("IsSystem").FromTable("WorkflowDefinitions"); Delete.Column("IsSystem").FromTable("WorkflowInstances"); + Delete.Column("IsSystem").FromTable("WorkflowDefinitions"); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Management/V3_2.cs b/src/modules/Elsa.Dapper.Migrations/Management/V3_2.cs new file mode 100644 index 0000000000..248e5c5cb9 --- /dev/null +++ b/src/modules/Elsa.Dapper.Migrations/Management/V3_2.cs @@ -0,0 +1,26 @@ +using System.Diagnostics.CodeAnalysis; +using FluentMigrator; +using JetBrains.Annotations; + +namespace Elsa.Dapper.Migrations.Management; + +/// +[Migration(10003, "Elsa:Management:V3.2")] +[PublicAPI] +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class V3_2 : Migration +{ + /// + public override void Up() + { + Alter.Table("WorkflowDefinitions").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("WorkflowInstances").AddColumn("TenantId").AsString().Nullable(); + } + + /// + public override void Down() + { + Delete.Column("TenantId").FromTable("WorkflowDefinitions"); + Delete.Column("TenantId").FromTable("WorkflowInstances"); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Runtime/Initial.cs b/src/modules/Elsa.Dapper.Migrations/Runtime/Initial.cs index 221838fbd6..866b4f6d79 100644 --- a/src/modules/Elsa.Dapper.Migrations/Runtime/Initial.cs +++ b/src/modules/Elsa.Dapper.Migrations/Runtime/Initial.cs @@ -5,7 +5,7 @@ namespace Elsa.Dapper.Migrations.Runtime; /// -[Migration(20001, "Elsa:Runtime:Initial")] +[Migration(20001, "Elsa:Runtime:V3.0")] [PublicAPI] public class Initial : Migration { diff --git a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_1.cs b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_1.cs index c438cca442..ff74e9fb24 100644 --- a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_1.cs +++ b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_1.cs @@ -16,7 +16,8 @@ public override void Up() { Create .Table("KeyValuePairs") - .WithColumn("Key").AsString().PrimaryKey() + .WithColumn("Id").AsString().PrimaryKey() + .WithColumn("Key").AsString().Indexed() .WithColumn("Value").AsString(MaxValue).NotNullable(); } diff --git a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_2.cs b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_2.cs index 02a6cdfe80..c4299bfd4b 100644 --- a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_2.cs +++ b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_2.cs @@ -6,7 +6,7 @@ namespace Elsa.Dapper.Migrations.Runtime; /// -[Migration(20002, "Elsa:Runtime:V3.2")] +[Migration(20003, "Elsa:Runtime:V3.2")] [PublicAPI] [SuppressMessage("ReSharper", "InconsistentNaming")] public class V3_2 : Migration @@ -15,11 +15,22 @@ public class V3_2 : Migration public override void Up() { Delete.Table("WorkflowInboxMessages"); + Alter.Table("Triggers").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("Bookmarks").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("WorkflowExecutionLogRecords").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("ActivityExecutionRecords").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("KeyValuePairs").AddColumn("TenantId").AsString().Nullable(); } /// public override void Down() { + Delete.Column("TenantId").FromTable("Triggers"); + Delete.Column("TenantId").FromTable("Bookmarks"); + Delete.Column("TenantId").FromTable("WorkflowExecutionLogRecords"); + Delete.Column("TenantId").FromTable("ActivityExecutionRecords"); + Delete.Column("TenantId").FromTable("KeyValuePairs"); + IfDatabase("SqlServer", "Oracle", "MySql", "Postgres") .Create .Table("WorkflowInboxMessages") diff --git a/src/modules/Elsa.Dapper/Elsa.Dapper.csproj b/src/modules/Elsa.Dapper/Elsa.Dapper.csproj index 5015d637d2..e28b191cd9 100644 --- a/src/modules/Elsa.Dapper/Elsa.Dapper.csproj +++ b/src/modules/Elsa.Dapper/Elsa.Dapper.csproj @@ -10,6 +10,7 @@ + diff --git a/src/modules/Elsa.Dapper/Extensions/ParameterizedQueryBuilderExtensions.cs b/src/modules/Elsa.Dapper/Extensions/ParameterizedQueryBuilderExtensions.cs index b0195cf556..a6502e45c2 100644 --- a/src/modules/Elsa.Dapper/Extensions/ParameterizedQueryBuilderExtensions.cs +++ b/src/modules/Elsa.Dapper/Extensions/ParameterizedQueryBuilderExtensions.cs @@ -119,6 +119,7 @@ public static ParameterizedQuery Count(this ParameterizedQuery query, string exp public static ParameterizedQuery Is(this ParameterizedQuery query, string field, object? value) { if (value == null) return query; + if (value is DBNull) return IsNull(query, field); query.Sql.AppendLine(query.Dialect.And(field)); query.Parameters.Add($"@{field}", value); @@ -134,6 +135,8 @@ public static ParameterizedQuery Is(this ParameterizedQuery query, string field, public static ParameterizedQuery IsNot(this ParameterizedQuery query, string field, object? value) { if (value == null) return query; + if (value is DBNull) return IsNotNull(query, field); + query.Sql.AppendLine(query.Dialect.AndNot(field)); query.Parameters.Add($"@{field}", value); diff --git a/src/modules/Elsa.Dapper/Extensions/ServiceCollectionExtensions.cs b/src/modules/Elsa.Dapper/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000000..42c11854e3 --- /dev/null +++ b/src/modules/Elsa.Dapper/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,22 @@ +using Elsa.Common.Entities; +using Elsa.Dapper.Records; +using Elsa.Dapper.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Dapper.Extensions; + +/// +/// Extension methods for to register Dapper stores. +/// +public static class ServiceCollectionExtensions +{ + /// + /// Registers a Dapper store. + /// + public static IServiceCollection AddDapperStore(this IServiceCollection services, string tableName, string primaryKey = nameof(Entity.Id)) where TStore : class where TRecord : Record + { + services.AddScoped(); + services.AddScoped(sp => ActivatorUtilities.CreateInstance>(sp, tableName, primaryKey)); + return services; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Features/Feature.cs b/src/modules/Elsa.Dapper/Modules/Identity/Features/Feature.cs index 76264fcc7a..6e6d628748 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Features/Feature.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Features/Feature.cs @@ -1,4 +1,6 @@ +using Elsa.Dapper.Extensions; using Elsa.Dapper.Features; +using Elsa.Dapper.Modules.Identity.Records; using Elsa.Dapper.Modules.Identity.Stores; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -38,8 +40,8 @@ public override void Apply() { base.Apply(); - Services.AddScoped(); - Services.AddScoped(); - Services.AddScoped(); + Services.AddDapperStore("Users"); + Services.AddDapperStore("Applications"); + Services.AddDapperStore("Roles"); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Records/ApplicationRecord.cs b/src/modules/Elsa.Dapper/Modules/Identity/Records/ApplicationRecord.cs index 3c83131a4b..2a60ce2dc3 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Records/ApplicationRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Records/ApplicationRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Identity.Records; -internal class ApplicationRecord +internal class ApplicationRecord : Record { - public string Id { get; set; } = default!; public string ClientId { get; set; } = default!; public string HashedClientSecret { get; set; } = default!; public string HashedClientSecretSalt { get; set; } = default!; diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Records/RoleRecord.cs b/src/modules/Elsa.Dapper/Modules/Identity/Records/RoleRecord.cs index 7686271f06..a1f912258c 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Records/RoleRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Records/RoleRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Identity.Records; -internal class RoleRecord +internal class RoleRecord : Record { - public string Id { get; set; } = default!; public string Name { get; set; } = default!; public string Permissions { get; set; } = default!; } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Records/UserRecord.cs b/src/modules/Elsa.Dapper/Modules/Identity/Records/UserRecord.cs index 381f537226..4438bcfc98 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Records/UserRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Records/UserRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Identity.Records; -internal class UserRecord +internal class UserRecord : Record { - public string Id { get; set; } = default!; public string Name { get; set; } = default!; public string HashedPassword { get; set; } = default!; public string HashedPasswordSalt { get; set; } = default!; diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Stores/ApplicationStore.cs b/src/modules/Elsa.Dapper/Modules/Identity/Stores/ApplicationStore.cs index 88871d2574..f63d4db009 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Stores/ApplicationStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Stores/ApplicationStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Identity.Records; @@ -12,36 +11,25 @@ namespace Elsa.Dapper.Modules.Identity.Stores; /// /// A Dapper implementation of . /// -public class DapperApplicationStore : IApplicationStore +internal class DapperApplicationStore(Store store) : IApplicationStore { - private const string TableName = "Applications"; - private readonly Store _store; - - /// - /// Initializes a new instance of . - /// - public DapperApplicationStore(IDbConnectionProvider dbConnectionProvider) - { - _store = new Store(dbConnectionProvider, TableName); - } - /// public async Task SaveAsync(Application application, CancellationToken cancellationToken = default) { var record = Map(application); - await _store.SaveAsync(record, cancellationToken); + await store.SaveAsync(record, cancellationToken); } /// public async Task DeleteAsync(ApplicationFilter filter, CancellationToken cancellationToken = default) { - await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task FindAsync(ApplicationFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(query => ApplyFilter(query, filter), cancellationToken); + var record = await store.FindAsync(query => ApplyFilter(query, filter), cancellationToken); return record == null ? null : Map(record); } @@ -54,33 +42,35 @@ private void ApplyFilter(ParameterizedQuery query, ApplicationFilter filter) ; } - private ApplicationRecord Map(Application application) + private ApplicationRecord Map(Application source) { return new() { - Id = application.Id, - ClientId = application.ClientId, - HashedClientSecret = application.HashedClientSecret, - HashedClientSecretSalt = application.HashedClientSecretSalt, - Name = application.Name, - HashedApiKey = application.HashedApiKey, - HashedApiKeySalt = application.HashedApiKeySalt, - Roles = string.Join(',', application.Roles) + Id = source.Id, + ClientId = source.ClientId, + HashedClientSecret = source.HashedClientSecret, + HashedClientSecretSalt = source.HashedClientSecretSalt, + Name = source.Name, + HashedApiKey = source.HashedApiKey, + HashedApiKeySalt = source.HashedApiKeySalt, + Roles = string.Join(',', source.Roles), + TenantId = source.TenantId }; } - private Application Map(ApplicationRecord record) + private Application Map(ApplicationRecord source) { return new() { - Id = record.Id, - ClientId = record.ClientId, - HashedClientSecret = record.HashedClientSecret, - HashedClientSecretSalt = record.HashedClientSecretSalt, - Name = record.Name, - HashedApiKey = record.HashedApiKey, - HashedApiKeySalt = record.HashedApiKeySalt, - Roles = record.Roles.Split(',', StringSplitOptions.RemoveEmptyEntries) + Id = source.Id, + ClientId = source.ClientId, + HashedClientSecret = source.HashedClientSecret, + HashedClientSecretSalt = source.HashedClientSecretSalt, + Name = source.Name, + HashedApiKey = source.HashedApiKey, + HashedApiKeySalt = source.HashedApiKeySalt, + Roles = source.Roles.Split(',', StringSplitOptions.RemoveEmptyEntries), + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Stores/RoleStore.cs b/src/modules/Elsa.Dapper/Modules/Identity/Stores/RoleStore.cs index 50cd5bbc52..4787bd4dac 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Stores/RoleStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Stores/RoleStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Identity.Records; @@ -13,50 +12,39 @@ namespace Elsa.Dapper.Modules.Identity.Stores; /// /// A Dapper implementation of . /// -public class DapperRoleStore : IRoleStore +internal class DapperRoleStore(Store store) : IRoleStore { - private const string TableName = "Roles"; - private readonly Store _store; - - /// - /// Initializes a new instance of . - /// - public DapperRoleStore(IDbConnectionProvider dbConnectionProvider) - { - _store = new Store(dbConnectionProvider, TableName); - } - /// public async Task SaveAsync(Role application, CancellationToken cancellationToken = default) { var record = Map(application); - await _store.SaveAsync(record, cancellationToken); + await store.SaveAsync(record, cancellationToken); } /// public async Task AddAsync(Role role, CancellationToken cancellationToken = default) { var record = Map(role); - await _store.AddAsync(record, cancellationToken); + await store.AddAsync(record, cancellationToken); } /// public async Task DeleteAsync(RoleFilter filter, CancellationToken cancellationToken = default) { - await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task FindAsync(RoleFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : Map(record); } /// public async Task> FindManyAsync(RoleFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(queryable => ApplyFilter(queryable, filter), cancellationToken).ToList(); + var records = await store.FindManyAsync(queryable => ApplyFilter(queryable, filter), cancellationToken).ToList(); return records.Select(Map); } @@ -74,7 +62,8 @@ private RoleRecord Map(Role source) { Id = source.Id, Name = source.Name, - Permissions = string.Join(',', source.Permissions) + Permissions = string.Join(',', source.Permissions), + TenantId = source.TenantId }; } @@ -84,7 +73,8 @@ private Role Map(RoleRecord source) { Id = source.Id, Name = source.Name, - Permissions = source.Permissions.Split(',', StringSplitOptions.RemoveEmptyEntries) + Permissions = source.Permissions.Split(',', StringSplitOptions.RemoveEmptyEntries), + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Identity/Stores/UserStore.cs b/src/modules/Elsa.Dapper/Modules/Identity/Stores/UserStore.cs index 16faa0f501..23a13c47e6 100644 --- a/src/modules/Elsa.Dapper/Modules/Identity/Stores/UserStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Identity/Stores/UserStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Identity.Records; @@ -12,36 +11,25 @@ namespace Elsa.Dapper.Modules.Identity.Stores; /// /// A Dapper implementation of . /// -public class DapperUserStore : IUserStore +internal class DapperUserStore(Store store) : IUserStore { - private const string TableName = "Users"; - private readonly Store _store; - - /// - /// Initializes a new instance of . - /// - public DapperUserStore(IDbConnectionProvider dbConnectionProvider) - { - _store = new Store(dbConnectionProvider, TableName); - } - /// public async Task SaveAsync(User user, CancellationToken cancellationToken = default) { var record = Map(user); - await _store.SaveAsync(record, cancellationToken); + await store.SaveAsync(record, cancellationToken); } /// public async Task DeleteAsync(UserFilter filter, CancellationToken cancellationToken = default) { - await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task FindAsync(UserFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : Map(record); } @@ -53,27 +41,29 @@ private static void ApplyFilter(ParameterizedQuery query, UserFilter filter) ; } - private UserRecord Map(User user) + private UserRecord Map(User source) { return new() { - Id = user.Id, - Name = user.Name, - HashedPassword = user.HashedPassword, - HashedPasswordSalt = user.HashedPasswordSalt, - Roles = string.Join(',', user.Roles) + Id = source.Id, + Name = source.Name, + HashedPassword = source.HashedPassword, + HashedPasswordSalt = source.HashedPasswordSalt, + Roles = string.Join(',', source.Roles), + TenantId = source.TenantId }; } - private User Map(UserRecord user) + private User Map(UserRecord source) { return new() { - Id = user.Id, - Name = user.Name, - HashedPassword = user.HashedPassword, - HashedPasswordSalt = user.HashedPasswordSalt, - Roles = user.Roles.Split(',', StringSplitOptions.RemoveEmptyEntries) + Id = source.Id, + Name = source.Name, + HashedPassword = source.HashedPassword, + HashedPasswordSalt = source.HashedPasswordSalt, + Roles = source.Roles.Split(',', StringSplitOptions.RemoveEmptyEntries), + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowDefinitionPersistenceFeature.cs b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowDefinitionPersistenceFeature.cs index d73d0388f3..aed0b03e4e 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowDefinitionPersistenceFeature.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowDefinitionPersistenceFeature.cs @@ -1,4 +1,6 @@ +using Elsa.Dapper.Extensions; using Elsa.Dapper.Features; +using Elsa.Dapper.Modules.Management.Records; using Elsa.Dapper.Modules.Management.Stores; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -34,6 +36,6 @@ public override void Apply() { base.Apply(); - Services.AddScoped(); + Services.AddDapperStore("WorkflowDefinitions"); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowInstancePersistenceFeature.cs b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowInstancePersistenceFeature.cs index 4a65f875d6..83ba9c740c 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowInstancePersistenceFeature.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowInstancePersistenceFeature.cs @@ -25,12 +25,4 @@ public override void Configure() { Module.Configure(feature => { feature.WorkflowInstanceStore = sp => sp.GetRequiredService(); }); } - - /// - public override void Apply() - { - base.Apply(); - - Services.AddScoped(); - } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowManagementPersistenceFeature.cs b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowManagementPersistenceFeature.cs index 0e6aa3acef..fa4d4f03e5 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowManagementPersistenceFeature.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Features/DapperWorkflowManagementPersistenceFeature.cs @@ -1,4 +1,6 @@ +using Elsa.Dapper.Extensions; using Elsa.Dapper.Features; +using Elsa.Dapper.Modules.Management.Records; using Elsa.Dapper.Modules.Management.Stores; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -36,7 +38,7 @@ public override void Apply() { base.Apply(); - Services.AddScoped(); - Services.AddScoped(); + Services.AddDapperStore("WorkflowInstances"); + Services.AddDapperStore("WorkflowDefinitions"); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowDefinitionRecord.cs b/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowDefinitionRecord.cs index 6735731c56..0db52eb4ed 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowDefinitionRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowDefinitionRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Management.Records; -internal class WorkflowDefinitionRecord +internal class WorkflowDefinitionRecord : Record { - public string Id { get; set; } = default!; public string DefinitionId { get; set; } = default!; public string? Name { get; set; } public string? ToolVersion { get; set; } diff --git a/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowInstanceRecord.cs b/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowInstanceRecord.cs index acd0bb5fe1..8168fcd953 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowInstanceRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Records/WorkflowInstanceRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Management.Records; -internal class WorkflowInstanceRecord +internal class WorkflowInstanceRecord : Record { - public string Id { get; set; } = default!; public string DefinitionId { get; set; } = default!; public string DefinitionVersionId { get; set; } = default!; public int Version { get; set; } diff --git a/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowDefinitionStore.cs b/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowDefinitionStore.cs index 972f3d5aeb..b2d841d98d 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowDefinitionStore.cs @@ -1,51 +1,40 @@ -using System.Text.Json.Serialization; using Elsa.Common.Entities; using Elsa.Common.Models; -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Management.Records; using Elsa.Dapper.Services; using Elsa.Extensions; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; +using JetBrains.Annotations; +using Newtonsoft.Json; namespace Elsa.Dapper.Modules.Management.Stores; /// /// Provides a Dapper implementation of . /// -public class DapperWorkflowDefinitionStore : IWorkflowDefinitionStore +[UsedImplicitly] +internal class DapperWorkflowDefinitionStore(Store store, IPayloadSerializer payloadSerializer) + : IWorkflowDefinitionStore { - private const string TableName = "WorkflowDefinitions"; - private readonly IPayloadSerializer _payloadSerializer; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperWorkflowDefinitionStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer) - { - _payloadSerializer = payloadSerializer; - _store = new Store(dbConnectionProvider, TableName); - } - /// public async Task FindAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : Map(record); } /// public async Task FindAsync(WorkflowDefinitionFilter filter, WorkflowDefinitionOrder order, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return record == null ? null : Map(record); } @@ -62,21 +51,21 @@ public async Task> FindManyAsync(WorkflowDefinitionFilt /// public async Task> FindManyAsync(WorkflowDefinitionFilter filter, WorkflowDefinitionOrder order, PageArgs pageArgs, CancellationToken cancellationToken = default) { - var page = await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var page = await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return Map(page); } /// public async Task> FindManyAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return Map(records).ToList(); } /// public async Task> FindManyAsync(WorkflowDefinitionFilter filter, WorkflowDefinitionOrder order, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return Map(records).ToList(); } @@ -93,26 +82,26 @@ public async Task> FindSummariesAsync(WorkflowDe /// public async Task> FindSummariesAsync(WorkflowDefinitionFilter filter, WorkflowDefinitionOrder order, PageArgs pageArgs, CancellationToken cancellationToken = default) { - return await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + return await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); } /// public async Task> FindSummariesAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return records.ToList(); } /// public async Task> FindSummariesAsync(WorkflowDefinitionFilter filter, WorkflowDefinitionOrder order, CancellationToken cancellationToken = default) { - return await _store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + return await store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); } /// public async Task FindLastVersionAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), nameof(WorkflowDefinitionRecord.Version), OrderDirection.Descending, cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), nameof(WorkflowDefinitionRecord.Version), OrderDirection.Descending, cancellationToken); return record == null ? null : Map(record); } @@ -120,40 +109,40 @@ public async Task> FindSummariesAsync public async Task SaveManyAsync(IEnumerable definitions, CancellationToken cancellationToken = default) { var records = definitions.Select(Map).ToList(); - await _store.SaveManyAsync(records, nameof(WorkflowDefinitionRecord.Id), cancellationToken); + await store.SaveManyAsync(records, cancellationToken); } /// public async Task DeleteAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task AnyAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { - return await _store.AnyAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.AnyAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task CountDistinctAsync(CancellationToken cancellationToken = default) { - return await _store.CountAsync( - filter => filter.Count($"distinct {nameof(WorkflowDefinition.DefinitionId)}", TableName), + return await store.CountAsync( + filter => filter.Count($"distinct {nameof(WorkflowDefinition.DefinitionId)}", store.TableName), cancellationToken); } /// public async Task GetIsNameUnique(string name, string? definitionId = default, CancellationToken cancellationToken = default) { - var exists = await _store.AnyAsync(query => + var exists = await store.AnyAsync(query => { query.Is(nameof(WorkflowDefinition.Name), name); @@ -190,7 +179,7 @@ private void ApplyFilter(ParameterizedQuery query, WorkflowDefinitionFilter filt private WorkflowDefinition Map(WorkflowDefinitionRecord source) { - var props = _payloadSerializer.Deserialize(source.Props); + var props = payloadSerializer.Deserialize(source.Props); return new WorkflowDefinition { Id = source.Id, @@ -213,7 +202,8 @@ private WorkflowDefinition Map(WorkflowDefinitionRecord source) MaterializerContext = source.MaterializerContext, BinaryData = source.BinaryData, MaterializerName = source.MaterializerName, - ProviderName = source.ProviderName + ProviderName = source.ProviderName, + TenantId = source.TenantId }; } @@ -242,12 +232,13 @@ private WorkflowDefinitionRecord Map(WorkflowDefinition source) IsReadonly = source.IsReadonly, IsSystem = source.IsSystem, StringData = source.StringData, - Props = _payloadSerializer.Serialize(props), + Props = payloadSerializer.Serialize(props), MaterializerName = source.MaterializerName, UsableAsActivity = source.Options.UsableAsActivity, ProviderName = source.ProviderName, BinaryData = source.BinaryData, - MaterializerContext = source.MaterializerContext + MaterializerContext = source.MaterializerContext, + TenantId = source.TenantId }; } diff --git a/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowInstanceStore.cs b/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowInstanceStore.cs index 40c747f74c..075471c8fe 100644 --- a/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowInstanceStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Management/Stores/DapperWorkflowInstanceStore.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Elsa.Common.Entities; using Elsa.Common.Models; -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Management.Records; @@ -9,39 +8,31 @@ using Elsa.Extensions; using Elsa.Workflows; using Elsa.Workflows.Contracts; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Models; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Management.Stores; /// /// Provides a Dapper implementation of . /// -public class DapperWorkflowInstanceStore : IWorkflowInstanceStore +[UsedImplicitly] +internal class DapperWorkflowInstanceStore(Store store, IWorkflowStateSerializer workflowStateSerializer) + : IWorkflowInstanceStore { - private const string TableName = "WorkflowInstances"; - private readonly IWorkflowStateSerializer _workflowStateSerializer; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperWorkflowInstanceStore(IDbConnectionProvider dbConnectionProvider, IWorkflowStateSerializer workflowStateSerializer) - { - _workflowStateSerializer = workflowStateSerializer; - _store = new Store(dbConnectionProvider, TableName); - } - /// + [RequiresUnreferencedCode("Calls Elsa.Dapper.Modules.Management.Stores.DapperWorkflowInstanceStore.MapAsync(WorkflowInstanceRecord)")] public async ValueTask FindAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : Map(record); } /// + [RequiresUnreferencedCode("Calls Elsa.Dapper.Modules.Management.Stores.DapperWorkflowInstanceStore.FindManyAsync(WorkflowInstanceFilter, PageArgs, WorkflowInstanceOrder, CancellationToken)")] public async ValueTask> FindManyAsync(WorkflowInstanceFilter filter, PageArgs pageArgs, CancellationToken cancellationToken = default) { return await FindManyAsync( @@ -52,30 +43,33 @@ public async ValueTask> FindManyAsync(WorkflowInstanceFil } /// + [RequiresUnreferencedCode("Calls Elsa.Dapper.Modules.Management.Stores.DapperWorkflowInstanceStore.MapAsync(Page)")] public async ValueTask> FindManyAsync(WorkflowInstanceFilter filter, PageArgs pageArgs, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) { - var page = await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var page = await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return Map(page); } /// + [RequiresUnreferencedCode("Calls Elsa.Dapper.Modules.Management.Stores.DapperWorkflowInstanceStore.MapAsync(IEnumerable)")] public async ValueTask> FindManyAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return Map(records).ToList(); } /// + [RequiresUnreferencedCode("Calls Elsa.Dapper.Modules.Management.Stores.DapperWorkflowInstanceStore.MapAsync(IEnumerable)")] public async ValueTask> FindManyAsync(WorkflowInstanceFilter filter, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return Map(records).ToList(); } /// public async ValueTask CountAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - return await _store.CountAsync(query => ApplyFilter(query, filter), cancellationToken); + return await store.CountAsync(query => ApplyFilter(query, filter), cancellationToken); } /// @@ -91,7 +85,7 @@ public async ValueTask> SummarizeManyAsync(Workflo /// public async ValueTask> SummarizeManyAsync(WorkflowInstanceFilter filter, PageArgs pageArgs, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) { - return await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + return await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); } /// @@ -103,13 +97,13 @@ public async ValueTask> SummarizeManyAsync( /// public async ValueTask> SummarizeManyAsync(WorkflowInstanceFilter filter, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) { - return await _store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + return await store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); } /// public async ValueTask> FindManyIdsAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - var items = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var items = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return items.Select(x => x.Id).ToList(); } @@ -126,7 +120,7 @@ public async ValueTask> FindManyIdsAsync(WorkflowInstanceFilter fil /// public async ValueTask> FindManyIdsAsync(WorkflowInstanceFilter filter, PageArgs pageArgs, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) { - var page = await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var page = await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); var ids = page.Items.Select(x => x.Id).ToList(); return Page.Of(ids, page.TotalCount); } @@ -136,21 +130,21 @@ public async ValueTask> FindManyIdsAsync(WorkflowInstance public async ValueTask SaveAsync(WorkflowInstance instance, CancellationToken cancellationToken = default) { var record = Map(instance); - await _store.SaveAsync(record, cancellationToken); + await store.SaveAsync(record, cancellationToken); } /// public async ValueTask AddAsync(WorkflowInstance instance, CancellationToken cancellationToken = default) { var record = Map(instance); - await _store.AddAsync(record, cancellationToken); + await store.AddAsync(record, cancellationToken); } /// public async ValueTask UpdateAsync(WorkflowInstance instance, CancellationToken cancellationToken = default) { var record = Map(instance); - await _store.UpdateAsync(record, cancellationToken); + await store.UpdateAsync(record, cancellationToken); } /// @@ -158,13 +152,13 @@ public async ValueTask UpdateAsync(WorkflowInstance instance, CancellationToken public async ValueTask SaveManyAsync(IEnumerable instances, CancellationToken cancellationToken = default) { var records = Map(instances); - await _store.SaveManyAsync(records, cancellationToken); + await store.SaveManyAsync(records, cancellationToken); } /// public async ValueTask DeleteAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } private void ApplyFilter(ParameterizedQuery query, WorkflowInstanceFilter filter) @@ -209,7 +203,7 @@ private IEnumerable Map(IEnumerable so [RequiresUnreferencedCode("Calls Elsa.Workflows.Contracts.IWorkflowStateSerializer.DeserializeAsync(String, CancellationToken)")] private WorkflowInstance Map(WorkflowInstanceRecord source) { - var workflowState = _workflowStateSerializer.Deserialize(source.WorkflowState); + var workflowState = workflowStateSerializer.Deserialize(source.WorkflowState); return new WorkflowInstance { Id = source.Id, @@ -226,13 +220,14 @@ private WorkflowInstance Map(WorkflowInstanceRecord source) Status = Enum.Parse(source.Status), SubStatus = Enum.Parse(source.SubStatus), CorrelationId = source.CorrelationId, + TenantId = source.TenantId }; } [RequiresUnreferencedCode("Calls Elsa.Workflows.Contracts.IWorkflowStateSerializer.DeserializeAsync(String, CancellationToken)")] private WorkflowInstanceRecord Map(WorkflowInstance source) { - var workflowState = _workflowStateSerializer.Serialize(source.WorkflowState); + var workflowState = workflowStateSerializer.Serialize(source.WorkflowState); return new WorkflowInstanceRecord { Id = source.Id, @@ -248,7 +243,8 @@ private WorkflowInstanceRecord Map(WorkflowInstance source) FinishedAt = source.FinishedAt, Status = source.Status.ToString(), SubStatus = source.SubStatus.ToString(), - CorrelationId = source.CorrelationId + CorrelationId = source.CorrelationId, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Features/DapperWorkflowRuntimePersistenceFeature.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Features/DapperWorkflowRuntimePersistenceFeature.cs index bd77bbc47e..6ef3bae1ed 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Features/DapperWorkflowRuntimePersistenceFeature.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Features/DapperWorkflowRuntimePersistenceFeature.cs @@ -1,4 +1,6 @@ +using Elsa.Dapper.Extensions; using Elsa.Dapper.Features; +using Elsa.Dapper.Modules.Runtime.Records; using Elsa.Dapper.Modules.Runtime.Stores; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -43,10 +45,10 @@ public override void Apply() { base.Apply(); - Services.AddScoped(); - Services.AddScoped(); - Services.AddScoped(); - Services.AddScoped(); - Services.AddScoped(); + Services.AddDapperStore("Triggers"); + Services.AddDapperStore("Bookmarks"); + Services.AddDapperStore("WorkflowExecutionLogRecords"); + Services.AddDapperStore("ActivityExecutionRecords"); + Services.AddDapperStore("KeyValues"); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionRecord.cs index ee98a3aa2f..9887a92bc3 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionRecord.cs @@ -1,15 +1,12 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; /// /// Represents a single workflow execution, associated with an individual activity instance. /// -public class ActivityExecutionRecordRecord +internal class ActivityExecutionRecordRecord : Record { - /// - /// Gets or sets the ID of the activity execution record. - /// - public string Id { get; set; } = default!; - /// /// Gets or sets the workflow instance ID. /// diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionSummaryRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionSummaryRecord.cs index 6a7dd30770..0e389202bc 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionSummaryRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/ActivityExecutionSummaryRecord.cs @@ -1,15 +1,12 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; /// /// Represents a single workflow execution, associated with an individual activity instance. /// -public class ActivityExecutionSummaryRecord +internal class ActivityExecutionSummaryRecord : Record { - /// - /// Gets or sets the ID of the activity execution record. - /// - public string Id { get; set; } = default!; - /// /// Gets or sets the workflow instance ID. /// diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/KeyValuePairRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/KeyValuePairRecord.cs index 64730f781c..a1d97edff1 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/KeyValuePairRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/KeyValuePairRecord.cs @@ -1,7 +1,8 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; -public class KeyValuePairRecord +internal class KeyValuePairRecord : Record { - public string Key { get; set; } = default!; public string Value { get; set; } = default!; } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredBookmarkRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredBookmarkRecord.cs index caa1a9c9b5..ecaf036520 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredBookmarkRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredBookmarkRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; -internal class StoredBookmarkRecord +internal class StoredBookmarkRecord : Record { - public string Id { get; set; } = default!; public string ActivityTypeName { get; set; } = default!; public string Hash { get; set; } = default!; public string WorkflowInstanceId { get; set; } = default!; diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredTriggerRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredTriggerRecord.cs index 0f190c3daa..c81a8318c7 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredTriggerRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/StoredTriggerRecord.cs @@ -1,8 +1,9 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; -internal class StoredTriggerRecord +internal class StoredTriggerRecord : Record { - public string Id { get; set; } = default!; public string WorkflowDefinitionId { get; set; } = default!; public string WorkflowDefinitionVersionId { get; set; } = default!; public string Name { get; set; } = default!; diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Records/WorkflowExecutionLogRecordRecord.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Records/WorkflowExecutionLogRecordRecord.cs index 6a3fa00023..60115f2867 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Records/WorkflowExecutionLogRecordRecord.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Records/WorkflowExecutionLogRecordRecord.cs @@ -1,6 +1,8 @@ +using Elsa.Dapper.Records; + namespace Elsa.Dapper.Modules.Runtime.Records; -internal class WorkflowExecutionLogRecordRecord +internal class WorkflowExecutionLogRecordRecord : Record { public string Id { get; set; } = default!; public string WorkflowDefinitionId { get; set; } = default!; diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperActivityExecutionRecordStore.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperActivityExecutionRecordStore.cs index 3f33a49f44..f5742b4725 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperActivityExecutionRecordStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperActivityExecutionRecordStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Runtime.Records; @@ -12,89 +11,76 @@ using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; using Elsa.Workflows.State; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Runtime.Stores; /// /// Implements the using Dapper. /// -public class DapperActivityExecutionRecordStore : IActivityExecutionStore +[UsedImplicitly] +internal class DapperActivityExecutionRecordStore(Store store, IPayloadSerializer payloadSerializer, ISafeSerializer safeSerializer) + : IActivityExecutionStore { - private const string TableName = "ActivityExecutionRecords"; - private const string PrimaryKeyName = "Id"; - private readonly IPayloadSerializer _payloadSerializer; - private readonly ISafeSerializer _safeSerializer; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperActivityExecutionRecordStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer, ISafeSerializer safeSerializer) - { - _payloadSerializer = payloadSerializer; - _safeSerializer = safeSerializer; - _store = new Store(dbConnectionProvider, TableName, PrimaryKeyName); - } - /// public async Task SaveAsync(ActivityExecutionRecord record, CancellationToken cancellationToken = default) { var mappedRecord = await Map(record, cancellationToken); - await _store.SaveAsync(mappedRecord, PrimaryKeyName, cancellationToken); + await store.SaveAsync(mappedRecord, cancellationToken); } /// public async Task SaveManyAsync(IEnumerable records, CancellationToken cancellationToken = default) { var mappedRecords = await Task.WhenAll(records.Select(async x => await Map(x, cancellationToken))); - await _store.SaveManyAsync(mappedRecords, PrimaryKeyName, cancellationToken); + await store.SaveManyAsync(mappedRecords, cancellationToken); } /// public async Task FindAsync(ActivityExecutionRecordFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : await MapAsync(record, cancellationToken); } /// public async Task> FindManyAsync(ActivityExecutionRecordFilter filter, ActivityExecutionRecordOrder order, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return await Task.WhenAll(records.Select(async x => await MapAsync(x, cancellationToken))); } /// public async Task> FindManyAsync(ActivityExecutionRecordFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return await Task.WhenAll(records.Select(async x => await MapAsync(x, cancellationToken))); } /// public async Task> FindManySummariesAsync(ActivityExecutionRecordFilter filter, ActivityExecutionRecordOrder order, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return records.Select(MapSummary).ToList(); } /// public async Task> FindManySummariesAsync(ActivityExecutionRecordFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return records.Select(MapSummary).ToList(); } /// public async Task CountAsync(ActivityExecutionRecordFilter filter, CancellationToken cancellationToken = default) { - return await _store.CountAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.CountAsync(q => ApplyFilter(q, filter), cancellationToken); } /// public async Task DeleteManyAsync(ActivityExecutionRecordFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } private static void ApplyFilter(ParameterizedQuery query, ActivityExecutionRecordFilter filter) @@ -131,10 +117,11 @@ private async ValueTask Map(ActivityExecutionReco HasBookmarks = source.HasBookmarks, Status = source.Status.ToString(), ActivityTypeVersion = source.ActivityTypeVersion, - SerializedActivityState = source.ActivityState != null ? await _safeSerializer.SerializeAsync(source.ActivityState, cancellationToken) : default, - SerializedPayload = source.Payload != null ? await _safeSerializer.SerializeAsync(source.Payload, cancellationToken) : default, - SerializedOutputs = source.Outputs != null ? await _safeSerializer.SerializeAsync(source.Outputs, cancellationToken) : default, - SerializedException = source.Exception != null ? _payloadSerializer.Serialize(source.Exception) : default + SerializedActivityState = source.ActivityState != null ? await safeSerializer.SerializeAsync(source.ActivityState, cancellationToken) : default, + SerializedPayload = source.Payload != null ? await safeSerializer.SerializeAsync(source.Payload, cancellationToken) : default, + SerializedOutputs = source.Outputs != null ? await safeSerializer.SerializeAsync(source.Outputs, cancellationToken) : default, + SerializedException = source.Exception != null ? payloadSerializer.Serialize(source.Exception) : default, + TenantId = source.TenantId }; } @@ -153,10 +140,11 @@ private async ValueTask MapAsync(ActivityExecutionRecor HasBookmarks = source.HasBookmarks, Status = Enum.Parse(source.Status), ActivityTypeVersion = source.ActivityTypeVersion, - ActivityState = source.SerializedActivityState != null ? _payloadSerializer.Deserialize>(source.SerializedActivityState) : default, - Payload = source.SerializedPayload != null ? await _safeSerializer.DeserializeAsync>(source.SerializedPayload, cancellationToken) : default, - Outputs = source.SerializedOutputs != null ? await _safeSerializer.DeserializeAsync>(source.SerializedOutputs, cancellationToken) : default, - Exception = source.SerializedException != null ? _payloadSerializer.Deserialize(source.SerializedException) : default + ActivityState = source.SerializedActivityState != null ? payloadSerializer.Deserialize>(source.SerializedActivityState) : default, + Payload = source.SerializedPayload != null ? await safeSerializer.DeserializeAsync>(source.SerializedPayload, cancellationToken) : default, + Outputs = source.SerializedOutputs != null ? await safeSerializer.DeserializeAsync>(source.SerializedOutputs, cancellationToken) : default, + Exception = source.SerializedException != null ? payloadSerializer.Deserialize(source.SerializedException) : default, + TenantId = source.TenantId }; } @@ -174,7 +162,8 @@ private ActivityExecutionRecordSummary MapSummary(ActivityExecutionSummaryRecord StartedAt = source.StartedAt, HasBookmarks = source.HasBookmarks, Status = Enum.Parse(source.Status), - ActivityTypeVersion = source.ActivityTypeVersion + ActivityTypeVersion = source.ActivityTypeVersion, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperBookmarkStore.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperBookmarkStore.cs index 06372b80cf..cc1f393dc0 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperBookmarkStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperBookmarkStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Runtime.Records; @@ -8,59 +7,48 @@ using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Runtime.Stores; /// /// A Dapper-based implementation. /// -public class DapperBookmarkStore : IBookmarkStore +[UsedImplicitly] +internal class DapperBookmarkStore(Store store, IPayloadSerializer payloadSerializer) : IBookmarkStore { - private readonly IPayloadSerializer _payloadSerializer; - private const string TableName = "Bookmarks"; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperBookmarkStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer) - { - _payloadSerializer = payloadSerializer; - _store = new Store(dbConnectionProvider, TableName); - } - /// public async ValueTask SaveAsync(StoredBookmark record, CancellationToken cancellationToken = default) { var mappedRecord = Map(record); - await _store.SaveAsync(mappedRecord, cancellationToken); + await store.SaveAsync(mappedRecord, cancellationToken); } /// public async ValueTask SaveManyAsync(IEnumerable records, CancellationToken cancellationToken) { var mappedRecords = Map(records); - await _store.SaveManyAsync(mappedRecords, cancellationToken); + await store.SaveManyAsync(mappedRecords, cancellationToken); } /// public async ValueTask FindAsync(BookmarkFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record != null ? Map(record) : default; } /// public async ValueTask> FindManyAsync(BookmarkFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), filter.TenantAgnostic, cancellationToken); return Map(records); } /// public async ValueTask DeleteAsync(BookmarkFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } private void ApplyFilter(ParameterizedQuery query, BookmarkFilter filter) @@ -84,15 +72,16 @@ private StoredBookmarkRecord Map(StoredBookmark source) { return new StoredBookmarkRecord { - Id = source.BookmarkId, + Id = source.Id, WorkflowInstanceId = source.WorkflowInstanceId, CorrelationId = source.CorrelationId, ActivityInstanceId = source.ActivityInstanceId, ActivityTypeName = source.ActivityTypeName, Hash = source.Hash, - SerializedPayload = source.Payload != null ? _payloadSerializer.Serialize(source.Payload) : default, - SerializedMetadata = source.Metadata != null ? _payloadSerializer.Serialize(source.Metadata) : default, - CreatedAt = source.CreatedAt + SerializedPayload = source.Payload != null ? payloadSerializer.Serialize(source.Payload) : default, + SerializedMetadata = source.Metadata != null ? payloadSerializer.Serialize(source.Metadata) : default, + CreatedAt = source.CreatedAt, + TenantId = source.TenantId }; } @@ -100,15 +89,16 @@ private StoredBookmark Map(StoredBookmarkRecord source) { return new StoredBookmark { - BookmarkId = source.Id, + Id = source.Id, WorkflowInstanceId = source.WorkflowInstanceId, CorrelationId = source.CorrelationId, ActivityInstanceId = source.ActivityInstanceId, ActivityTypeName = source.ActivityTypeName, Hash = source.Hash, - Payload = source.SerializedPayload != null ? _payloadSerializer.Deserialize(source.SerializedPayload) : default, - Metadata = source.SerializedMetadata != null ? _payloadSerializer.Deserialize>(source.SerializedMetadata) : default, - CreatedAt = source.CreatedAt + Payload = source.SerializedPayload != null ? payloadSerializer.Deserialize(source.SerializedPayload) : default, + Metadata = source.SerializedMetadata != null ? payloadSerializer.Deserialize>(source.SerializedMetadata) : default, + CreatedAt = source.CreatedAt, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperTriggerStore.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperTriggerStore.cs index 528c916163..507b313478 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperTriggerStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperTriggerStore.cs @@ -1,5 +1,4 @@ -using Elsa.Dapper.Contracts; -using Elsa.Dapper.Extensions; +using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Runtime.Records; using Elsa.Dapper.Services; @@ -8,59 +7,51 @@ using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Runtime.Stores; /// /// Provides a Dapper implementation of . /// -public class DapperTriggerStore : ITriggerStore +[UsedImplicitly] +internal class DapperTriggerStore(Store store, IPayloadSerializer payloadSerializer) : ITriggerStore { - private const string TableName = "Triggers"; - private readonly IPayloadSerializer _payloadSerializer; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperTriggerStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer) - { - _payloadSerializer = payloadSerializer; - _store = new Store(dbConnectionProvider, TableName); - } - /// public async ValueTask SaveAsync(StoredTrigger record, CancellationToken cancellationToken = default) { var mappedRecord = Map(record); - await _store.SaveAsync(mappedRecord, cancellationToken); + await store.SaveAsync(mappedRecord, cancellationToken); } /// public async ValueTask SaveManyAsync(IEnumerable records, CancellationToken cancellationToken = default) { var mappedRecords = records.Select(Map); - await _store.SaveManyAsync(mappedRecords, cancellationToken); + await store.SaveManyAsync(mappedRecords, cancellationToken); } /// public async ValueTask FindAsync(TriggerFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record != null ? Map(record) : default; } /// public async ValueTask> FindManyAsync(TriggerFilter filter, CancellationToken cancellationToken = default) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return Map(records); } /// public async ValueTask ReplaceAsync(IEnumerable removed, IEnumerable added, CancellationToken cancellationToken = default) { - var filter = new TriggerFilter { Ids = removed.Select(r => r.Id).ToList() }; + var filter = new TriggerFilter + { + Ids = removed.Select(r => r.Id).ToList() + }; await DeleteManyAsync(filter, cancellationToken); await SaveManyAsync(added, cancellationToken); } @@ -68,7 +59,7 @@ public async ValueTask ReplaceAsync(IEnumerable removed, IEnumera /// public async ValueTask DeleteManyAsync(TriggerFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } private void ApplyFilter(ParameterizedQuery query, TriggerFilter filter) @@ -98,7 +89,8 @@ private StoredTrigger Map(StoredTriggerRecord source) Name = source.Name, WorkflowDefinitionId = source.WorkflowDefinitionId, WorkflowDefinitionVersionId = source.WorkflowDefinitionVersionId, - Payload = source.SerializedPayload != null ? _payloadSerializer.Deserialize(source.SerializedPayload) : default + Payload = source.SerializedPayload != null ? payloadSerializer.Deserialize(source.SerializedPayload) : default, + TenantId = source.TenantId }; } @@ -112,7 +104,8 @@ private StoredTriggerRecord Map(StoredTrigger source) Name = source.Name, WorkflowDefinitionId = source.WorkflowDefinitionId, WorkflowDefinitionVersionId = source.WorkflowDefinitionVersionId, - SerializedPayload = source.Payload != null ? _payloadSerializer.Serialize(source.Payload) : default + SerializedPayload = source.Payload != null ? payloadSerializer.Serialize(source.Payload) : default, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperWorkflowExecutionLogStore.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperWorkflowExecutionLogStore.cs index 34ad39393e..5d497f9bd7 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperWorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/DapperWorkflowExecutionLogStore.cs @@ -1,6 +1,5 @@ using Elsa.Common.Entities; using Elsa.Common.Models; -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Runtime.Records; @@ -12,66 +11,55 @@ using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Runtime.Stores; /// /// Implements the using Dapper. /// -public class DapperWorkflowExecutionLogStore : IWorkflowExecutionLogStore +[UsedImplicitly] +internal class DapperWorkflowExecutionLogStore(Store store, IPayloadSerializer payloadSerializer) : IWorkflowExecutionLogStore { - private const string TableName = "WorkflowExecutionLogRecords"; - private readonly IPayloadSerializer _payloadSerializer; - private readonly Store _store; - - /// - /// Initializes a new instance of the class. - /// - public DapperWorkflowExecutionLogStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer) - { - _payloadSerializer = payloadSerializer; - _store = new Store(dbConnectionProvider, TableName); - } - /// public async Task AddAsync(WorkflowExecutionLogRecord record, CancellationToken cancellationToken = default) { var mappedRecord = Map(record); - await _store.AddAsync(mappedRecord, cancellationToken); + await store.AddAsync(mappedRecord, cancellationToken); } /// public async Task AddManyAsync(IEnumerable records, CancellationToken cancellationToken = default) { var mappedRecords = records.Select(Map); - await _store.AddManyAsync(mappedRecords, cancellationToken); + await store.AddManyAsync(mappedRecords, cancellationToken); } /// public async Task SaveAsync(WorkflowExecutionLogRecord record, CancellationToken cancellationToken = default) { var mappedRecord = Map(record); - await _store.SaveAsync(mappedRecord, cancellationToken); + await store.SaveAsync(mappedRecord, cancellationToken); } /// public async Task SaveManyAsync(IEnumerable records, CancellationToken cancellationToken = default) { var mappedRecords = records.Select(Map); - await _store.SaveManyAsync(mappedRecords, cancellationToken); + await store.SaveManyAsync(mappedRecords, cancellationToken); } /// public async Task FindAsync(WorkflowExecutionLogRecordFilter filter, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record != null ? Map(record) : default; } /// public async Task FindAsync(WorkflowExecutionLogRecordFilter filter, WorkflowExecutionLogRecordOrder order, CancellationToken cancellationToken = default) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return record != null ? Map(record) : default; } @@ -88,14 +76,14 @@ public async Task> FindManyAsync(WorkflowExecut /// public async Task> FindManyAsync(WorkflowExecutionLogRecordFilter filter, PageArgs pageArgs, WorkflowExecutionLogRecordOrder order, CancellationToken cancellationToken = default) { - var page = await _store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); + var page = await store.FindManyAsync(q => ApplyFilter(q, filter), pageArgs, order.KeySelector.GetPropertyName(), order.Direction, cancellationToken); return Map(page); } /// public async Task DeleteManyAsync(WorkflowExecutionLogRecordFilter filter, CancellationToken cancellationToken = default) { - return await _store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); + return await store.DeleteAsync(q => ApplyFilter(q, filter), cancellationToken); } private static void ApplyFilter(ParameterizedQuery query, WorkflowExecutionLogRecordFilter filter) @@ -139,8 +127,9 @@ private WorkflowExecutionLogRecordRecord Map(WorkflowExecutionLogRecord source) EventName = source.EventName, Message = source.Message, Source = source.Source, - SerializedActivityState = source.ActivityState != null ? _payloadSerializer.Serialize(source.ActivityState) : null, - SerializedPayload = source.Payload != null ? _payloadSerializer.Serialize(source.Payload) : null, + SerializedActivityState = source.ActivityState != null ? payloadSerializer.Serialize(source.ActivityState) : null, + SerializedPayload = source.Payload != null ? payloadSerializer.Serialize(source.Payload) : null, + TenantId = source.TenantId }; } @@ -165,8 +154,9 @@ private WorkflowExecutionLogRecord Map(WorkflowExecutionLogRecordRecord source) EventName = source.EventName, Message = source.Message, Source = source.Source, - ActivityState = source.SerializedActivityState != null ? _payloadSerializer.Deserialize>(source.SerializedActivityState) : null, - Payload = source.SerializedPayload != null ? _payloadSerializer.Deserialize(source.SerializedPayload) : null, + ActivityState = source.SerializedActivityState != null ? payloadSerializer.Deserialize>(source.SerializedActivityState) : null, + Payload = source.SerializedPayload != null ? payloadSerializer.Deserialize(source.SerializedPayload) : null, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/KeyValueStore.cs b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/KeyValueStore.cs index 3eb19191e2..7323281df1 100644 --- a/src/modules/Elsa.Dapper/Modules/Runtime/Stores/KeyValueStore.cs +++ b/src/modules/Elsa.Dapper/Modules/Runtime/Stores/KeyValueStore.cs @@ -1,4 +1,3 @@ -using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; using Elsa.Dapper.Modules.Runtime.Records; @@ -6,76 +5,68 @@ using Elsa.KeyValues.Contracts; using Elsa.KeyValues.Entities; using Elsa.KeyValues.Models; +using JetBrains.Annotations; namespace Elsa.Dapper.Modules.Runtime.Stores; /// /// A Dapper implementation of . /// -public class DapperKeyValueStore : IKeyValueStore +[UsedImplicitly] +internal class DapperKeyValueStore(Store store) : IKeyValueStore { - private const string TableName = "Users"; - private const string PrimaryKeyName = "Key"; - private readonly Store _store; - - /// - /// Initializes a new instance of . - /// - public DapperKeyValueStore(IDbConnectionProvider dbConnectionProvider) - { - _store = new Store(dbConnectionProvider, TableName, PrimaryKeyName); - } - /// public Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken) { var record = Map(keyValuePair); - return _store.SaveAsync(record, PrimaryKeyName, cancellationToken); + return store.SaveAsync(record, cancellationToken); } /// public async Task FindAsync(KeyValueFilter filter, CancellationToken cancellationToken) { - var record = await _store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); + var record = await store.FindAsync(q => ApplyFilter(q, filter), cancellationToken); return record == null ? null : Map(record); } /// public async Task> FindManyAsync(KeyValueFilter filter, CancellationToken cancellationToken) { - var records = await _store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); + var records = await store.FindManyAsync(q => ApplyFilter(q, filter), cancellationToken); return records.Select(Map); } /// public Task DeleteAsync(string key, CancellationToken cancellationToken) { - return _store.DeleteAsync(query => query.Is(nameof(KeyValuePairRecord.Key), key), cancellationToken); + return store.DeleteAsync(query => query.Is(nameof(KeyValuePairRecord.Id), key), cancellationToken); } private void ApplyFilter(ParameterizedQuery query, KeyValueFilter filter) { query - .Is(nameof(KeyValuePairRecord.Key), filter.Key) - .In(nameof(KeyValuePairRecord.Key), filter.Keys) - .StartsWith(nameof(KeyValuePairRecord.Key), filter.StartsWith, filter.Key); + .Is(nameof(KeyValuePairRecord.Id), filter.Key) + .In(nameof(KeyValuePairRecord.Id), filter.Keys) + .StartsWith(nameof(KeyValuePairRecord.Id), filter.StartsWith, filter.Key); } - private KeyValuePairRecord Map(SerializedKeyValuePair kvp) + private KeyValuePairRecord Map(SerializedKeyValuePair source) { return new() { - Key = kvp.Key, - Value = kvp.SerializedValue + Id = source.Id, + Value = source.SerializedValue, + TenantId = source.TenantId }; } - private SerializedKeyValuePair Map(KeyValuePairRecord kvp) + private SerializedKeyValuePair Map(KeyValuePairRecord source) { return new() { - Key = kvp.Key, - SerializedValue = kvp.Value + Id = source.Id, + SerializedValue = source.Value, + TenantId = source.TenantId }; } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Records/Record.cs b/src/modules/Elsa.Dapper/Records/Record.cs new file mode 100644 index 0000000000..00fd5355c9 --- /dev/null +++ b/src/modules/Elsa.Dapper/Records/Record.cs @@ -0,0 +1,7 @@ +namespace Elsa.Dapper.Records; + +public class Record +{ + public string Id { get; set; } = default!; + public string? TenantId { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/Services/Store.cs b/src/modules/Elsa.Dapper/Services/Store.cs index 9a4efd114d..64fad2aa2b 100644 --- a/src/modules/Elsa.Dapper/Services/Store.cs +++ b/src/modules/Elsa.Dapper/Services/Store.cs @@ -1,9 +1,12 @@ using Dapper; +using Elsa.Common.Contracts; using Elsa.Common.Entities; using Elsa.Common.Models; using Elsa.Dapper.Contracts; using Elsa.Dapper.Extensions; using Elsa.Dapper.Models; +using Elsa.Dapper.Records; +using Elsa.Tenants; using JetBrains.Annotations; namespace Elsa.Dapper.Services; @@ -12,29 +15,18 @@ namespace Elsa.Dapper.Services; /// Provides a generic store using Dapper. /// [PublicAPI] -public class Store where T : notnull +public class Store(IDbConnectionProvider dbConnectionProvider, ITenantResolver tenantResolver, string tableName, string primaryKey = "Id") + where T : notnull { - private readonly IDbConnectionProvider _dbConnectionProvider; - - /// - /// Initializes a new instance of the class. - /// - public Store(IDbConnectionProvider dbConnectionProvider, string tableName, string primaryKey = "Id") - { - _dbConnectionProvider = dbConnectionProvider; - TableName = tableName; - PrimaryKey = primaryKey; - } - /// /// The name of the table. /// - public string TableName { get; } + public string TableName { get; } = tableName; /// /// The name of the primary key column. /// - public string PrimaryKey { get; } + public string PrimaryKey { get; } = primaryKey; /// /// Finds a single record. @@ -44,10 +36,19 @@ public Store(IDbConnectionProvider dbConnectionProvider, string tableName, strin /// The record, if found. public async Task FindAsync(Action filter, CancellationToken cancellationToken = default) { - var query = _dbConnectionProvider.CreateQuery().From(TableName); - filter(query); - using var connection = _dbConnectionProvider.GetConnection(); - return await query.FirstOrDefaultAsync(connection); + return await FindAsync(filter, false, cancellationToken); + } + + /// + /// Finds a single record. + /// + /// The conditions to apply to the query. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// The record, if found. + public async Task FindAsync(Action filter, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + return await FindAsync(filter, null, null, tenantAgnostic, cancellationToken); } /// @@ -60,10 +61,28 @@ public Store(IDbConnectionProvider dbConnectionProvider, string tableName, strin /// The record, if found. public async Task FindAsync(Action filter, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = _dbConnectionProvider.CreateQuery().From(TableName); + return await FindAsync(filter, orderKey, orderDirection, false, cancellationToken); + } + + /// + /// Finds a single record using the specified order key selector and order direction. + /// + /// The conditions to apply to the query. + /// The order key. + /// The order direction. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// The record, if found. + public async Task FindAsync(Action filter, string? orderKey = null, OrderDirection? orderDirection = null, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + var query = dbConnectionProvider.CreateQuery().From(TableName); + await ApplyTenantFilterAsync(query, tenantAgnostic, cancellationToken); filter(query); - query = query.OrderBy(orderKey, orderDirection); + + if (orderKey != null && orderDirection != null) + query = query.OrderBy(orderKey, orderDirection.Value); + + using var connection = dbConnectionProvider.GetConnection(); return await query.FirstOrDefaultAsync(connection); } @@ -76,8 +95,25 @@ public Store(IDbConnectionProvider dbConnectionProvider, string tableName, strin /// The order direction. /// The cancellation token. /// A page of records. - public async Task> FindManyAsync(Action filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) => - await FindManyAsync(filter, pageArgs, orderKey, orderDirection, cancellationToken); + public async Task> FindManyAsync(Action filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, pageArgs, orderKey, orderDirection, false, cancellationToken); + } + + /// + /// Returns a page of records. + /// + /// The conditions to apply to the query. + /// The page arguments. + /// The order key selector. + /// The order direction. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// A page of records. + public async Task> FindManyAsync(Action filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, bool tenantAgnostic, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, pageArgs, orderKey, orderDirection, tenantAgnostic, cancellationToken); + } /// /// Returns a page of records in the specified shape. @@ -89,7 +125,21 @@ public Store(IDbConnectionProvider dbConnectionProvider, string tableName, strin /// A page of records. public async Task> FindManyAsync(Action filter, PageArgs pageArgs, IEnumerable orderFields, CancellationToken cancellationToken = default) { - return await FindManyAsync(filter, pageArgs, orderFields, cancellationToken); + return await FindManyAsync(filter, pageArgs, orderFields, false, cancellationToken); + } + + /// + /// Returns a page of records in the specified shape. + /// + /// The conditions to apply to the query. + /// The page arguments. + /// The fields by which to order the results. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// A page of records. + public async Task> FindManyAsync(Action filter, PageArgs pageArgs, IEnumerable orderFields, bool tenantAgnostic, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, pageArgs, orderFields, tenantAgnostic, cancellationToken); } /// @@ -103,11 +153,27 @@ public async Task> FindManyAsync(Action filter, Page /// The shape type. /// A page of records. public async Task> FindManyAsync(Action filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, pageArgs, orderKey, orderDirection, false, cancellationToken); + } + + /// + /// Returns a page of records in the specified shape. + /// + /// The conditions to apply to the query. + /// The page arguments. + /// The order key selector. + /// The order direction. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// The shape type. + /// A page of records. + public async Task> FindManyAsync(Action filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, bool tenantAgnostic, CancellationToken cancellationToken = default) { return await FindManyAsync(filter, pageArgs, new[] { new OrderField(orderKey, orderDirection) - }, cancellationToken); + }, tenantAgnostic, cancellationToken); } /// @@ -121,15 +187,30 @@ public async Task> FindManyAsync(Action /// A page of records. public async Task> FindManyAsync(Action filter, PageArgs pageArgs, IEnumerable orderFields, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); + return await FindManyAsync(filter, pageArgs, orderFields, false, cancellationToken); + } - var query = _dbConnectionProvider.CreateQuery().From(TableName); + /// + /// Returns a page of records in the specified shape. + /// + /// The conditions to apply to the query. + /// The page arguments. + /// The fields by which to order the results. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// The shape type. + /// A page of records. + public async Task> FindManyAsync(Action filter, PageArgs pageArgs, IEnumerable orderFields, bool tenantAgnostic, CancellationToken cancellationToken = default) + { + var query = dbConnectionProvider.CreateQuery().From(TableName); + await ApplyTenantFilterAsync(query, tenantAgnostic, cancellationToken); filter(query); query = query.OrderBy(orderFields.ToArray()).Page(pageArgs); - var countQuery = _dbConnectionProvider.CreateQuery().Count(TableName); + var countQuery = dbConnectionProvider.CreateQuery().Count(TableName); filter(countQuery); + using var connection = dbConnectionProvider.GetConnection(); var records = (await query.QueryAsync(connection)).ToList(); var totalCount = await countQuery.SingleAsync(connection); return Page.Of(records, totalCount); @@ -141,7 +222,22 @@ public async Task> FindManyAsync(Action /// The conditions to apply to the query. /// The cancellation token. /// A set of records. - public async Task> FindManyAsync(Action filter, CancellationToken cancellationToken = default) => await FindManyAsync(filter, cancellationToken); + public async Task> FindManyAsync(Action filter, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, false, cancellationToken); + } + + /// + /// Returns a set of records. + /// + /// The conditions to apply to the query. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// A set of records. + public async Task> FindManyAsync(Action filter, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, tenantAgnostic, cancellationToken); + } /// /// Returns a set of records in the specified shape. @@ -152,8 +248,22 @@ public async Task> FindManyAsync(Action /// A set of records. public async Task> FindManyAsync(Action filter, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = _dbConnectionProvider.CreateQuery().From(TableName); + return await FindManyAsync(filter, false, cancellationToken); + } + + /// + /// Returns a set of records in the specified shape. + /// + /// The conditions to apply to the query. + /// Whether to ignore the tenant filter. + /// The cancellation token. + /// /// The shape type. + /// A set of records. + public async Task> FindManyAsync(Action filter, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + using var connection = dbConnectionProvider.GetConnection(); + var query = dbConnectionProvider.CreateQuery().From(TableName); + await ApplyTenantFilterAsync(query, tenantAgnostic, cancellationToken); filter(query); return await query.QueryAsync(connection); } @@ -166,83 +276,94 @@ public async Task> FindManyAsync(ActionThe order direction. /// The cancellation token. /// A set of records. - public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) => - await FindManyAsync(filter, orderKey, orderDirection, cancellationToken); + public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) + { + return await FindManyAsync(filter, orderKey, orderDirection, false, cancellationToken); + } /// - /// Returns a set of records in the specified shape, ordered by the specified key selector in the specified direction. + /// Returns a set of records, ordered by the specified key selector in the specified direction. /// /// The conditions to apply to the query. /// The order key selector. /// The order direction. + /// Whether to ignore the tenant filter. /// The cancellation token. /// A set of records. - public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) + public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, bool tenantAgnostic = false, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = _dbConnectionProvider.CreateQuery().From(TableName); - filter(query); - query = query.OrderBy(orderKey, orderDirection); - return await query.QueryAsync(connection); + return await FindManyAsync(filter, orderKey, orderDirection, tenantAgnostic, cancellationToken); } /// - /// Adds or updates the specified record. + /// Returns a set of records in the specified shape, ordered by the specified key selector in the specified direction. /// - /// The record. + /// The conditions to apply to the query. + /// The order key selector. + /// The order direction. /// The cancellation token. - public Task SaveAsync(T record, CancellationToken cancellationToken = default) + /// A set of records. + public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) { - return SaveAsync(record, PrimaryKey, cancellationToken); + return await FindManyAsync(filter, orderKey, orderDirection, false, cancellationToken); } - + /// - /// Adds or updates the specified record. + /// Returns a set of records in the specified shape, ordered by the specified key selector in the specified direction. /// - /// The record. - /// The primary key. + /// The conditions to apply to the query. + /// The order key selector. + /// The order direction. + /// Whether to ignore the tenant filter. /// The cancellation token. - public async Task SaveAsync(T record, string primaryKey = "Id", CancellationToken cancellationToken = default) + /// A set of records. + public async Task> FindManyAsync(Action filter, string orderKey, OrderDirection orderDirection, bool tenantAgnostic = false, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = new ParameterizedQuery(_dbConnectionProvider.Dialect).Upsert(TableName, primaryKey, record); - await query.ExecuteAsync(connection); + using var connection = dbConnectionProvider.GetConnection(); + var query = dbConnectionProvider.CreateQuery().From(TableName); + await ApplyTenantFilterAsync(query, tenantAgnostic, cancellationToken); + filter(query); + query = query.OrderBy(orderKey, orderDirection); + return await query.QueryAsync(connection); } /// - /// Adds or updates the specified records. + /// Adds or updates the specified record. /// - /// The records. + /// The record. /// The cancellation token. - public Task SaveManyAsync(IEnumerable records, CancellationToken cancellationToken = default) + public async Task SaveAsync(T record, CancellationToken cancellationToken = default) { - return SaveManyAsync(records, PrimaryKey, cancellationToken); + using var connection = dbConnectionProvider.GetConnection(); + await SetTenantIdAsync(record, cancellationToken); + var query = new ParameterizedQuery(dbConnectionProvider.Dialect).Upsert(TableName, PrimaryKey, record); + await query.ExecuteAsync(connection); } - + /// /// Adds or updates the specified records. /// /// The records. - /// The primary key. /// The cancellation token. - public async Task SaveManyAsync(IEnumerable records, string primaryKey = "Id", CancellationToken cancellationToken = default) + public async Task SaveManyAsync(IEnumerable records, CancellationToken cancellationToken = default) { var recordsList = records.ToList(); if (!recordsList.Any()) return; - var query = new ParameterizedQuery(_dbConnectionProvider.Dialect); + var query = new ParameterizedQuery(dbConnectionProvider.Dialect); var currentIndex = 0; foreach (var record in recordsList) { var index = currentIndex; - query.Upsert(TableName, primaryKey, record, field => $"{field}_{index}"); + await SetTenantIdAsync(record, cancellationToken); + query.Upsert(TableName, PrimaryKey, record, field => $"{field}_{index}"); currentIndex++; } - using var connection = _dbConnectionProvider.GetConnection(); + using var connection = dbConnectionProvider.GetConnection(); await query.ExecuteAsync(connection); } @@ -253,8 +374,9 @@ public async Task SaveManyAsync(IEnumerable records, string primaryKey = "Id" /// The cancellation token. public async Task AddAsync(T record, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = new ParameterizedQuery(_dbConnectionProvider.Dialect).Insert(TableName, record); + using var connection = dbConnectionProvider.GetConnection(); + await SetTenantIdAsync(record, cancellationToken); + var query = new ParameterizedQuery(dbConnectionProvider.Dialect).Insert(TableName, record); await query.ExecuteAsync(connection); } @@ -270,7 +392,7 @@ public async Task AddManyAsync(IEnumerable records, CancellationToken cancell if (!recordsList.Any()) return; - var query = new ParameterizedQuery(_dbConnectionProvider.Dialect); + var query = new ParameterizedQuery(dbConnectionProvider.Dialect); var currentIndex = 0; foreach (var record in recordsList) @@ -280,7 +402,7 @@ public async Task AddManyAsync(IEnumerable records, CancellationToken cancell currentIndex++; } - using var connection = _dbConnectionProvider.GetConnection(); + using var connection = dbConnectionProvider.GetConnection(); await query.ExecuteAsync(connection); } @@ -291,8 +413,8 @@ public async Task AddManyAsync(IEnumerable records, CancellationToken cancell /// The cancellation token. public async Task UpdateAsync(T record, CancellationToken cancellationToken = default) { - using var connection = _dbConnectionProvider.GetConnection(); - var query = new ParameterizedQuery(_dbConnectionProvider.Dialect).Insert(TableName, record); + using var connection = dbConnectionProvider.GetConnection(); + var query = new ParameterizedQuery(dbConnectionProvider.Dialect).Insert(TableName, record); await query.ExecuteAsync(connection); } @@ -304,14 +426,16 @@ public async Task UpdateAsync(T record, CancellationToken cancellationToken = de /// The number of records deleted. public async Task DeleteAsync(Action filter, CancellationToken cancellationToken = default) { - var query = _dbConnectionProvider.CreateQuery().Delete(TableName); - filter(query); + var query = dbConnectionProvider.CreateQuery().Delete(TableName); // If there are no conditions, we don't want to delete all records. if (!query.Parameters.ParameterNames.Any()) return 0; - using var connection = _dbConnectionProvider.GetConnection(); + await ApplyTenantFilterAsync(query, false, cancellationToken); + filter(query); + + using var connection = dbConnectionProvider.GetConnection(); return await query.ExecuteAsync(connection); } @@ -326,17 +450,18 @@ public async Task DeleteAsync(Action filter, Cancellat /// The number of records deleted. public async Task DeleteAsync(Action filter, PageArgs pageArgs, IEnumerable orderFields, string primaryKey = "Id", CancellationToken cancellationToken = default) { - var selectQuery = _dbConnectionProvider.CreateQuery().From(TableName, primaryKey); - filter(selectQuery); + var selectQuery = dbConnectionProvider.CreateQuery().From(TableName, primaryKey); // If there are no conditions, we don't want to delete all records. if (!selectQuery.Parameters.ParameterNames.Any()) return 0; + await ApplyTenantFilterAsync(selectQuery, false, cancellationToken); + filter(selectQuery); selectQuery = selectQuery.OrderBy(orderFields.ToArray()).Page(pageArgs); - var deleteQuery = _dbConnectionProvider.CreateQuery().Delete(TableName, primaryKey, selectQuery); - using var connection = _dbConnectionProvider.GetConnection(); + var deleteQuery = dbConnectionProvider.CreateQuery().Delete(TableName, primaryKey, selectQuery); + using var connection = dbConnectionProvider.GetConnection(); return await deleteQuery.ExecuteAsync(connection); } @@ -348,9 +473,10 @@ public async Task DeleteAsync(Action filter, PageArgs /// true if any records match the specified query. public async Task AnyAsync(Action filter, CancellationToken cancellationToken = default) { - var query = _dbConnectionProvider.CreateQuery().From(TableName, PrimaryKey); + var query = dbConnectionProvider.CreateQuery().From(TableName, PrimaryKey); + await ApplyTenantFilterAsync(query, false, cancellationToken); filter(query); - using var connection = _dbConnectionProvider.GetConnection(); + using var connection = dbConnectionProvider.GetConnection(); return await connection.QueryFirstOrDefaultAsync(query.Sql.ToString(), query.Parameters) != null; } @@ -362,9 +488,30 @@ public async Task AnyAsync(Action filter, Cancellation /// The number of records matching the specified query. public async Task CountAsync(Action filter, CancellationToken cancellationToken = default) { - var countQuery = _dbConnectionProvider.CreateQuery().Count(TableName); + var countQuery = dbConnectionProvider.CreateQuery().Count(TableName); + await ApplyTenantFilterAsync(countQuery, false, cancellationToken); filter(countQuery); - using var connection = _dbConnectionProvider.GetConnection(); + using var connection = dbConnectionProvider.GetConnection(); return await countQuery.SingleAsync(connection); } + + private async Task ApplyTenantFilterAsync(ParameterizedQuery query, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + if (tenantAgnostic) + return; + + var tenant = await tenantResolver.GetTenantAsync(cancellationToken); + var tenantId = tenant?.Id; + query.Is(nameof(Record.TenantId), (object?)tenantId ?? DBNull.Value); + } + + private async Task SetTenantIdAsync(T record, CancellationToken cancellationToken) + { + if (record is not Record recordWithTenant) + return; + + var tenant = await tenantResolver.GetTenantAsync(cancellationToken); + var tenantId = tenant?.Id; + recordWithTenant.TenantId = tenantId; + } } \ No newline at end of file diff --git a/src/modules/Elsa.Elasticsearch/Modules/Management/WorkflowInstanceStore.cs b/src/modules/Elsa.Elasticsearch/Modules/Management/WorkflowInstanceStore.cs index aba971ccd8..20197b4a3a 100644 --- a/src/modules/Elsa.Elasticsearch/Modules/Management/WorkflowInstanceStore.cs +++ b/src/modules/Elsa.Elasticsearch/Modules/Management/WorkflowInstanceStore.cs @@ -4,7 +4,7 @@ using Elsa.Common.Models; using Elsa.Elasticsearch.Common; using Elsa.Extensions; -using Elsa.Workflows.Management.Contracts; +using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Models; @@ -77,7 +77,7 @@ public async ValueTask> SummarizeManyAsync public async ValueTask> FindManyIdsAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) { - var results = await _store.SearchAsync(d => SelectId( Filter(d, filter)), cancellationToken); + var results = await _store.SearchAsync(d => SelectId(Filter(d, filter)), cancellationToken); return results.Select(x => x.Id).ToList(); } @@ -172,8 +172,8 @@ private static QueryDescriptor Filter(QueryDescriptor c - .Query(filter.SearchTerm)); + .QueryString(c => c + .Query(filter.SearchTerm)); } private static SearchRequestDescriptor Summarize(SearchRequestDescriptor descriptor) => @@ -191,7 +191,7 @@ private static QueryDescriptor Filter(QueryDescriptor field.Field(f => f.DefinitionVersionId), field => field.Field(f => f.UpdatedAt) ); - + private static SearchRequestDescriptor SelectId(SearchRequestDescriptor descriptor) => descriptor.Fields(field => field.Field(f => f.Id)); } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Abstractions/DesignTimeDbContextFactoryBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/Abstractions/DesignTimeDbContextFactoryBase.cs index f1d2b11cb7..e5284bf079 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/Abstractions/DesignTimeDbContextFactoryBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Abstractions/DesignTimeDbContextFactoryBase.cs @@ -1,7 +1,8 @@ -using System.CommandLine; -using System.CommandLine.Parsing; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; +using System.CommandLine; +using System.CommandLine.Parsing; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.EntityFrameworkCore.Common.Abstractions; @@ -22,10 +23,11 @@ public TDbContext CreateDbContext(string[] args) var parser = new Parser(command); var parseResult = parser.Parse(args); var connectionString = parseResult.GetValueForOption(connectionStringOption) ?? "Data Source=local"; + var serviceProvider = new ServiceCollection().BuildServiceProvider(); ConfigureBuilder(builder, connectionString); - return (TDbContext)Activator.CreateInstance(typeof(TDbContext), builder.Options)!; + return (TDbContext)Activator.CreateInstance(typeof(TDbContext), builder.Options, serviceProvider); } /// diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs new file mode 100644 index 0000000000..ec69674820 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs @@ -0,0 +1,18 @@ +using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.EntityHandlers; +using Elsa.Features.Abstractions; +using Elsa.Features.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.EntityFrameworkCore.Common; + +/// +public class CommonPersistenceFeature(IModule module) : FeatureBase(module) +{ + /// + public override void Apply() + { + Services.AddScoped(); + Services.AddScoped(); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntityModelCreatingHandler.cs b/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntityModelCreatingHandler.cs new file mode 100644 index 0000000000..bc34bb19bb --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntityModelCreatingHandler.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Elsa.EntityFrameworkCore.Common.Contracts; + +/// +/// Represents handler for entity model creation. +/// +public interface IEntityModelCreatingHandler +{ + /// + /// Handles the entity model being created. + /// + void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType); +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntitySavingHandler.cs b/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntitySavingHandler.cs new file mode 100644 index 0000000000..082837fa7f --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Contracts/IEntitySavingHandler.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace Elsa.EntityFrameworkCore.Common.Contracts; + +/// +/// Represents handler for entities before saving changes. +/// +public interface IEntitySavingHandler +{ + /// + /// Handles the entity before saving changes. + /// + ValueTask HandleAsync(ElsaDbContextBase dbContext, EntityEntry entry, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj b/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj index f7beacf884..2531e74025 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj @@ -19,6 +19,7 @@ + diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs index da24d5a29b..81657d190d 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs @@ -1,7 +1,8 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; -using Elsa.EntityFrameworkCore.Extensions; +using Elsa.Common.Entities; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.EntityFrameworkCore.Common; @@ -10,6 +11,15 @@ namespace Elsa.EntityFrameworkCore.Common; /// public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema { + private static readonly ISet ModifiedEntityStates = new HashSet + { + EntityState.Added, + EntityState.Modified, + }; + + protected readonly IServiceProvider ServiceProvider; + public string? TenantId { get; set; } + /// /// The default schema used by Elsa. /// @@ -26,13 +36,21 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema /// /// Initializes a new instance of the class. /// - protected ElsaDbContextBase(DbContextOptions options) : base(options) + protected ElsaDbContextBase(DbContextOptions options, IServiceProvider serviceProvider) : base(options) { + ServiceProvider = serviceProvider; var elsaDbContextOptions = options.FindExtension()?.Options; // ReSharper disable once VirtualMemberCallInConstructor Schema = !string.IsNullOrWhiteSpace(elsaDbContextOptions?.SchemaName) ? elsaDbContextOptions.SchemaName : ElsaSchema; } + + /// + public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + await OnBeforeSavingAsync(cancellationToken); + return await base.SaveChangesAsync(cancellationToken); + } /// protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -42,52 +60,33 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) if (!Database.IsSqlite()) modelBuilder.HasDefaultSchema(Schema); } + + var entityTypeHandlers = ServiceProvider.GetServices().ToList(); - ApplyEntityConfigurations(modelBuilder); - - if (Database.IsSqlite()) SetupForSqlite(modelBuilder); - if (Database.IsOracle()) SetupForOracle(modelBuilder); - } - - /// - /// Override this method to apply entity configurations. - /// - protected virtual void ApplyEntityConfigurations(ModelBuilder modelBuilder) - { - } - - /// - /// Override this method to apply entity configurations. - /// - protected virtual void Configure(ModelBuilder modelBuilder) - { - } - - /// - /// Override this method to apply entity configurations for the SQLite provider. - /// - protected virtual void SetupForSqlite(ModelBuilder modelBuilder) - { - // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations - // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { - var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTimeOffset) || p.PropertyType == typeof(DateTimeOffset?)); - - foreach (var property in properties) + foreach (var handler in entityTypeHandlers) { - modelBuilder - .Entity(entityType.Name) - .Property(property.Name) - .HasConversion(new DateTimeOffsetToStringConverter()); + handler.Handle(this, modelBuilder, entityType); } } } + + private async Task OnBeforeSavingAsync(CancellationToken cancellationToken) + { + var handlers = ServiceProvider.GetServices().ToList(); + foreach (var entry in ChangeTracker.Entries().Where(IsModifiedEntity)) + { + foreach (var handler in handlers) + await handler.HandleAsync(this, entry, cancellationToken); + } + } /// - /// Override this method to apply entity configurations for the Oracle provider. + /// Determine if an entity was modified. /// - protected virtual void SetupForOracle(ModelBuilder modelBuilder) + private bool IsModifiedEntity(EntityEntry entityEntry) { + return ModifiedEntityStates.Contains(entityEntry.State) && entityEntry.Entity is Entity; } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextOptions.cs b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextOptions.cs index b67834f9c0..e69ff6c96f 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextOptions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextOptions.cs @@ -12,14 +12,14 @@ public class ElsaDbContextOptions /// The schema used by Elsa. /// public string? SchemaName { get; set; } - + /// /// The table used to store the migrations history. /// public string? MigrationsHistoryTableName { get; set; } - + /// /// The assembly name containing the migrations. /// public string? MigrationsAssemblyName { get; set; } -} +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/ApplyTenantId.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/ApplyTenantId.cs new file mode 100644 index 0000000000..e142d3480a --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/ApplyTenantId.cs @@ -0,0 +1,20 @@ +using Elsa.Common.Entities; +using Elsa.EntityFrameworkCore.Common.Contracts; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace Elsa.EntityFrameworkCore.Common.EntityHandlers; + +/// +/// Represents a handler for applying the tenant ID to an entity before saving changes. +/// +public class ApplyTenantId : IEntitySavingHandler +{ + /// + public ValueTask HandleAsync(ElsaDbContextBase dbContext, EntityEntry entry, CancellationToken cancellationToken = default) + { + if (entry.Entity is Entity entity) + entity.TenantId = dbContext.TenantId; + + return default; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs new file mode 100644 index 0000000000..821c1c9636 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs @@ -0,0 +1,28 @@ +using System.Linq.Expressions; +using Elsa.Common.Entities; +using Elsa.EntityFrameworkCore.Common.Contracts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query; + +namespace Elsa.EntityFrameworkCore.Common.EntityHandlers; + +/// +/// Represents a class that applies a filter to set the TenantId for entities. +/// +public class SetTenantIdFilter : IEntityModelCreatingHandler +{ + /// + public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) + { + if (!entityType.ClrType.IsAssignableTo(typeof(Entity))) + return; + + var parameter = Expression.Parameter(entityType.ClrType); + Expression> filterExpr = entity => dbContext.TenantId == entity.TenantId; + var body = ReplacingExpressionVisitor.Replace(filterExpr.Parameters[0], parameter, filterExpr.Body); + var lambdaExpression = Expression.Lambda(body, parameter); + + entityType.SetQueryFilter(lambdaExpression); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs new file mode 100644 index 0000000000..639fdb4e31 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs @@ -0,0 +1,31 @@ +using Elsa.EntityFrameworkCore.Common.Contracts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Elsa.EntityFrameworkCore.Common.EntityHandlers; + +/// +/// Represents a class that handles entity model creation for SQLite databases. +/// +public class SetupForSqlite : IEntityModelCreatingHandler +{ + /// + public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) + { + if(!dbContext.Database.IsSqlite()) + return; + + // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations + // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations + var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTimeOffset) || p.PropertyType == typeof(DateTimeOffset?)); + + foreach (var property in properties) + { + modelBuilder + .Entity(entityType.Name) + .Property(property.Name) + .HasConversion(new DateTimeOffsetToStringConverter()); + } + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs index d97a47a063..794c139dbe 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs @@ -1,5 +1,4 @@ using Elsa.Common.Entities; -using Microsoft.EntityFrameworkCore; namespace Elsa.EntityFrameworkCore.Common; @@ -8,10 +7,10 @@ namespace Elsa.EntityFrameworkCore.Common; /// /// The type of the database context. /// The type of the entity. -public class EntityStore : Store where TDbContext : DbContext where TEntity : Entity, new() +public class EntityStore : Store where TDbContext : ElsaDbContextBase where TEntity : Entity, new() { /// - public EntityStore(IDbContextFactory dbContextFactory) : base(dbContextFactory) + public EntityStore(IServiceProvider serviceProvider) : base(serviceProvider) { } diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Extensions/DatabaseFacadeExtensions.cs b/src/modules/Elsa.EntityFrameworkCore.Common/Extensions/DatabaseFacadeExtensions.cs index fa0ec76d99..f4fe914a0e 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/Extensions/DatabaseFacadeExtensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Extensions/DatabaseFacadeExtensions.cs @@ -3,9 +3,23 @@ // ReSharper disable once CheckNamespace namespace Elsa.EntityFrameworkCore.Extensions; -internal static class DatabaseFacadeExtensions +/// +/// Extension methods for the DatabaseFacade class. +/// +public static class DatabaseFacadeExtensions { + /// + /// Returns true if the database provider is MySql. + /// public static bool IsMySql(this DatabaseFacade database) => database.ProviderName == "Pomelo.EntityFrameworkCore.MySql"; + + /// + /// Returns true if the database provider is Oracle. + /// public static bool IsOracle(this DatabaseFacade database) => database.ProviderName == "Oracle.EntityFrameworkCore"; + + /// + /// Returns true if the database provider is Postgres. + /// public static bool IsPostgres(this DatabaseFacade database) => database.ProviderName == "Npgsql.EntityFrameworkCore.PostgreSQL"; } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs index 6ec73b7d61..dec7feb991 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs @@ -1,5 +1,6 @@ using Elsa.Common.Entities; using Elsa.Features.Abstractions; +using Elsa.Features.Attributes; using Elsa.Features.Services; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -10,7 +11,9 @@ namespace Elsa.EntityFrameworkCore.Common; /// Base class for features that require Entity Framework Core. /// /// The type of the database context. -public abstract class PersistenceFeatureBase : FeatureBase where TDbContext : DbContext +/// The type of the feature. +[DependsOn(typeof(CommonPersistenceFeature))] +public abstract class PersistenceFeatureBase : FeatureBase where TDbContext : ElsaDbContextBase { /// protected PersistenceFeatureBase(IModule module) : base(module) diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Store.cs b/src/modules/Elsa.EntityFrameworkCore.Common/Store.cs index 80953e45c2..23c8555181 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/Store.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Store.cs @@ -1,10 +1,13 @@ -using System.Linq.Expressions; using Elsa.Common.Entities; using Elsa.Common.Models; using Elsa.EntityFrameworkCore.Extensions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Open.Linq.AsyncExtensions; +using System.Linq.Expressions; +using Elsa.Common.Contracts; +using Elsa.Tenants; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.EntityFrameworkCore.Common; @@ -14,20 +17,20 @@ namespace Elsa.EntityFrameworkCore.Common; /// The type of the database context. /// The type of the entity. [PublicAPI] -public class Store where TDbContext : DbContext where TEntity : class, new() +public class Store where TDbContext : ElsaDbContextBase where TEntity : class, new() { + private readonly IServiceProvider _serviceProvider; + // ReSharper disable once StaticMemberInGenericType // Justification: This is a static member that is used to ensure that only one thread can access the database for TEntity at a time. private static readonly SemaphoreSlim Semaphore = new(1, 1); - private readonly IDbContextFactory _dbContextFactory; - /// /// Initializes a new instance of the class. /// - public Store(IDbContextFactory dbContextFactory) + public Store(IServiceProvider serviceProvider) { - _dbContextFactory = dbContextFactory; + _serviceProvider = serviceProvider; } /// @@ -35,7 +38,15 @@ public Store(IDbContextFactory dbContextFactory) /// /// The cancellation token. /// The database context. - public async Task CreateDbContextAsync(CancellationToken cancellationToken = default) => await _dbContextFactory.CreateDbContextAsync(cancellationToken); + public async Task CreateDbContextAsync(CancellationToken cancellationToken = default) + { + var dbContextFactory = _serviceProvider.GetRequiredService>(); + var tenantResolver = _serviceProvider.GetRequiredService(); + var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); + var tenant = await tenantResolver.GetTenantAsync(cancellationToken); + dbContext.TenantId = tenant?.Id; + return dbContext; + } /// /// Adds the specified entity. @@ -228,7 +239,20 @@ public async Task UpdateAsync(TEntity entity, FuncThe entity if found, otherwise null public async Task FindAsync(Func, IQueryable> query, Func? onLoading = default, CancellationToken cancellationToken = default) { - return await QueryAsync(query, onLoading, cancellationToken).FirstOrDefault(); + return await FindAsync(query, onLoading, false, cancellationToken); + } + + /// + /// Finds a single entity using a query + /// + /// The query to use + /// A callback to run after the entity is loaded + /// Define is the request should be tenant agnostic or not + /// The cancellation token + /// The entity if found, otherwise null + public async Task FindAsync(Func, IQueryable> query, Func? onLoading = default, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, onLoading, tenantAgnostic, cancellationToken).FirstOrDefault(); } /// @@ -239,7 +263,19 @@ public async Task UpdateAsync(TEntity entity, FuncThe entity if found, otherwise null public async Task FindAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) { - return await QueryAsync(query, cancellationToken).FirstOrDefault(); + return await FindAsync(query, false, cancellationToken); + } + + /// + /// Finds a single entity using a query + /// + /// The query to use + /// Define is the request should be tenant agnostic or not + /// The cancellation token + /// The entity if found, otherwise null + public async Task FindAsync(Func, IQueryable> query, bool tenantAgnostic = false, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, tenantAgnostic, cancellationToken).FirstOrDefault(); } /// @@ -341,18 +377,40 @@ public async Task DeleteWhereAsync(Func, IQueryable /// Queries the database using a query. /// - public async Task> QueryAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) => await QueryAsync(query, default, cancellationToken); + public async Task> QueryAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, default, false, cancellationToken); + } + + /// + /// Queries the database using a query. + /// + public async Task> QueryAsync(Func, IQueryable> query, bool tenantAgnostic, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, default, tenantAgnostic, cancellationToken); + } /// /// Queries the database using a query and a selector. /// public async Task> QueryAsync(Func, IQueryable> query, Func? onLoading = default, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, onLoading, false, cancellationToken); + } + + /// + /// Queries the database using a query and a selector. + /// + public async Task> QueryAsync(Func, IQueryable> query, Func? onLoading = default, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); var asNoTracking = onLoading == null; var set = asNoTracking ? dbContext.Set().AsNoTracking() : dbContext.Set(); var queryable = query(set.AsQueryable()); + if (ignoreQueryFilters) + queryable = queryable.IgnoreQueryFilters(); + var entities = await queryable.ToListAsync(cancellationToken); if (onLoading != null) @@ -368,11 +426,22 @@ public async Task> QueryAsync(Func, IQu /// Queries the database using a query and a selector. /// public async Task> QueryAsync(Func, IQueryable> query, Expression> selector, CancellationToken cancellationToken = default) + { + return await QueryAsync(query, selector, false, cancellationToken); + } + + /// + /// Queries the database using a query and a selector. + /// + public async Task> QueryAsync(Func, IQueryable> query, Expression> selector, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); var set = dbContext.Set().AsNoTracking(); var queryable = query(set.AsQueryable()); + if (ignoreQueryFilters) + queryable = queryable.IgnoreQueryFilters(); + queryable = query(queryable); return await queryable.Select(selector).ToListAsync(cancellationToken); } @@ -381,11 +450,22 @@ public async Task> QueryAsync(Func public async Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) + { + return await CountAsync(query, false, cancellationToken); + } + + /// + /// Counts the number of entities matching a query. + /// + public async Task CountAsync(Func, IQueryable> query, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); var set = dbContext.Set().AsNoTracking(); var queryable = query(set.AsQueryable()); + if (ignoreQueryFilters) + queryable = queryable.IgnoreQueryFilters(); + queryable = query(queryable); return await queryable.LongCountAsync(cancellationToken: cancellationToken); } @@ -394,6 +474,14 @@ public async Task CountAsync(Func, IQueryable /// Checks if any entities exist. /// public async Task AnyAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + return await AnyAsync(predicate, false, cancellationToken); + } + + /// + /// Checks if any entities exist. + /// + public async Task AnyAsync(Expression> predicate, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); var set = dbContext.Set().AsNoTracking(); @@ -406,10 +494,25 @@ public async Task AnyAsync(Expression> predicate, Canc /// The predicate. /// The cancellation token. public async Task CountAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + return await CountAsync(predicate, false, cancellationToken); + } + + /// + /// Counts the number of entities matching a predicate. + /// + /// The predicate. + /// Whether to ignore query filters. + /// The cancellation token. + public async Task CountAsync(Expression> predicate, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); - var set = dbContext.Set().AsNoTracking(); - return await set.CountAsync(predicate, cancellationToken); + var queryable = dbContext.Set().AsNoTracking(); + + if (ignoreQueryFilters) + queryable = queryable.IgnoreQueryFilters(); + + return await queryable.CountAsync(predicate, cancellationToken); } /// @@ -419,10 +522,26 @@ public async Task CountAsync(Expression> predicate, Ca /// The property selector to distinct by. /// The cancellation token. public async Task CountAsync(Expression> predicate, Expression> propertySelector, CancellationToken cancellationToken = default) + { + return await CountAsync(predicate, propertySelector, false, cancellationToken); + } + + /// + /// Counts the distinct number of entities matching a predicate. + /// + /// The predicate. + /// The property selector to distinct by. + /// Whether to ignore query filters. + /// The cancellation token. + public async Task CountAsync(Expression> predicate, Expression> propertySelector, bool ignoreQueryFilters = false, CancellationToken cancellationToken = default) { await using var dbContext = await CreateDbContextAsync(cancellationToken); - var set = dbContext.Set().AsNoTracking(); - return await set + var queryable = dbContext.Set().AsNoTracking(); + + if (ignoreQueryFilters) + queryable = queryable.IgnoreQueryFilters(); + + return await queryable .Where(predicate) .Select(propertySelector) .Distinct() diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240525185519_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610184517_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240525185519_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610184517_V3_2.Designer.cs index 309f70501c..ed6e592156 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240525185519_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610184517_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Alterations { [DbContext(typeof(AlterationsElsaDbContext))] - [Migration("20240525185519_V3_2")] + [Migration("20240610184517_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240525185519_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610184517_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240525185519_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610184517_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.Designer.cs new file mode 100644 index 0000000000..b4f80f0fb3 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.Designer.cs @@ -0,0 +1,133 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Alterations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Alterations +{ + [DbContext(typeof(AlterationsElsaDbContext))] + [Migration("20240610190336_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("CompletedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlanId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("SerializedLog") + .HasColumnType("longtext"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationJob_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationJob_CreatedAt"); + + b.HasIndex("PlanId") + .HasDatabaseName("IX_AlterationJob_PlanId"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationJob_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationJob_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); + + b.ToTable("AlterationJobs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationPlan", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("CompletedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("SerializedAlterations") + .HasColumnType("longtext"); + + b.Property("SerializedWorkflowInstanceFilter") + .HasColumnType("longtext"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationPlan_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationPlan_CreatedAt"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationPlan_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationPlan_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + + b.ToTable("AlterationPlans", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.cs new file mode 100644 index 0000000000..d9eb12f911 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/20240610190336_V3_3.cs @@ -0,0 +1,74 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Alterations +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs index 7a1346ce58..841118fd09 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => @@ -45,6 +45,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("varchar(255)"); @@ -66,6 +69,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationJob_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); @@ -96,6 +102,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.HasKey("Id"); b.HasIndex("CompletedAt") @@ -110,6 +119,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationPlan_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + b.ToTable("AlterationPlans", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20231015122238_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20231015122238_Initial.cs index b49ca9108f..6af677656a 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20231015122238_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20231015122238_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240525185727_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610184903_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240525185727_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610184903_V3_2.Designer.cs index 6ae4a5550d..e25e181018 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240525185727_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610184903_V3_2.Designer.cs @@ -10,7 +10,7 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Identity { [DbContext(typeof(IdentityElsaDbContext))] - [Migration("20240525185727_V3_2")] + [Migration("20240610184903_V3_2")] partial class V3_2 { /// @@ -19,7 +19,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Identity.Entities.Application", b => diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240525185727_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610184903_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240525185727_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610184903_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.Designer.cs new file mode 100644 index 0000000000..f3972749ed --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.Designer.cs @@ -0,0 +1,146 @@ +// +using Elsa.EntityFrameworkCore.Modules.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Identity +{ + [DbContext(typeof(IdentityElsaDbContext))] + [Migration("20240610190454_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Elsa.Identity.Entities.Application", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("HashedApiKey") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HashedApiKeySalt") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HashedClientSecret") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HashedClientSecretSalt") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("IX_Application_ClientId"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Application_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + + b.ToTable("Applications", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.Role", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("Permissions"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Role_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + + b.ToTable("Roles", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.User", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("HashedPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HashedPasswordSalt") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_User_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + + b.ToTable("Users", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.cs new file mode 100644 index 0000000000..83ba924dec --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/20240610190454_V3_3.cs @@ -0,0 +1,98 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Identity +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs index e247172df8..ce297cd993 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs @@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Identity.Entities.Application", b => @@ -53,6 +53,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("longtext") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.HasKey("Id"); b.HasIndex("ClientId") @@ -63,6 +66,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasDatabaseName("IX_Application_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + b.ToTable("Applications", "Elsa"); }); @@ -80,12 +86,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("longtext") .HasColumnName("Permissions"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_Role_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + b.ToTable("Roles", "Elsa"); }); @@ -111,12 +123,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("longtext") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_User_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + b.ToTable("Users", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20231015122253_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20231015122253_Initial.cs index f0f037d5dc..2677c8bd67 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20231015122253_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20231015122253_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240525185754_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610184957_V3_2.Designer.cs similarity index 96% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240525185754_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610184957_V3_2.Designer.cs index 73d1c2d176..cdd9a69484 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240525185754_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610184957_V3_2.Designer.cs @@ -10,7 +10,7 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Labels { [DbContext(typeof(LabelsElsaDbContext))] - [Migration("20240525185754_V3_2")] + [Migration("20240610184957_V3_2")] partial class V3_2 { /// @@ -19,7 +19,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Labels.Entities.Label", b => diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240525185754_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610184957_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240525185754_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610184957_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.Designer.cs new file mode 100644 index 0000000000..38ba298df7 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.Designer.cs @@ -0,0 +1,91 @@ +// +using Elsa.EntityFrameworkCore.Modules.Labels; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Labels +{ + [DbContext(typeof(LabelsElsaDbContext))] + [Migration("20240610190535_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Elsa.Labels.Entities.Label", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("Color") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Labels", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Labels.Entities.WorkflowDefinitionLabel", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("LabelId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("LabelId") + .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionVersionId"); + + b.ToTable("WorkflowDefinitionLabels", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.cs new file mode 100644 index 0000000000..ca38c07dd8 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/20240610190535_V3_3.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Labels +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs index 2ace32719d..2d13796d5d 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs @@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Labels.Entities.Label", b => @@ -38,6 +38,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("longtext"); + b.HasKey("Id"); b.ToTable("Labels", "Elsa"); @@ -52,6 +55,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("varchar(255)"); @@ -65,6 +71,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("LabelId") .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240525185700_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610184802_V3_2.Designer.cs similarity index 98% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240525185700_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610184802_V3_2.Designer.cs index 9c12066b51..164db5fe22 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240525185700_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610184802_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management { [DbContext(typeof(ManagementElsaDbContext))] - [Migration("20240525185700_V3_2")] + [Migration("20240610184802_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240525185700_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610184802_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240525185700_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610184802_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.Designer.cs new file mode 100644 index 0000000000..13fcccb782 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.Designer.cs @@ -0,0 +1,223 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Management; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management +{ + [DbContext(typeof(ManagementElsaDbContext))] + [Migration("20240610190425_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("BinaryData") + .HasColumnType("longblob"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsLatest") + .HasColumnType("tinyint(1)"); + + b.Property("IsPublished") + .HasColumnType("tinyint(1)"); + + b.Property("IsReadonly") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("MaterializerContext") + .HasColumnType("longtext"); + + b.Property("MaterializerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("ProviderName") + .HasColumnType("longtext"); + + b.Property("StringData") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.Property("ToolVersion") + .HasColumnType("longtext"); + + b.Property("UsableAsActivity") + .HasColumnType("tinyint(1)"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IsLatest") + .HasDatabaseName("IX_WorkflowDefinition_IsLatest"); + + b.HasIndex("IsPublished") + .HasDatabaseName("IX_WorkflowDefinition_IsPublished"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowDefinition_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowDefinition_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + + b.HasIndex("UsableAsActivity") + .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); + + b.HasIndex("Version") + .HasDatabaseName("IX_WorkflowDefinition_Version"); + + b.HasIndex("DefinitionId", "Version") + .IsUnique() + .HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version"); + + b.ToTable("WorkflowDefinitions", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("CorrelationId") + .HasColumnType("varchar(255)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DataCompressionAlgorithm") + .HasColumnType("longtext"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("DefinitionVersionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FinishedAt") + .HasColumnType("datetime(6)"); + + b.Property("IncidentCount") + .HasColumnType("int"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("ParentWorkflowInstanceId") + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("SubStatus") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId") + .HasDatabaseName("IX_WorkflowInstance_CorrelationId"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_WorkflowInstance_CreatedAt"); + + b.HasIndex("DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_DefinitionId"); + + b.HasIndex("FinishedAt") + .HasDatabaseName("IX_WorkflowInstance_FinishedAt"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowInstance_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowInstance_Name"); + + b.HasIndex("Status") + .HasDatabaseName("IX_WorkflowInstance_Status"); + + b.HasIndex("SubStatus") + .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + + b.HasIndex("UpdatedAt") + .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); + + b.HasIndex("Status", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId"); + + b.HasIndex("Status", "SubStatus") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus"); + + b.HasIndex("SubStatus", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId"); + + b.HasIndex("Status", "SubStatus", "DefinitionId", "Version") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version"); + + b.ToTable("WorkflowInstances", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.cs new file mode 100644 index 0000000000..25e6d6278d --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/20240610190425_V3_3.cs @@ -0,0 +1,74 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs index 6843a8afb7..d22a62d550 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => @@ -69,6 +69,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StringData") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("ToolVersion") .HasColumnType("longtext"); @@ -92,6 +95,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_WorkflowDefinition_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + b.HasIndex("UsableAsActivity") .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); @@ -153,6 +159,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("UpdatedAt") .HasColumnType("datetime(6)"); @@ -185,6 +194,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubStatus") .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + b.HasIndex("UpdatedAt") .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.cs deleted file mode 100644 index 50a7bd72fe..0000000000 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime -{ - /// - public partial class V3_2 : Migration - { - private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; - - /// - public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) - { - _schema = schema; - } - - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema, - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ActivityInstanceId = table.Column(type: "varchar(255)", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ActivityTypeName = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - CorrelationId = table.Column(type: "varchar(255)", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - CreatedAt = table.Column(type: "datetime(6)", nullable: false), - ExpiresAt = table.Column(type: "datetime(6)", nullable: false), - Hash = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SerializedBookmarkPayload = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SerializedInput = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - WorkflowInstanceId = table.Column(type: "varchar(255)", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityInstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityTypeName", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityTypeName"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CorrelationId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CorrelationId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CreatedAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ExpiresAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ExpiresAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_Hash", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "Hash"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_WorkflowInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "WorkflowInstanceId"); - } - } -} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.Designer.cs new file mode 100644 index 0000000000..112124942e --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.Designer.cs @@ -0,0 +1,405 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime +{ + [DbContext(typeof(RuntimeElsaDbContext))] + [Migration("20240610184652_V3_2")] + partial class V3_2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => + { + b.Property("Key") + .HasColumnType("varchar(255)"); + + b.Property("SerializedValue") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("KeyValuePairs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityName") + .HasColumnType("varchar(255)"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityTypeVersion") + .HasColumnType("int"); + + b.Property("CompletedAt") + .HasColumnType("datetime(6)"); + + b.Property("HasBookmarks") + .HasColumnType("tinyint(1)"); + + b.Property("SerializedActivityState") + .HasColumnType("longtext"); + + b.Property("SerializedActivityStateCompressionAlgorithm") + .HasColumnType("longtext"); + + b.Property("SerializedException") + .HasColumnType("longtext"); + + b.Property("SerializedOutputs") + .HasColumnType("longtext"); + + b.Property("SerializedPayload") + .HasColumnType("longtext"); + + b.Property("SerializedProperties") + .HasColumnType("longtext"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt"); + + b.HasIndex("HasBookmarks") + .HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion"); + + b.ToTable("ActivityExecutionRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => + { + b.Property("BookmarkId") + .HasColumnType("varchar(255)"); + + b.Property("ActivityInstanceId") + .HasColumnType("varchar(255)"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("CorrelationId") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("SerializedMetadata") + .HasColumnType("longtext"); + + b.Property("SerializedPayload") + .HasColumnType("longtext"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("BookmarkId"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt"); + + b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); + + b.ToTable("Bookmarks", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Hash") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("SerializedPayload") + .HasColumnType("longtext"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Hash") + .HasDatabaseName("IX_StoredTrigger_Hash"); + + b.HasIndex("Name") + .HasDatabaseName("IX_StoredTrigger_Name"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId"); + + b.ToTable("Triggers", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityInstanceId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityName") + .HasColumnType("varchar(255)"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ActivityTypeVersion") + .HasColumnType("int"); + + b.Property("EventName") + .HasColumnType("varchar(255)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("ParentActivityInstanceId") + .HasColumnType("varchar(255)"); + + b.Property("Sequence") + .HasColumnType("bigint"); + + b.Property("SerializedActivityState") + .HasColumnType("longtext"); + + b.Property("SerializedPayload") + .HasColumnType("longtext"); + + b.Property("Source") + .HasColumnType("longtext"); + + b.Property("Timestamp") + .HasColumnType("datetime(6)"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkflowVersion") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId"); + + b.HasIndex("ActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion"); + + b.HasIndex("EventName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName"); + + b.HasIndex("ParentActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId"); + + b.HasIndex("Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + + b.HasIndex("Timestamp") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId"); + + b.HasIndex("WorkflowVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion"); + + b.HasIndex("Timestamp", "Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence"); + + b.ToTable("WorkflowExecutionLogRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ActivityInstanceId") + .HasColumnType("varchar(255)"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("CorrelationId") + .HasColumnType("varchar(255)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("SerializedBookmarkPayload") + .HasColumnType("longtext"); + + b.Property("SerializedInput") + .HasColumnType("longtext"); + + b.Property("WorkflowInstanceId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName"); + + b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt"); + + b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt"); + + b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId"); + + b.ToTable("WorkflowInboxMessages", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.cs new file mode 100644 index 0000000000..c841275351 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610184652_V3_2.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime +{ + /// + public partial class V3_2 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.Designer.cs similarity index 90% rename from src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.Designer.cs index ec34e58e03..cc0dd15d29 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240525185623_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.Designer.cs @@ -11,8 +11,8 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime { [DbContext(typeof(RuntimeElsaDbContext))] - [Migration("20240525185623_V3_2")] - partial class V3_2 + [Migration("20240610190402_V3_3")] + partial class V3_3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -20,19 +20,24 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("varchar(255)"); b.Property("SerializedValue") .IsRequired() .HasColumnType("longtext"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -91,6 +96,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("varchar(255)"); @@ -124,6 +132,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -135,7 +146,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("varchar(255)"); b.Property("ActivityInstanceId") @@ -161,11 +172,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("varchar(255)"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -179,6 +193,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -203,6 +219,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("varchar(255)"); @@ -219,6 +238,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -276,6 +298,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("Timestamp") .HasColumnType("datetime(6)"); @@ -323,6 +348,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.cs new file mode 100644 index 0000000000..98159a97dc --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/20240610190402_V3_3.cs @@ -0,0 +1,247 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema); + + migrationBuilder.RenameColumn( + name: "Key", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "BookmarkId", + schema: _schema.Schema, + table: "Bookmarks", + newName: "Id"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + type: "varchar(255)", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Key"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "Bookmarks", + newName: "BookmarkId"); + + migrationBuilder.CreateTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema, + columns: table => new + { + Id = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ActivityInstanceId = table.Column(type: "varchar(255)", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ActivityTypeName = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CorrelationId = table.Column(type: "varchar(255)", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + ExpiresAt = table.Column(type: "datetime(6)", nullable: false), + Hash = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + SerializedBookmarkPayload = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SerializedInput = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + WorkflowInstanceId = table.Column(type: "varchar(255)", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityInstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityTypeName", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityTypeName"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CorrelationId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CorrelationId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CreatedAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CreatedAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ExpiresAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ExpiresAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_Hash", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "Hash"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_WorkflowInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "WorkflowInstanceId"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs index 2d42b270cc..31561dbe4f 100644 --- a/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.MySql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs @@ -17,19 +17,24 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("varchar(255)"); b.Property("SerializedValue") .IsRequired() .HasColumnType("longtext"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -88,6 +93,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("varchar(255)"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("varchar(255)"); @@ -121,6 +129,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -132,7 +143,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("varchar(255)"); b.Property("ActivityInstanceId") @@ -158,11 +169,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("varchar(255)"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -176,6 +190,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -200,6 +216,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("varchar(255)"); @@ -216,6 +235,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -273,6 +295,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("longtext"); + b.Property("TenantId") + .HasColumnType("varchar(255)"); + b.Property("Timestamp") .HasColumnType("datetime(6)"); @@ -320,6 +345,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240525185612_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610184626_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240525185612_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610184626_V3_2.Designer.cs index 20a0cb1929..19292f0429 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240525185612_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610184626_V3_2.Designer.cs @@ -12,7 +12,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Alterations { [DbContext(typeof(AlterationsElsaDbContext))] - [Migration("20240525185612_V3_2")] + [Migration("20240610184626_V3_2")] partial class V3_2 { /// @@ -21,7 +21,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240525185612_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610184626_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240525185612_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610184626_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.Designer.cs new file mode 100644 index 0000000000..bcdb6b2a73 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.Designer.cs @@ -0,0 +1,136 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Alterations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Alterations +{ + [DbContext(typeof(AlterationsElsaDbContext))] + [Migration("20240610190356_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PlanId") + .IsRequired() + .HasColumnType("text"); + + b.Property("SerializedLog") + .HasColumnType("text"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationJob_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationJob_CreatedAt"); + + b.HasIndex("PlanId") + .HasDatabaseName("IX_AlterationJob_PlanId"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationJob_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationJob_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); + + b.ToTable("AlterationJobs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationPlan", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("SerializedAlterations") + .HasColumnType("text"); + + b.Property("SerializedWorkflowInstanceFilter") + .HasColumnType("text"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationPlan_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationPlan_CreatedAt"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationPlan_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationPlan_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + + b.ToTable("AlterationPlans", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.cs new file mode 100644 index 0000000000..cacd59115c --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/20240610190356_V3_3.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Alterations +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs index 0df80dcb59..de2c4b5a9b 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -48,6 +48,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("text"); @@ -69,6 +72,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationJob_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); @@ -99,6 +105,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("CompletedAt") @@ -113,6 +122,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationPlan_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + b.ToTable("AlterationPlans", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20231015122250_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20231015122250_Initial.cs index 7abc872aab..d24ec33463 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20231015122250_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20231015122250_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -7,7 +7,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Identity { /// public partial class Initial : Migration - { + { private readonly IElsaDbContextSchema _schema; public Initial(IElsaDbContextSchema schema) { diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240525185746_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610184941_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240525185746_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610184941_V3_2.Designer.cs index 5008099276..1b341e0844 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240525185746_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610184941_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Identity { [DbContext(typeof(IdentityElsaDbContext))] - [Migration("20240525185746_V3_2")] + [Migration("20240610184941_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240525185746_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610184941_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240525185746_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610184941_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.Designer.cs new file mode 100644 index 0000000000..cdfc0dc048 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.Designer.cs @@ -0,0 +1,149 @@ +// +using Elsa.EntityFrameworkCore.Modules.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Identity +{ + [DbContext(typeof(IdentityElsaDbContext))] + [Migration("20240610190526_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Identity.Entities.Application", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("HashedApiKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("HashedApiKeySalt") + .IsRequired() + .HasColumnType("text"); + + b.Property("HashedClientSecret") + .IsRequired() + .HasColumnType("text"); + + b.Property("HashedClientSecretSalt") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("IX_Application_ClientId"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Application_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + + b.ToTable("Applications", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.Role", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Permissions"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Role_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + + b.ToTable("Roles", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.User", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("HashedPassword") + .IsRequired() + .HasColumnType("text"); + + b.Property("HashedPasswordSalt") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_User_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + + b.ToTable("Users", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.cs new file mode 100644 index 0000000000..bb59138beb --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/20240610190526_V3_3.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Identity +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs index 957f158c53..962ab1ec4d 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -56,6 +56,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("ClientId") @@ -66,6 +69,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasDatabaseName("IX_Application_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + b.ToTable("Applications", "Elsa"); }); @@ -83,12 +89,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("Permissions"); + b.Property("TenantId") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_Role_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + b.ToTable("Roles", "Elsa"); }); @@ -114,12 +126,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_User_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + b.ToTable("Users", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20231015122304_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20231015122304_Initial.cs index 9dffb53933..3f70be6c78 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20231015122304_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20231015122304_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -7,7 +7,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Labels { /// public partial class Initial : Migration - { + { private readonly IElsaDbContextSchema _schema; public Initial(IElsaDbContextSchema schema) { diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240525185812_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610185037_V3_2.Designer.cs similarity index 96% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240525185812_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610185037_V3_2.Designer.cs index 5250296229..280ac5e3f9 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240525185812_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610185037_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Labels { [DbContext(typeof(LabelsElsaDbContext))] - [Migration("20240525185812_V3_2")] + [Migration("20240610185037_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240525185812_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610185037_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240525185812_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610185037_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.Designer.cs new file mode 100644 index 0000000000..862bb97135 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.Designer.cs @@ -0,0 +1,94 @@ +// +using Elsa.EntityFrameworkCore.Modules.Labels; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Labels +{ + [DbContext(typeof(LabelsElsaDbContext))] + [Migration("20240610190559_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Labels.Entities.Label", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Color") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Labels", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Labels.Entities.WorkflowDefinitionLabel", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("LabelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LabelId") + .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionVersionId"); + + b.ToTable("WorkflowDefinitionLabels", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.cs new file mode 100644 index 0000000000..68a642b5c5 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/20240610190559_V3_3.cs @@ -0,0 +1,61 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Labels +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs index be95920bce..bb51ff5c1e 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -41,6 +41,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.HasKey("Id"); b.ToTable("Labels", "Elsa"); @@ -55,6 +58,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("text"); @@ -68,6 +74,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("LabelId") .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240525185721_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610184839_V3_2.Designer.cs similarity index 98% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240525185721_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610184839_V3_2.Designer.cs index 12409f6d0a..8484325d55 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240525185721_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610184839_V3_2.Designer.cs @@ -12,7 +12,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management { [DbContext(typeof(ManagementElsaDbContext))] - [Migration("20240525185721_V3_2")] + [Migration("20240610184839_V3_2")] partial class V3_2 { /// @@ -21,7 +21,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240525185721_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610184839_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240525185721_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610184839_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.Designer.cs new file mode 100644 index 0000000000..481df325ac --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.Designer.cs @@ -0,0 +1,226 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Management; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management +{ + [DbContext(typeof(ManagementElsaDbContext))] + [Migration("20240610190446_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("BinaryData") + .HasColumnType("bytea"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsLatest") + .HasColumnType("boolean"); + + b.Property("IsPublished") + .HasColumnType("boolean"); + + b.Property("IsReadonly") + .HasColumnType("boolean"); + + b.Property("IsSystem") + .HasColumnType("boolean"); + + b.Property("MaterializerContext") + .HasColumnType("text"); + + b.Property("MaterializerName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ProviderName") + .HasColumnType("text"); + + b.Property("StringData") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.Property("ToolVersion") + .HasColumnType("text"); + + b.Property("UsableAsActivity") + .HasColumnType("boolean"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IsLatest") + .HasDatabaseName("IX_WorkflowDefinition_IsLatest"); + + b.HasIndex("IsPublished") + .HasDatabaseName("IX_WorkflowDefinition_IsPublished"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowDefinition_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowDefinition_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + + b.HasIndex("UsableAsActivity") + .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); + + b.HasIndex("Version") + .HasDatabaseName("IX_WorkflowDefinition_Version"); + + b.HasIndex("DefinitionId", "Version") + .IsUnique() + .HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version"); + + b.ToTable("WorkflowDefinitions", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DataCompressionAlgorithm") + .HasColumnType("text"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionVersionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("FinishedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IncidentCount") + .HasColumnType("integer"); + + b.Property("IsSystem") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ParentWorkflowInstanceId") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId") + .HasDatabaseName("IX_WorkflowInstance_CorrelationId"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_WorkflowInstance_CreatedAt"); + + b.HasIndex("DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_DefinitionId"); + + b.HasIndex("FinishedAt") + .HasDatabaseName("IX_WorkflowInstance_FinishedAt"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowInstance_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowInstance_Name"); + + b.HasIndex("Status") + .HasDatabaseName("IX_WorkflowInstance_Status"); + + b.HasIndex("SubStatus") + .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + + b.HasIndex("UpdatedAt") + .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); + + b.HasIndex("Status", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId"); + + b.HasIndex("Status", "SubStatus") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus"); + + b.HasIndex("SubStatus", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId"); + + b.HasIndex("Status", "SubStatus", "DefinitionId", "Version") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version"); + + b.ToTable("WorkflowInstances", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.cs new file mode 100644 index 0000000000..ca2832f293 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/20240610190446_V3_3.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs index 2e2dbda37f..482d94b147 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -72,6 +72,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StringData") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("ToolVersion") .HasColumnType("text"); @@ -95,6 +98,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_WorkflowDefinition_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + b.HasIndex("UsableAsActivity") .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); @@ -156,6 +162,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); @@ -188,6 +197,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubStatus") .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + b.HasIndex("UpdatedAt") .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.cs deleted file mode 100644 index 8596885ae7..0000000000 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime -{ - /// - public partial class V3_2 : Migration - { - private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; - - /// - public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) - { - _schema = schema; - } - - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema, - columns: table => new - { - Id = table.Column(type: "text", nullable: false), - ActivityInstanceId = table.Column(type: "text", nullable: true), - ActivityTypeName = table.Column(type: "text", nullable: false), - CorrelationId = table.Column(type: "text", nullable: true), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - ExpiresAt = table.Column(type: "timestamp with time zone", nullable: false), - Hash = table.Column(type: "text", nullable: false), - SerializedBookmarkPayload = table.Column(type: "text", nullable: true), - SerializedInput = table.Column(type: "text", nullable: true), - WorkflowInstanceId = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityInstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityTypeName", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityTypeName"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CorrelationId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CorrelationId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CreatedAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ExpiresAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ExpiresAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_Hash", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "Hash"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_WorkflowInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "WorkflowInstanceId"); - } - } -} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.Designer.cs new file mode 100644 index 0000000000..c9cd11aba7 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.Designer.cs @@ -0,0 +1,408 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime +{ + [DbContext(typeof(RuntimeElsaDbContext))] + [Migration("20240610184748_V3_2")] + partial class V3_2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => + { + b.Property("Key") + .HasColumnType("text"); + + b.Property("SerializedValue") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("KeyValuePairs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityName") + .HasColumnType("text"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityTypeVersion") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HasBookmarks") + .HasColumnType("boolean"); + + b.Property("SerializedActivityState") + .HasColumnType("text"); + + b.Property("SerializedActivityStateCompressionAlgorithm") + .HasColumnType("text"); + + b.Property("SerializedException") + .HasColumnType("text"); + + b.Property("SerializedOutputs") + .HasColumnType("text"); + + b.Property("SerializedPayload") + .HasColumnType("text"); + + b.Property("SerializedProperties") + .HasColumnType("text"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt"); + + b.HasIndex("HasBookmarks") + .HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion"); + + b.ToTable("ActivityExecutionRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => + { + b.Property("BookmarkId") + .HasColumnType("text"); + + b.Property("ActivityInstanceId") + .HasColumnType("text"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("text"); + + b.Property("SerializedMetadata") + .HasColumnType("text"); + + b.Property("SerializedPayload") + .HasColumnType("text"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("BookmarkId"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt"); + + b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); + + b.ToTable("Bookmarks", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hash") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SerializedPayload") + .HasColumnType("text"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Hash") + .HasDatabaseName("IX_StoredTrigger_Hash"); + + b.HasIndex("Name") + .HasDatabaseName("IX_StoredTrigger_Name"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId"); + + b.ToTable("Triggers", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityInstanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityName") + .HasColumnType("text"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityTypeVersion") + .HasColumnType("integer"); + + b.Property("EventName") + .HasColumnType("text"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("ParentActivityInstanceId") + .HasColumnType("text"); + + b.Property("Sequence") + .HasColumnType("bigint"); + + b.Property("SerializedActivityState") + .HasColumnType("text"); + + b.Property("SerializedPayload") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkflowVersion") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId"); + + b.HasIndex("ActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion"); + + b.HasIndex("EventName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName"); + + b.HasIndex("ParentActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId"); + + b.HasIndex("Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + + b.HasIndex("Timestamp") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId"); + + b.HasIndex("WorkflowVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion"); + + b.HasIndex("Timestamp", "Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence"); + + b.ToTable("WorkflowExecutionLogRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ActivityInstanceId") + .HasColumnType("text"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("text"); + + b.Property("SerializedBookmarkPayload") + .HasColumnType("text"); + + b.Property("SerializedInput") + .HasColumnType("text"); + + b.Property("WorkflowInstanceId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName"); + + b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt"); + + b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt"); + + b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId"); + + b.ToTable("WorkflowInboxMessages", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.cs new file mode 100644 index 0000000000..7d4b3c4dbb --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610184748_V3_2.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime +{ + /// + public partial class V3_2 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.Designer.cs similarity index 91% rename from src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.Designer.cs index 2a067311be..feb8938425 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240525185652_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.Designer.cs @@ -12,8 +12,8 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime { [DbContext(typeof(RuntimeElsaDbContext))] - [Migration("20240525185652_V3_2")] - partial class V3_2 + [Migration("20240610190419_V3_3")] + partial class V3_3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -21,21 +21,26 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("text"); b.Property("SerializedValue") .IsRequired() .HasColumnType("text"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -94,6 +99,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("text"); @@ -127,6 +135,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -138,7 +149,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("text"); b.Property("ActivityInstanceId") @@ -164,11 +175,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("text"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -182,6 +196,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -206,6 +222,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("text"); @@ -222,6 +241,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -279,6 +301,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("Timestamp") .HasColumnType("timestamp with time zone"); @@ -326,6 +351,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.cs new file mode 100644 index 0000000000..943f014bce --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/20240610190419_V3_3.cs @@ -0,0 +1,233 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema); + + migrationBuilder.RenameColumn( + name: "Key", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "BookmarkId", + schema: _schema.Schema, + table: "Bookmarks", + newName: "Id"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Key"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "Bookmarks", + newName: "BookmarkId"); + + migrationBuilder.CreateTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema, + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + ActivityInstanceId = table.Column(type: "text", nullable: true), + ActivityTypeName = table.Column(type: "text", nullable: false), + CorrelationId = table.Column(type: "text", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ExpiresAt = table.Column(type: "timestamp with time zone", nullable: false), + Hash = table.Column(type: "text", nullable: false), + SerializedBookmarkPayload = table.Column(type: "text", nullable: true), + SerializedInput = table.Column(type: "text", nullable: true), + WorkflowInstanceId = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityInstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityTypeName", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityTypeName"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CorrelationId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CorrelationId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CreatedAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CreatedAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ExpiresAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ExpiresAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_Hash", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "Hash"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_WorkflowInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "WorkflowInstanceId"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs index 1d22232efd..397b42256f 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs @@ -18,21 +18,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("text"); b.Property("SerializedValue") .IsRequired() .HasColumnType("text"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -91,6 +96,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("text"); @@ -124,6 +132,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -135,7 +146,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("text"); b.Property("ActivityInstanceId") @@ -161,11 +172,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("text"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -179,6 +193,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -203,6 +219,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("text"); @@ -219,6 +238,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -276,6 +298,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("text"); + b.Property("Timestamp") .HasColumnType("timestamp with time zone"); @@ -323,6 +348,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240525185545_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610184545_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240525185545_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610184545_V3_2.Designer.cs index 2472ee5811..bc6ee01d2f 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240525185545_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610184545_V3_2.Designer.cs @@ -12,7 +12,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Alterations { [DbContext(typeof(AlterationsElsaDbContext))] - [Migration("20240525185545_V3_2")] + [Migration("20240610184545_V3_2")] partial class V3_2 { /// @@ -21,7 +21,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240525185545_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610184545_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240525185545_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610184545_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.Designer.cs new file mode 100644 index 0000000000..89de37f8e6 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.Designer.cs @@ -0,0 +1,136 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Alterations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Alterations +{ + [DbContext(typeof(AlterationsElsaDbContext))] + [Migration("20240610190343_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CompletedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("PlanId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SerializedLog") + .HasColumnType("nvarchar(max)"); + + b.Property("StartedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationJob_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationJob_CreatedAt"); + + b.HasIndex("PlanId") + .HasDatabaseName("IX_AlterationJob_PlanId"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationJob_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationJob_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); + + b.ToTable("AlterationJobs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationPlan", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CompletedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("SerializedAlterations") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedWorkflowInstanceFilter") + .HasColumnType("nvarchar(max)"); + + b.Property("StartedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationPlan_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationPlan_CreatedAt"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationPlan_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationPlan_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + + b.ToTable("AlterationPlans", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.cs new file mode 100644 index 0000000000..44c2b37a00 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/20240610190343_V3_3.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Alterations +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_AlterationPlan_TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropIndex( + name: "IX_AlterationJob_TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationPlans"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "AlterationJobs"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs index 2a2f198160..344167fa10 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -48,6 +48,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -69,6 +72,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationJob_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); @@ -99,6 +105,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); b.HasIndex("CompletedAt") @@ -113,6 +122,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationPlan_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + b.ToTable("AlterationPlans", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20231015122242_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20231015122242_Initial.cs index 722a891007..3f3b0c5a03 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20231015122242_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20231015122242_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240525185734_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610184919_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240525185734_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610184919_V3_2.Designer.cs index a842b05ef9..0ba11aa949 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240525185734_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610184919_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Identity { [DbContext(typeof(IdentityElsaDbContext))] - [Migration("20240525185734_V3_2")] + [Migration("20240610184919_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240525185734_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610184919_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240525185734_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610184919_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.Designer.cs new file mode 100644 index 0000000000..ce5464d51f --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.Designer.cs @@ -0,0 +1,149 @@ +// +using Elsa.EntityFrameworkCore.Modules.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Identity +{ + [DbContext(typeof(IdentityElsaDbContext))] + [Migration("20240610190505_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Identity.Entities.Application", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("HashedApiKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HashedApiKeySalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HashedClientSecret") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HashedClientSecretSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("IX_Application_ClientId"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Application_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + + b.ToTable("Applications", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.Role", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Permissions"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Role_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + + b.ToTable("Roles", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("HashedPassword") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HashedPasswordSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_User_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + + b.ToTable("Users", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.cs new file mode 100644 index 0000000000..385a7d6601 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/20240610190505_V3_3.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Identity +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_User_TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Role_TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_Application_TenantId", + schema: _schema.Schema, + table: "Applications"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Users"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Roles"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Applications"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs index e4bbf05a33..138d62a57e 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -56,6 +56,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); b.HasIndex("ClientId") @@ -66,6 +69,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasDatabaseName("IX_Application_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + b.ToTable("Applications", "Elsa"); }); @@ -83,12 +89,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)") .HasColumnName("Permissions"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_Role_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + b.ToTable("Roles", "Elsa"); }); @@ -114,12 +126,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_User_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + b.ToTable("Users", "Elsa"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20231015122257_Initial.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20231015122257_Initial.cs index 0271aced39..414d5d3f84 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20231015122257_Initial.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20231015122257_Initial.cs @@ -1,4 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -7,7 +7,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Labels { /// public partial class Initial : Migration - { + { private readonly IElsaDbContextSchema _schema; public Initial(IElsaDbContextSchema schema) { diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240525185800_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610185009_V3_2.Designer.cs similarity index 96% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240525185800_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610185009_V3_2.Designer.cs index 69c034e148..0667dd0d95 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240525185800_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610185009_V3_2.Designer.cs @@ -11,7 +11,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Labels { [DbContext(typeof(LabelsElsaDbContext))] - [Migration("20240525185800_V3_2")] + [Migration("20240610185009_V3_2")] partial class V3_2 { /// @@ -20,7 +20,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240525185800_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610185009_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240525185800_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610185009_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.Designer.cs new file mode 100644 index 0000000000..dc6a41f7b1 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.Designer.cs @@ -0,0 +1,94 @@ +// +using Elsa.EntityFrameworkCore.Modules.Labels; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Labels +{ + [DbContext(typeof(LabelsElsaDbContext))] + [Migration("20240610190545_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Labels.Entities.Label", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Color") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Labels", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Labels.Entities.WorkflowDefinitionLabel", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("LabelId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("LabelId") + .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionVersionId"); + + b.ToTable("WorkflowDefinitionLabels", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.cs new file mode 100644 index 0000000000..9c94c0b585 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/20240610190545_V3_3.cs @@ -0,0 +1,61 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Labels +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels", + type: "nvarchar(max)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "WorkflowDefinitionLabel_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Labels"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs index b2628e26f1..a1cb5bc81c 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -41,6 +41,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.ToTable("Labels", "Elsa"); @@ -55,6 +58,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -68,6 +74,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("LabelId") .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240525185707_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610184814_V3_2.Designer.cs similarity index 98% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240525185707_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610184814_V3_2.Designer.cs index 183c029d00..fd6cb595b1 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240525185707_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610184814_V3_2.Designer.cs @@ -12,7 +12,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management { [DbContext(typeof(ManagementElsaDbContext))] - [Migration("20240525185707_V3_2")] + [Migration("20240610184814_V3_2")] partial class V3_2 { /// @@ -21,7 +21,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240525185707_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610184814_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240525185707_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610184814_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.Designer.cs new file mode 100644 index 0000000000..66906607e4 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.Designer.cs @@ -0,0 +1,226 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Management; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management +{ + [DbContext(typeof(ManagementElsaDbContext))] + [Migration("20240610190431_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BinaryData") + .HasColumnType("varbinary(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("IsLatest") + .HasColumnType("bit"); + + b.Property("IsPublished") + .HasColumnType("bit"); + + b.Property("IsReadonly") + .HasColumnType("bit"); + + b.Property("IsSystem") + .HasColumnType("bit"); + + b.Property("MaterializerContext") + .HasColumnType("nvarchar(max)"); + + b.Property("MaterializerName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderName") + .HasColumnType("nvarchar(max)"); + + b.Property("StringData") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.Property("ToolVersion") + .HasColumnType("nvarchar(max)"); + + b.Property("UsableAsActivity") + .HasColumnType("bit"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IsLatest") + .HasDatabaseName("IX_WorkflowDefinition_IsLatest"); + + b.HasIndex("IsPublished") + .HasDatabaseName("IX_WorkflowDefinition_IsPublished"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowDefinition_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowDefinition_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + + b.HasIndex("UsableAsActivity") + .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); + + b.HasIndex("Version") + .HasDatabaseName("IX_WorkflowDefinition_Version"); + + b.HasIndex("DefinitionId", "Version") + .IsUnique() + .HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version"); + + b.ToTable("WorkflowDefinitions", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CorrelationId") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("DataCompressionAlgorithm") + .HasColumnType("nvarchar(max)"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("DefinitionVersionId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FinishedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IncidentCount") + .HasColumnType("int"); + + b.Property("IsSystem") + .HasColumnType("bit"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("ParentWorkflowInstanceId") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SubStatus") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId") + .HasDatabaseName("IX_WorkflowInstance_CorrelationId"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_WorkflowInstance_CreatedAt"); + + b.HasIndex("DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_DefinitionId"); + + b.HasIndex("FinishedAt") + .HasDatabaseName("IX_WorkflowInstance_FinishedAt"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowInstance_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowInstance_Name"); + + b.HasIndex("Status") + .HasDatabaseName("IX_WorkflowInstance_Status"); + + b.HasIndex("SubStatus") + .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + + b.HasIndex("UpdatedAt") + .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); + + b.HasIndex("Status", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId"); + + b.HasIndex("Status", "SubStatus") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus"); + + b.HasIndex("SubStatus", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId"); + + b.HasIndex("Status", "SubStatus", "DefinitionId", "Version") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version"); + + b.ToTable("WorkflowInstances", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.cs new file mode 100644 index 0000000000..7eeb709dbf --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/20240610190431_V3_3.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowInstance_TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropIndex( + name: "IX_WorkflowDefinition_TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowInstances"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowDefinitions"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs index 35a163009a..4997ce5e1d 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -72,6 +72,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StringData") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("ToolVersion") .HasColumnType("nvarchar(max)"); @@ -95,6 +98,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_WorkflowDefinition_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + b.HasIndex("UsableAsActivity") .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); @@ -156,6 +162,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("UpdatedAt") .HasColumnType("datetimeoffset"); @@ -188,6 +197,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubStatus") .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + b.HasIndex("UpdatedAt") .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.cs deleted file mode 100644 index 06f4e13e97..0000000000 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime -{ - /// - public partial class V3_2 : Migration - { - private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; - - /// - public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) - { - _schema = schema; - } - - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "WorkflowInboxMessages", - schema: _schema.Schema, - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - ActivityInstanceId = table.Column(type: "nvarchar(450)", nullable: true), - ActivityTypeName = table.Column(type: "nvarchar(450)", nullable: false), - CorrelationId = table.Column(type: "nvarchar(450)", nullable: true), - CreatedAt = table.Column(type: "datetimeoffset", nullable: false), - ExpiresAt = table.Column(type: "datetimeoffset", nullable: false), - Hash = table.Column(type: "nvarchar(450)", nullable: false), - SerializedBookmarkPayload = table.Column(type: "nvarchar(max)", nullable: true), - SerializedInput = table.Column(type: "nvarchar(max)", nullable: true), - WorkflowInstanceId = table.Column(type: "nvarchar(450)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityInstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityTypeName", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ActivityTypeName"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CorrelationId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CorrelationId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CreatedAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ExpiresAt", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "ExpiresAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_Hash", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "Hash"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_WorkflowInstanceId", - schema: _schema.Schema, - table: "WorkflowInboxMessages", - column: "WorkflowInstanceId"); - } - } -} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.Designer.cs new file mode 100644 index 0000000000..4112cb97da --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.Designer.cs @@ -0,0 +1,408 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime +{ + [DbContext(typeof(RuntimeElsaDbContext))] + [Migration("20240610184719_V3_2")] + partial class V3_2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Elsa") + .HasAnnotation("ProductVersion", "7.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => + { + b.Property("Key") + .HasColumnType("nvarchar(450)"); + + b.Property("SerializedValue") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Key"); + + b.ToTable("KeyValuePairs", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityName") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityTypeVersion") + .HasColumnType("int"); + + b.Property("CompletedAt") + .HasColumnType("datetimeoffset"); + + b.Property("HasBookmarks") + .HasColumnType("bit"); + + b.Property("SerializedActivityState") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedActivityStateCompressionAlgorithm") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedException") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedOutputs") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedPayload") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("StartedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt"); + + b.HasIndex("HasBookmarks") + .HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion"); + + b.ToTable("ActivityExecutionRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => + { + b.Property("BookmarkId") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityInstanceId") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("CorrelationId") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SerializedMetadata") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedPayload") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("BookmarkId"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt"); + + b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); + + b.ToTable("Bookmarks", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Hash") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SerializedPayload") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Hash") + .HasDatabaseName("IX_StoredTrigger_Hash"); + + b.HasIndex("Name") + .HasDatabaseName("IX_StoredTrigger_Name"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId"); + + b.ToTable("Triggers", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityInstanceId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityName") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityTypeVersion") + .HasColumnType("int"); + + b.Property("EventName") + .HasColumnType("nvarchar(450)"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("ParentActivityInstanceId") + .HasColumnType("nvarchar(450)"); + + b.Property("Sequence") + .HasColumnType("bigint"); + + b.Property("SerializedActivityState") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedPayload") + .HasColumnType("nvarchar(max)"); + + b.Property("Source") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkflowVersion") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId"); + + b.HasIndex("ActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion"); + + b.HasIndex("EventName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName"); + + b.HasIndex("ParentActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId"); + + b.HasIndex("Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + + b.HasIndex("Timestamp") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId"); + + b.HasIndex("WorkflowVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion"); + + b.HasIndex("Timestamp", "Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence"); + + b.ToTable("WorkflowExecutionLogRecords", "Elsa"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityInstanceId") + .HasColumnType("nvarchar(450)"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("CorrelationId") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("ExpiresAt") + .HasColumnType("datetimeoffset"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SerializedBookmarkPayload") + .HasColumnType("nvarchar(max)"); + + b.Property("SerializedInput") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkflowInstanceId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName"); + + b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt"); + + b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt"); + + b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId"); + + b.ToTable("WorkflowInboxMessages", "Elsa"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.cs new file mode 100644 index 0000000000..e7f437821f --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610184719_V3_2.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime +{ + /// + public partial class V3_2 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.Designer.cs similarity index 90% rename from src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.Designer.cs index dff405b182..a1528e5728 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240525185633_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.Designer.cs @@ -12,8 +12,8 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime { [DbContext(typeof(RuntimeElsaDbContext))] - [Migration("20240525185633_V3_2")] - partial class V3_2 + [Migration("20240610190408_V3_3")] + partial class V3_3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -21,21 +21,26 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("nvarchar(450)"); b.Property("SerializedValue") .IsRequired() .HasColumnType("nvarchar(max)"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -94,6 +99,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -127,6 +135,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -138,7 +149,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("nvarchar(450)"); b.Property("ActivityInstanceId") @@ -164,11 +175,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("nvarchar(450)"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -182,6 +196,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -206,6 +222,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -222,6 +241,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -279,6 +301,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("Timestamp") .HasColumnType("datetimeoffset"); @@ -326,6 +351,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.cs new file mode 100644 index 0000000000..8fe2a08f46 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/20240610190408_V3_3.cs @@ -0,0 +1,233 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema); + + migrationBuilder.RenameColumn( + name: "Key", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "BookmarkId", + schema: _schema.Schema, + table: "Bookmarks", + newName: "Id"); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropIndex( + name: "IX_StoredTrigger_TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropIndex( + name: "IX_SerializedKeyValuePair_TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropIndex( + name: "IX_StoredBookmark_TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropIndex( + name: "IX_ActivityExecutionRecord_TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Triggers"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "KeyValuePairs"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "Bookmarks"); + + migrationBuilder.DropColumn( + name: "TenantId", + schema: _schema.Schema, + table: "ActivityExecutionRecords"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "KeyValuePairs", + newName: "Key"); + + migrationBuilder.RenameColumn( + name: "Id", + schema: _schema.Schema, + table: "Bookmarks", + newName: "BookmarkId"); + + migrationBuilder.CreateTable( + name: "WorkflowInboxMessages", + schema: _schema.Schema, + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + ActivityInstanceId = table.Column(type: "nvarchar(450)", nullable: true), + ActivityTypeName = table.Column(type: "nvarchar(450)", nullable: false), + CorrelationId = table.Column(type: "nvarchar(450)", nullable: true), + CreatedAt = table.Column(type: "datetimeoffset", nullable: false), + ExpiresAt = table.Column(type: "datetimeoffset", nullable: false), + Hash = table.Column(type: "nvarchar(450)", nullable: false), + SerializedBookmarkPayload = table.Column(type: "nvarchar(max)", nullable: true), + SerializedInput = table.Column(type: "nvarchar(max)", nullable: true), + WorkflowInstanceId = table.Column(type: "nvarchar(450)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityInstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityTypeName", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ActivityTypeName"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CorrelationId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CorrelationId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CreatedAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "CreatedAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ExpiresAt", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "ExpiresAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_Hash", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "Hash"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_WorkflowInstanceId", + schema: _schema.Schema, + table: "WorkflowInboxMessages", + column: "WorkflowInstanceId"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs index fabb7f363b..34dcaec4a4 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs @@ -18,21 +18,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Elsa") - .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("ProductVersion", "7.0.20") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("nvarchar(450)"); b.Property("SerializedValue") .IsRequired() .HasColumnType("nvarchar(max)"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs", "Elsa"); }); @@ -91,6 +96,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -124,6 +132,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -135,7 +146,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("nvarchar(450)"); b.Property("ActivityInstanceId") @@ -161,11 +172,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("nvarchar(450)"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -179,6 +193,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks", "Elsa"); @@ -203,6 +219,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("nvarchar(450)"); @@ -219,6 +238,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -276,6 +298,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("nvarchar(max)"); + b.Property("TenantId") + .HasColumnType("nvarchar(450)"); + b.Property("Timestamp") .HasColumnType("datetimeoffset"); @@ -323,6 +348,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Features.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Features.cs index 8650c66679..8e1acda114 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Features.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Features.cs @@ -1,10 +1,8 @@ using System.Reflection; using Elsa.EntityFrameworkCore.Common; -using Elsa.EntityFrameworkCore.Modules.Alterations; -using Elsa.EntityFrameworkCore.Modules.Identity; -using Elsa.EntityFrameworkCore.Modules.Labels; -using Elsa.EntityFrameworkCore.Modules.Management; -using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Common.EntityHandlers; +using Microsoft.Extensions.DependencyInjection; // ReSharper disable once CheckNamespace namespace Elsa.EntityFrameworkCore.Extensions; @@ -17,65 +15,15 @@ public static class SqliteProvidersExtensions private static Assembly Assembly => typeof(SqliteProvidersExtensions).Assembly; /// - /// Configures the to use Sqlite. + /// Configures the feature to use Sqlite. /// - public static EFCoreIdentityPersistenceFeature UseSqlite(this EFCoreIdentityPersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) + public static TFeature UseSqlite(this PersistenceFeatureBase feature, string? connectionString = null, ElsaDbContextOptions? options = null) + where TDbContext : ElsaDbContextBase + where TFeature : PersistenceFeatureBase { + connectionString ??= "Data Source=elsa.sqlite.db;Cache=Shared;"; + feature.Module.Services.AddScoped(); feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static EFCoreAlterationsPersistenceFeature UseSqlite(this EFCoreAlterationsPersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static EFCoreLabelPersistenceFeature UseSqlite(this EFCoreLabelPersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static EFCoreWorkflowDefinitionPersistenceFeature UseSqlite(this EFCoreWorkflowDefinitionPersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static EFCoreWorkflowInstancePersistenceFeature UseSqlite(this EFCoreWorkflowInstancePersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static WorkflowManagementPersistenceFeature UseSqlite(this WorkflowManagementPersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; - } - - /// - /// Configures the to use Sqlite. - /// - public static EFCoreWorkflowRuntimePersistenceFeature UseSqlite(this EFCoreWorkflowRuntimePersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) - { - feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(Assembly, connectionString, options); - return feature; + return (TFeature)feature; } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240525185559_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610184608_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240525185559_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610184608_V3_2.Designer.cs index 2f7dcb9c52..74f9a7fa88 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240525185559_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610184608_V3_2.Designer.cs @@ -10,14 +10,14 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Alterations { [DbContext(typeof(AlterationsElsaDbContext))] - [Migration("20240525185559_V3_2")] + [Migration("20240610184608_V3_2")] partial class V3_2 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => { diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240525185559_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610184608_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240525185559_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610184608_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.Designer.cs new file mode 100644 index 0000000000..2505f35a79 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.Designer.cs @@ -0,0 +1,130 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Alterations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Alterations +{ + [DbContext(typeof(AlterationsElsaDbContext))] + [Migration("20240610190350_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CompletedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("PlanId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SerializedLog") + .HasColumnType("TEXT"); + + b.Property("StartedAt") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationJob_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationJob_CreatedAt"); + + b.HasIndex("PlanId") + .HasDatabaseName("IX_AlterationJob_PlanId"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationJob_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationJob_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); + + b.ToTable("AlterationJobs"); + }); + + modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationPlan", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CompletedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("SerializedAlterations") + .HasColumnType("TEXT"); + + b.Property("SerializedWorkflowInstanceFilter") + .HasColumnType("TEXT"); + + b.Property("StartedAt") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_AlterationPlan_CompletedAt"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_AlterationPlan_CreatedAt"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_AlterationPlan_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_AlterationPlan_Status"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + + b.ToTable("AlterationPlans"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.cs new file mode 100644 index 0000000000..fa9f6e33b1 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/20240610190350_V3_3.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Alterations +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + table: "AlterationPlans", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "AlterationJobs", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_AlterationPlan_TenantId", + table: "AlterationPlans", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_AlterationJob_TenantId", + table: "AlterationJobs", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_AlterationPlan_TenantId", + table: "AlterationPlans"); + + migrationBuilder.DropIndex( + name: "IX_AlterationJob_TenantId", + table: "AlterationJobs"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "AlterationPlans"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "AlterationJobs"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs index f18f4ecb34..b9c83bb783 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Alterations/AlterationsElsaDbContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using Elsa.EntityFrameworkCore.Modules.Alterations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -14,18 +15,17 @@ partial class AlterationsElsaDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Alterations.Core.Entities.AlterationJob", b => { b.Property("Id") .HasColumnType("TEXT"); - b.Property("CompletedAt") + b.Property("CompletedAt") .HasColumnType("TEXT"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("PlanId") @@ -35,13 +35,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedLog") .HasColumnType("TEXT"); - b.Property("StartedAt") + b.Property("StartedAt") .HasColumnType("TEXT"); b.Property("Status") .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("TEXT"); @@ -63,6 +66,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationJob_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationJob_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_AlterationJob_WorkflowInstanceId"); @@ -74,11 +80,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .HasColumnType("TEXT"); - b.Property("CompletedAt") + b.Property("CompletedAt") .HasColumnType("TEXT"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("SerializedAlterations") @@ -87,13 +92,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedWorkflowInstanceFilter") .HasColumnType("TEXT"); - b.Property("StartedAt") + b.Property("StartedAt") .HasColumnType("TEXT"); b.Property("Status") .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.HasIndex("CompletedAt") @@ -108,6 +116,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_AlterationPlan_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_AlterationPlan_TenantId"); + b.ToTable("AlterationPlans"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240525185740_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610184930_V3_2.Designer.cs similarity index 97% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240525185740_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610184930_V3_2.Designer.cs index 768c13109c..d94c085c81 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240525185740_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610184930_V3_2.Designer.cs @@ -10,14 +10,14 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Identity { [DbContext(typeof(IdentityElsaDbContext))] - [Migration("20240525185740_V3_2")] + [Migration("20240610184930_V3_2")] partial class V3_2 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Identity.Entities.Application", b => { diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240525185740_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610184930_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240525185740_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610184930_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.Designer.cs new file mode 100644 index 0000000000..6718046e1c --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.Designer.cs @@ -0,0 +1,143 @@ +// +using Elsa.EntityFrameworkCore.Modules.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Identity +{ + [DbContext(typeof(IdentityElsaDbContext))] + [Migration("20240610190514_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); + + modelBuilder.Entity("Elsa.Identity.Entities.Application", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HashedApiKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HashedApiKeySalt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HashedClientSecret") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HashedClientSecretSalt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("IX_Application_ClientId"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Application_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.Role", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Permissions"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_Role_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Elsa.Identity.Entities.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("HashedPassword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HashedPasswordSalt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Roles"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_User_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.cs new file mode 100644 index 0000000000..ab710e6543 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20240610190514_V3_3.cs @@ -0,0 +1,83 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Identity +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + table: "Users", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "Roles", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "Applications", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_User_TenantId", + table: "Users", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Role_TenantId", + table: "Roles", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_Application_TenantId", + table: "Applications", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_User_TenantId", + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Role_TenantId", + table: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_Application_TenantId", + table: "Applications"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Roles"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Applications"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs index c166edc031..5fc41875fc 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/IdentityElsaDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ partial class IdentityElsaDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Identity.Entities.Application", b => { @@ -50,6 +50,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.HasIndex("ClientId") @@ -60,6 +63,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasDatabaseName("IX_Application_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Application_TenantId"); + b.ToTable("Applications"); }); @@ -77,12 +83,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("Permissions"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_Role_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_Role_TenantId"); + b.ToTable("Roles"); }); @@ -108,12 +120,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("Roles"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.HasIndex("Name") .IsUnique() .HasDatabaseName("IX_User_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_User_TenantId"); + b.ToTable("Users"); }); #pragma warning restore 612, 618 diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240525185806_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610185018_V3_2.Designer.cs similarity index 96% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240525185806_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610185018_V3_2.Designer.cs index 8d082cbd4e..45554fb6f5 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240525185806_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610185018_V3_2.Designer.cs @@ -10,14 +10,14 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Labels { [DbContext(typeof(LabelsElsaDbContext))] - [Migration("20240525185806_V3_2")] + [Migration("20240610185018_V3_2")] partial class V3_2 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Labels.Entities.Label", b => { diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240525185806_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610185018_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240525185806_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610185018_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.Designer.cs new file mode 100644 index 0000000000..a352958018 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.Designer.cs @@ -0,0 +1,88 @@ +// +using Elsa.EntityFrameworkCore.Modules.Labels; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Labels +{ + [DbContext(typeof(LabelsElsaDbContext))] + [Migration("20240610190552_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); + + modelBuilder.Entity("Elsa.Labels.Entities.Label", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Color") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Labels"); + }); + + modelBuilder.Entity("Elsa.Labels.Entities.WorkflowDefinitionLabel", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("LabelId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LabelId") + .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionVersionId"); + + b.ToTable("WorkflowDefinitionLabels"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.cs new file mode 100644 index 0000000000..b853391493 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/20240610190552_V3_3.cs @@ -0,0 +1,55 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Labels +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + table: "WorkflowDefinitionLabels", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "Labels", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateIndex( + name: "WorkflowDefinitionLabel_TenantId", + table: "WorkflowDefinitionLabels", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "WorkflowDefinitionLabel_TenantId", + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "WorkflowDefinitionLabels"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Labels"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs index 82ae014e55..e8e00f2a63 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Labels/LabelsElsaDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ partial class LabelsElsaDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Labels.Entities.Label", b => { @@ -35,6 +35,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.ToTable("Labels"); @@ -49,6 +52,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("TEXT"); @@ -62,6 +68,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("LabelId") .HasDatabaseName("WorkflowDefinitionLabel_LabelId"); + b.HasIndex("TenantId") + .HasDatabaseName("WorkflowDefinitionLabel_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("WorkflowDefinitionLabel_WorkflowDefinitionId"); diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240525185713_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610184829_V3_2.Designer.cs similarity index 98% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240525185713_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610184829_V3_2.Designer.cs index 3e428ce076..e04c4c939c 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240525185713_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610184829_V3_2.Designer.cs @@ -11,14 +11,14 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management { [DbContext(typeof(ManagementElsaDbContext))] - [Migration("20240525185713_V3_2")] + [Migration("20240610184829_V3_2")] partial class V3_2 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => { diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240525185713_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610184829_V3_2.cs similarity index 100% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240525185713_V3_2.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610184829_V3_2.cs diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.Designer.cs new file mode 100644 index 0000000000..9ddcb82ae8 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.Designer.cs @@ -0,0 +1,220 @@ +// +using System; +using Elsa.EntityFrameworkCore.Modules.Management; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management +{ + [DbContext(typeof(ManagementElsaDbContext))] + [Migration("20240610190438_V3_3")] + partial class V3_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BinaryData") + .HasColumnType("BLOB"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsLatest") + .HasColumnType("INTEGER"); + + b.Property("IsPublished") + .HasColumnType("INTEGER"); + + b.Property("IsReadonly") + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("MaterializerContext") + .HasColumnType("TEXT"); + + b.Property("MaterializerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ProviderName") + .HasColumnType("TEXT"); + + b.Property("StringData") + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("ToolVersion") + .HasColumnType("TEXT"); + + b.Property("UsableAsActivity") + .HasColumnType("INTEGER"); + + b.Property("Version") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("IsLatest") + .HasDatabaseName("IX_WorkflowDefinition_IsLatest"); + + b.HasIndex("IsPublished") + .HasDatabaseName("IX_WorkflowDefinition_IsPublished"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowDefinition_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowDefinition_Name"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + + b.HasIndex("UsableAsActivity") + .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); + + b.HasIndex("Version") + .HasDatabaseName("IX_WorkflowDefinition_Version"); + + b.HasIndex("DefinitionId", "Version") + .IsUnique() + .HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version"); + + b.ToTable("WorkflowDefinitions"); + }); + + modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CorrelationId") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DataCompressionAlgorithm") + .HasColumnType("TEXT"); + + b.Property("DefinitionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DefinitionVersionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FinishedAt") + .HasColumnType("TEXT"); + + b.Property("IncidentCount") + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ParentWorkflowInstanceId") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubStatus") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Version") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId") + .HasDatabaseName("IX_WorkflowInstance_CorrelationId"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("IX_WorkflowInstance_CreatedAt"); + + b.HasIndex("DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_DefinitionId"); + + b.HasIndex("FinishedAt") + .HasDatabaseName("IX_WorkflowInstance_FinishedAt"); + + b.HasIndex("IsSystem") + .HasDatabaseName("IX_WorkflowInstance_IsSystem"); + + b.HasIndex("Name") + .HasDatabaseName("IX_WorkflowInstance_Name"); + + b.HasIndex("Status") + .HasDatabaseName("IX_WorkflowInstance_Status"); + + b.HasIndex("SubStatus") + .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + + b.HasIndex("UpdatedAt") + .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); + + b.HasIndex("Status", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId"); + + b.HasIndex("Status", "SubStatus") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus"); + + b.HasIndex("SubStatus", "DefinitionId") + .HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId"); + + b.HasIndex("Status", "SubStatus", "DefinitionId", "Version") + .HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version"); + + b.ToTable("WorkflowInstances"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.cs new file mode 100644 index 0000000000..377da30b17 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/20240610190438_V3_3.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TenantId", + table: "WorkflowInstances", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "WorkflowDefinitions", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInstance_TenantId", + table: "WorkflowInstances", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowDefinition_TenantId", + table: "WorkflowDefinitions", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowInstance_TenantId", + table: "WorkflowInstances"); + + migrationBuilder.DropIndex( + name: "IX_WorkflowDefinition_TenantId", + table: "WorkflowDefinitions"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "WorkflowInstances"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "WorkflowDefinitions"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs index adf6c58405..9209851728 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Management/ManagementElsaDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class ManagementElsaDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b => { @@ -25,8 +25,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("BinaryData") .HasColumnType("BLOB"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("Data") @@ -67,6 +66,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StringData") .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("ToolVersion") .HasColumnType("TEXT"); @@ -90,6 +92,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_WorkflowDefinition_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowDefinition_TenantId"); + b.HasIndex("UsableAsActivity") .HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity"); @@ -111,8 +116,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CorrelationId") .HasColumnType("TEXT"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("Data") @@ -129,7 +133,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("TEXT"); - b.Property("FinishedAt") + b.Property("FinishedAt") .HasColumnType("TEXT"); b.Property("IncidentCount") @@ -152,8 +156,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("TEXT"); - b.Property("UpdatedAt") - .IsRequired() + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") .HasColumnType("TEXT"); b.Property("Version") @@ -185,6 +191,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubStatus") .HasDatabaseName("IX_WorkflowInstance_SubStatus"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowInstance_TenantId"); + b.HasIndex("UpdatedAt") .HasDatabaseName("IX_WorkflowInstance_UpdatedAt"); diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.cs deleted file mode 100644 index 1f014fd379..0000000000 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.cs +++ /dev/null @@ -1,84 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime -{ - /// - public partial class V3_2 : Migration - { - private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; - - /// - public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) - { - _schema = schema; - } - - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "WorkflowInboxMessages"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "WorkflowInboxMessages", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - ActivityInstanceId = table.Column(type: "TEXT", nullable: true), - ActivityTypeName = table.Column(type: "TEXT", nullable: false), - CorrelationId = table.Column(type: "TEXT", nullable: true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - ExpiresAt = table.Column(type: "TEXT", nullable: false), - Hash = table.Column(type: "TEXT", nullable: false), - SerializedBookmarkPayload = table.Column(type: "TEXT", nullable: true), - SerializedInput = table.Column(type: "TEXT", nullable: true), - WorkflowInstanceId = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityInstanceId", - table: "WorkflowInboxMessages", - column: "ActivityInstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ActivityTypeName", - table: "WorkflowInboxMessages", - column: "ActivityTypeName"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CorrelationId", - table: "WorkflowInboxMessages", - column: "CorrelationId"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_CreatedAt", - table: "WorkflowInboxMessages", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_ExpiresAt", - table: "WorkflowInboxMessages", - column: "ExpiresAt"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_Hash", - table: "WorkflowInboxMessages", - column: "Hash"); - - migrationBuilder.CreateIndex( - name: "IX_WorkflowInboxMessage_WorkflowInstanceId", - table: "WorkflowInboxMessages", - column: "WorkflowInstanceId"); - } - } -} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.Designer.cs new file mode 100644 index 0000000000..1408fee545 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.Designer.cs @@ -0,0 +1,406 @@ +// +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime +{ + [DbContext(typeof(RuntimeElsaDbContext))] + [Migration("20240610184731_V3_2")] + partial class V3_2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); + + modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => + { + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("SerializedValue") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("KeyValuePairs"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityName") + .HasColumnType("TEXT"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityTypeVersion") + .HasColumnType("INTEGER"); + + b.Property("CompletedAt") + .HasColumnType("TEXT"); + + b.Property("HasBookmarks") + .HasColumnType("INTEGER"); + + b.Property("SerializedActivityState") + .HasColumnType("TEXT"); + + b.Property("SerializedActivityStateCompressionAlgorithm") + .HasColumnType("TEXT"); + + b.Property("SerializedException") + .HasColumnType("TEXT"); + + b.Property("SerializedOutputs") + .HasColumnType("TEXT"); + + b.Property("SerializedPayload") + .HasColumnType("TEXT"); + + b.Property("SerializedProperties") + .HasColumnType("TEXT"); + + b.Property("StartedAt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion"); + + b.HasIndex("CompletedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt"); + + b.HasIndex("HasBookmarks") + .HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks"); + + b.HasIndex("StartedAt") + .HasDatabaseName("IX_ActivityExecutionRecord_StartedAt"); + + b.HasIndex("Status") + .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion"); + + b.ToTable("ActivityExecutionRecords"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => + { + b.Property("BookmarkId") + .HasColumnType("TEXT"); + + b.Property("ActivityInstanceId") + .HasColumnType("TEXT"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CorrelationId") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SerializedMetadata") + .HasColumnType("TEXT"); + + b.Property("SerializedPayload") + .HasColumnType("TEXT"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("BookmarkId"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash"); + + b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt"); + + b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); + + b.ToTable("Bookmarks"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Hash") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SerializedPayload") + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Hash") + .HasDatabaseName("IX_StoredTrigger_Hash"); + + b.HasIndex("Name") + .HasDatabaseName("IX_StoredTrigger_Name"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId"); + + b.ToTable("Triggers"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActivityId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityInstanceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityName") + .HasColumnType("TEXT"); + + b.Property("ActivityNodeId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ActivityTypeVersion") + .HasColumnType("INTEGER"); + + b.Property("EventName") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ParentActivityInstanceId") + .HasColumnType("TEXT"); + + b.Property("Sequence") + .HasColumnType("INTEGER"); + + b.Property("SerializedActivityState") + .HasColumnType("TEXT"); + + b.Property("SerializedPayload") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowDefinitionVersionId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowInstanceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WorkflowVersion") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId"); + + b.HasIndex("ActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId"); + + b.HasIndex("ActivityName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName"); + + b.HasIndex("ActivityNodeId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId"); + + b.HasIndex("ActivityType") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType"); + + b.HasIndex("ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion"); + + b.HasIndex("EventName") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName"); + + b.HasIndex("ParentActivityInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId"); + + b.HasIndex("Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + + b.HasIndex("Timestamp") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); + + b.HasIndex("WorkflowDefinitionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId"); + + b.HasIndex("WorkflowDefinitionVersionId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId"); + + b.HasIndex("WorkflowInstanceId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId"); + + b.HasIndex("WorkflowVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion"); + + b.HasIndex("ActivityType", "ActivityTypeVersion") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion"); + + b.HasIndex("Timestamp", "Sequence") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence"); + + b.ToTable("WorkflowExecutionLogRecords"); + }); + + modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActivityInstanceId") + .HasColumnType("TEXT"); + + b.Property("ActivityTypeName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CorrelationId") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ExpiresAt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SerializedBookmarkPayload") + .HasColumnType("TEXT"); + + b.Property("SerializedInput") + .HasColumnType("TEXT"); + + b.Property("WorkflowInstanceId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId"); + + b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName"); + + b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId"); + + b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt"); + + b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt"); + + b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash"); + + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId"); + + b.ToTable("WorkflowInboxMessages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.cs new file mode 100644 index 0000000000..95b9649aaf --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610184731_V3_2.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime +{ + /// + public partial class V3_2 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_2(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.Designer.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.Designer.cs similarity index 89% rename from src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.Designer.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.Designer.cs index 832fb615ca..27f0a9a4fb 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240525185643_V3_2.Designer.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.Designer.cs @@ -1,4 +1,5 @@ // +using System; using Elsa.EntityFrameworkCore.Modules.Runtime; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -10,25 +11,30 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime { [DbContext(typeof(RuntimeElsaDbContext))] - [Migration("20240525185643_V3_2")] - partial class V3_2 + [Migration("20240610190414_V3_3")] + partial class V3_3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("TEXT"); b.Property("SerializedValue") .IsRequired() .HasColumnType("TEXT"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs"); }); @@ -56,7 +62,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("ActivityTypeVersion") .HasColumnType("INTEGER"); - b.Property("CompletedAt") + b.Property("CompletedAt") .HasColumnType("TEXT"); b.Property("HasBookmarks") @@ -80,14 +86,16 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedProperties") .HasColumnType("TEXT"); - b.Property("StartedAt") - .IsRequired() + b.Property("StartedAt") .HasColumnType("TEXT"); b.Property("Status") .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("TEXT"); @@ -121,6 +129,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -132,7 +143,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("TEXT"); b.Property("ActivityInstanceId") @@ -145,8 +156,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CorrelationId") .HasColumnType("TEXT"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("Hash") @@ -159,11 +169,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("TEXT"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -177,6 +190,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks"); @@ -201,6 +216,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("TEXT"); @@ -217,6 +235,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -274,8 +295,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("TEXT"); - b.Property("Timestamp") - .IsRequired() + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("Timestamp") .HasColumnType("TEXT"); b.Property("WorkflowDefinitionId") @@ -322,6 +345,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.cs new file mode 100644 index 0000000000..c446347c8a --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/20240610190414_V3_3.cs @@ -0,0 +1,199 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime +{ + /// + public partial class V3_3 : Migration + { + private readonly Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema _schema; + + /// + public V3_3(Elsa.EntityFrameworkCore.Common.Contracts.IElsaDbContextSchema schema) + { + _schema = schema; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "WorkflowInboxMessages"); + + migrationBuilder.RenameColumn( + name: "Key", + table: "KeyValuePairs", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "BookmarkId", + table: "Bookmarks", + newName: "Id"); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "WorkflowExecutionLogRecords", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "Triggers", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "KeyValuePairs", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "Bookmarks", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "ActivityExecutionRecords", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + table: "WorkflowExecutionLogRecords", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredTrigger_TenantId", + table: "Triggers", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_SerializedKeyValuePair_TenantId", + table: "KeyValuePairs", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StoredBookmark_TenantId", + table: "Bookmarks", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ActivityExecutionRecord_TenantId", + table: "ActivityExecutionRecords", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_WorkflowExecutionLogRecord_TenantId", + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropIndex( + name: "IX_StoredTrigger_TenantId", + table: "Triggers"); + + migrationBuilder.DropIndex( + name: "IX_SerializedKeyValuePair_TenantId", + table: "KeyValuePairs"); + + migrationBuilder.DropIndex( + name: "IX_StoredBookmark_TenantId", + table: "Bookmarks"); + + migrationBuilder.DropIndex( + name: "IX_ActivityExecutionRecord_TenantId", + table: "ActivityExecutionRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "WorkflowExecutionLogRecords"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Triggers"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "KeyValuePairs"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "Bookmarks"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "ActivityExecutionRecords"); + + migrationBuilder.RenameColumn( + name: "Id", + table: "KeyValuePairs", + newName: "Key"); + + migrationBuilder.RenameColumn( + name: "Id", + table: "Bookmarks", + newName: "BookmarkId"); + + migrationBuilder.CreateTable( + name: "WorkflowInboxMessages", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ActivityInstanceId = table.Column(type: "TEXT", nullable: true), + ActivityTypeName = table.Column(type: "TEXT", nullable: false), + CorrelationId = table.Column(type: "TEXT", nullable: true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + ExpiresAt = table.Column(type: "TEXT", nullable: false), + Hash = table.Column(type: "TEXT", nullable: false), + SerializedBookmarkPayload = table.Column(type: "TEXT", nullable: true), + SerializedInput = table.Column(type: "TEXT", nullable: true), + WorkflowInstanceId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_WorkflowInboxMessages", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityInstanceId", + table: "WorkflowInboxMessages", + column: "ActivityInstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ActivityTypeName", + table: "WorkflowInboxMessages", + column: "ActivityTypeName"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CorrelationId", + table: "WorkflowInboxMessages", + column: "CorrelationId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_CreatedAt", + table: "WorkflowInboxMessages", + column: "CreatedAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_ExpiresAt", + table: "WorkflowInboxMessages", + column: "ExpiresAt"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_Hash", + table: "WorkflowInboxMessages", + column: "Hash"); + + migrationBuilder.CreateIndex( + name: "IX_WorkflowInboxMessage_WorkflowInstanceId", + table: "WorkflowInboxMessages", + column: "WorkflowInstanceId"); + } + } +} diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs index 3870b06c59..30d187720c 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Runtime/RuntimeElsaDbContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using Elsa.EntityFrameworkCore.Modules.Runtime; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -14,18 +15,23 @@ partial class RuntimeElsaDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.20"); modelBuilder.Entity("Elsa.KeyValues.Entities.SerializedKeyValuePair", b => { - b.Property("Key") + b.Property("Id") .HasColumnType("TEXT"); b.Property("SerializedValue") .IsRequired() .HasColumnType("TEXT"); - b.HasKey("Key"); + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TenantId" }, "IX_SerializedKeyValuePair_TenantId"); b.ToTable("KeyValuePairs"); }); @@ -53,7 +59,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("ActivityTypeVersion") .HasColumnType("INTEGER"); - b.Property("CompletedAt") + b.Property("CompletedAt") .HasColumnType("TEXT"); b.Property("HasBookmarks") @@ -77,14 +83,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedProperties") .HasColumnType("TEXT"); - b.Property("StartedAt") - .IsRequired() + b.Property("StartedAt") .HasColumnType("TEXT"); b.Property("Status") .IsRequired() .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("TEXT"); @@ -118,6 +126,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Status") .HasDatabaseName("IX_ActivityExecutionRecord_Status"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_ActivityExecutionRecord_TenantId"); + b.HasIndex("WorkflowInstanceId") .HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId"); @@ -129,7 +140,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b => { - b.Property("BookmarkId") + b.Property("Id") .HasColumnType("TEXT"); b.Property("ActivityInstanceId") @@ -142,8 +153,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CorrelationId") .HasColumnType("TEXT"); - b.Property("CreatedAt") - .IsRequired() + b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("Hash") @@ -156,11 +166,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowInstanceId") .IsRequired() .HasColumnType("TEXT"); - b.HasKey("BookmarkId"); + b.HasKey("Id"); b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId"); @@ -174,6 +187,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash"); + b.HasIndex(new[] { "TenantId" }, "IX_StoredBookmark_TenantId"); + b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId"); b.ToTable("Bookmarks"); @@ -198,6 +213,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SerializedPayload") .HasColumnType("TEXT"); + b.Property("TenantId") + .HasColumnType("TEXT"); + b.Property("WorkflowDefinitionId") .IsRequired() .HasColumnType("TEXT"); @@ -214,6 +232,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Name") .HasDatabaseName("IX_StoredTrigger_Name"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_StoredTrigger_TenantId"); + b.HasIndex("WorkflowDefinitionId") .HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId"); @@ -271,8 +292,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Source") .HasColumnType("TEXT"); - b.Property("Timestamp") - .IsRequired() + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("Timestamp") .HasColumnType("TEXT"); b.Property("WorkflowDefinitionId") @@ -319,6 +342,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("Sequence") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence"); + b.HasIndex("TenantId") + .HasDatabaseName("IX_WorkflowExecutionLogRecord_TenantId"); + b.HasIndex("Timestamp") .HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp"); diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Configurations.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Configurations.cs index 8f52749e21..16eb4c7e28 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Configurations.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Configurations.cs @@ -21,6 +21,7 @@ public void Configure(EntityTypeBuilder builder) builder.HasIndex(x => x.CreatedAt).HasDatabaseName($"IX_{nameof(AlterationPlan)}_{nameof(AlterationPlan.CreatedAt)}"); builder.HasIndex(x => x.StartedAt).HasDatabaseName($"IX_{nameof(AlterationPlan)}_{nameof(AlterationPlan.StartedAt)}"); builder.HasIndex(x => x.CompletedAt).HasDatabaseName($"IX_{nameof(AlterationPlan)}_{nameof(AlterationPlan.CompletedAt)}"); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(AlterationPlan)}_{nameof(AlterationPlan.TenantId)}"); } /// @@ -35,5 +36,6 @@ public void Configure(EntityTypeBuilder builder) builder.HasIndex(x => x.CreatedAt).HasDatabaseName($"IX_{nameof(AlterationJob)}_{nameof(AlterationJob.CreatedAt)}"); builder.HasIndex(x => x.StartedAt).HasDatabaseName($"IX_{nameof(AlterationJob)}_{nameof(AlterationJob.StartedAt)}"); builder.HasIndex(x => x.CompletedAt).HasDatabaseName($"IX_{nameof(AlterationJob)}_{nameof(AlterationJob.CompletedAt)}"); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(AlterationJob)}_{nameof(AlterationJob.TenantId)}"); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/DbContext.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/DbContext.cs index a9d480bad1..9166d61171 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/DbContext.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/DbContext.cs @@ -1,7 +1,8 @@ -using Elsa.Alterations.Core.Entities; +using Elsa.Alterations.Core.Entities; using Elsa.Alterations.Core.Models; using Elsa.EntityFrameworkCore.Common; using Elsa.Workflows.Management.Models; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; namespace Elsa.EntityFrameworkCore.Modules.Alterations; @@ -9,18 +10,19 @@ namespace Elsa.EntityFrameworkCore.Modules.Alterations; /// /// DB context for the runtime module. /// +[UsedImplicitly] public class AlterationsElsaDbContext : ElsaDbContextBase { /// - public AlterationsElsaDbContext(DbContextOptions options) : base(options) + public AlterationsElsaDbContext(DbContextOptions options, IServiceProvider serviceProvider) : base(options, serviceProvider) { } - + /// /// The alteration plans. /// public DbSet AlterationPlans { get; set; } = default!; - + /// /// The alteration jobs. /// @@ -31,25 +33,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Ignore(); modelBuilder.Ignore(); - base.OnModelCreating(modelBuilder); - } - - /// - protected override void ApplyEntityConfigurations(ModelBuilder modelBuilder) - { - var config = new Configurations(); modelBuilder.Ignore(); - modelBuilder.ApplyConfiguration(config); - modelBuilder.ApplyConfiguration(config); - } - - /// - protected override void SetupForOracle(ModelBuilder modelBuilder) - { - // In order to use data more than 2000 char we have to use NCLOB. - // In Oracle we have to explicitly say the column is NCLOB otherwise it would be considered nvarchar(2000). - modelBuilder.Entity().Property("SerializedAlterations").HasColumnType("NCLOB"); - modelBuilder.Entity().Property("SerializedWorkflowInstanceFilter").HasColumnType("NCLOB"); - modelBuilder.Entity().Property("SerializedLog").HasColumnType("NCLOB"); + + var configuration = new Configurations(); + modelBuilder.ApplyConfiguration(configuration); + modelBuilder.ApplyConfiguration(configuration); + base.OnModelCreating(modelBuilder); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs index 5a66c8fb4d..bf387b703b 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs @@ -1,6 +1,7 @@ using Elsa.Alterations.Core.Entities; using Elsa.Alterations.Features; using Elsa.EntityFrameworkCore.Common; +using Elsa.EntityFrameworkCore.Common.Contracts; using Elsa.Features.Attributes; using Elsa.Features.Services; using Microsoft.Extensions.DependencyInjection; @@ -11,7 +12,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Alterations; /// Configures the default workflow runtime to use EF Core persistence providers. /// [DependsOn(typeof(AlterationsFeature))] -public class EFCoreAlterationsPersistenceFeature : PersistenceFeatureBase +public class EFCoreAlterationsPersistenceFeature : PersistenceFeatureBase { /// public EFCoreAlterationsPersistenceFeature(IModule module) : base(module) @@ -35,5 +36,6 @@ public override void Apply() AddEntityStore(); AddEntityStore(); + Services.AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs new file mode 100644 index 0000000000..90f12f0ae0 --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs @@ -0,0 +1,27 @@ +using Elsa.Alterations.Core.Entities; +using Elsa.EntityFrameworkCore.Common; +using Elsa.EntityFrameworkCore.Common.Contracts; +using Elsa.EntityFrameworkCore.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Elsa.EntityFrameworkCore.Modules.Alterations; + +/// +/// Represents a class that handles entity model creation for SQLite databases. +/// +public class SetupForOracle : IEntityModelCreatingHandler +{ + /// + public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) + { + if(!dbContext.Database.IsOracle()) + return; + + // In order to use data more than 2000 char we have to use NCLOB. + // In Oracle, we have to explicitly say the column is NCLOB otherwise it would be considered nvarchar(2000). + modelBuilder.Entity().Property("SerializedAlterations").HasColumnType("NCLOB"); + modelBuilder.Entity().Property("SerializedWorkflowInstanceIds").HasColumnType("NCLOB"); + modelBuilder.Entity().Property("SerializedLog").HasColumnType("NCLOB"); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Configurations.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Configurations.cs index c531780afc..ac15f24e33 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Configurations.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Configurations.cs @@ -19,6 +19,7 @@ internal class Configurations : IEntityTypeConfiguration, IEntityTypeConfi public void Configure(EntityTypeBuilder builder) { builder.HasIndex(x => x.Name).HasDatabaseName($"IX_{nameof(User)}_{nameof(User.Name)}").IsUnique(); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(User)}_{nameof(User.TenantId)}"); builder.Property(x => x.Roles).HasColumnName("Roles").HasConversion(StringCollectionToStringConverter, StringToStringCollectionConverter).IsRequired().Metadata.SetValueComparer(StringCollectionComparer); } @@ -26,12 +27,14 @@ public void Configure(EntityTypeBuilder builder) { builder.HasIndex(x => x.ClientId).HasDatabaseName($"IX_{nameof(Application)}_{nameof(Application.ClientId)}").IsUnique(); builder.HasIndex(x => x.Name).HasDatabaseName($"IX_{nameof(Application)}_{nameof(Application.Name)}").IsUnique(); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(Application)}_{nameof(Application.TenantId)}"); builder.Property(x => x.Roles).HasColumnName("Roles").HasConversion(StringCollectionToStringConverter, StringToStringCollectionConverter).IsRequired().Metadata.SetValueComparer(StringCollectionComparer); } public void Configure(EntityTypeBuilder builder) { builder.HasIndex(x => x.Name).HasDatabaseName($"IX_{nameof(Role)}_{nameof(Role.Name)}").IsUnique(); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(Role)}_{nameof(Role.TenantId)}"); builder.Property(x => x.Permissions).HasColumnName("Permissions").HasConversion(StringCollectionToStringConverter, StringToStringCollectionConverter).IsRequired().Metadata.SetValueComparer(StringCollectionComparer); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/DbContext.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/DbContext.cs index 7ec3b4fa3d..3d65f52425 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/DbContext.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/DbContext.cs @@ -10,7 +10,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Identity; public class IdentityElsaDbContext : ElsaDbContextBase { /// - public IdentityElsaDbContext(DbContextOptions options) : base(options) + public IdentityElsaDbContext(DbContextOptions options, IServiceProvider serviceProvider) : base(options, serviceProvider) { } @@ -18,7 +18,7 @@ public IdentityElsaDbContext(DbContextOptions options) : base(options) /// The users. /// public DbSet Users { get; set; } = default!; - + /// /// The applications. /// @@ -30,8 +30,10 @@ public IdentityElsaDbContext(DbContextOptions options) : base(options) public DbSet Roles { get; set; } = default!; /// - protected override void ApplyEntityConfigurations(ModelBuilder modelBuilder) + protected override void OnModelCreating(ModelBuilder modelBuilder) { + base.OnModelCreating(modelBuilder); + var config = new Configurations(); modelBuilder.ApplyConfiguration(config); modelBuilder.ApplyConfiguration(config); diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Feature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Feature.cs index a314772330..af6819c85b 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Feature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Identity/Feature.cs @@ -13,7 +13,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Identity; /// [DependsOn(typeof(IdentityFeature))] [PublicAPI] -public class EFCoreIdentityPersistenceFeature : PersistenceFeatureBase +public class EFCoreIdentityPersistenceFeature : PersistenceFeatureBase { /// public EFCoreIdentityPersistenceFeature(IModule module) : base(module) diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/Configurations.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/Configurations.cs index 782ca7f15f..b20ea10888 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/Configurations.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/Configurations.cs @@ -15,5 +15,6 @@ public void Configure(EntityTypeBuilder builder) builder.HasIndex(x => x.WorkflowDefinitionId).HasDatabaseName($"{nameof(WorkflowDefinitionLabel)}_{nameof(WorkflowDefinitionLabel.WorkflowDefinitionId)}"); builder.HasIndex(x => x.WorkflowDefinitionVersionId).HasDatabaseName($"{nameof(WorkflowDefinitionLabel)}_{nameof(WorkflowDefinitionLabel.WorkflowDefinitionVersionId)}"); builder.HasIndex(x => x.LabelId).HasDatabaseName($"{nameof(WorkflowDefinitionLabel)}_{nameof(WorkflowDefinitionLabel.LabelId)}"); + builder.HasIndex(x => x.TenantId).HasDatabaseName($"{nameof(WorkflowDefinitionLabel)}_{nameof(WorkflowDefinitionLabel.TenantId)}"); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/DbContext.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/DbContext.cs index 88bae96476..72f5bbfa6b 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/DbContext.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Labels/DbContext.cs @@ -6,15 +6,18 @@ namespace Elsa.EntityFrameworkCore.Modules.Labels; public class LabelsElsaDbContext : ElsaDbContextBase { - public LabelsElsaDbContext(DbContextOptions options) : base(options) + public LabelsElsaDbContext(DbContextOptions options, IServiceProvider serviceProvider) : base(options, serviceProvider) { } - + public DbSet