diff --git a/Directory.Packages.props b/Directory.Packages.props index 48d6cdfc5..329ccbdbf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,8 +3,8 @@ 8.2.0 2.14.1 3.3.0-rc7 - 8.3.0 - 8.3.0 + 8.3.4 + 8.3.4 8.0.0 8.0.0 8.0.0 diff --git a/apps/vben5/apps/app-antd/src/locales/index.ts b/apps/vben5/apps/app-antd/src/locales/index.ts index 60e61112a..ea615d6fd 100644 --- a/apps/vben5/apps/app-antd/src/locales/index.ts +++ b/apps/vben5/apps/app-antd/src/locales/index.ts @@ -15,6 +15,7 @@ import { useAbpStore } from '@abp/core'; import antdEnLocale from 'ant-design-vue/es/locale/en_US'; import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN'; import dayjs from 'dayjs'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; import { useAbpConfigApi } from '#/api/core/useAbpConfigApi'; @@ -72,6 +73,7 @@ async function loadDayjsLocale(lang: SupportedLanguagesType) { } } if (locale) { + dayjs.extend(localizedFormat); dayjs.locale(locale); } else { console.error(`Failed to load dayjs locale for ${lang}`); diff --git a/aspnet-core/LINGYUN.MicroService.SingleProject.sln b/aspnet-core/LINGYUN.MicroService.SingleProject.sln index 967bd3158..1eac58707 100644 --- a/aspnet-core/LINGYUN.MicroService.SingleProject.sln +++ b/aspnet-core/LINGYUN.MicroService.SingleProject.sln @@ -618,6 +618,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.Application EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Encryption.SM4", "framework\security\LINGYUN.Abp.Encryption.SM4\LINGYUN.Abp.Encryption.SM4.csproj", "{15106D95-EE9A-4C9D-AB12-41FBE46A9A89}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer", "modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer.csproj", "{EB3EC78D-CD1C-423F-B866-74E0DC8D429D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql", "modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql\LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql.csproj", "{C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql", "migrations\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql.csproj", "{FCD95DCE-9DF4-403C-966C-FF19ADD2EA43}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1628,6 +1634,18 @@ Global {15106D95-EE9A-4C9D-AB12-41FBE46A9A89}.Debug|Any CPU.Build.0 = Debug|Any CPU {15106D95-EE9A-4C9D-AB12-41FBE46A9A89}.Release|Any CPU.ActiveCfg = Release|Any CPU {15106D95-EE9A-4C9D-AB12-41FBE46A9A89}.Release|Any CPU.Build.0 = Release|Any CPU + {EB3EC78D-CD1C-423F-B866-74E0DC8D429D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB3EC78D-CD1C-423F-B866-74E0DC8D429D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB3EC78D-CD1C-423F-B866-74E0DC8D429D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB3EC78D-CD1C-423F-B866-74E0DC8D429D}.Release|Any CPU.Build.0 = Release|Any CPU + {C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01}.Release|Any CPU.Build.0 = Release|Any CPU + {FCD95DCE-9DF4-403C-966C-FF19ADD2EA43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCD95DCE-9DF4-403C-966C-FF19ADD2EA43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCD95DCE-9DF4-403C-966C-FF19ADD2EA43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCD95DCE-9DF4-403C-966C-FF19ADD2EA43}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1928,6 +1946,9 @@ Global {77B3C7A4-15C7-4EFF-8451-4F13B4CCA4AE} = {C22741F9-FC56-4AE3-B543-9F15C779D345} {746813A9-4221-42D8-AAB5-66CB69EC844F} = {0D69B63D-F082-4D57-9FF0-355642C56993} {15106D95-EE9A-4C9D-AB12-41FBE46A9A89} = {99B7CBDE-A251-4738-97F0-DB1DB484BEE1} + {EB3EC78D-CD1C-423F-B866-74E0DC8D429D} = {07DFEB1E-ED92-4E97-A801-FAB2D70F4F35} + {C4761F7E-6DFB-4D84-BCA1-38A7EDC28B01} = {07DFEB1E-ED92-4E97-A801-FAB2D70F4F35} + {FCD95DCE-9DF4-403C-966C-FF19ADD2EA43} = {0D69B63D-F082-4D57-9FF0-355642C56993} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1} diff --git a/aspnet-core/LINGYUN.MicroService.Workflow.sln b/aspnet-core/LINGYUN.MicroService.Workflow.sln index be7c2023c..eae44fa72 100644 --- a/aspnet-core/LINGYUN.MicroService.Workflow.sln +++ b/aspnet-core/LINGYUN.MicroService.Workflow.sln @@ -175,6 +175,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Elsa.EntityFram EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer", "modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer.csproj", "{22BB3760-8DA1-4714-ADB7-1585A4EB8496}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.x", "2.x", "{618DAF98-06CE-48BB-8A48-60C92C55F9FC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.x", "3.x", "{52E78BD0-DB63-4C5A-A88E-9AD3EFB2E618}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ElsaNext", "modules\elsa\LINGYUN.Abp.ElsaNext\LINGYUN.Abp.ElsaNext.csproj", "{90D14180-20AC-44E6-BC7B-D9DA0868C5E1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ElsaNext.Server", "modules\elsa\LINGYUN.Abp.ElsaNext.Server\LINGYUN.Abp.ElsaNext.Server.csproj", "{F6A800FC-3DE0-410E-9096-92404F11E2D1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.x", "2.x", "{55400168-8E20-4D10-A3F0-FC591271E71F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.x", "3.x", "{9CD04B74-AA10-4253-BEEC-4837D48AD3EB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.WorkflowManagement.Next.HttpApi.Host", "services\LY.MicroService.WorkflowManagement.Next.HttpApi.Host\LY.MicroService.WorkflowManagement.Next.HttpApi.Host.csproj", "{09CDA563-DE16-41F6-B61C-56102E7D9B2E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -469,30 +483,42 @@ Global {22BB3760-8DA1-4714-ADB7-1585A4EB8496}.Debug|Any CPU.Build.0 = Debug|Any CPU {22BB3760-8DA1-4714-ADB7-1585A4EB8496}.Release|Any CPU.ActiveCfg = Release|Any CPU {22BB3760-8DA1-4714-ADB7-1585A4EB8496}.Release|Any CPU.Build.0 = Release|Any CPU + {90D14180-20AC-44E6-BC7B-D9DA0868C5E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90D14180-20AC-44E6-BC7B-D9DA0868C5E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90D14180-20AC-44E6-BC7B-D9DA0868C5E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90D14180-20AC-44E6-BC7B-D9DA0868C5E1}.Release|Any CPU.Build.0 = Release|Any CPU + {F6A800FC-3DE0-410E-9096-92404F11E2D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6A800FC-3DE0-410E-9096-92404F11E2D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6A800FC-3DE0-410E-9096-92404F11E2D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6A800FC-3DE0-410E-9096-92404F11E2D1}.Release|Any CPU.Build.0 = Release|Any CPU + {09CDA563-DE16-41F6-B61C-56102E7D9B2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09CDA563-DE16-41F6-B61C-56102E7D9B2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09CDA563-DE16-41F6-B61C-56102E7D9B2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09CDA563-DE16-41F6-B61C-56102E7D9B2E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B} = {6CB521FC-AC40-49A6-B9A5-91399CAA59AB} - {17EA5194-BBE8-4CE1-B6F9-DF6829622F38} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {88AA0D46-597E-4969-8382-A3F8054B9409} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {CAC0D3A2-8BFA-4A84-A7FA-550A3BB16288} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {81CB5141-4FC5-413A-A516-CD65F40465C0} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {F5023AD3-D9C5-40C9-B76A-58D95E441997} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {4FD7B21B-3689-4D4A-BDD2-A07E2DC2E80C} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {FF3A193B-6131-4B4D-9729-1BF8A125C0AB} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B} = {55400168-8E20-4D10-A3F0-FC591271E71F} + {17EA5194-BBE8-4CE1-B6F9-DF6829622F38} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {88AA0D46-597E-4969-8382-A3F8054B9409} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {CAC0D3A2-8BFA-4A84-A7FA-550A3BB16288} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {81CB5141-4FC5-413A-A516-CD65F40465C0} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {F5023AD3-D9C5-40C9-B76A-58D95E441997} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {4FD7B21B-3689-4D4A-BDD2-A07E2DC2E80C} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {FF3A193B-6131-4B4D-9729-1BF8A125C0AB} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} {18A20311-84D8-49C4-B7BA-1187FF25E9BC} = {54C52918-0B8B-4036-B673-23BE74AFFA95} {2C3FABD7-808B-47B5-A194-849A1738E9A2} = {927A4A04-56EF-4A0F-B17C-E80ABA78C554} {8BE6BA3E-048E-4FC7-81DD-7FCD29AE2126} = {7AF97C49-F445-4D77-9DBF-1A211933A471} - {9E213E6F-77CB-4068-93EB-465C47FDA8FA} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {EEE9DF30-1901-4070-8E03-A8D8A0E10E34} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {9E213E6F-77CB-4068-93EB-465C47FDA8FA} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {EEE9DF30-1901-4070-8E03-A8D8A0E10E34} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} {CE1B9AD0-7CDA-4459-86A3-A3162C1095D9} = {927A4A04-56EF-4A0F-B17C-E80ABA78C554} - {2CA34976-4A80-485C-8572-6004829BB727} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {2CA34976-4A80-485C-8572-6004829BB727} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} {44E4EBFA-6F25-4FD7-A4B3-536C3A42677C} = {7C1D7F97-1D2C-47F3-B3E7-8275D57267C4} {6489B162-2B28-42B9-9AD4-EB5CCBB8AE85} = {7C1D7F97-1D2C-47F3-B3E7-8275D57267C4} {B6246B7A-4095-433A-B981-5D1E43CDF712} = {7C1D7F97-1D2C-47F3-B3E7-8275D57267C4} - {4B20572A-10E7-4414-943A-974F275677B4} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {4B20572A-10E7-4414-943A-974F275677B4} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} {9F96F261-93F7-47C0-8F07-72CE39CE20A3} = {035B86BF-DD63-4A78-B8CE-29994860C948} {8395DA41-AF40-4B0D-B36D-FA8A56E75AED} = {035B86BF-DD63-4A78-B8CE-29994860C948} {B3C2AFCC-EE59-4CB4-AB62-B90D60335632} = {035B86BF-DD63-4A78-B8CE-29994860C948} @@ -501,7 +527,7 @@ Global {90B326F6-99DF-4EEC-A480-26C27EE22237} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {96EBCB1F-DB7B-40BA-B59E-82FC1AE13EA0} = {927A4A04-56EF-4A0F-B17C-E80ABA78C554} {6399C2FB-B063-4BB3-B605-88CE5303198B} = {927A4A04-56EF-4A0F-B17C-E80ABA78C554} - {D2F6105D-D667-46DB-8CDA-89B4D3F69067} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {D2F6105D-D667-46DB-8CDA-89B4D3F69067} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} {CE550720-FA77-4FF3-B5F0-A2B7A1781E61} = {7B82C484-4DDF-45F2-B5FC-DFA9FFC3258B} {ECA9D3FA-248F-4D0E-A612-FE1CC72241D5} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {C2F7971A-CFCE-4BE0-9A3A-805972A5F00B} = {7B82C484-4DDF-45F2-B5FC-DFA9FFC3258B} @@ -546,8 +572,15 @@ Global {1859E205-88DC-4E08-A0BD-55A045DCC495} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {6ECF678D-6F3A-4084-8538-A86C1D67C703} = {9C73D4E6-4408-4717-B51C-63C20321D4DA} {9FB5E943-7F6F-4281-9C00-E76284B4F1F3} = {9C73D4E6-4408-4717-B51C-63C20321D4DA} - {D56851BB-557E-4CF9-B724-8E607EEE9D07} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} - {22BB3760-8DA1-4714-ADB7-1585A4EB8496} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {D56851BB-557E-4CF9-B724-8E607EEE9D07} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {22BB3760-8DA1-4714-ADB7-1585A4EB8496} = {618DAF98-06CE-48BB-8A48-60C92C55F9FC} + {618DAF98-06CE-48BB-8A48-60C92C55F9FC} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {52E78BD0-DB63-4C5A-A88E-9AD3EFB2E618} = {F1CCBEC7-ACAB-4DC5-909E-D8CC2E1B7EEC} + {90D14180-20AC-44E6-BC7B-D9DA0868C5E1} = {52E78BD0-DB63-4C5A-A88E-9AD3EFB2E618} + {F6A800FC-3DE0-410E-9096-92404F11E2D1} = {52E78BD0-DB63-4C5A-A88E-9AD3EFB2E618} + {55400168-8E20-4D10-A3F0-FC591271E71F} = {6CB521FC-AC40-49A6-B9A5-91399CAA59AB} + {9CD04B74-AA10-4253-BEEC-4837D48AD3EB} = {6CB521FC-AC40-49A6-B9A5-91399CAA59AB} + {09CDA563-DE16-41F6-B61C-56102E7D9B2E} = {9CD04B74-AA10-4253-BEEC-4837D48AD3EB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xml b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xml new file mode 100644 index 000000000..5d6962159 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xsd b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN.Abp.ElsaNext.Server.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN.Abp.ElsaNext.Server.csproj new file mode 100644 index 000000000..701112322 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN.Abp.ElsaNext.Server.csproj @@ -0,0 +1,28 @@ + + + + + + + net8.0 + LINGYUN.Abp.ElsaNext.Server + LINGYUN.Abp.ElsaNext.Server + false + false + false + + Enable + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN/Abp/ElsaNext/Server/AbpElsaNextServerModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN/Abp/ElsaNext/Server/AbpElsaNextServerModule.cs new file mode 100644 index 000000000..409295960 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Server/LINGYUN/Abp/ElsaNext/Server/AbpElsaNextServerModule.cs @@ -0,0 +1,41 @@ +using Elsa.Extensions; +using Elsa.Features.Services; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.ElsaNext.Server; + +[DependsOn(typeof(AbpElsaNextModule))] +public class AbpElsaNextServerModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(elsa => + { + // see: https://v3.elsaworkflows.io/docs/installation/elsa-server + + // Expose Elsa API endpoints. + elsa.UseWorkflowsApi(); + + // Setup a SignalR hub for real-time updates from the server. + elsa.UseRealTimeWorkflows(); + + // Enable C# workflow expressions + elsa.UseCSharp(); + + // Enable Liquid workflow expressions. + elsa.UseLiquid(); + + // Enable HTTP activities. + elsa.UseHttp(); + + // Use timer activities. + elsa.UseScheduling(); + + // Register custom activities from the application, if any. + elsa.AddActivitiesFrom(); + + // Register custom workflows from the application, if any. + elsa.AddWorkflowsFrom(); + }); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xml b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xml new file mode 100644 index 000000000..5d6962159 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xsd b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN.Abp.ElsaNext.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN.Abp.ElsaNext.csproj new file mode 100644 index 000000000..957d001a4 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN.Abp.ElsaNext.csproj @@ -0,0 +1,28 @@ + + + + + + + net8.0 + LINGYUN.Abp.ElsaNext + LINGYUN.Abp.ElsaNext + false + false + false + + Enable + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaIdentityGenerator.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaIdentityGenerator.cs new file mode 100644 index 000000000..7ca4f748d --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaIdentityGenerator.cs @@ -0,0 +1,19 @@ +using Elsa.Workflows; +using Volo.Abp.Guids; + +namespace LINGYUN.Abp.ElsaNext; + +public class AbpElsaIdentityGenerator : IIdentityGenerator +{ + private readonly IGuidGenerator _guidGenerator; + + public AbpElsaIdentityGenerator(IGuidGenerator guidGenerator) + { + _guidGenerator = guidGenerator; + } + + public string GenerateId() + { + return _guidGenerator.Create().ToString("N"); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextAutoMapperProfile.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextAutoMapperProfile.cs new file mode 100644 index 000000000..f6cad9125 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextAutoMapperProfile.cs @@ -0,0 +1,10 @@ +using AutoMapper; + +namespace LINGYUN.Abp.ElsaNext; +public class AbpElsaNextAutoMapperProfile : Profile +{ + public AbpElsaNextAutoMapperProfile() + { + + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextModule.cs new file mode 100644 index 000000000..193c7b789 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/AbpElsaNextModule.cs @@ -0,0 +1,62 @@ +using Elsa.Common.Features; +using Elsa.Common.Multitenancy; +using Elsa.Extensions; +using Elsa.Features.Services; +using Elsa.Tenants.Extensions; +using Elsa.Workflows; +using LINGYUN.Abp.ElsaNext.Localization; +using LINGYUN.Abp.ElsaNext.Multitenancy; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.AutoMapper; +using Volo.Abp.Features; +using Volo.Abp.Json; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.ElsaNext; + +[DependsOn( + typeof(AbpAutoMapperModule), + typeof(AbpFeaturesModule), + typeof(AbpThreadingModule), + typeof(AbpJsonModule))] +public class AbpElsaNextModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddScoped(); + + var elsaModule = context.Services.GetPreConfigureActions(); + + context.Services.AddElsa(elsa => + { + elsa + .AddActivitiesFrom() + .AddWorkflowsFrom() + .UseTenants(tenants => + { + tenants.ConfigureMultitenancy(options => + { + options.TenantResolverPipelineBuilder.Append(); + }); + }); + + elsa.Configure(feature => + { + feature.UseTenantsProvider(); + }); + + elsaModule.Configure(elsa); + }); + + context.Services.Replace( + ServiceDescriptor.Singleton()); + + Configure(options => + { + options.Resources.Add("en"); + }); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Localization/ElsaNextResource.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Localization/ElsaNextResource.cs new file mode 100644 index 000000000..375fa4d8e --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Localization/ElsaNextResource.cs @@ -0,0 +1,8 @@ +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.ElsaNext.Localization; + +[LocalizationResourceName("ElsaNext")] +public class ElsaNextResource +{ +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantResolver.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantResolver.cs new file mode 100644 index 000000000..c70fe041f --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantResolver.cs @@ -0,0 +1,18 @@ +using Elsa.Common.Multitenancy; +using System.Threading.Tasks; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.ElsaNext.Multitenancy; +public class AbpTenantResolver(ITenantConfigurationProvider tenantConfigurationProvider) : TenantResolverBase +{ + protected async override Task ResolveAsync(TenantResolverContext context) + { + var tenant = await tenantConfigurationProvider.GetAsync(); + if (tenant == null) + { + return Unresolved(); + } + + return AutoResolve(tenant.Id.ToString()); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantsProvider.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantsProvider.cs new file mode 100644 index 000000000..68fb642f1 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/Multitenancy/AbpTenantsProvider.cs @@ -0,0 +1,42 @@ +using Elsa.Common.Multitenancy; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.ElsaNext.Multitenancy; +public class AbpTenantsProvider : ITenantsProvider +{ + private readonly ITenantStore _tenantStore; + public AbpTenantsProvider(ITenantStore tenantStore) + { + _tenantStore = tenantStore; + } + + public async virtual Task FindAsync(TenantFilter filter, CancellationToken cancellationToken = default) + { + if (Guid.TryParse(filter.Id, out var tenantId)) + { + var tenant = await _tenantStore.FindAsync(tenantId); + return tenant != null ? new Tenant + { + Id = tenant.Id.ToString(), + Name = tenant.Name, + } : null; + } + return null; + } + + public async virtual Task> ListAsync(CancellationToken cancellationToken = default) + { + var tenants = await _tenantStore.GetListAsync(); + + return tenants.Select(tenant => new Tenant + { + Id = tenant.Id.ToString(), + Name = tenant.Name + }); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/README.md b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/README.md new file mode 100644 index 000000000..189f7755d --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/README.md @@ -0,0 +1,29 @@ +# LINGYUN.Abp.ElsaNext + +[elsa-core](https://github.com/elsa-workflows/elsa-core) 工作流的abp集成(3.x版本) + +## 特性 + +* 定义**AbpTenantResolver**与多租户集成,使elsa支持abp租户解析 +* 定义**AbpTenantsProvider**与多租户集成,使elsa从abp中取租户信息 +* 定义**AbpElsaIdGenerator**通过**IGuidGenerator**接口生成工作流标识 +* 定义**abp**相关JavaScript扩展 + +## 配置使用 + +```csharp + + [DependsOn( + typeof(AbpElsaNextModule) + )] + public class YouProjectModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(elsa => + { + // 自定义elsa相关配置 + }); + } + } +``` \ No newline at end of file diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/DefaultIdentitySessionChecker.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/DefaultIdentitySessionChecker.cs index 0b0f69dfd..6bb746682 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/DefaultIdentitySessionChecker.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN/Abp/Identity/Session/DefaultIdentitySessionChecker.cs @@ -70,14 +70,15 @@ public class DefaultIdentitySessionChecker : IIdentitySessionChecker, ITransient identitySessionCacheItem.LastAccessed = accressedTime; identitySessionCacheItem.IpAddresses = DeviceInfoProvider.ClientIpAddress; + // TODO: 暂时移除,否则刷新令牌将无效 // 2024-10-10 从令牌中取颁布时间与过期时间计算时间戳,作为默认缓存过期时间 - var expirainTime = claimsPrincipal.FindExpirainTime(); - var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - if (expirainTime.HasValue) - { - // 2024-10-25 应计算剩余过期时间 - identitySessionCacheItem.ExpiraIn = (expirainTime.Value - timestamp) * 1000; - } + //var expirainTime = claimsPrincipal.FindExpirainTime(); + //var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + //if (expirainTime.HasValue) + //{ + // // 2024-10-25 应计算剩余过期时间 + // identitySessionCacheItem.ExpiraIn = (expirainTime.Value - timestamp) * 1000; + //} Logger.LogDebug($"Refresh the user access info in the cache from {sessionId}."); await IdentitySessionCache.RefreshAsync(sessionId, identitySessionCacheItem, cancellationToken); diff --git a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json index 6f6a2b0a2..12fd97f4f 100644 --- a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json +++ b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json @@ -73,6 +73,7 @@ "Available": "Available", "Propertites:New": "New Property", "Propertites:Key": "Key", - "Propertites:Value": "Value" + "Propertites:Value": "Value", + "Requirements:PKCE": "Enabling PKCE enforcement" } } \ No newline at end of file diff --git a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json index 8bb76ac83..97ef91bab 100644 --- a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json @@ -73,6 +73,7 @@ "Available": "已拥有的", "Propertites:New": "新属性", "Propertites:Key": "属性名称", - "Propertites:Value": "属性值" + "Propertites:Value": "属性值", + "Requirements:PKCE": "启用PKCE" } } \ No newline at end of file diff --git a/aspnet-core/services/Directory.Packages.props b/aspnet-core/services/Directory.Packages.props index 84f4c0737..07b6d5424 100644 --- a/aspnet-core/services/Directory.Packages.props +++ b/aspnet-core/services/Directory.Packages.props @@ -3,53 +3,6 @@ 8.3.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj b/aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj index 0fbfdd223..04284570c 100644 --- a/aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj +++ b/aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj @@ -212,8 +212,6 @@ - - @@ -261,12 +259,4 @@ - - - - - - - - diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs index 6b72a8062..827d0b29a 100644 --- a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs @@ -251,6 +251,16 @@ public partial class MicroServiceApplicationsSingleModule options.DisableTransportSecurityRequirement = true; }); + Configure(options => + { + options.PersistentSessionGrantTypes.Add(SmsTokenExtensionGrantConsts.GrantType); + options.PersistentSessionGrantTypes.Add(PortalTokenExtensionGrantConsts.GrantType); + options.PersistentSessionGrantTypes.Add(LinkUserTokenExtensionGrantConsts.GrantType); + options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.OfficialGrantType); + options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.MiniProgramGrantType); + options.PersistentSessionGrantTypes.Add(AbpWeChatWorkGlobalConsts.GrantType); + }); + Configure(options => { var lifetime = configuration.GetSection("OpenIddict:Lifetime"); @@ -262,15 +272,6 @@ public partial class MicroServiceApplicationsSingleModule options.RefreshTokenReuseLeeway = lifetime.GetValue("RefreshTokenReuseLeeway", options.RefreshTokenReuseLeeway); options.UserCodeLifetime = lifetime.GetValue("UserCode", options.UserCodeLifetime); }); - Configure(options => - { - options.PersistentSessionGrantTypes.Add(SmsTokenExtensionGrantConsts.GrantType); - options.PersistentSessionGrantTypes.Add(PortalTokenExtensionGrantConsts.GrantType); - options.PersistentSessionGrantTypes.Add(LinkUserTokenExtensionGrantConsts.GrantType); - options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.OfficialGrantType); - options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.MiniProgramGrantType); - options.PersistentSessionGrantTypes.Add(AbpWeChatWorkGlobalConsts.GrantType); - }); } private void ConfigureEndpoints(IServiceCollection services) diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/.gitignore b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/.gitignore new file mode 100644 index 000000000..8d69d5adc --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/.gitignore @@ -0,0 +1 @@ +elsa.sqlite.* \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpActivityFactory.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpActivityFactory.cs new file mode 100644 index 000000000..4286abc2a --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpActivityFactory.cs @@ -0,0 +1,113 @@ +using Elsa.Expressions.Helpers; +using Elsa.Extensions; +using Elsa.Workflows; +using Elsa.Workflows.Memory; +using Elsa.Workflows.Models; +using Humanizer; +using System.Text.Json; + +namespace LY.MicroService.WorkflowManagement.Next; + +public class AbpActivityFactory : IActivityFactory +{ + public IActivity Create(Type type, ActivityConstructorContext context) + { + // Backwards compatibility for older JSON schemas. + var canStartWorkflow = GetBoolean(context.Element, "canStartWorkflow"); + var runAsynchronously = GetBoolean(context.Element, "runAsynchronously"); + var activityElement = context.Element; + var activityDescriptor = context.ActivityDescriptor; + var activity = (IActivity)context.Element.Deserialize(type, context.SerializerOptions)!; + var composite = activity as IComposite; + + composite?.Setup(); + + // TODO: 反序列化未创建默认值? + if (activityDescriptor != null) + { + ReadSyntheticInputs(activityDescriptor, activity, activityElement, context.SerializerOptions); + ReadSyntheticOutputs(activityDescriptor, activity, activityElement); + } + + activity.SetCanStartWorkflow(canStartWorkflow); + activity.SetRunAsynchronously(runAsynchronously); + + return activity; + } + + private void ReadSyntheticInputs(ActivityDescriptor activityDescriptor, IActivity activity, JsonElement activityRoot, JsonSerializerOptions options) + { + foreach (var inputDescriptor in activityDescriptor.Inputs.Where(x => x.IsSynthetic)) + { + var inputName = inputDescriptor.Name; + var propertyName = inputName.Camelize(); + var nakedType = inputDescriptor.Type; + var wrappedType = typeof(Input<>).MakeGenericType(nakedType); + + if (!activityRoot.TryGetProperty(propertyName, out var propertyElement) || propertyElement.ValueKind == JsonValueKind.Null || propertyElement.ValueKind == JsonValueKind.Undefined) + continue; + + var isWrapped = propertyElement.ValueKind == JsonValueKind.Object && propertyElement.GetProperty("typeName").ValueKind != JsonValueKind.Undefined; + + if (isWrapped) + { + var json = propertyElement.ToString(); + var inputValue = JsonSerializer.Deserialize(json, wrappedType, options); + + activity.SyntheticProperties[inputName] = inputValue!; + } + else + { + activity.SyntheticProperties[inputName] = propertyElement.ConvertTo(inputDescriptor.Type)!; + } + } + } + + private void ReadSyntheticOutputs(ActivityDescriptor activityDescriptor, IActivity activity, JsonElement activityRoot) + { + foreach (var outputDescriptor in activityDescriptor.Outputs.Where(x => x.IsSynthetic)) + { + var outputName = outputDescriptor.Name; + var propertyName = outputName.Camelize(); + var nakedType = outputDescriptor.Type; + var wrappedType = typeof(Output<>).MakeGenericType(nakedType); + + if (!activityRoot.TryGetProperty(propertyName, out var propertyElement) || propertyElement.ValueKind == JsonValueKind.Null || propertyElement.ValueKind == JsonValueKind.Undefined) + continue; + + var memoryReferenceElement = propertyElement.GetProperty("memoryReference"); + + if (!memoryReferenceElement.TryGetProperty("id", out var memoryReferenceIdElement)) + continue; + + var variable = new Variable + { + Id = memoryReferenceIdElement.GetString()! + }; + variable.Name = variable.Id; + + var output = Activator.CreateInstance(wrappedType, variable)!; + + activity.SyntheticProperties[outputName] = output!; + } + } + + private static bool GetBoolean(JsonElement element, string propertyName) + { + var propertyNames = new[] { propertyName.Camelize(), propertyName.Pascalize() }; + + foreach (var name in propertyNames) + { + if (element.TryGetProperty("customProperties", out var customPropertyElement)) + { + if (customPropertyElement.TryGetProperty(name, out var canStartWorkflowElement)) + return canStartWorkflowElement.GetBoolean(); + } + + if (element.TryGetProperty(propertyName.Camelize(), out var property) && property.GetBoolean()) + return true; + } + + return false; + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpBlazorServerCultureService.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpBlazorServerCultureService.cs new file mode 100644 index 000000000..46fc009c7 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/AbpBlazorServerCultureService.cs @@ -0,0 +1,29 @@ +using Elsa.Studio.Localization.Services; +using Microsoft.AspNetCore.Components; +using System.Globalization; + +namespace LY.MicroService.WorkflowManagement.Next; + +public class AbpBlazorServerCultureService(NavigationManager navigationManager) : ICultureService +{ + public Task ChangeCultureAsync(CultureInfo culture) + { + if (CultureInfo.CurrentUICulture.Name != culture.Name) + { + var cultureString = culture.Name; + var uri = new Uri(navigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped); + + // Set culture of the current thread. + CultureInfo.CurrentCulture = culture; + CultureInfo.CurrentUICulture = culture; + var cultureEscaped = Uri.EscapeDataString(cultureString); + // var uriEscaped = Uri.EscapeDataString(uri); + + navigationManager.NavigateTo( + $"Culture/Set?culture={cultureEscaped}&redirectUri=/", + forceLoad: true); + } + + return Task.CompletedTask; + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Controllers/HomeController.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 000000000..689d19362 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace LY.MicroService.WorkflowManagement.Next.Controllers; + +public class HomeController : AbpControllerBase +{ + public IActionResult Index() + { + return Redirect("/swagger/index.html"); + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/LY.MicroService.WorkflowManagement.Next.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/LY.MicroService.WorkflowManagement.Next.HttpApi.Host.csproj new file mode 100644 index 000000000..6b3d9a601 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/LY.MicroService.WorkflowManagement.Next.HttpApi.Host.csproj @@ -0,0 +1,61 @@ + + + + net8.0 + enable + enable + LY.MicroService.WorkflowManagement.Next + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml new file mode 100644 index 000000000..122874b25 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml @@ -0,0 +1,61 @@ +@page "/" +@namespace LY.MicroService.WorkflowManagement.Next.Pages + +@inject IConfiguration Configuration; +@{ + var baseUrl = $"{Request.Scheme}://{Request.Host}"; + var apiUrl = baseUrl + Url.Content("~/elsa/api"); + var basePath = ""; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + + + + + + + \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml.cs new file mode 100644 index 000000000..b89af3c6a --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_Host.cshtml.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace LY.MicroService.WorkflowManagement.Next.Pages +{ + public class _HostModel : PageModel + { + public void OnGet() + { + } + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_ViewImports.cshtml b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_ViewImports.cshtml new file mode 100644 index 000000000..78403a954 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@using Elsa.Studio.Shell +@using Microsoft.Extensions.Configuration +@using Microsoft.AspNetCore.Components.Web +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Program.cs new file mode 100644 index 000000000..5e6b024ae --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Program.cs @@ -0,0 +1,89 @@ +using Elsa.Extensions; +using Elsa.Studio.Contracts; +using Elsa.Studio.Localization.BlazorServer.Extensions; +using LY.MicroService.WorkflowManagement.Next; +using Serilog; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +var builder = WebApplication.CreateBuilder(args); + +builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + var agileConfigEnabled = context.Configuration["AgileConfig:IsEnabled"]; + if (context.Configuration.GetSection("AgileConfig").Exists() && + (agileConfigEnabled.IsNullOrWhiteSpace() || bool.Parse(agileConfigEnabled))) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + +await builder.AddApplicationAsync(options => +{ + options.ApplicationName = "AbpElsaNextWebModule"; + // ӻȡû, + options.Configuration.UserSecretsId = Environment.GetEnvironmentVariable("APPLICATION_USER_SECRETS_ID"); + // ûָû, Ŀȡ + options.Configuration.UserSecretsAssembly = typeof(WorkflowManagementNextHttpApiHostModule).Assembly; + // Modules Ŀ¼ļΪ + // ȡʾĿģ飬Ϊͨʽ + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + + DirectoryHelper.CreateIfNotExists(pluginFolder); + + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); +}); + +// Build the web application. +var app = builder.Build(); + +await app.InitializeApplicationAsync(); + +// Run each startup task. +var startupTaskRunner = app.Services.GetRequiredService(); +await startupTaskRunner.RunStartupTasksAsync(); + +// Configure web application's middleware pipeline. +// Configure the HTTP request pipeline. +if (!app.Environment.IsDevelopment()) +{ + app.UseResponseCompression(); + + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseCors(); +app.UseForwardedHeaders(); +app.UseCorrelationId(); +app.UseElsaLocalization(); +app.UseStaticFiles(); +app.UseRouting(); // Required for SignalR. +app.UseAuthentication(); +app.UseJwtTokenMiddleware(); +app.UseMultiTenancy(); +app.UseDynamicClaims(); +app.UseAuthorization(); +app.MapBlazorHub(); +app.UseWorkflowsApi(); // Use Elsa API endpoints. +app.UseWorkflows(); // Use Elsa middleware to handle HTTP requests mapped to HTTP Endpoint activities. +app.UseWorkflowsSignalRHubs(); // Optional SignalR integration. Elsa Studio uses SignalR to receive real-time updates from the server. +app.UseSwagger(); +app.UseSwaggerUI(options => +{ + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API"); +}); + +app.UseAuditing(); +app.UseAbpSerilogEnrichers(); +app.UseConfiguredEndpoints(); + +app.MapFallbackToPage("/_Host"); + +await app.RunAsync(); diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 000000000..2286902eb --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:36683", + "sslPort": 0 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://127.0.0.1:30036", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/TenantHeaderParamter.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/TenantHeaderParamter.cs new file mode 100644 index 000000000..3fb4d7e1f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/TenantHeaderParamter.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LY.MicroService.WorkflowManagement.Next; + +public class TenantHeaderParamter : IOperationFilter +{ + private readonly AbpMultiTenancyOptions _multiTenancyOptions; + private readonly AbpAspNetCoreMultiTenancyOptions _aspNetCoreMultiTenancyOptions; + public TenantHeaderParamter( + IOptions multiTenancyOptions, + IOptions aspNetCoreMultiTenancyOptions) + { + _multiTenancyOptions = multiTenancyOptions.Value; + _aspNetCoreMultiTenancyOptions = aspNetCoreMultiTenancyOptions.Value; + } + + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + if (_multiTenancyOptions.IsEnabled) + { + operation.Parameters = operation.Parameters ?? new List(); + operation.Parameters.Add(new OpenApiParameter + { + Name = _aspNetCoreMultiTenancyOptions.TenantKey, + In = ParameterLocation.Header, + Description = "Tenant Id/Name in http header", + Required = false + }); + } + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/WorkflowManagementNextHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/WorkflowManagementNextHttpApiHostModule.cs new file mode 100644 index 000000000..47cc217ed --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/WorkflowManagementNextHttpApiHostModule.cs @@ -0,0 +1,147 @@ +using Elsa.EntityFrameworkCore.Extensions; +using Elsa.EntityFrameworkCore.Modules.Management; +using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.Extensions; +using Elsa.Features.Services; +using Elsa.Studio.Dashboard.Extensions; +using Elsa.Studio.Extensions; +using Elsa.Studio.Localization.BlazorServer.Extensions; +using Elsa.Studio.Localization.BlazorServer.Services; +using Elsa.Studio.Localization.Models; +using Elsa.Studio.Localization.Services; +using Elsa.Studio.Login.BlazorServer.Extensions; +using Elsa.Studio.Login.HttpMessageHandlers; +using Elsa.Studio.Models; +using Elsa.Studio.Shell.Extensions; +using Elsa.Studio.Translations; +using Elsa.Studio.Workflows.Designer.Extensions; +using Elsa.Studio.Workflows.Extensions; +using Elsa.Workflows; +using LINGYUN.Abp.ElsaNext.Server; +using Microsoft.OpenApi.Models; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Json; +using Volo.Abp.MailKit; +using Volo.Abp.Modularity; +using Volo.Abp.Swashbuckle; + +namespace LY.MicroService.WorkflowManagement.Next; + +[DependsOn(typeof(AbpElsaNextServerModule))] +[DependsOn(typeof(AbpAspNetCoreSerilogModule))] +[DependsOn(typeof(AbpAspNetCoreMultiTenancyModule))] +[DependsOn(typeof(AbpAspNetCoreAuthenticationJwtBearerModule))] +[DependsOn(typeof(AbpJsonModule))] +[DependsOn(typeof(AbpSwashbuckleModule))] +[DependsOn(typeof(AbpMailKitModule))] +[DependsOn(typeof(AbpAutofacModule))] +public class WorkflowManagementNextHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(elsa => + { + // Configure Management layer to use EF Core. + elsa.UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite())); + + // Configure Runtime layer to use EF Core. + elsa.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite())); + + // Default Identity features for authentication/authorization. + elsa.UseIdentity(identity => + { + identity.TokenOptions = options => options.SigningKey = "sufficiently-large-secret-signing-key"; // This key needs to be at least 256 bits long. + identity.UseAdminUserProvider(); + }); + + // Configure ASP.NET authentication/authorization. + elsa.UseDefaultAuthentication(auth => auth.UseAdminApiKey()); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + // Register Razor services. + context.Services.AddRazorPages(); + + context.Services.AddCoreInternal(); + context.Services.AddSharedServices(); + context.Services.AddTranslations(); + + context.Services.AddServerSideBlazor(options => + { + // Register the root components. + options.RootComponents.RegisterCustomElsaStudioElements(); + }); + // Register shell services and modules. + var backendApiConfig = new BackendApiConfig + { + ConfigureBackendOptions = options => configuration.GetSection("Backend").Bind(options), + ConfigureHttpClientBuilder = options => options.AuthenticationHandler = typeof(AuthenticatingApiHttpMessageHandler), + }; + context.Services.AddShell(options => configuration.GetSection("Shell").Bind(options)); + context.Services.AddRemoteBackend(backendApiConfig); + context.Services.AddLoginModule(); + context.Services.AddDashboardModule(); + context.Services.AddWorkflowsModule(); + context.Services.AddLocalizationModule(new LocalizationConfig + { + ConfigureLocalizationOptions = options => configuration.GetSection("Localization").Bind(options), + }); + // Configure SignalR. + context.Services.AddSignalR(options => + { + // Set MaximumReceiveMessageSize to handle large workflows. + options.MaximumReceiveMessageSize = 5 * 1024 * 1000; // 5MB + }); + + // Add Health Checks. + context.Services.AddHealthChecks(); + + + // Configure CORS to allow designer app hosted on a different origin to invoke the APIs. + context.Services.AddCors(cors => cors + .AddDefaultPolicy(policy => policy + .AllowAnyOrigin() // For demo purposes only. Use a specific origin instead. + .AllowAnyHeader() + .AllowAnyMethod() + .WithExposedHeaders("x-elsa-workflow-instance-id"))); + + // Swagger + context.Services.AddSwaggerGen( + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Workflow API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", + Name = "Authorization", + In = ParameterLocation.Header, + Scheme = "bearer", + Type = SecuritySchemeType.Http, + BearerFormat = "JWT" + }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } + }, + new string[] { } + } + }); + options.OperationFilter(); + }); + + context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.AddScoped(); + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.Development.json new file mode 100644 index 000000000..350bb5d9c --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,76 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Debug" + } + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft.AspNetCore.Routing": "Debug", + "System": "Information", + "Microsoft": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Console", + "Args": { + "initialMinimumLevel": "Verbose", + "standardErrorFromLevel": "Verbose", + "restrictedToMinimumLevel": "Verbose", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Debug-.log", + "restrictedToMinimumLevel": "Debug", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Info-.log", + "restrictedToMinimumLevel": "Information", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Warn-.log", + "restrictedToMinimumLevel": "Warning", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Error-.log", + "restrictedToMinimumLevel": "Error", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Fatal-.log", + "restrictedToMinimumLevel": "Fatal", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + } + ] + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.json b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.json new file mode 100644 index 000000000..e03a5ee82 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.Next.HttpApi.Host/appsettings.json @@ -0,0 +1,29 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Backend": { + "Url": "http://localhost:30036/elsa/api" + }, + "Hosting": { + "BaseUrl": "http://localhost:30036", + "BasePath": "/api/workflows" + }, + "Localization": { + "SupportedCultures": [ + "ar", + "de", + "fa", + "fr", + "nl", + "pt", + "uk", + "zh-Hans", + "zh-Hant" + ] + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests.csproj index 25fd83291..490c2930e 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests/LINGYUN.Abp.Elsa.Activities.Webhooks.Tests.csproj @@ -15,10 +15,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/aspnet-core/tests/LINGYUN.Abp.Elsa.Tests/LINGYUN.Abp.Elsa.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Elsa.Tests/LINGYUN.Abp.Elsa.Tests.csproj index bb4199176..9b7dae2ab 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Elsa.Tests/LINGYUN.Abp.Elsa.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Elsa.Tests/LINGYUN.Abp.Elsa.Tests.csproj @@ -15,10 +15,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all -