diff --git a/Directory.Packages.props b/Directory.Packages.props index c69c93d3f..78ac63050 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,7 @@ 9.0.5 9.0.5 9.0.5 + 13.1.0 true @@ -171,14 +172,30 @@ + + + + + + + + + + + + + + + + @@ -244,6 +261,7 @@ + @@ -305,15 +323,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/apps/vben5/apps/app-antd/.env.development b/apps/vben5/apps/app-antd/.env.development index 2e7b0f3d5..b9e43314c 100644 --- a/apps/vben5/apps/app-antd/.env.development +++ b/apps/vben5/apps/app-antd/.env.development @@ -18,7 +18,7 @@ VITE_INJECT_APP_LOADING=true # 是否仅允许OIDC登录 VITE_GLOB_ONLY_OIDC=false # 认证服务器 -VITE_GLOB_AUTHORITY="http://127.0.0.1:30001" +VITE_GLOB_AUTHORITY="http://localhost:30000" # 授权范围 VITE_GLOB_AUDIENCE="openid email address phone profile offline_access lingyun-abp-application" # 客户端Id diff --git a/apps/vben5/apps/app-antd/vite.config.mts b/apps/vben5/apps/app-antd/vite.config.mts index ae6f52e14..8a822964f 100644 --- a/apps/vben5/apps/app-antd/vite.config.mts +++ b/apps/vben5/apps/app-antd/vite.config.mts @@ -8,19 +8,19 @@ export default defineConfig(async () => { proxy: { '/.well-known': { changeOrigin: true, - target: 'http://127.0.0.1:30001/', + target: 'http://localhost:30000/', }, '/api': { changeOrigin: true, - target: 'http://127.0.0.1:30001/', + target: 'http://localhost:30000/', }, '/connect': { changeOrigin: true, - target: 'http://127.0.0.1:30001/', + target: 'http://localhost:30000/', }, '/signalr-hubs': { changeOrigin: true, - target: 'http://127.0.0.1:30001/', + target: 'http://localhost:30000/', ws: true, }, }, diff --git a/apps/vben5/packages/@abp/request/src/hooks/useWrapperResult.ts b/apps/vben5/packages/@abp/request/src/hooks/useWrapperResult.ts index 9f672f76f..2aacc6002 100644 --- a/apps/vben5/packages/@abp/request/src/hooks/useWrapperResult.ts +++ b/apps/vben5/packages/@abp/request/src/hooks/useWrapperResult.ts @@ -8,7 +8,11 @@ export function useWrapperResult(response: AxiosResponse) { const { data, headers } = response; /** 是否已包装结果 */ function hasWrapResult(): boolean { - return headers[_defaultWrapperHeaderKey] === 'true' || hasError(); + const wrapperHeader = headers[_defaultWrapperHeaderKey]; + if (!wrapperHeader) { + return false; + } + return String(wrapperHeader).includes('true') || hasError(); } /** 获取包装结果 */ diff --git a/aspnet-core/LINGYUN.MicroService.Aspire.sln b/aspnet-core/LINGYUN.MicroService.Aspire.sln new file mode 100644 index 000000000..643cb28c3 --- /dev/null +++ b/aspnet-core/LINGYUN.MicroService.Aspire.sln @@ -0,0 +1,2896 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "framework", "framework", "{C5CAD011-DF84-4914-939C-0C029DCEF26F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "settings", "settings", "{BA00B3F2-199B-40E2-B0EA-0AA4F51A1C52}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.SettingManagement.Application.Contracts", "framework\settings\LINGYUN.Abp.SettingManagement.Application.Contracts\LINGYUN.Abp.SettingManagement.Application.Contracts.csproj", "{77BDEF2B-1A30-4E64-BC35-0DFC21091327}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.SettingManagement.Application", "modules\settings\LINGYUN.Abp.SettingManagement.Application\LINGYUN.Abp.SettingManagement.Application.csproj", "{573B7B0E-3065-42DE-A391-EE026CE7A366}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.SettingManagement.HttpApi", "modules\settings\LINGYUN.Abp.SettingManagement.HttpApi\LINGYUN.Abp.SettingManagement.HttpApi.csproj", "{FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identityServer", "identityServer", "{0439B173-F41E-4CE0-A44A-CCB70328F272}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application.Contracts", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application.Contracts\LINGYUN.Abp.IdentityServer.Application.Contracts.csproj", "{3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application\LINGYUN.Abp.IdentityServer.Application.csproj", "{A584D040-95AC-4422-93FF-7B80532213F0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.HttpApi", "modules\identityServer\LINGYUN.Abp.IdentityServer.HttpApi\LINGYUN.Abp.IdentityServer.HttpApi.csproj", "{76249548-4344-4CD0-A0AC-12AC54184B58}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{A5543E56-DA53-494D-A531-DA75091D46FF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{8AC72641-30D3-4ACF-89FA-808FADC55C2E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "framework\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{AEC1E6D3-DC23-41BD-B456-3AAD26E34978}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.SmsValidator", "modules\identityServer\LINGYUN.Abp.IdentityServer.SmsValidator\LINGYUN.Abp.IdentityServer.SmsValidator.csproj", "{E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{9E72FEB9-A626-4312-892B-CDD043879758}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application.Contracts", "modules\account\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj", "{8B09385A-719C-4B83-B61E-0ECD5D2734BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application", "modules\account\LINGYUN.Abp.Account.Application\LINGYUN.Abp.Account.Application.csproj", "{8E569C1C-2637-4D89-804C-50FBC83948FB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.HttpApi", "modules\account\LINGYUN.Abp.Account.HttpApi\LINGYUN.Abp.Account.HttpApi.csproj", "{5A10C02B-D12C-479C-9E7F-9A7D9DDD753D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Aliyun", "framework\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj", "{FF1839EA-FB6B-4ED5-9804-E40427046D35}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location", "framework\common\LINGYUN.Abp.Location\LINGYUN.Abp.Location.csproj", "{9FE2A95F-D7A3-4305-9E12-E955EF74CF8D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Baidu", "framework\common\LINGYUN.Abp.Location.Baidu\LINGYUN.Abp.Location.Baidu.csproj", "{6E4A0D87-C3CE-430F-A475-A6B68C116D96}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "realtime-message", "realtime-message", "{3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Shared", "modules\realtime-message\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj", "{A5851F0F-CB0D-4E29-A829-D1BDEADB807B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain", "modules\realtime-message\LINGYUN.Abp.MessageService.Domain\LINGYUN.Abp.MessageService.Domain.csproj", "{FDEECE0D-6F66-4053-948E-9AC021B97C8D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime", "framework\common\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj", "{4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore", "modules\realtime-message\LINGYUN.Abp.MessageService.EntityFrameworkCore\LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj", "{371B293B-0CA9-4385-8EBB-5224332066D2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi", "modules\realtime-message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj", "{9E12ADBF-713B-4FE7-B71F-52B5078A57CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Storage.MySql", "framework\common\LINGYUN.Abp.Hangfire.MySqlStorage\LINGYUN.Abp.Hangfire.Storage.MySql.csproj", "{47CC8F7A-681D-42B9-AE04-78453782C1B6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Storage.SqlServer", "framework\common\LINGYUN.Abp.Hangfire.Storage.SqlServer\LINGYUN.Abp.Hangfire.Storage.SqlServer.csproj", "{F595CB9F-B117-4D62-A1AE-48599927DB36}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs.Hangfire", "framework\common\LINGYUN.Abp.BackgroundJobs.Hangfire\LINGYUN.Abp.BackgroundJobs.Hangfire.csproj", "{5CF403B2-47C9-4E4E-8856-0294BDD64884}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Aliyun", "framework\common\LINGYUN.Abp.BlobStoring.Aliyun\LINGYUN.Abp.BlobStoring.Aliyun.csproj", "{059473BA-FAF9-405F-9985-33DDCA2E9F0D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Aliyun.Tests", "tests\LINGYUN.Abp.BlobStoring.Aliyun.Tests\LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj", "{C8A00439-5B8D-4923-8FAA-AB75E2A786ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application.Contracts", "modules\realtime-message\LINGYUN.Abp.MessageService.Application.Contracts\LINGYUN.Abp.MessageService.Application.Contracts.csproj", "{31B03DCB-ED12-4412-867A-61E347D40D8C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application", "modules\realtime-message\LINGYUN.Abp.MessageService.Application\LINGYUN.Abp.MessageService.Application.csproj", "{AB984240-EF03-416F-A9B2-F5CF169E04B7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi.Client", "modules\realtime-message\LINGYUN.Abp.MessageService.HttpApi.Client\LINGYUN.Abp.MessageService.HttpApi.Client.csproj", "{EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "framework\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{65DDA934-B76B-4018-A565-CF6CEF0D6BB0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Emailing", "framework\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj", "{376D8343-DF83-41D2-BF6E-2F5DC8DBF259}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Emailing.Tests", "tests\LINGYUN.Abp.ExceptionHandling.Emailing.Tests\LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj", "{6259BCB9-A302-4CE7-AF48-9283A0DFD3CB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Tencent", "framework\common\LINGYUN.Abp.Location.Tencent\LINGYUN.Abp.Location.Tencent.csproj", "{1DA91161-8757-4A68-A0A1-8C94C36C9240}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "platform", "platform", "{F4923692-D343-4318-AECA-96F580B1A563}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Domain.Shared", "modules\platform\LINGYUN.Platform.Domain.Shared\LINGYUN.Platform.Domain.Shared.csproj", "{F135B9E8-3FFE-44E9-835B-7B6A928F4823}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Domain", "modules\platform\LINGYUN.Platform.Domain\LINGYUN.Platform.Domain.csproj", "{75A6D078-C19D-4030-88CC-C2A8608FF604}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.EntityFrameworkCore", "modules\platform\LINGYUN.Platform.EntityFrameworkCore\LINGYUN.Platform.EntityFrameworkCore.csproj", "{2D895594-3FF5-4507-853A-CB65F2DB72ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Application.Contracts", "modules\platform\LINGYUN.Platform.Application.Contracts\LINGYUN.Platform.Application.Contracts.csproj", "{AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Application", "modules\platform\LINGYUN.Platform.Application\LINGYUN.Platform.Application.csproj", "{0655A0FB-59E8-4A9F-BAF5-47A89377F747}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.HttpApi", "modules\platform\LINGYUN.Platform.HttpApi\LINGYUN.Platform.HttpApi.csproj", "{5FBBBA6A-D6EC-42E1-8164-15C411EC77BE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{F3D9B137-32DE-4018-8058-78AB17FCDF9C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{52B5D4F7-237B-4E0A-A167-68442164F70A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{F19C8B0F-A332-4190-9ABE-95790E0AE864}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application", "modules\identity\LINGYUN.Abp.Identity.Application\LINGYUN.Abp.Identity.Application.csproj", "{BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi", "modules\identity\LINGYUN.Abp.Identity.HttpApi\LINGYUN.Abp.Identity.HttpApi.csproj", "{72DCA4CF-8B95-47C9-B02A-2671953B7987}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi.Client", "modules\identity\LINGYUN.Abp.Identity.HttpApi.Client\LINGYUN.Abp.Identity.HttpApi.Client.csproj", "{7DDEAEA9-E392-469C-ACB6-908C5BAD669E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "oss-management", "oss-management", "{B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}" + ProjectSection(SolutionItems) = preProject + modules\oss-management\README.md = modules\oss-management\README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Application", "modules\oss-management\LINGYUN.Abp.OssManagement.Application\LINGYUN.Abp.OssManagement.Application.csproj", "{F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Application.Contracts", "modules\oss-management\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj", "{86A67B8C-EFA0-4103-B60F-312F07C15A7A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.HttpApi", "modules\oss-management\LINGYUN.Abp.OssManagement.HttpApi\LINGYUN.Abp.OssManagement.HttpApi.csproj", "{854E1A42-FEA4-420E-9E83-0A39EE03F1ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Domain.Shared", "modules\oss-management\LINGYUN.Abp.OssManagement.Domain.Shared\LINGYUN.Abp.OssManagement.Domain.Shared.csproj", "{21FCEF89-9A3F-476E-833A-A9C2131B2AE6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Domain", "modules\oss-management\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj", "{14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Domain", "modules\identityServer\LINGYUN.Abp.IdentityServer.Domain\LINGYUN.Abp.IdentityServer.Domain.csproj", "{F359AAA1-C854-444A-88F2-1C0D8A07F864}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{5D0ED1FC-3A7C-4531-9512-832E73AD9555}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{2BF7FB73-0C62-4ECF-99F0-0583855D2777}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{6FE7E243-2D99-4567-8786-6C9283D608EF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation", "framework\common\LINGYUN.Abp.Features.LimitValidation\LINGYUN.Abp.Features.LimitValidation.csproj", "{65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation.Redis", "framework\common\LINGYUN.Abp.Features.LimitValidation.Redis\LINGYUN.Abp.Features.LimitValidation.Redis.csproj", "{D3E65610-4167-4235-9C9D-1E1FAD4C0CE6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation.Redis.Tests", "tests\LINGYUN.Abp.Features.LimitValidation.Redis.Tests\LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj", "{F12F4645-C0FE-4129-8C71-65B4039DC445}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation.Tests", "tests\LINGYUN.Abp.Features.LimitValidation.Tests\LINGYUN.Abp.Features.LimitValidation.Tests.csproj", "{C457FA70-8732-44B8-A018-C96D14025D4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "features", "features", "{08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.FeatureManagement.Client", "framework\features\LINGYUN.Abp.FeatureManagement.Client\LINGYUN.Abp.FeatureManagement.Client.csproj", "{7071E78B-755B-410A-830B-AA05D7168944}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.Client", "framework\features\LINGYUN.Abp.Features.Client\LINGYUN.Abp.Features.Client.csproj", "{87B65CBD-0FF4-4FB5-9ABC-161911A71179}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "auditing", "auditing", "{67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.Application.Contracts", "modules\auditing\LINGYUN.Abp.Auditing.Application.Contracts\LINGYUN.Abp.Auditing.Application.Contracts.csproj", "{F40F88F1-CA90-4A79-B772-80E287E25982}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.Application", "modules\auditing\LINGYUN.Abp.Auditing.Application\LINGYUN.Abp.Auditing.Application.csproj", "{AC3C8985-73C2-472A-8E76-A0B8786FEC3F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.HttpApi", "modules\auditing\LINGYUN.Abp.Auditing.HttpApi\LINGYUN.Abp.Auditing.HttpApi.csproj", "{07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "permission-management", "permission-management", "{CC362C67-6FC1-42B3-A130-8120AA8D790C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "framework\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{BAE74ABC-1096-495F-A624-BEBFBC1896F2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{E92A1CAA-5758-41EF-B67E-C0D394E85417}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "framework\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{F18DE651-A3E4-478F-A2B5-686429729EB8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Official", "framework\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj", "{42309C06-C0F2-490F-931B-CF41FA1970FF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.SettingManagement", "framework\wechat\LINGYUN.Abp.WeChat.SettingManagement\LINGYUN.Abp.WeChat.SettingManagement.csproj", "{EC19F867-E9EA-4B26-A1E7-87AAA3EB9296}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\realtime-notifications\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cloud-aliyun", "cloud-aliyun", "{14CDBAD1-10C8-464A-B445-1F727C988010}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cloud-tencent", "cloud-tencent", "{3B96F4D8-4993-419B-BCEB-AFE4ED39449F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun", "framework\cloud-aliyun\LINGYUN.Abp.Aliyun\LINGYUN.Abp.Aliyun.csproj", "{FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Tencent", "framework\cloud-tencent\LINGYUN.Abp.Tencent\LINGYUN.Abp.Tencent.csproj", "{97B4A37E-B93E-48C9-95D5-689CB9495D8B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.SettingManagement", "framework\cloud-aliyun\LINGYUN.Abp.Aliyun.SettingManagement\LINGYUN.Abp.Aliyun.SettingManagement.csproj", "{FE0F0889-C4AF-43C5-B851-B8CCC873BA2C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Tests", "tests\LINGYUN.Abp.Aliyun.Tests\LINGYUN.Abp.Aliyun.Tests.csproj", "{B86EBB6F-A27F-4277-8265-937951A9DCB0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Aliyun", "modules\oss-management\LINGYUN.Abp.OssManagement.Aliyun\LINGYUN.Abp.OssManagement.Aliyun.csproj", "{35B17218-9FB6-439E-AF73-9A1454BC923C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.FileSystem", "modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem\LINGYUN.Abp.OssManagement.FileSystem.csproj", "{D5036D3F-1C53-47EE-BA50-AD290AE062D7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.SettingManagement", "modules\oss-management\LINGYUN.Abp.OssManagement.SettingManagement\LINGYUN.Abp.OssManagement.SettingManagement.csproj", "{BD74BE00-54E4-4979-8797-E8027695F396}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation.Redis.Client", "framework\common\LINGYUN.Abp.Features.LimitValidation.Redis.Client\LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj", "{48DE251A-3482-4934-BC26-F99D2235AC9F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Tencent.Tests", "tests\LINGYUN.Abp.Location.Tencent.Tests\LINGYUN.Abp.Location.Tencent.Tests.csproj", "{94B47385-E47F-4FD7-A3A9-A7AA122EFC93}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Baidu.Tests", "tests\LINGYUN.Abp.Location.Baidu.Tests\LINGYUN.Abp.Location.Baidu.Tests.csproj", "{C892CD81-50AE-49E5-BF44-A0C28A1614CC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Client", "framework\common\LINGYUN.Abp.AspNetCore.Mvc.Client\LINGYUN.Abp.AspNetCore.Mvc.Client.csproj", "{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization", "localization", "{90E88EAC-4291-4406-8D88-EFDF61B11292}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml", "framework\localization\LINGYUN.Abp.Localization.Xml\LINGYUN.Abp.Localization.Xml.csproj", "{84868710-ECBB-4025-900A-EEB99EC49534}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml.Tests", "tests\LINGYUN.Abp.Localization.Xml.Tests\LINGYUN.Abp.Localization.Xml.Tests.csproj", "{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization-management", "localization-management", "{D3BAA44E-8395-4E8A-AA96-6B463356C537}" + ProjectSection(SolutionItems) = preProject + modules\localization-management\README.md = modules\localization-management\README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.Domain.Shared", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.Domain.Shared\LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj", "{5BE18D72-0D02-4854-966E-745CE5DAF77F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.Domain", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.Domain\LINGYUN.Abp.LocalizationManagement.Domain.csproj", "{73EAD4FE-B44F-44A7-904E-FFA5096D91BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.Application.Contracts", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.Application.Contracts\LINGYUN.Abp.LocalizationManagement.Application.Contracts.csproj", "{06D34108-01BA-4C77-A704-4DD9E6F7E32C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.Application", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.Application\LINGYUN.Abp.LocalizationManagement.Application.csproj", "{A98C939C-9F48-414A-A2D3-853BE4447397}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj", "{A94BE05F-7DAB-461C-93E7-914CBDF4FA93}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.LocalizationManagement.HttpApi", "modules\localization-management\LINGYUN.Abp.LocalizationManagement.HttpApi\LINGYUN.Abp.LocalizationManagement.HttpApi.csproj", "{FBE91498-D83B-4873-A67E-0FB9D1C366F0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rules", "rules", "{6084D52D-775B-4A39-8CD5-AA2F362B5A61}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules", "framework\rules\LINGYUN.Abp.Rules\LINGYUN.Abp.Rules.csproj", "{D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.NRules", "framework\rules\LINGYUN.Abp.Rules.NRules\LINGYUN.Abp.Rules.NRules.csproj", "{34BB9810-2983-4E55-A96A-132D32310145}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.RulesEngine", "framework\rules\LINGYUN.Abp.Rules.RulesEngine\LINGYUN.Abp.Rules.RulesEngine.csproj", "{4D83BDA7-2059-41C7-85AE-FEFAD5CD9498}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.RulesEngine.Tests", "tests\LINGYUN.Abp.Rules.RulesEngine.Tests\LINGYUN.Abp.Rules.RulesEngine.Tests.csproj", "{8EF31071-3521-409D-9740-BBFBFC04C50E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.HttpOverrides", "framework\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj", "{13219C1C-23E1-4EBA-93FB-86830C93A800}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundWorkers.Hangfire", "framework\common\LINGYUN.Abp.BackgroundWorkers.Hangfire\LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj", "{60D0BEF2-FEAF-4066-8377-6C873CB24858}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Dashboard", "framework\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj", "{340BE5AC-68EC-41A5-9D0D-266037C58F13}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat", "framework\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj", "{BC518F26-996E-4DF0-BB44-783EB1C275D2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logging", "logging", "{6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elasticsearch", "elasticsearch", "{B981DD7D-7083-4C7A-9A5F-B8CFAE7B670B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elasticsearch", "framework\elasticsearch\LINGYUN.Abp.Elasticsearch\LINGYUN.Abp.Elasticsearch.csproj", "{63D1DC91-C7C7-491A-8423-B0B89F39443F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Logging", "framework\logging\LINGYUN.Abp.Logging\LINGYUN.Abp.Logging.csproj", "{1E0E82D2-F53A-4326-9E39-D7D677590543}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Logging.Serilog.Elasticsearch", "framework\logging\LINGYUN.Abp.Logging.Serilog.Elasticsearch\LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj", "{D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging", "framework\auditing\LINGYUN.Abp.AuditLogging\LINGYUN.Abp.AuditLogging.csproj", "{6C3D4C1C-4864-44A9-8649-9856ABF667FA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.Elasticsearch", "framework\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj", "{AD3CC5B5-366B-4E34-8E80-EC5BB68B573A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.EntityFrameworkCore", "framework\auditing\LINGYUN.Abp.AuditLogging.EntityFrameworkCore\LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj", "{F71A0D28-397D-4094-B1C2-7925E1310676}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Serilog.Enrichers.Application", "framework\logging\LINGYUN.Abp.Serilog.Enrichers.Application\LINGYUN.Abp.Serilog.Enrichers.Application.csproj", "{CEAF0044-28D3-4585-B69D-D65FF6D4745E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Data.DbMigrator", "framework\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj", "{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "navigation", "navigation", "{7D02D803-F9A9-492C-9B5E-454E4B258466}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation", "framework\navigation\LINGYUN.Abp.UI.Navigation\LINGYUN.Abp.UI.Navigation.csproj", "{FD04A084-BB8A-4733-B9C5-FACF40342A8A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation.VueVbenAdmin", "modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj", "{67A76560-D39F-4D49-B858-B476E1DFE37B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dapr", "dapr", "{DC33925B-264D-421B-96CC-46F853CBCC70}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr", "framework\dapr\LINGYUN.Abp.Dapr\LINGYUN.Abp.Dapr.csproj", "{1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Client", "framework\dapr\LINGYUN.Abp.Dapr.Client\LINGYUN.Abp.Dapr.Client.csproj", "{93317D44-835C-4F5E-B85D-580D51D5FFF4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors", "framework\dapr\LINGYUN.Abp.Dapr.Actors\LINGYUN.Abp.Dapr.Actors.csproj", "{DAF80936-FBEC-45AB-92DF-34966B0148FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors.AspNetCore", "framework\dapr\LINGYUN.Abp.Dapr.Actors.AspNetCore\LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj", "{995756A1-A379-4797-89F0-87D219B5AF00}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.CultureMap", "framework\localization\LINGYUN.Abp.Localization.CultureMap\LINGYUN.Abp.Localization.CultureMap.csproj", "{EB73D2CC-B1BE-471A-B76E-35F288CD0E16}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Client.Wrapper", "framework\dapr\LINGYUN.Abp.Dapr.Client.Wrapper\LINGYUN.Abp.Dapr.Client.Wrapper.csproj", "{842E19B3-8110-40FE-AAFF-D288BC928E55}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Wrapper", "framework\mvc\LINGYUN.Abp.AspNetCore.Mvc.Wrapper\LINGYUN.Abp.AspNetCore.Mvc.Wrapper.csproj", "{C1319EC1-A489-482B-A343-38B52D8AB0B0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "open-api", "open-api", "{3C7A8246-DE82-4330-8697-24EF1B1C515D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi", "framework\open-api\LINGYUN.Abp.OpenApi\LINGYUN.Abp.OpenApi.csproj", "{4059F87E-9762-46C1-AEB1-B1128EA533AE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.Authorization", "framework\open-api\LINGYUN.Abp.OpenApi.Authorization\LINGYUN.Abp.OpenApi.Authorization.csproj", "{433AD1FB-2DE8-479F-B89E-A17217591538}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Wrapper", "framework\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj", "{65311EC9-7A86-4E73-A587-F06A99474EDD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.OssManagement", "modules\oss-management\LINGYUN.Abp.BlobStoring.OssManagement\LINGYUN.Abp.BlobStoring.OssManagement.csproj", "{CD9081C6-7CA0-4A93-9318-33E54F3ED275}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.HttpApi.Client", "modules\oss-management\LINGYUN.Abp.OssManagement.HttpApi.Client\LINGYUN.Abp.OssManagement.HttpApi.Client.csproj", "{D262405E-1C72-4F14-A799-40471BAD48DC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data-protection", "data-protection", "{529DF802-97C4-4BF2-BE7C-39663B3D9EA3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection", "framework\data-protection\LINGYUN.Abp.DataProtection\LINGYUN.Abp.DataProtection.csproj", "{BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.EntityFrameworkCore", "framework\data-protection\LINGYUN.Abp.DataProtection.EntityFrameworkCore\LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj", "{19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdGenerator", "framework\common\LINGYUN.Abp.IdGenerator\LINGYUN.Abp.IdGenerator.csproj", "{440C9BD9-85EA-4473-AB1C-7C3562DF4915}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Serilog.Enrichers.UniqueId", "framework\logging\LINGYUN.Abp.Serilog.Enrichers.UniqueId\LINGYUN.Abp.Serilog.Enrichers.UniqueId.csproj", "{23C3B247-523A-4FBF-B785-2F035E0089BD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solution Items", "{A76A4741-AF91-44EF-A7B6-8E7AF4961146}" + ProjectSection(SolutionItems) = preProject + aspire\.gitignore = aspire\.gitignore + ..\common.props = ..\common.props + ..\common.secrets.props = ..\common.secrets.props + ..\configureawait.props = ..\configureawait.props + ..\Directory.Build.props = ..\Directory.Build.props + ..\Directory.Packages.props = ..\Directory.Packages.props + ..\NuGet.Config = ..\NuGet.Config + aspire\README.md = aspire\README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Tencent.SettingManagement", "framework\cloud-tencent\LINGYUN.Abp.Tencent.SettingManagement\LINGYUN.Abp.Tencent.SettingManagement.csproj", "{C7CF4193-6397-4450-AF42-3BACD7CF292E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Tencent", "framework\cloud-tencent\LINGYUN.Abp.Sms.Tencent\LINGYUN.Abp.Sms.Tencent.csproj", "{8FE2725C-6829-4778-93BA-A53260697AFB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Tencent", "framework\cloud-tencent\LINGYUN.Abp.BlobStoring.Tencent\LINGYUN.Abp.BlobStoring.Tencent.csproj", "{A4B972EC-9F0B-4405-9965-766FABC9B07E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Tencent", "modules\oss-management\LINGYUN.Abp.OssManagement.Tencent\LINGYUN.Abp.OssManagement.Tencent.csproj", "{31E60E23-FD98-4D5E-A137-2B3F2968BA09}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.LinkUser", "modules\identityServer\LINGYUN.Abp.IdentityServer.LinkUser\LINGYUN.Abp.IdentityServer.LinkUser.csproj", "{25378F9D-2A66-4568-AAC6-E9282ACA3DD3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Tencent.QQ", "framework\cloud-tencent\LINGYUN.Abp.Tencent.QQ\LINGYUN.Abp.Tencent.QQ.csproj", "{3FCB1BCD-34BC-4F66-968F-38DB28371D0F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.Editions", "framework\tenants\LINGYUN.Abp.MultiTenancy.Editions\LINGYUN.Abp.MultiTenancy.Editions.csproj", "{A030CD8E-61F3-4C15-B28A-C301446DDBEC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "saas", "saas", "{D01D859E-4B72-478A-BABD-90F0981652D5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Domain.Shared", "modules\saas\LINGYUN.Abp.Saas.Domain.Shared\LINGYUN.Abp.Saas.Domain.Shared.csproj", "{049E09BF-2E11-4E3B-926D-9DD6051A2DA4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Domain", "modules\saas\LINGYUN.Abp.Saas.Domain\LINGYUN.Abp.Saas.Domain.csproj", "{F1BE6113-3439-45BB-8B58-20ACA4056895}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.EntityFrameworkCore", "modules\saas\LINGYUN.Abp.Saas.EntityFrameworkCore\LINGYUN.Abp.Saas.EntityFrameworkCore.csproj", "{77C2E24A-D143-44E7-86F9-AB6C5D444F63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Application.Contracts", "modules\saas\LINGYUN.Abp.Saas.Application.Contracts\LINGYUN.Abp.Saas.Application.Contracts.csproj", "{D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Application", "modules\saas\LINGYUN.Abp.Saas.Application\LINGYUN.Abp.Saas.Application.csproj", "{B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.HttpApi", "modules\saas\LINGYUN.Abp.Saas.HttpApi\LINGYUN.Abp.Saas.HttpApi.csproj", "{8DF50094-6791-4C7C-B07D-C3E995B69C49}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.HttpApi.Client", "modules\saas\LINGYUN.Abp.Saas.HttpApi.Client\LINGYUN.Abp.Saas.HttpApi.Client.csproj", "{96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "webhooks", "webhooks", "{13ACF670-F109-404E-B252-2FA34A4EA061}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WebHooks", "modules\webhooks\LINGYUN.Abp.WebHooks\LINGYUN.Abp.WebHooks.csproj", "{91AE01B1-CC82-40E2-8290-B8A84C6E90D1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "authorization", "authorization", "{9EC33D45-CCC7-41DF-829E-6B89A640FE35}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Authorization.OrganizationUnits", "framework\authorization\LINGYUN.Abp.Authorization.OrganizationUnits\LINGYUN.Abp.Authorization.OrganizationUnits.csproj", "{902D822A-52B6-481C-96C5-ECD891FF83FC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits", "modules\permissions-management\LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits\LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits.csproj", "{46244C99-3A0D-4D88-9F24-2B7B586ADBA4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.OrganizaztionUnits", "modules\identity\LINGYUN.Abp.Identity.OrganizaztionUnits\LINGYUN.Abp.Identity.OrganizaztionUnits.csproj", "{76A5564E-033B-4AA6-A22B-78B6EB134CC6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Theme.VueVbenAdmin", "modules\platform\LINGYUN.Platform.Theme.VueVbenAdmin\LINGYUN.Platform.Theme.VueVbenAdmin.csproj", "{67DC7FA0-506A-4977-95F6-BC739B2BC4BA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Platform.Settings.VueVbenAdmin", "modules\platform\LINGYUN.Platform.Settings.VueVbenAdmin\LINGYUN.Platform.Settings.VueVbenAdmin.csproj", "{8DF55DAB-4C1D-46F7-9324-0050F47B3BED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "text-templating", "text-templating", "{ABD89F39-62D9-439E-8662-BE4F36BFA04F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Domain.Shared", "modules\text-templating\LINGYUN.Abp.TextTemplating.Domain.Shared\LINGYUN.Abp.TextTemplating.Domain.Shared.csproj", "{D4B4800F-6238-4EA9-A9BB-298D668C26C4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Domain", "modules\text-templating\LINGYUN.Abp.TextTemplating.Domain\LINGYUN.Abp.TextTemplating.Domain.csproj", "{F9AC4123-7987-47D3-85D6-CD13928F3683}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Application.Contracts", "modules\text-templating\LINGYUN.Abp.TextTemplating.Application.Contracts\LINGYUN.Abp.TextTemplating.Application.Contracts.csproj", "{22BDDF5C-F911-4978-B83F-981F3652BF45}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Application", "modules\text-templating\LINGYUN.Abp.TextTemplating.Application\LINGYUN.Abp.TextTemplating.Application.csproj", "{0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.HttpApi", "modules\text-templating\LINGYUN.Abp.TextTemplating.HttpApi\LINGYUN.Abp.TextTemplating.HttpApi.csproj", "{4711320B-F98D-4CB0-BFEB-B9685B6CBCB7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.EntityFrameworkCore", "modules\text-templating\LINGYUN.Abp.TextTemplating.EntityFrameworkCore\LINGYUN.Abp.TextTemplating.EntityFrameworkCore.csproj", "{130F8ED1-A64F-48DE-BF43-18EAD19CAF63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.HttpApi.Client", "modules\text-templating\LINGYUN.Abp.TextTemplating.HttpApi.Client\LINGYUN.Abp.TextTemplating.HttpApi.Client.csproj", "{A53FE09E-6B1C-46C0-9422-C313D14AE9E4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Localization", "framework\localization\LINGYUN.Abp.AspNetCore.Mvc.Localization\LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj", "{995DB1CE-A2FC-4468-A521-4207FD587EC5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "caching-management", "caching-management", "{63FCC71F-1CEF-44D3-B95B-23EE58DE8C95}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.CachingManagement.Domain", "modules\caching-management\LINGYUN.Abp.CachingManagement.Domain\LINGYUN.Abp.CachingManagement.Domain.csproj", "{7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.CachingManagement.StackExchangeRedis", "modules\caching-management\LINGYUN.Abp.CachingManagement.StackExchangeRedis\LINGYUN.Abp.CachingManagement.StackExchangeRedis.csproj", "{920867B4-4740-4074-9B49-14002B272A63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.CachingManagement.Application.Contracts", "modules\caching-management\LINGYUN.Abp.CachingManagement.Application.Contracts\LINGYUN.Abp.CachingManagement.Application.Contracts.csproj", "{3D422738-B111-4DEE-82E1-C3A90F1133B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.CachingManagement.Application", "modules\caching-management\LINGYUN.Abp.CachingManagement.Application\LINGYUN.Abp.CachingManagement.Application.csproj", "{08CC528E-98D7-41D9-957D-9F9064645788}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.CachingManagement.HttpApi", "modules\caching-management\LINGYUN.Abp.CachingManagement.HttpApi\LINGYUN.Abp.CachingManagement.HttpApi.csproj", "{B507D18B-770E-4581-854B-15579AC7074F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DistributedLocking.Dapr", "framework\dapr\LINGYUN.Abp.DistributedLocking.Dapr\LINGYUN.Abp.DistributedLocking.Dapr.csproj", "{178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wx-pusher", "wx-pusher", "{53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WxPusher", "framework\wx-pusher\LINGYUN.Abp.WxPusher\LINGYUN.Abp.WxPusher.csproj", "{7C4C266C-DC2A-4A48-AB87-185E284B86E9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WxPusher", "modules\realtime-notifications\LINGYUN.Abp.Notifications.WxPusher\LINGYUN.Abp.Notifications.WxPusher.csproj", "{0380623A-EC74-430B-AA59-A6D23BC5E108}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WxPusher.SettingManagement", "framework\wx-pusher\LINGYUN.Abp.WxPusher.SettingManagement\LINGYUN.Abp.WxPusher.SettingManagement.csproj", "{C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WxPusher", "framework\wx-pusher\LINGYUN.Abp.Identity.WxPusher\LINGYUN.Abp.Identity.WxPusher.csproj", "{C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pushplus", "pushplus", "{A8F1C9FA-4F16-43F9-8CC6-CCD124154440}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PushPlus", "framework\pushplus\LINGYUN.Abp.PushPlus\LINGYUN.Abp.PushPlus.csproj", "{82CB7E17-ED5A-4D26-B116-BA7B4226E43C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PushPlus.SettingManagement", "framework\pushplus\LINGYUN.Abp.PushPlus.SettingManagement\LINGYUN.Abp.PushPlus.SettingManagement.csproj", "{102C3711-135E-446D-9A35-AEFB79993CAA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.PushPlus", "modules\realtime-notifications\LINGYUN.Abp.Notifications.PushPlus\LINGYUN.Abp.Notifications.PushPlus.csproj", "{2B7C1441-8801-4121-ABFB-03771E9DFE46}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "realtime", "realtime", "{ECC8B9A9-9E92-4493-984D-2E350A49189D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Http.Client.Wrapper", "framework\common\LINGYUN.Abp.Http.Client.Wrapper\LINGYUN.Abp.Http.Client.Wrapper.csproj", "{942816E3-B270-40DC-9532-C1077FF59A32}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors.AspNetCore.Wrapper", "framework\dapr\LINGYUN.Abp.Dapr.Actors.AspNetCore.Wrapper\LINGYUN.Abp.Dapr.Actors.AspNetCore.Wrapper.csproj", "{FBB50072-33BE-4B4A-8908-E98BC0C80B92}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "openiddict", "openiddict", "{83E698F6-F8CD-4604-AB80-01A203389501}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.Application.Contracts", "modules\openIddict\LINGYUN.Abp.OpenIddict.Application.Contracts\LINGYUN.Abp.OpenIddict.Application.Contracts.csproj", "{D509011F-4690-4F21-BA30-E4C31799993F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.Application", "modules\openIddict\LINGYUN.Abp.OpenIddict.Application\LINGYUN.Abp.OpenIddict.Application.csproj", "{257C64BC-BD16-4F6D-A0B9-E286A4161241}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.HttpApi", "modules\openIddict\LINGYUN.Abp.OpenIddict.HttpApi\LINGYUN.Abp.OpenIddict.HttpApi.csproj", "{785251E2-6E77-40E3-90C2-4DFB63D0721B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.HttpApi.Client", "modules\openIddict\LINGYUN.Abp.OpenIddict.HttpApi.Client\LINGYUN.Abp.OpenIddict.HttpApi.Client.csproj", "{0521239A-6B83-414F-B3E2-0515FC70F121}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.Dapr.Client", "modules\openIddict\LINGYUN.Abp.OpenIddict.Dapr.Client\LINGYUN.Abp.OpenIddict.Dapr.Client.csproj", "{44E33132-9427-4E52-B105-67A8BC2BC29E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "authentication", "authentication", "{E567A760-D19A-4CAC-BD6B-BAA0CE0BBC1B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Authentication.QQ", "framework\authentication\LINGYUN.Abp.Authentication.QQ\LINGYUN.Abp.Authentication.QQ.csproj", "{D3008465-B344-4243-B14A-A1430E2BEC48}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Authentication.WeChat", "framework\authentication\LINGYUN.Abp.Authentication.WeChat\LINGYUN.Abp.Authentication.WeChat.csproj", "{3CBA6005-B412-4D2A-8F1E-01D53D5C657E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.LinkUser", "modules\openIddict\LINGYUN.Abp.OpenIddict.LinkUser\LINGYUN.Abp.OpenIddict.LinkUser.csproj", "{15EC4A03-D172-4984-B9CA-2C73929838DE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.Sms", "modules\openIddict\LINGYUN.Abp.OpenIddict.Sms\LINGYUN.Abp.OpenIddict.Sms.csproj", "{74C13BCC-A5A5-40FA-81E8-83DCCF760148}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.WeChat", "modules\openIddict\LINGYUN.Abp.OpenIddict.WeChat\LINGYUN.Abp.OpenIddict.WeChat.csproj", "{427382F6-3153-47A2-BBC4-88F6EA116A8F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdGenerator.Tests", "tests\LINGYUN.Abp.IdGenerator.Tests\LINGYUN.Abp.IdGenerator.Tests.csproj", "{2BFFE9C3-E022-4B57-9E4D-0A0408424B1A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Official.Senparc", "framework\wechat\LINGYUN.Abp.WeChat.Official.Senparc\LINGYUN.Abp.WeChat.Official.Senparc.csproj", "{CA8D7141-9520-46AC-83FD-6E034AD6EBDD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Webhooks.Core", "modules\webhooks\LINGYUN.Abp.Webhooks.Core\LINGYUN.Abp.Webhooks.Core.csproj", "{42FD76A3-803A-4E07-8A90-4269204B7B87}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "realtime-notifications", "realtime-notifications", "{1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Domain.Shared", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Domain.Shared\LINGYUN.Abp.Notifications.Domain.Shared.csproj", "{4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Domain", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Domain\LINGYUN.Abp.Notifications.Domain.csproj", "{CDD4CC0F-5493-40C2-B889-3670263888D8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.EntityFrameworkCore", "modules\realtime-notifications\LINGYUN.Abp.Notifications.EntityFrameworkCore\LINGYUN.Abp.Notifications.EntityFrameworkCore.csproj", "{F74AAE01-7B87-44CA-85ED-9A6307D51504}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Application.Contracts", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Application.Contracts\LINGYUN.Abp.Notifications.Application.Contracts.csproj", "{E3F010C7-6C96-4EEA-B5FA-BF80515E195F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Application", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Application\LINGYUN.Abp.Notifications.Application.csproj", "{B153F98A-7DA9-4A12-A1D7-105BE9408FA1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.HttpApi", "modules\realtime-notifications\LINGYUN.Abp.Notifications.HttpApi\LINGYUN.Abp.Notifications.HttpApi.csproj", "{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{52E60F16-6304-4E37-A220-C94D8C5D27DC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{F3E04039-7BEE-46F8-B33B-FE13E977DCCA}" + ProjectSection(SolutionItems) = preProject + ..\.github\workflows\build.yml = ..\.github\workflows\build.yml + ..\.github\workflows\publish.yml = ..\.github\workflows\publish.yml + ..\.github\workflows\release.yml = ..\.github\workflows\release.yml + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Application.Contracts", "modules\permissions-management\LINGYUN.Abp.PermissionManagement.Application.Contracts\LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj", "{35D17AF3-FDCD-4704-969C-E82DBCC0A232}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Application", "modules\permissions-management\LINGYUN.Abp.PermissionManagement.Application\LINGYUN.Abp.PermissionManagement.Application.csproj", "{984F481B-79FF-4825-917B-944F151694BC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.HttpApi", "modules\permissions-management\LINGYUN.Abp.PermissionManagement.HttpApi\LINGYUN.Abp.PermissionManagement.HttpApi.csproj", "{B12BECC4-8A58-4DBD-A5CD-144A507972BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "feature-management", "feature-management", "{12896A3F-5F7E-4192-8A58-E1D2527109D1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.FeatureManagement.Application.Contracts", "modules\feature-management\LINGYUN.Abp.FeatureManagement.Application.Contracts\LINGYUN.Abp.FeatureManagement.Application.Contracts.csproj", "{F7A8000A-D8DA-4A1F-B0B2-9A52183F2012}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.FeatureManagement.Application", "modules\feature-management\LINGYUN.Abp.FeatureManagement.Application\LINGYUN.Abp.FeatureManagement.Application.csproj", "{4E8DA436-8FAF-4028-8A0C-E4EEB3615972}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.FeatureManagement.HttpApi", "modules\feature-management\LINGYUN.Abp.FeatureManagement.HttpApi\LINGYUN.Abp.FeatureManagement.HttpApi.csproj", "{405694F8-0051-4DAE-A991-919FAC36C7DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rules-management", "rules-management", "{5F0BB690-0FBB-455A-AE9A-8BA914AA78F6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rules-engine", "rules-engine", "{F7103498-8B5B-4698-AACE-9E949F732E77}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.Domain.Shared", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.Domain.Shared\LINGYUN.Abp.RulesEngineManagement.Domain.Shared.csproj", "{2EAA690B-1395-4952-95A0-A52F929028C4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.Domain", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.Domain\LINGYUN.Abp.RulesEngineManagement.Domain.csproj", "{722FE012-8F23-4558-9E8F-A37C02902058}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.Application.Contracts", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.Application.Contracts\LINGYUN.Abp.RulesEngineManagement.Application.Contracts.csproj", "{79D3C6D6-6433-471D-B354-477E07CB08EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.Application", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.Application\LINGYUN.Abp.RulesEngineManagement.Application.csproj", "{5A3B9F4D-E6CC-410F-B307-0E69CCA213F5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.EntityFrameworkCore", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.EntityFrameworkCore\LINGYUN.Abp.RulesEngineManagement.EntityFrameworkCore.csproj", "{4CDCD854-6E06-4076-AE94-53C1C1D7F6FA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngineManagement.HttpApi", "modules\rules-management\rules-engine\LINGYUN.Abp.RulesEngineManagement.HttpApi\LINGYUN.Abp.RulesEngineManagement.HttpApi.csproj", "{97062425-3379-4F8D-BFA2-D445C56C0801}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Portal", "modules\identityServer\LINGYUN.Abp.IdentityServer.Portal\LINGYUN.Abp.IdentityServer.Portal.csproj", "{5B20BA13-40FF-4743-AEEE-2E3F887F50C6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.Portal", "modules\openIddict\LINGYUN.Abp.OpenIddict.Portal\LINGYUN.Abp.OpenIddict.Portal.csproj", "{03EC70B8-912C-4FBE-94DD-6327F4F23021}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elsa", "elsa", "{0A00FAF9-A96B-4BF5-8D42-15C8678F70F3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa", "modules\elsa\LINGYUN.Abp.Elsa\LINGYUN.Abp.Elsa.csproj", "{C037F0CE-8223-4D4A-B15F-18B7D6AA447F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities", "modules\elsa\LINGYUN.Abp.Elsa.Activities\LINGYUN.Abp.Elsa.Activities.csproj", "{E293BB96-5054-497B-BCE5-64AF9B0457B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.BlobStoring", "modules\elsa\LINGYUN.Abp.Elsa.Activities.BlobStoring\LINGYUN.Abp.Elsa.Activities.BlobStoring.csproj", "{FB7AF3F8-44CD-4732-8A25-A43902437B89}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.Emailing", "modules\elsa\LINGYUN.Abp.Elsa.Activities.Emailing\LINGYUN.Abp.Elsa.Activities.Emailing.csproj", "{6472B3C1-C237-49CD-82C8-821AD001096A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.IM", "modules\elsa\LINGYUN.Abp.Elsa.Activities.IM\LINGYUN.Abp.Elsa.Activities.IM.csproj", "{4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.Notifications", "modules\elsa\LINGYUN.Abp.Elsa.Activities.Notifications\LINGYUN.Abp.Elsa.Activities.Notifications.csproj", "{FB0B28CA-EE88-4DBF-9E0D-E442757E2B98}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.Sms", "modules\elsa\LINGYUN.Abp.Elsa.Activities.Sms\LINGYUN.Abp.Elsa.Activities.Sms.csproj", "{47D57848-A910-4869-8A46-84E40A985FEE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Activities.Webhooks", "modules\elsa\LINGYUN.Abp.Elsa.Activities.Webhooks\LINGYUN.Abp.Elsa.Activities.Webhooks.csproj", "{8A1F9647-B773-40AB-9126-30868014AE58}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.EntityFrameworkCore", "modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore\LINGYUN.Abp.Elsa.EntityFrameworkCore.csproj", "{4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql", "modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql\LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj", "{10CF8240-4276-4199-B3D1-C45F16468EBD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Notifications", "modules\elsa\LINGYUN.Abp.Elsa.Notifications\LINGYUN.Abp.Elsa.Notifications.csproj", "{39DFEFCD-7C73-450F-9A2F-7426188A890B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elsa.Server", "modules\elsa\LINGYUN.Abp.Elsa.Server\LINGYUN.Abp.Elsa.Server.csproj", "{C465BB41-9DB7-470F-BC7F-A59D2A7D6083}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "entity-change", "entity-change", "{DD1B10ED-73E2-41BE-928A-46501050FE2A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityChange.Application.Contracts", "framework\entity-change\LINGYUN.Abp.EntityChange.Application.Contracts\LINGYUN.Abp.EntityChange.Application.Contracts.csproj", "{7779D9BD-5928-49A2-965F-537967004238}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityChange.Application", "framework\entity-change\LINGYUN.Abp.EntityChange.Application\LINGYUN.Abp.EntityChange.Application.csproj", "{AC41F335-E240-47E0-B409-AFAD1400E626}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityChange.HttpApi", "framework\entity-change\LINGYUN.Abp.EntityChange.HttpApi\LINGYUN.Abp.EntityChange.HttpApi.csproj", "{1D420BA6-2155-4E0D-AAAF-EECC0330A38C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cli", "cli", "{59627844-A66A-46AC-B882-E8F302D0EC24}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Cli", "framework\cli\LINGYUN.Abp.Cli\LINGYUN.Abp.Cli.csproj", "{2F49E870-DAE2-4D89-98CA-46BBD91C68E2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work", "framework\wechat\LINGYUN.Abp.WeChat.Work\LINGYUN.Abp.WeChat.Work.csproj", "{E4CEED06-B8E9-41FA-82BF-5401AE101C4B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Tests", "tests\LINGYUN.Abp.WeChat.Work.Tests\LINGYUN.Abp.WeChat.Work.Tests.csproj", "{9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Application.Contracts", "framework\wechat\LINGYUN.Abp.WeChat.Work.Application.Contracts\LINGYUN.Abp.WeChat.Work.Application.Contracts.csproj", "{B4C8056F-7325-4DB1-9F09-A6F37B052192}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Application", "framework\wechat\LINGYUN.Abp.WeChat.Work.Application\LINGYUN.Abp.WeChat.Work.Application.csproj", "{D5AEBB8E-713C-4DD2-BA18-7B0B48489901}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.HttpApi", "framework\wechat\LINGYUN.Abp.WeChat.Work.HttpApi\LINGYUN.Abp.WeChat.Work.HttpApi.csproj", "{CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.WeChat.Work", "modules\identityServer\LINGYUN.Abp.IdentityServer.WeChat.Work\LINGYUN.Abp.IdentityServer.WeChat.Work.csproj", "{DEDB69A9-657F-4B8B-81A7-4ADB19664F35}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.WeChat.Work", "modules\openIddict\LINGYUN.Abp.OpenIddict.WeChat.Work\LINGYUN.Abp.OpenIddict.WeChat.Work.csproj", "{2C86306D-D626-41F8-BA3C-5C9B4123CE7D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.Work", "modules\realtime-notifications\LINGYUN.Abp.Notifications.WeChat.Work\LINGYUN.Abp.Notifications.WeChat.Work.csproj", "{2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat.Work", "framework\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj", "{3E32DBDA-1C63-42B4-85D1-E84BBD072D89}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nexus", "nexus", "{87CE2F0B-0469-4C76-B325-00EA7AB94B99}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Nexus", "framework\nexus\LINGYUN.Abp.BlobStoring.Nexus\LINGYUN.Abp.BlobStoring.Nexus.csproj", "{34987F45-8234-428C-AB41-783D42295C32}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Nexus.Tests", "tests\LINGYUN.Abp.BlobStoring.Nexus.Tests\LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj", "{227DA969-291B-4749-985C-7A83523B7F53}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sonatype.Nexus", "framework\nexus\LINGYUN.Abp.Sonatype.Nexus\LINGYUN.Abp.Sonatype.Nexus.csproj", "{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Nexus.Tests", "tests\LINGYUN.Abp.OssManagement.Nexus.Tests\LINGYUN.Abp.OssManagement.Nexus.Tests.csproj", "{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{D52D5A11-78EF-4154-8298-267738A6715B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "exception-handling", "exception-handling", "{11CDB632-9A54-439F-8B68-32B3C775BC3A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hangfire", "hangfire", "{C6D62079-B3F5-4006-AA49-3BF12C4805BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wrapper", "wrapper", "{848F6760-9B11-4C9A-9843-9D71DD66D9DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "location", "location", "{6255DBAD-A388-4418-A5EB-C79630786028}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Nexus", "modules\oss-management\LINGYUN.Abp.OssManagement.Nexus\LINGYUN.Abp.OssManagement.Nexus.csproj", "{A025B8D2-5D92-4023-82AB-97A672A5A132}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM", "modules\realtime-message\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj", "{5D99743B-7044-4BE9-8F7A-E195F2A3E2EC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM.SignalR", "modules\realtime-message\LINGYUN.Abp.IM.SignalR\LINGYUN.Abp.IM.SignalR.csproj", "{E09E476C-9DF8-46AC-848E-4E7635369117}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Core", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Core\LINGYUN.Abp.Notifications.Core.csproj", "{E414F7BC-215C-46D0-99EC-CD78EB31FC3C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications", "modules\realtime-notifications\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj", "{8142FB8C-3D32-4062-BD95-B2F61A1A390A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Common", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Common\LINGYUN.Abp.Notifications.Common.csproj", "{4155336A-DC06-4885-878D-03AF5DFAF47D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Emailing", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Emailing\LINGYUN.Abp.Notifications.Emailing.csproj", "{ADAB35CB-A34E-448D-ACBB-FA054A3B90AA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Jobs", "modules\task-management\LINGYUN.Abp.Notifications.Jobs\LINGYUN.Abp.Notifications.Jobs.csproj", "{1B112FAC-CB57-48B6-A3D5-95456477CB8D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.SignalR", "modules\realtime-notifications\LINGYUN.Abp.Notifications.SignalR\LINGYUN.Abp.Notifications.SignalR.csproj", "{B84E4D98-0B10-4189-8572-F6F7B4E384B7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms", "modules\realtime-notifications\LINGYUN.Abp.Notifications.Sms\LINGYUN.Abp.Notifications.Sms.csproj", "{E81EC3E4-521F-4C52-8AA0-A783847E764E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.Saas", "modules\saas\LINGYUN.Abp.MultiTenancy.Saas\LINGYUN.Abp.MultiTenancy.Saas.csproj", "{49EB2864-B715-47DD-AE47-C5243C656F47}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "settings", "settings", "{A057F430-AD93-49D9-8080-6E074AF05694}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Notifications", "modules\realtime-notifications\LINGYUN.Abp.ExceptionHandling.Notifications\LINGYUN.Abp.ExceptionHandling.Notifications.csproj", "{68538541-4280-46F5-BA08-99ACA8575615}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "framework\settings\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{F6F93723-5BC3-4D25-A83E-25B41B6D956F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "auditing", "auditing", "{6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "task-management", "task-management", "{77ED7922-BF30-4436-8A85-78F812583913}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.Abstractions", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Abstractions\LINGYUN.Abp.BackgroundTasks.Abstractions.csproj", "{109BF321-1BC6-4031-A59B-7B5375EBA8C5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Common", "framework\wechat\LINGYUN.Abp.WeChat.Common\LINGYUN.Abp.WeChat.Common.csproj", "{08A78A69-913B-4C5E-BCE0-739585F82D1E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dynamic-queryable", "dynamic-queryable", "{4FAE314C-36CB-4E3F-85B7-41D0A428B37D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Linq.Dynamic.Queryable", "framework\dynamic-queryable\LINGYUN.Linq.Dynamic.Queryable\LINGYUN.Linq.Dynamic.Queryable.csproj", "{B6857FC4-97C2-4E20-B005-1FAABC574B88}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.Application.Contracts", "framework\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj", "{B6D4AADE-3ABA-45E6-9916-2F8798412549}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.Application", "framework\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application\LINGYUN.Abp.Dynamic.Queryable.Application.csproj", "{86E85013-7C71-4770-9323-18897A64F5B2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.HttpApi", "framework\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.HttpApi\LINGYUN.Abp.Dynamic.Queryable.HttpApi.csproj", "{014A9583-0EAA-48A4-ACBE-07DC88159E13}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.Tests", "tests\LINGYUN.Abp.DataProtection.Tests\LINGYUN.Abp.DataProtection.Tests.csproj", "{AAC0C407-B4B9-4E90-99FC-2D793AC229D9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "security", "security", "{9D1302BE-3886-49F8-B0CD-35D2AC1E5A37}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Security", "framework\security\LINGYUN.Abp.Security\LINGYUN.Abp.Security.csproj", "{4C71CA88-0D04-4DDB-8906-B953908B8B8B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.Jobs", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Jobs\LINGYUN.Abp.BackgroundTasks.Jobs.csproj", "{50FF92EA-8BA4-445D-AB04-E7568EE5D3FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.TaskManagement", "modules\task-management\LINGYUN.Abp.BackgroundTasks.TaskManagement\LINGYUN.Abp.BackgroundTasks.TaskManagement.csproj", "{1E00BE51-A1AE-447D-B6E0-F28EC12B259A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.Application.Contracts", "modules\task-management\LINGYUN.Abp.TaskManagement.Application.Contracts\LINGYUN.Abp.TaskManagement.Application.Contracts.csproj", "{61F0EEB2-5ED0-4809-8EF9-0676C7A680CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.HttpApi.Client", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi.Client\LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj", "{72D54834-7ADF-4B18-A745-FCBBC255073B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data-protection", "data-protection", "{F6A9D966-0022-440B-AE27-564A74CDED48}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.Domain.Shared", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.Domain.Shared\LINGYUN.Abp.DataProtectionManagement.Domain.Shared.csproj", "{8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.Domain", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.Domain\LINGYUN.Abp.DataProtectionManagement.Domain.csproj", "{6C0DB8F2-FB0A-4922-B8FE-177DCF37A918}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore\LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore.csproj", "{D73200F6-CBB3-4BA8-B9BF-7110AAF05596}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Wrapper", "framework\common\LINGYUN.Abp.AspNetCore.Wrapper\LINGYUN.Abp.AspNetCore.Wrapper.csproj", "{30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.Application.Contracts", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.Application.Contracts\LINGYUN.Abp.DataProtectionManagement.Application.Contracts.csproj", "{40D7A0A3-68BD-431E-A67A-E2A35508D55D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.Application", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.Application\LINGYUN.Abp.DataProtectionManagement.Application.csproj", "{8EA8C998-F81A-46E9-8C7E-C944D2503A0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.Abstractions", "framework\data-protection\LINGYUN.Abp.DataProtection.Abstractions\LINGYUN.Abp.DataProtection.Abstractions.csproj", "{47550AB9-FA06-42D6-A4B8-7DD12FE66563}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtectionManagement.HttpApi", "modules\data-protection\LINGYUN.Abp.DataProtectionManagement.HttpApi\LINGYUN.Abp.DataProtectionManagement.HttpApi.csproj", "{835E51CE-1E6B-4C8C-9736-8C5B61F5E08E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.IdentityServer", "framework\open-api\LINGYUN.Abp.OpenApi.IdentityServer\LINGYUN.Abp.OpenApi.IdentityServer.csproj", "{FDAAAD2E-42A7-44EC-8971-B5277FD6D404}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.OpenIddict", "framework\open-api\LINGYUN.Abp.OpenApi.OpenIddict\LINGYUN.Abp.OpenApi.OpenIddict.csproj", "{ED3DF100-C5DB-4334-A847-118922B28D95}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Scriban", "modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj", "{15482834-9242-4D20-9736-9DA571A9A83A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{8A255A72-50FC-460E-9897-FA53F455580B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Common", "framework\wechat\LINGYUN.Abp.WeChat.Work.Common\LINGYUN.Abp.WeChat.Work.Common.csproj", "{CED33625-A034-475B-A4C0-A4E7D1BADD10}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session", "modules\identity\LINGYUN.Abp.Identity.Session\LINGYUN.Abp.Identity.Session.csproj", "{E3BA2413-5755-4F61-9A7C-5D49AE9E7016}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session.AspNetCore", "modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj", "{BF85DB7F-70C2-4804-AA57-FACE204981DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Session", "modules\identityServer\LINGYUN.Abp.IdentityServer.Session\LINGYUN.Abp.IdentityServer.Session.csproj", "{893F7376-0913-43DC-AD3D-40AF5B8F9E3B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.AspNetCore.Session", "modules\identity\LINGYUN.Abp.Identity.AspNetCore.Session\LINGYUN.Abp.Identity.AspNetCore.Session.csproj", "{8826831D-8733-473A-B47B-A30C3732B13D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.AspNetCore.Session", "modules\openIddict\LINGYUN.Abp.OpenIddict.AspNetCore.Session\LINGYUN.Abp.OpenIddict.AspNetCore.Session.csproj", "{D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Notifications", "modules\identity\LINGYUN.Abp.Identity.Notifications\LINGYUN.Abp.Identity.Notifications.csproj", "{54BBA043-317B-4A4F-B583-513D08BC25A7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Handlers", "framework\wechat\LINGYUN.Abp.WeChat.Work.Handlers\LINGYUN.Abp.WeChat.Work.Handlers.csproj", "{79FA2CBA-2904-4D80-A217-DCC0A38F93C4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Official.Handlers", "framework\wechat\LINGYUN.Abp.WeChat.Official.Handlers\LINGYUN.Abp.WeChat.Official.Handlers.csproj", "{E469F047-6AD0-4D2B-9900-46358DA3BC30}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Minio", "modules\oss-management\LINGYUN.Abp.OssManagement.Minio\LINGYUN.Abp.OssManagement.Minio.csproj", "{EB9F1905-1798-4766-8347-A8D2A9DBFAED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Minio.Tests", "tests\LINGYUN.Abp.OssManagement.Minio.Tests\LINGYUN.Abp.OssManagement.Minio.Tests.csproj", "{CCE5C620-E17A-4EB1-A17A-9F90311B197D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Domain.Tests", "tests\LINGYUN.Abp.OssManagement.Domain.Tests\LINGYUN.Abp.OssManagement.Domain.Tests.csproj", "{F2AD691B-71B9-4B86-95BC-E020DA6B1E4A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.ImageSharp", "modules\oss-management\LINGYUN.Abp.OssManagement.ImageSharp\LINGYUN.Abp.OssManagement.ImageSharp.csproj", "{76DDE71D-00BD-4BC8-AEA2-31209E2B7E05}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.Imaging", "modules\oss-management\LINGYUN.Abp.OssManagement.Imaging\LINGYUN.Abp.OssManagement.Imaging.csproj", "{267933BD-BFB8-4906-BA39-DF193B2FD558}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.HttpApi.Client", "modules\realtime-notifications\LINGYUN.Abp.Notifications.HttpApi.Client\LINGYUN.Abp.Notifications.HttpApi.Client.csproj", "{3CBD1342-C021-49FB-933F-FAC1DAFC7B48}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Sms.Platform", "modules\platform\LINGYUN.Abp.Sms.Platform\LINGYUN.Abp.Sms.Platform.csproj", "{01B86C39-B0C8-48A4-949C-1C63D755B02C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Emailing.Platform", "modules\platform\LINGYUN.Abp.Emailing.Platform\LINGYUN.Abp.Emailing.Platform.csproj", "{DD6609C7-07AC-49FD-B588-44E649D0AE6E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Sms.Platform.Tests", "tests\LINGYUN.Abp.Sms.Platform.Tests\LINGYUN.Abp.Sms.Platform.Tests.csproj", "{856B4ACA-BD13-417F-A6E2-0F401F877189}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Platform.HttpApi.Client", "modules\platform\LINGYUN.Platform.HttpApi.Client\LINGYUN.Platform.HttpApi.Client.csproj", "{B52B199C-0E1C-4CE9-B066-71D26F618424}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Emailing.Platform.Tests", "tests\LINGYUN.Abp.Emailing.Platform.Tests\LINGYUN.Abp.Emailing.Platform.Tests.csproj", "{80F44B5B-F8FF-47FA-9A77-BE2D176B2721}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gdpr", "gdpr", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Domain.Shared", "modules\gdpr\LINGYUN.Abp.Gdpr.Domain.Shared\LINGYUN.Abp.Gdpr.Domain.Shared.csproj", "{DD365101-E8FC-6516-2883-B9CA024B36FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Domain", "modules\gdpr\LINGYUN.Abp.Gdpr.Domain\LINGYUN.Abp.Gdpr.Domain.csproj", "{C330BADD-59A0-A3CD-E839-A0D4C2C636EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Domain.Identity", "modules\gdpr\LINGYUN.Abp.Gdpr.Domain.Identity\LINGYUN.Abp.Gdpr.Domain.Identity.csproj", "{F1C6C6B6-5B99-5AA6-7F76-27560C111605}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Application.Contracts", "modules\gdpr\LINGYUN.Abp.Gdpr.Application.Contracts\LINGYUN.Abp.Gdpr.Application.Contracts.csproj", "{459DA653-F12A-65B5-41EF-A5877B1C38BA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Application", "modules\gdpr\LINGYUN.Abp.Gdpr.Application\LINGYUN.Abp.Gdpr.Application.csproj", "{9DD70A99-41A6-8598-553E-2B5AB6277035}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.EntityFrameworkCore", "modules\gdpr\LINGYUN.Abp.Gdpr.EntityFrameworkCore\LINGYUN.Abp.Gdpr.EntityFrameworkCore.csproj", "{016CCD97-3551-B6C7-FC6C-FF1CB7F84B88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.HttpApi", "modules\gdpr\LINGYUN.Abp.Gdpr.HttpApi\LINGYUN.Abp.Gdpr.HttpApi.csproj", "{F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Encryption.SM4", "framework\security\LINGYUN.Abp.Encryption.SM4\LINGYUN.Abp.Encryption.SM4.csproj", "{AE00DA82-B33A-CAF7-D9CD-D5E26608741B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Web", "modules\account\LINGYUN.Abp.Account.Web\LINGYUN.Abp.Account.Web.csproj", "{F9A0D88F-53AE-4AC7-8E15-163C34386E7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Web.IdentityServer", "modules\account\LINGYUN.Abp.Account.Web.IdentityServer\LINGYUN.Abp.Account.Web.IdentityServer.csproj", "{0FF0A04C-B580-4A56-9171-CF2988B5DE5A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Web.OpenIddict", "modules\account\LINGYUN.Abp.Account.Web.OpenIddict\LINGYUN.Abp.Account.Web.OpenIddict.csproj", "{F810C8A8-1256-440F-BAAF-7F3588291963}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.HttpApi.Client", "modules\account\LINGYUN.Abp.Account.HttpApi.Client\LINGYUN.Abp.Account.HttpApi.Client.csproj", "{FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.HttpApi.Client", "modules\gdpr\LINGYUN.Abp.Gdpr.HttpApi.Client\LINGYUN.Abp.Gdpr.HttpApi.Client.csproj", "{C95DE287-9D21-4DCD-9281-A060B6D99774}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Web", "modules\gdpr\LINGYUN.Abp.Gdpr.Web\LINGYUN.Abp.Gdpr.Web.csproj", "{96748DAE-D367-48C0-B64E-2F25010EAC4D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "exporter", "exporter", "{A4633711-7FB6-411A-8D08-BB9A0A778046}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Core", "framework\exporter\LINGYUN.Abp.Exporter.Core\LINGYUN.Abp.Exporter.Core.csproj", "{5A0063BF-EE72-E688-84C6-9E3CE0616C94}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.MiniExcel", "framework\exporter\LINGYUN.Abp.Exporter.MiniExcel\LINGYUN.Abp.Exporter.MiniExcel.csproj", "{ECE61F58-1AEC-1E4F-1543-76C2242B6F70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.MagicodesIE.Excel", "framework\exporter\LINGYUN.Abp.Exporter.MagicodesIE.Excel\LINGYUN.Abp.Exporter.MagicodesIE.Excel.csproj", "{B7B63E08-8F62-34F6-FEA5-063267F1FC85}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Auditing.HttpApi.Client", "modules\auditing\LINGYUN.Abp.Auditing.HttpApi.Client\LINGYUN.Abp.Auditing.HttpApi.Client.csproj", "{7C48C1CA-7E53-4261-A477-454DD3A8402C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.AspNetCore", "framework\wechat\LINGYUN.Abp.WeChat.Work.AspNetCore\LINGYUN.Abp.WeChat.Work.AspNetCore.csproj", "{A54344EB-05A7-A405-5368-4A9C0A60B078}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.QrCode", "modules\identity\LINGYUN.Abp.Identity.QrCode\LINGYUN.Abp.Identity.QrCode.csproj", "{7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.AspNetCore.QrCode", "modules\identity\LINGYUN.Abp.Identity.AspNetCore.QrCode\LINGYUN.Abp.Identity.AspNetCore.QrCode.csproj", "{C9266D5D-3860-09C3-F566-489BBB57A534}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tracking", "tracking", "{21542881-C560-4CBB-8AB1-CF757071A057}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.APM", "framework\telemetry\LINGYUN.Abp.Telemetry.APM\LINGYUN.Abp.Telemetry.APM.csproj", "{F3DF1C3E-7319-48B1-81AB-0284853BB567}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.OpenTelemetry", "framework\telemetry\LINGYUN.Abp.Telemetry.OpenTelemetry\LINGYUN.Abp.Telemetry.OpenTelemetry.csproj", "{7D7561CB-5059-4F5F-B736-B97195B46A91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.SkyWalking", "framework\telemetry\LINGYUN.Abp.Telemetry.SkyWalking\LINGYUN.Abp.Telemetry.SkyWalking.csproj", "{5B9CA129-16CE-4BEF-B22D-C084B38B4EDA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.IP.Location", "framework\common\LINGYUN.Abp.IP.Location\LINGYUN.Abp.IP.Location.csproj", "{418EE258-2670-29D3-480F-EC0FD07700E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.IP2Region", "framework\common\LINGYUN.Abp.IP2Region\LINGYUN.Abp.IP2Region.csproj", "{7984F6B6-726F-9F30-3B6F-08A90AD75A7D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AuditLogging.IP.Location", "framework\auditing\LINGYUN.Abp.AuditLogging.IP.Location\LINGYUN.Abp.AuditLogging.IP.Location.csproj", "{D63FEED3-2342-7E96-4121-B0C19CF1EA81}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Saas.DbChecker", "modules\saas\LINGYUN.Abp.Saas.DbChecker\LINGYUN.Abp.Saas.DbChecker.csproj", "{DED16774-635C-D781-4D5B-D1FA56EECF10}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.UI.Navigation.VueVbenAdmin5", "modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin5\LINGYUN.Abp.UI.Navigation.VueVbenAdmin5.csproj", "{4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Web.OAuth", "modules\account\LINGYUN.Abp.Account.Web.OAuth\LINGYUN.Abp.Account.Web.OAuth.csproj", "{DD11D070-F39E-1C41-1843-AE3ADBE501EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.OAuth", "modules\account\LINGYUN.Abp.Account.OAuth\LINGYUN.Abp.Account.OAuth.csproj", "{001D0817-1EED-4C04-821E-F815F148EC90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf", "framework\exporter\LINGYUN.Abp.Exporter.Pdf\LINGYUN.Abp.Exporter.Pdf.csproj", "{546E4417-5409-40F4-A125-E08329DD82BB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.LibreOffice", "framework\exporter\LINGYUN.Abp.Exporter.Pdf.LibreOffice\LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj", "{738A72FB-ED83-4127-AA3B-59BF90635F8F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.SpireLib", "framework\exporter\LINGYUN.Abp.Exporter.Pdf.SpireLib\LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj", "{9950639D-AA4C-4FF1-A65E-9790EB561C8A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Security", "modules\account\LINGYUN.Abp.Account.Security\LINGYUN.Abp.Account.Security.csproj", "{5FA85E8E-3276-43DF-CC93-6A9847905166}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AspNetCore.MultiTenancy", "framework\tenants\LINGYUN.Abp.AspNetCore.MultiTenancy\LINGYUN.Abp.AspNetCore.MultiTenancy.csproj", "{AEEA81D6-B282-93CF-862B-9FCF1A5052F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.Contacts", "framework\wechat\LINGYUN.Abp.WeChat.Work.Contacts\LINGYUN.Abp.WeChat.Work.Contacts.csproj", "{69419D6B-9DA5-D9BD-1D6C-61BBAE331057}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.ExternalContact", "framework\wechat\LINGYUN.Abp.WeChat.Work.ExternalContact\LINGYUN.Abp.WeChat.Work.ExternalContact.csproj", "{B4311504-B0C8-AC8D-02A5-81AD43B4087B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aspire", "aspire", "{FAB71536-FCDB-4135-B61A-732B72FDA6A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.ServiceDefaults", "aspire\LINGYUN.Abp.MicroService.ServiceDefaults\LINGYUN.Abp.MicroService.ServiceDefaults.csproj", "{C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AppHost", "aspire\LINGYUN.Abp.MicroService.AppHost\LINGYUN.Abp.MicroService.AppHost.csproj", "{9FF83836-8627-2943-3344-60319FB85B39}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin-service", "admin-service", "{EB06B90A-D05C-486C-9787-BA5581664641}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AdminService", "aspire\LINGYUN.Abp.MicroService.AdminService\LINGYUN.Abp.MicroService.AdminService.csproj", "{2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "platform-service", "platform-service", "{1AE7D817-E837-4C25-9850-8AB11030713F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.PlatformService", "aspire\LINGYUN.Abp.MicroService.PlatformService\LINGYUN.Abp.MicroService.PlatformService.csproj", "{1B5368E2-8A31-F686-3120-770BAD793962}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore\LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore.csproj", "{BFFC0787-81F4-4751-9385-B91BB8CB183A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AdminService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.AdminService.DbMigrator\LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj", "{E0EEFE73-EF05-491B-A265-E2B613D0C82F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "auth-server", "auth-server", "{A4EF0E36-156F-4D12-A6B0-3C681A1AE6A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore\LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore.csproj", "{2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AuthServer.DbMigrator", "aspire\LINGYUN.Abp.MicroService.AuthServer.DbMigrator\LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj", "{B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.AuthServer", "aspire\LINGYUN.Abp.MicroService.AuthServer\LINGYUN.Abp.MicroService.AuthServer.csproj", "{569667D0-2038-4566-9711-6B174C631063}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore\LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj", "{7760B229-E3EA-4A60-9E32-7B2F7FB199E7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.PlatformService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.PlatformService.DbMigrator\LINGYUN.Abp.MicroService.PlatformService.DbMigrator.csproj", "{3672F185-59B2-490D-A00B-5CA9815909B6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization-service", "localization-service", "{2D8CA6FB-3FE7-4218-829E-0A1B36A5340D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.LocalizationService", "aspire\LINGYUN.Abp.MicroService.LocalizationService\LINGYUN.Abp.MicroService.LocalizationService.csproj", "{1B9DC76D-942D-4DCC-979F-E9E56BB7073E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore\LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore.csproj", "{7F65C827-914D-42B1-AE26-44053AE3140F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.LocalizationService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.LocalizationService.DbMigrator\LINGYUN.Abp.MicroService.LocalizationService.DbMigrator.csproj", "{1425C1AB-048F-4ABF-ACAB-793E2524F0A8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "message-service", "message-service", "{647AB3E7-2F32-43D1-AFDC-877C7412F4DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.MessageService", "aspire\LINGYUN.Abp.MicroService.MessageService\LINGYUN.Abp.MicroService.MessageService.csproj", "{4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.MessageService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.MessageService.DbMigrator\LINGYUN.Abp.MicroService.MessageService.DbMigrator.csproj", "{09B8B63F-972B-4055-9BAD-B2883EBA3EF0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore\LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore.csproj", "{4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.SqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.SqlInstaller\LINGYUN.Abp.Quartz.SqlInstaller.csproj", "{0EEA73CA-D8DD-F044-045D-F070F8831E26}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.MySqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.MySqlInstaller\LINGYUN.Abp.Quartz.MySqlInstaller.csproj", "{B6452D3F-E58C-C433-E52A-F65EE2657E01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-service", "identity-service", "{19F90E75-657C-4542-A798-8E9CE9AF3128}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.IdentityService", "aspire\LINGYUN.Abp.MicroService.IdentityService\LINGYUN.Abp.MicroService.IdentityService.csproj", "{62FB9F56-221E-47D5-8B30-311A13D6A568}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "task-service", "task-service", "{9F260C45-199D-460C-A5C0-6C2B62594DFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.TaskService", "aspire\LINGYUN.Abp.MicroService.TaskService\LINGYUN.Abp.MicroService.TaskService.csproj", "{ACEEA6F9-868B-4701-AF65-89292F656A1D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.TaskService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.TaskService.DbMigrator\LINGYUN.Abp.MicroService.TaskService.DbMigrator.csproj", "{FB12303C-7A3A-4A42-900F-C131D0FD7BA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore\LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore.csproj", "{BAE82F6F-2528-45DF-9571-F733C31CEB1E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Domain.Shared", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain.Shared\LINGYUN.Abp.TaskManagement.Domain.Shared.csproj", "{97C66786-03F8-4886-088E-FA1BECB1C574}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Domain", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain\LINGYUN.Abp.TaskManagement.Domain.csproj", "{7B927926-0AF4-A6F2-8ABA-331A6C138EAC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.EntityFrameworkCore", "modules\task-management\LINGYUN.Abp.TaskManagement.EntityFrameworkCore\LINGYUN.Abp.TaskManagement.EntityFrameworkCore.csproj", "{C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Notifications", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Notifications\LINGYUN.Abp.BackgroundTasks.Notifications.csproj", "{6FCE34BF-077B-9425-CD34-FA9B2CD190FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Application", "modules\task-management\LINGYUN.Abp.TaskManagement.Application\LINGYUN.Abp.TaskManagement.Application.csproj", "{A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.HttpApi", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi\LINGYUN.Abp.TaskManagement.HttpApi.csproj", "{107C0D30-35C1-142B-209A-29BD6BAE7DE9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "webhook-service", "webhook-service", "{D8AF0368-077D-4AAD-9929-43C598DE13B5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.WebhookService", "aspire\LINGYUN.Abp.MicroService.WebhookService\LINGYUN.Abp.MicroService.WebhookService.csproj", "{DB03F47B-4E3A-4484-86DC-741472AD49A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.WebhookService.DbMigrator", "aspire\LINGYUN.Abp.MicroService.WebhookService.DbMigrator\LINGYUN.Abp.MicroService.WebhookService.DbMigrator.csproj", "{2DB2EADB-745A-4442-A48A-B1B721412F78}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore", "aspire\LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore\LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore.csproj", "{4524F120-F72B-4373-B731-6A2D0EF633A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.EventBus", "modules\webhooks\LINGYUN.Abp.Webhooks.EventBus\LINGYUN.Abp.Webhooks.EventBus.csproj", "{0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.Identity", "modules\webhooks\LINGYUN.Abp.Webhooks.Identity\LINGYUN.Abp.Webhooks.Identity.csproj", "{8880DC40-7C67-AEBC-AFD6-45094E65D01B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.Saas", "modules\webhooks\LINGYUN.Abp.Webhooks.Saas\LINGYUN.Abp.Webhooks.Saas.csproj", "{DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Domain.Shared", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Domain.Shared\LINGYUN.Abp.WebhooksManagement.Domain.Shared.csproj", "{A076DAB1-03F6-0592-4900-5CEF38A76026}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Domain", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Domain\LINGYUN.Abp.WebhooksManagement.Domain.csproj", "{9CA173D6-B883-9629-EFB3-A37D89AAEE81}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Application.Contracts", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Application.Contracts\LINGYUN.Abp.WebhooksManagement.Application.Contracts.csproj", "{FDE1FE78-B568-3602-653D-2E641AD999D5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Application", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Application\LINGYUN.Abp.WebhooksManagement.Application.csproj", "{2F99A8DC-3A89-3004-66F2-B61158DA9F61}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore.csproj", "{4AC7962E-AB5E-BEE5-DC17-22A29FE73DED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.HttpApi", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.HttpApi\LINGYUN.Abp.WebhooksManagement.HttpApi.csproj", "{E5343E6A-61DC-46E0-6A7A-9F93362AF113}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat-service", "wechat-service", "{125E78AC-071D-4F82-88CE-1D7D2D0AAFF4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.WeChatService", "aspire\LINGYUN.Abp.MicroService.WeChatService\LINGYUN.Abp.MicroService.WeChatService.csproj", "{A768070E-FF34-424C-9945-B75533E7ADD3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.OA", "framework\wechat\LINGYUN.Abp.WeChat.Work.OA\LINGYUN.Abp.WeChat.Work.OA.csproj", "{AB207B2A-C8E7-977D-98E6-66527CBB2B7F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Official.Application.Contracts", "framework\wechat\LINGYUN.Abp.WeChat.Official.Application.Contracts\LINGYUN.Abp.WeChat.Official.Application.Contracts.csproj", "{AB981FD3-3523-CDEA-73C9-D6280400062C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Official.Application", "framework\wechat\LINGYUN.Abp.WeChat.Official.Application\LINGYUN.Abp.WeChat.Official.Application.csproj", "{B760E50F-F5B6-1266-02A8-0056483F475B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Official.HttpApi", "framework\wechat\LINGYUN.Abp.WeChat.Official.HttpApi\LINGYUN.Abp.WeChat.Official.HttpApi.csproj", "{CDD00CAC-4A4E-FAD5-E8C3-B833C2994314}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflow-service", "workflow-service", "{F38C6E5A-1C5F-49FF-9174-95430D6C91ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.WorkflowService", "aspire\LINGYUN.Abp.MicroService.WorkflowService\LINGYUN.Abp.MicroService.WorkflowService.csproj", "{56778F12-42F0-4288-B559-218FC5A3C323}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{A72387FE-3361-45B3-AE7A-8BB212668A85}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.Domain.Shared", "modules\project\LINGYUN.Abp.ProjectManagement.Domain.Shared\LINGYUN.Abp.ProjectManagement.Domain.Shared.csproj", "{6120F990-8729-DD52-5CEA-F2295528ED07}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.Domain", "modules\project\LINGYUN.Abp.ProjectManagement.Domain\LINGYUN.Abp.ProjectManagement.Domain.csproj", "{32C35E78-BE23-2D27-F1B3-C2270E45B0C4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.Application.Contracts", "modules\project\LINGYUN.Abp.ProjectManagement.Application.Contracts\LINGYUN.Abp.ProjectManagement.Application.Contracts.csproj", "{9AC112AD-18C2-359E-6696-87B814A69E63}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.Application", "modules\project\LINGYUN.Abp.ProjectManagement.Application\LINGYUN.Abp.ProjectManagement.Application.csproj", "{B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.EntityFrameworkCore", "modules\project\LINGYUN.Abp.ProjectManagement.EntityFrameworkCore\LINGYUN.Abp.ProjectManagement.EntityFrameworkCore.csproj", "{D74CF5EA-4BE7-4F23-663A-490C29D7576A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.ProjectManagement.HttpApi", "modules\project\LINGYUN.Abp.ProjectManagement.HttpApi\LINGYUN.Abp.ProjectManagement.HttpApi.csproj", "{73A8BAF3-10A7-1C52-7CFF-6301B730A458}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.PostgresSqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.PostgresSqlInstaller\LINGYUN.Abp.Quartz.PostgresSqlInstaller.csproj", "{CD7B8501-57B7-6C0E-472F-4E9B894ED6C2}" +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", "{52186445-5B56-EA32-F154-39F47D2FB235}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "api-gateway", "api-gateway", "{B856BFF0-8D0E-4C4A-97C7-5406E1B7613C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MicroService.ApiGateway", "aspire\LINGYUN.Abp.MicroService.ApiGateway\LINGYUN.Abp.MicroService.ApiGateway.csproj", "{410E0FFF-705D-4471-9E52-FF495096A945}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Quartz", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Quartz\LINGYUN.Abp.BackgroundTasks.Quartz.csproj", "{ABCAB030-29ED-8219-F1DB-39D16098805F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {77BDEF2B-1A30-4E64-BC35-0DFC21091327}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77BDEF2B-1A30-4E64-BC35-0DFC21091327}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77BDEF2B-1A30-4E64-BC35-0DFC21091327}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77BDEF2B-1A30-4E64-BC35-0DFC21091327}.Release|Any CPU.Build.0 = Release|Any CPU + {573B7B0E-3065-42DE-A391-EE026CE7A366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {573B7B0E-3065-42DE-A391-EE026CE7A366}.Debug|Any CPU.Build.0 = Debug|Any CPU + {573B7B0E-3065-42DE-A391-EE026CE7A366}.Release|Any CPU.ActiveCfg = Release|Any CPU + {573B7B0E-3065-42DE-A391-EE026CE7A366}.Release|Any CPU.Build.0 = Release|Any CPU + {FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF}.Release|Any CPU.Build.0 = Release|Any CPU + {3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2}.Release|Any CPU.Build.0 = Release|Any CPU + {A584D040-95AC-4422-93FF-7B80532213F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A584D040-95AC-4422-93FF-7B80532213F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A584D040-95AC-4422-93FF-7B80532213F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A584D040-95AC-4422-93FF-7B80532213F0}.Release|Any CPU.Build.0 = Release|Any CPU + {76249548-4344-4CD0-A0AC-12AC54184B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76249548-4344-4CD0-A0AC-12AC54184B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76249548-4344-4CD0-A0AC-12AC54184B58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76249548-4344-4CD0-A0AC-12AC54184B58}.Release|Any CPU.Build.0 = Release|Any CPU + {AEC1E6D3-DC23-41BD-B456-3AAD26E34978}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEC1E6D3-DC23-41BD-B456-3AAD26E34978}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEC1E6D3-DC23-41BD-B456-3AAD26E34978}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEC1E6D3-DC23-41BD-B456-3AAD26E34978}.Release|Any CPU.Build.0 = Release|Any CPU + {E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB}.Release|Any CPU.Build.0 = Release|Any CPU + {8B09385A-719C-4B83-B61E-0ECD5D2734BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B09385A-719C-4B83-B61E-0ECD5D2734BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B09385A-719C-4B83-B61E-0ECD5D2734BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B09385A-719C-4B83-B61E-0ECD5D2734BD}.Release|Any CPU.Build.0 = Release|Any CPU + {8E569C1C-2637-4D89-804C-50FBC83948FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E569C1C-2637-4D89-804C-50FBC83948FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E569C1C-2637-4D89-804C-50FBC83948FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E569C1C-2637-4D89-804C-50FBC83948FB}.Release|Any CPU.Build.0 = Release|Any CPU + {5A10C02B-D12C-479C-9E7F-9A7D9DDD753D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A10C02B-D12C-479C-9E7F-9A7D9DDD753D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A10C02B-D12C-479C-9E7F-9A7D9DDD753D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A10C02B-D12C-479C-9E7F-9A7D9DDD753D}.Release|Any CPU.Build.0 = Release|Any CPU + {FF1839EA-FB6B-4ED5-9804-E40427046D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF1839EA-FB6B-4ED5-9804-E40427046D35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF1839EA-FB6B-4ED5-9804-E40427046D35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF1839EA-FB6B-4ED5-9804-E40427046D35}.Release|Any CPU.Build.0 = Release|Any CPU + {9FE2A95F-D7A3-4305-9E12-E955EF74CF8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FE2A95F-D7A3-4305-9E12-E955EF74CF8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FE2A95F-D7A3-4305-9E12-E955EF74CF8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FE2A95F-D7A3-4305-9E12-E955EF74CF8D}.Release|Any CPU.Build.0 = Release|Any CPU + {6E4A0D87-C3CE-430F-A475-A6B68C116D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E4A0D87-C3CE-430F-A475-A6B68C116D96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E4A0D87-C3CE-430F-A475-A6B68C116D96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E4A0D87-C3CE-430F-A475-A6B68C116D96}.Release|Any CPU.Build.0 = Release|Any CPU + {A5851F0F-CB0D-4E29-A829-D1BDEADB807B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5851F0F-CB0D-4E29-A829-D1BDEADB807B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5851F0F-CB0D-4E29-A829-D1BDEADB807B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5851F0F-CB0D-4E29-A829-D1BDEADB807B}.Release|Any CPU.Build.0 = Release|Any CPU + {FDEECE0D-6F66-4053-948E-9AC021B97C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDEECE0D-6F66-4053-948E-9AC021B97C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDEECE0D-6F66-4053-948E-9AC021B97C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDEECE0D-6F66-4053-948E-9AC021B97C8D}.Release|Any CPU.Build.0 = Release|Any CPU + {4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873}.Release|Any CPU.Build.0 = Release|Any CPU + {371B293B-0CA9-4385-8EBB-5224332066D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {371B293B-0CA9-4385-8EBB-5224332066D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {371B293B-0CA9-4385-8EBB-5224332066D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {371B293B-0CA9-4385-8EBB-5224332066D2}.Release|Any CPU.Build.0 = Release|Any CPU + {9E12ADBF-713B-4FE7-B71F-52B5078A57CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E12ADBF-713B-4FE7-B71F-52B5078A57CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E12ADBF-713B-4FE7-B71F-52B5078A57CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E12ADBF-713B-4FE7-B71F-52B5078A57CE}.Release|Any CPU.Build.0 = Release|Any CPU + {47CC8F7A-681D-42B9-AE04-78453782C1B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47CC8F7A-681D-42B9-AE04-78453782C1B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47CC8F7A-681D-42B9-AE04-78453782C1B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47CC8F7A-681D-42B9-AE04-78453782C1B6}.Release|Any CPU.Build.0 = Release|Any CPU + {F595CB9F-B117-4D62-A1AE-48599927DB36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F595CB9F-B117-4D62-A1AE-48599927DB36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F595CB9F-B117-4D62-A1AE-48599927DB36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F595CB9F-B117-4D62-A1AE-48599927DB36}.Release|Any CPU.Build.0 = Release|Any CPU + {5CF403B2-47C9-4E4E-8856-0294BDD64884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CF403B2-47C9-4E4E-8856-0294BDD64884}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CF403B2-47C9-4E4E-8856-0294BDD64884}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CF403B2-47C9-4E4E-8856-0294BDD64884}.Release|Any CPU.Build.0 = Release|Any CPU + {059473BA-FAF9-405F-9985-33DDCA2E9F0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {059473BA-FAF9-405F-9985-33DDCA2E9F0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {059473BA-FAF9-405F-9985-33DDCA2E9F0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {059473BA-FAF9-405F-9985-33DDCA2E9F0D}.Release|Any CPU.Build.0 = Release|Any CPU + {B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B}.Release|Any CPU.Build.0 = Release|Any CPU + {C8A00439-5B8D-4923-8FAA-AB75E2A786ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8A00439-5B8D-4923-8FAA-AB75E2A786ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8A00439-5B8D-4923-8FAA-AB75E2A786ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8A00439-5B8D-4923-8FAA-AB75E2A786ED}.Release|Any CPU.Build.0 = Release|Any CPU + {31B03DCB-ED12-4412-867A-61E347D40D8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31B03DCB-ED12-4412-867A-61E347D40D8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31B03DCB-ED12-4412-867A-61E347D40D8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31B03DCB-ED12-4412-867A-61E347D40D8C}.Release|Any CPU.Build.0 = Release|Any CPU + {AB984240-EF03-416F-A9B2-F5CF169E04B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB984240-EF03-416F-A9B2-F5CF169E04B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB984240-EF03-416F-A9B2-F5CF169E04B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB984240-EF03-416F-A9B2-F5CF169E04B7}.Release|Any CPU.Build.0 = Release|Any CPU + {EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415}.Release|Any CPU.Build.0 = Release|Any CPU + {65DDA934-B76B-4018-A565-CF6CEF0D6BB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65DDA934-B76B-4018-A565-CF6CEF0D6BB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65DDA934-B76B-4018-A565-CF6CEF0D6BB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65DDA934-B76B-4018-A565-CF6CEF0D6BB0}.Release|Any CPU.Build.0 = Release|Any CPU + {376D8343-DF83-41D2-BF6E-2F5DC8DBF259}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {376D8343-DF83-41D2-BF6E-2F5DC8DBF259}.Debug|Any CPU.Build.0 = Debug|Any CPU + {376D8343-DF83-41D2-BF6E-2F5DC8DBF259}.Release|Any CPU.ActiveCfg = Release|Any CPU + {376D8343-DF83-41D2-BF6E-2F5DC8DBF259}.Release|Any CPU.Build.0 = Release|Any CPU + {6259BCB9-A302-4CE7-AF48-9283A0DFD3CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6259BCB9-A302-4CE7-AF48-9283A0DFD3CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6259BCB9-A302-4CE7-AF48-9283A0DFD3CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6259BCB9-A302-4CE7-AF48-9283A0DFD3CB}.Release|Any CPU.Build.0 = Release|Any CPU + {1DA91161-8757-4A68-A0A1-8C94C36C9240}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1DA91161-8757-4A68-A0A1-8C94C36C9240}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1DA91161-8757-4A68-A0A1-8C94C36C9240}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DA91161-8757-4A68-A0A1-8C94C36C9240}.Release|Any CPU.Build.0 = Release|Any CPU + {F135B9E8-3FFE-44E9-835B-7B6A928F4823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F135B9E8-3FFE-44E9-835B-7B6A928F4823}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F135B9E8-3FFE-44E9-835B-7B6A928F4823}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F135B9E8-3FFE-44E9-835B-7B6A928F4823}.Release|Any CPU.Build.0 = Release|Any CPU + {75A6D078-C19D-4030-88CC-C2A8608FF604}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75A6D078-C19D-4030-88CC-C2A8608FF604}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75A6D078-C19D-4030-88CC-C2A8608FF604}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75A6D078-C19D-4030-88CC-C2A8608FF604}.Release|Any CPU.Build.0 = Release|Any CPU + {2D895594-3FF5-4507-853A-CB65F2DB72ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D895594-3FF5-4507-853A-CB65F2DB72ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D895594-3FF5-4507-853A-CB65F2DB72ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D895594-3FF5-4507-853A-CB65F2DB72ED}.Release|Any CPU.Build.0 = Release|Any CPU + {AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93}.Release|Any CPU.Build.0 = Release|Any CPU + {0655A0FB-59E8-4A9F-BAF5-47A89377F747}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0655A0FB-59E8-4A9F-BAF5-47A89377F747}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0655A0FB-59E8-4A9F-BAF5-47A89377F747}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0655A0FB-59E8-4A9F-BAF5-47A89377F747}.Release|Any CPU.Build.0 = Release|Any CPU + {5FBBBA6A-D6EC-42E1-8164-15C411EC77BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FBBBA6A-D6EC-42E1-8164-15C411EC77BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FBBBA6A-D6EC-42E1-8164-15C411EC77BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FBBBA6A-D6EC-42E1-8164-15C411EC77BE}.Release|Any CPU.Build.0 = Release|Any CPU + {F3D9B137-32DE-4018-8058-78AB17FCDF9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3D9B137-32DE-4018-8058-78AB17FCDF9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3D9B137-32DE-4018-8058-78AB17FCDF9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3D9B137-32DE-4018-8058-78AB17FCDF9C}.Release|Any CPU.Build.0 = Release|Any CPU + {F19C8B0F-A332-4190-9ABE-95790E0AE864}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F19C8B0F-A332-4190-9ABE-95790E0AE864}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F19C8B0F-A332-4190-9ABE-95790E0AE864}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F19C8B0F-A332-4190-9ABE-95790E0AE864}.Release|Any CPU.Build.0 = Release|Any CPU + {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}.Release|Any CPU.Build.0 = Release|Any CPU + {72DCA4CF-8B95-47C9-B02A-2671953B7987}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72DCA4CF-8B95-47C9-B02A-2671953B7987}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72DCA4CF-8B95-47C9-B02A-2671953B7987}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72DCA4CF-8B95-47C9-B02A-2671953B7987}.Release|Any CPU.Build.0 = Release|Any CPU + {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Release|Any CPU.Build.0 = Release|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Release|Any CPU.Build.0 = Release|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Release|Any CPU.Build.0 = Release|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Release|Any CPU.Build.0 = Release|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Release|Any CPU.Build.0 = Release|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Release|Any CPU.Build.0 = Release|Any CPU + {F359AAA1-C854-444A-88F2-1C0D8A07F864}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F359AAA1-C854-444A-88F2-1C0D8A07F864}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F359AAA1-C854-444A-88F2-1C0D8A07F864}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F359AAA1-C854-444A-88F2-1C0D8A07F864}.Release|Any CPU.Build.0 = Release|Any CPU + {5D0ED1FC-3A7C-4531-9512-832E73AD9555}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D0ED1FC-3A7C-4531-9512-832E73AD9555}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D0ED1FC-3A7C-4531-9512-832E73AD9555}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D0ED1FC-3A7C-4531-9512-832E73AD9555}.Release|Any CPU.Build.0 = Release|Any CPU + {2BF7FB73-0C62-4ECF-99F0-0583855D2777}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BF7FB73-0C62-4ECF-99F0-0583855D2777}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BF7FB73-0C62-4ECF-99F0-0583855D2777}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BF7FB73-0C62-4ECF-99F0-0583855D2777}.Release|Any CPU.Build.0 = Release|Any CPU + {6FE7E243-2D99-4567-8786-6C9283D608EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FE7E243-2D99-4567-8786-6C9283D608EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FE7E243-2D99-4567-8786-6C9283D608EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FE7E243-2D99-4567-8786-6C9283D608EF}.Release|Any CPU.Build.0 = Release|Any CPU + {65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED}.Release|Any CPU.Build.0 = Release|Any CPU + {D3E65610-4167-4235-9C9D-1E1FAD4C0CE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3E65610-4167-4235-9C9D-1E1FAD4C0CE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3E65610-4167-4235-9C9D-1E1FAD4C0CE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3E65610-4167-4235-9C9D-1E1FAD4C0CE6}.Release|Any CPU.Build.0 = Release|Any CPU + {F12F4645-C0FE-4129-8C71-65B4039DC445}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F12F4645-C0FE-4129-8C71-65B4039DC445}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F12F4645-C0FE-4129-8C71-65B4039DC445}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F12F4645-C0FE-4129-8C71-65B4039DC445}.Release|Any CPU.Build.0 = Release|Any CPU + {C457FA70-8732-44B8-A018-C96D14025D4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C457FA70-8732-44B8-A018-C96D14025D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C457FA70-8732-44B8-A018-C96D14025D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C457FA70-8732-44B8-A018-C96D14025D4B}.Release|Any CPU.Build.0 = Release|Any CPU + {7071E78B-755B-410A-830B-AA05D7168944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7071E78B-755B-410A-830B-AA05D7168944}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7071E78B-755B-410A-830B-AA05D7168944}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7071E78B-755B-410A-830B-AA05D7168944}.Release|Any CPU.Build.0 = Release|Any CPU + {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Release|Any CPU.Build.0 = Release|Any CPU + {F40F88F1-CA90-4A79-B772-80E287E25982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F40F88F1-CA90-4A79-B772-80E287E25982}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F40F88F1-CA90-4A79-B772-80E287E25982}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F40F88F1-CA90-4A79-B772-80E287E25982}.Release|Any CPU.Build.0 = Release|Any CPU + {AC3C8985-73C2-472A-8E76-A0B8786FEC3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC3C8985-73C2-472A-8E76-A0B8786FEC3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC3C8985-73C2-472A-8E76-A0B8786FEC3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC3C8985-73C2-472A-8E76-A0B8786FEC3F}.Release|Any CPU.Build.0 = Release|Any CPU + {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Release|Any CPU.Build.0 = Release|Any CPU + {BAE74ABC-1096-495F-A624-BEBFBC1896F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAE74ABC-1096-495F-A624-BEBFBC1896F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAE74ABC-1096-495F-A624-BEBFBC1896F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAE74ABC-1096-495F-A624-BEBFBC1896F2}.Release|Any CPU.Build.0 = Release|Any CPU + {E92A1CAA-5758-41EF-B67E-C0D394E85417}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E92A1CAA-5758-41EF-B67E-C0D394E85417}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E92A1CAA-5758-41EF-B67E-C0D394E85417}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E92A1CAA-5758-41EF-B67E-C0D394E85417}.Release|Any CPU.Build.0 = Release|Any CPU + {F18DE651-A3E4-478F-A2B5-686429729EB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F18DE651-A3E4-478F-A2B5-686429729EB8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F18DE651-A3E4-478F-A2B5-686429729EB8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F18DE651-A3E4-478F-A2B5-686429729EB8}.Release|Any CPU.Build.0 = Release|Any CPU + {42309C06-C0F2-490F-931B-CF41FA1970FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42309C06-C0F2-490F-931B-CF41FA1970FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42309C06-C0F2-490F-931B-CF41FA1970FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42309C06-C0F2-490F-931B-CF41FA1970FF}.Release|Any CPU.Build.0 = Release|Any CPU + {EC19F867-E9EA-4B26-A1E7-87AAA3EB9296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC19F867-E9EA-4B26-A1E7-87AAA3EB9296}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC19F867-E9EA-4B26-A1E7-87AAA3EB9296}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC19F867-E9EA-4B26-A1E7-87AAA3EB9296}.Release|Any CPU.Build.0 = Release|Any CPU + {DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91}.Release|Any CPU.Build.0 = Release|Any CPU + {FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC}.Release|Any CPU.Build.0 = Release|Any CPU + {97B4A37E-B93E-48C9-95D5-689CB9495D8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97B4A37E-B93E-48C9-95D5-689CB9495D8B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97B4A37E-B93E-48C9-95D5-689CB9495D8B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97B4A37E-B93E-48C9-95D5-689CB9495D8B}.Release|Any CPU.Build.0 = Release|Any CPU + {FE0F0889-C4AF-43C5-B851-B8CCC873BA2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE0F0889-C4AF-43C5-B851-B8CCC873BA2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE0F0889-C4AF-43C5-B851-B8CCC873BA2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE0F0889-C4AF-43C5-B851-B8CCC873BA2C}.Release|Any CPU.Build.0 = Release|Any CPU + {B86EBB6F-A27F-4277-8265-937951A9DCB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B86EBB6F-A27F-4277-8265-937951A9DCB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B86EBB6F-A27F-4277-8265-937951A9DCB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B86EBB6F-A27F-4277-8265-937951A9DCB0}.Release|Any CPU.Build.0 = Release|Any CPU + {35B17218-9FB6-439E-AF73-9A1454BC923C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35B17218-9FB6-439E-AF73-9A1454BC923C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35B17218-9FB6-439E-AF73-9A1454BC923C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35B17218-9FB6-439E-AF73-9A1454BC923C}.Release|Any CPU.Build.0 = Release|Any CPU + {D5036D3F-1C53-47EE-BA50-AD290AE062D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5036D3F-1C53-47EE-BA50-AD290AE062D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5036D3F-1C53-47EE-BA50-AD290AE062D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5036D3F-1C53-47EE-BA50-AD290AE062D7}.Release|Any CPU.Build.0 = Release|Any CPU + {BD74BE00-54E4-4979-8797-E8027695F396}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD74BE00-54E4-4979-8797-E8027695F396}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD74BE00-54E4-4979-8797-E8027695F396}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD74BE00-54E4-4979-8797-E8027695F396}.Release|Any CPU.Build.0 = Release|Any CPU + {48DE251A-3482-4934-BC26-F99D2235AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48DE251A-3482-4934-BC26-F99D2235AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48DE251A-3482-4934-BC26-F99D2235AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48DE251A-3482-4934-BC26-F99D2235AC9F}.Release|Any CPU.Build.0 = Release|Any CPU + {94B47385-E47F-4FD7-A3A9-A7AA122EFC93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94B47385-E47F-4FD7-A3A9-A7AA122EFC93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94B47385-E47F-4FD7-A3A9-A7AA122EFC93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94B47385-E47F-4FD7-A3A9-A7AA122EFC93}.Release|Any CPU.Build.0 = Release|Any CPU + {C892CD81-50AE-49E5-BF44-A0C28A1614CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C892CD81-50AE-49E5-BF44-A0C28A1614CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C892CD81-50AE-49E5-BF44-A0C28A1614CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C892CD81-50AE-49E5-BF44-A0C28A1614CC}.Release|Any CPU.Build.0 = Release|Any CPU + {EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Release|Any CPU.Build.0 = Release|Any CPU + {84868710-ECBB-4025-900A-EEB99EC49534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84868710-ECBB-4025-900A-EEB99EC49534}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84868710-ECBB-4025-900A-EEB99EC49534}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84868710-ECBB-4025-900A-EEB99EC49534}.Release|Any CPU.Build.0 = Release|Any CPU + {A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Release|Any CPU.Build.0 = Release|Any CPU + {5BE18D72-0D02-4854-966E-745CE5DAF77F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BE18D72-0D02-4854-966E-745CE5DAF77F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BE18D72-0D02-4854-966E-745CE5DAF77F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BE18D72-0D02-4854-966E-745CE5DAF77F}.Release|Any CPU.Build.0 = Release|Any CPU + {73EAD4FE-B44F-44A7-904E-FFA5096D91BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73EAD4FE-B44F-44A7-904E-FFA5096D91BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73EAD4FE-B44F-44A7-904E-FFA5096D91BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73EAD4FE-B44F-44A7-904E-FFA5096D91BD}.Release|Any CPU.Build.0 = Release|Any CPU + {06D34108-01BA-4C77-A704-4DD9E6F7E32C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06D34108-01BA-4C77-A704-4DD9E6F7E32C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06D34108-01BA-4C77-A704-4DD9E6F7E32C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06D34108-01BA-4C77-A704-4DD9E6F7E32C}.Release|Any CPU.Build.0 = Release|Any CPU + {A98C939C-9F48-414A-A2D3-853BE4447397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A98C939C-9F48-414A-A2D3-853BE4447397}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A98C939C-9F48-414A-A2D3-853BE4447397}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A98C939C-9F48-414A-A2D3-853BE4447397}.Release|Any CPU.Build.0 = Release|Any CPU + {A94BE05F-7DAB-461C-93E7-914CBDF4FA93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A94BE05F-7DAB-461C-93E7-914CBDF4FA93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A94BE05F-7DAB-461C-93E7-914CBDF4FA93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A94BE05F-7DAB-461C-93E7-914CBDF4FA93}.Release|Any CPU.Build.0 = Release|Any CPU + {FBE91498-D83B-4873-A67E-0FB9D1C366F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBE91498-D83B-4873-A67E-0FB9D1C366F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBE91498-D83B-4873-A67E-0FB9D1C366F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBE91498-D83B-4873-A67E-0FB9D1C366F0}.Release|Any CPU.Build.0 = Release|Any CPU + {D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF}.Release|Any CPU.Build.0 = Release|Any CPU + {34BB9810-2983-4E55-A96A-132D32310145}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34BB9810-2983-4E55-A96A-132D32310145}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34BB9810-2983-4E55-A96A-132D32310145}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34BB9810-2983-4E55-A96A-132D32310145}.Release|Any CPU.Build.0 = Release|Any CPU + {4D83BDA7-2059-41C7-85AE-FEFAD5CD9498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D83BDA7-2059-41C7-85AE-FEFAD5CD9498}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D83BDA7-2059-41C7-85AE-FEFAD5CD9498}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D83BDA7-2059-41C7-85AE-FEFAD5CD9498}.Release|Any CPU.Build.0 = Release|Any CPU + {8EF31071-3521-409D-9740-BBFBFC04C50E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EF31071-3521-409D-9740-BBFBFC04C50E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EF31071-3521-409D-9740-BBFBFC04C50E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EF31071-3521-409D-9740-BBFBFC04C50E}.Release|Any CPU.Build.0 = Release|Any CPU + {13219C1C-23E1-4EBA-93FB-86830C93A800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13219C1C-23E1-4EBA-93FB-86830C93A800}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13219C1C-23E1-4EBA-93FB-86830C93A800}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13219C1C-23E1-4EBA-93FB-86830C93A800}.Release|Any CPU.Build.0 = Release|Any CPU + {60D0BEF2-FEAF-4066-8377-6C873CB24858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60D0BEF2-FEAF-4066-8377-6C873CB24858}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60D0BEF2-FEAF-4066-8377-6C873CB24858}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60D0BEF2-FEAF-4066-8377-6C873CB24858}.Release|Any CPU.Build.0 = Release|Any CPU + {340BE5AC-68EC-41A5-9D0D-266037C58F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {340BE5AC-68EC-41A5-9D0D-266037C58F13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {340BE5AC-68EC-41A5-9D0D-266037C58F13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {340BE5AC-68EC-41A5-9D0D-266037C58F13}.Release|Any CPU.Build.0 = Release|Any CPU + {BC518F26-996E-4DF0-BB44-783EB1C275D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC518F26-996E-4DF0-BB44-783EB1C275D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC518F26-996E-4DF0-BB44-783EB1C275D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC518F26-996E-4DF0-BB44-783EB1C275D2}.Release|Any CPU.Build.0 = Release|Any CPU + {63D1DC91-C7C7-491A-8423-B0B89F39443F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63D1DC91-C7C7-491A-8423-B0B89F39443F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63D1DC91-C7C7-491A-8423-B0B89F39443F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63D1DC91-C7C7-491A-8423-B0B89F39443F}.Release|Any CPU.Build.0 = Release|Any CPU + {1E0E82D2-F53A-4326-9E39-D7D677590543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E0E82D2-F53A-4326-9E39-D7D677590543}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E0E82D2-F53A-4326-9E39-D7D677590543}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E0E82D2-F53A-4326-9E39-D7D677590543}.Release|Any CPU.Build.0 = Release|Any CPU + {D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9}.Release|Any CPU.Build.0 = Release|Any CPU + {6C3D4C1C-4864-44A9-8649-9856ABF667FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C3D4C1C-4864-44A9-8649-9856ABF667FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C3D4C1C-4864-44A9-8649-9856ABF667FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C3D4C1C-4864-44A9-8649-9856ABF667FA}.Release|Any CPU.Build.0 = Release|Any CPU + {AD3CC5B5-366B-4E34-8E80-EC5BB68B573A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD3CC5B5-366B-4E34-8E80-EC5BB68B573A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD3CC5B5-366B-4E34-8E80-EC5BB68B573A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD3CC5B5-366B-4E34-8E80-EC5BB68B573A}.Release|Any CPU.Build.0 = Release|Any CPU + {F71A0D28-397D-4094-B1C2-7925E1310676}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F71A0D28-397D-4094-B1C2-7925E1310676}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F71A0D28-397D-4094-B1C2-7925E1310676}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F71A0D28-397D-4094-B1C2-7925E1310676}.Release|Any CPU.Build.0 = Release|Any CPU + {CEAF0044-28D3-4585-B69D-D65FF6D4745E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEAF0044-28D3-4585-B69D-D65FF6D4745E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEAF0044-28D3-4585-B69D-D65FF6D4745E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CEAF0044-28D3-4585-B69D-D65FF6D4745E}.Release|Any CPU.Build.0 = Release|Any CPU + {91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Release|Any CPU.Build.0 = Release|Any CPU + {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Release|Any CPU.Build.0 = Release|Any CPU + {67A76560-D39F-4D49-B858-B476E1DFE37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67A76560-D39F-4D49-B858-B476E1DFE37B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.Build.0 = Release|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Release|Any CPU.Build.0 = Release|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Release|Any CPU.Build.0 = Release|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Release|Any CPU.Build.0 = Release|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Release|Any CPU.Build.0 = Release|Any CPU + {EB73D2CC-B1BE-471A-B76E-35F288CD0E16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB73D2CC-B1BE-471A-B76E-35F288CD0E16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB73D2CC-B1BE-471A-B76E-35F288CD0E16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB73D2CC-B1BE-471A-B76E-35F288CD0E16}.Release|Any CPU.Build.0 = Release|Any CPU + {842E19B3-8110-40FE-AAFF-D288BC928E55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {842E19B3-8110-40FE-AAFF-D288BC928E55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {842E19B3-8110-40FE-AAFF-D288BC928E55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {842E19B3-8110-40FE-AAFF-D288BC928E55}.Release|Any CPU.Build.0 = Release|Any CPU + {C1319EC1-A489-482B-A343-38B52D8AB0B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1319EC1-A489-482B-A343-38B52D8AB0B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1319EC1-A489-482B-A343-38B52D8AB0B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1319EC1-A489-482B-A343-38B52D8AB0B0}.Release|Any CPU.Build.0 = Release|Any CPU + {4059F87E-9762-46C1-AEB1-B1128EA533AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4059F87E-9762-46C1-AEB1-B1128EA533AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4059F87E-9762-46C1-AEB1-B1128EA533AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4059F87E-9762-46C1-AEB1-B1128EA533AE}.Release|Any CPU.Build.0 = Release|Any CPU + {433AD1FB-2DE8-479F-B89E-A17217591538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {433AD1FB-2DE8-479F-B89E-A17217591538}.Debug|Any CPU.Build.0 = Debug|Any CPU + {433AD1FB-2DE8-479F-B89E-A17217591538}.Release|Any CPU.ActiveCfg = Release|Any CPU + {433AD1FB-2DE8-479F-B89E-A17217591538}.Release|Any CPU.Build.0 = Release|Any CPU + {65311EC9-7A86-4E73-A587-F06A99474EDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65311EC9-7A86-4E73-A587-F06A99474EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65311EC9-7A86-4E73-A587-F06A99474EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65311EC9-7A86-4E73-A587-F06A99474EDD}.Release|Any CPU.Build.0 = Release|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Release|Any CPU.Build.0 = Release|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Release|Any CPU.Build.0 = Release|Any CPU + {BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156}.Release|Any CPU.Build.0 = Release|Any CPU + {19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D}.Release|Any CPU.Build.0 = Release|Any CPU + {440C9BD9-85EA-4473-AB1C-7C3562DF4915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {440C9BD9-85EA-4473-AB1C-7C3562DF4915}.Debug|Any CPU.Build.0 = Debug|Any CPU + {440C9BD9-85EA-4473-AB1C-7C3562DF4915}.Release|Any CPU.ActiveCfg = Release|Any CPU + {440C9BD9-85EA-4473-AB1C-7C3562DF4915}.Release|Any CPU.Build.0 = Release|Any CPU + {23C3B247-523A-4FBF-B785-2F035E0089BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23C3B247-523A-4FBF-B785-2F035E0089BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23C3B247-523A-4FBF-B785-2F035E0089BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23C3B247-523A-4FBF-B785-2F035E0089BD}.Release|Any CPU.Build.0 = Release|Any CPU + {C7CF4193-6397-4450-AF42-3BACD7CF292E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7CF4193-6397-4450-AF42-3BACD7CF292E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7CF4193-6397-4450-AF42-3BACD7CF292E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7CF4193-6397-4450-AF42-3BACD7CF292E}.Release|Any CPU.Build.0 = Release|Any CPU + {8FE2725C-6829-4778-93BA-A53260697AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FE2725C-6829-4778-93BA-A53260697AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FE2725C-6829-4778-93BA-A53260697AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FE2725C-6829-4778-93BA-A53260697AFB}.Release|Any CPU.Build.0 = Release|Any CPU + {A4B972EC-9F0B-4405-9965-766FABC9B07E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4B972EC-9F0B-4405-9965-766FABC9B07E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4B972EC-9F0B-4405-9965-766FABC9B07E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4B972EC-9F0B-4405-9965-766FABC9B07E}.Release|Any CPU.Build.0 = Release|Any CPU + {31E60E23-FD98-4D5E-A137-2B3F2968BA09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31E60E23-FD98-4D5E-A137-2B3F2968BA09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31E60E23-FD98-4D5E-A137-2B3F2968BA09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31E60E23-FD98-4D5E-A137-2B3F2968BA09}.Release|Any CPU.Build.0 = Release|Any CPU + {25378F9D-2A66-4568-AAC6-E9282ACA3DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25378F9D-2A66-4568-AAC6-E9282ACA3DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25378F9D-2A66-4568-AAC6-E9282ACA3DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25378F9D-2A66-4568-AAC6-E9282ACA3DD3}.Release|Any CPU.Build.0 = Release|Any CPU + {3FCB1BCD-34BC-4F66-968F-38DB28371D0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FCB1BCD-34BC-4F66-968F-38DB28371D0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FCB1BCD-34BC-4F66-968F-38DB28371D0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FCB1BCD-34BC-4F66-968F-38DB28371D0F}.Release|Any CPU.Build.0 = Release|Any CPU + {A030CD8E-61F3-4C15-B28A-C301446DDBEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A030CD8E-61F3-4C15-B28A-C301446DDBEC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A030CD8E-61F3-4C15-B28A-C301446DDBEC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A030CD8E-61F3-4C15-B28A-C301446DDBEC}.Release|Any CPU.Build.0 = Release|Any CPU + {049E09BF-2E11-4E3B-926D-9DD6051A2DA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {049E09BF-2E11-4E3B-926D-9DD6051A2DA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {049E09BF-2E11-4E3B-926D-9DD6051A2DA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {049E09BF-2E11-4E3B-926D-9DD6051A2DA4}.Release|Any CPU.Build.0 = Release|Any CPU + {F1BE6113-3439-45BB-8B58-20ACA4056895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1BE6113-3439-45BB-8B58-20ACA4056895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1BE6113-3439-45BB-8B58-20ACA4056895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1BE6113-3439-45BB-8B58-20ACA4056895}.Release|Any CPU.Build.0 = Release|Any CPU + {77C2E24A-D143-44E7-86F9-AB6C5D444F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77C2E24A-D143-44E7-86F9-AB6C5D444F63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77C2E24A-D143-44E7-86F9-AB6C5D444F63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77C2E24A-D143-44E7-86F9-AB6C5D444F63}.Release|Any CPU.Build.0 = Release|Any CPU + {D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3}.Release|Any CPU.Build.0 = Release|Any CPU + {B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5}.Release|Any CPU.Build.0 = Release|Any CPU + {8DF50094-6791-4C7C-B07D-C3E995B69C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DF50094-6791-4C7C-B07D-C3E995B69C49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DF50094-6791-4C7C-B07D-C3E995B69C49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DF50094-6791-4C7C-B07D-C3E995B69C49}.Release|Any CPU.Build.0 = Release|Any CPU + {96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC}.Release|Any CPU.Build.0 = Release|Any CPU + {91AE01B1-CC82-40E2-8290-B8A84C6E90D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91AE01B1-CC82-40E2-8290-B8A84C6E90D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91AE01B1-CC82-40E2-8290-B8A84C6E90D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91AE01B1-CC82-40E2-8290-B8A84C6E90D1}.Release|Any CPU.Build.0 = Release|Any CPU + {902D822A-52B6-481C-96C5-ECD891FF83FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {902D822A-52B6-481C-96C5-ECD891FF83FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {902D822A-52B6-481C-96C5-ECD891FF83FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {902D822A-52B6-481C-96C5-ECD891FF83FC}.Release|Any CPU.Build.0 = Release|Any CPU + {46244C99-3A0D-4D88-9F24-2B7B586ADBA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46244C99-3A0D-4D88-9F24-2B7B586ADBA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46244C99-3A0D-4D88-9F24-2B7B586ADBA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46244C99-3A0D-4D88-9F24-2B7B586ADBA4}.Release|Any CPU.Build.0 = Release|Any CPU + {76A5564E-033B-4AA6-A22B-78B6EB134CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76A5564E-033B-4AA6-A22B-78B6EB134CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76A5564E-033B-4AA6-A22B-78B6EB134CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76A5564E-033B-4AA6-A22B-78B6EB134CC6}.Release|Any CPU.Build.0 = Release|Any CPU + {67DC7FA0-506A-4977-95F6-BC739B2BC4BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67DC7FA0-506A-4977-95F6-BC739B2BC4BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67DC7FA0-506A-4977-95F6-BC739B2BC4BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67DC7FA0-506A-4977-95F6-BC739B2BC4BA}.Release|Any CPU.Build.0 = Release|Any CPU + {8DF55DAB-4C1D-46F7-9324-0050F47B3BED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DF55DAB-4C1D-46F7-9324-0050F47B3BED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DF55DAB-4C1D-46F7-9324-0050F47B3BED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DF55DAB-4C1D-46F7-9324-0050F47B3BED}.Release|Any CPU.Build.0 = Release|Any CPU + {D4B4800F-6238-4EA9-A9BB-298D668C26C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4B4800F-6238-4EA9-A9BB-298D668C26C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4B4800F-6238-4EA9-A9BB-298D668C26C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4B4800F-6238-4EA9-A9BB-298D668C26C4}.Release|Any CPU.Build.0 = Release|Any CPU + {F9AC4123-7987-47D3-85D6-CD13928F3683}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9AC4123-7987-47D3-85D6-CD13928F3683}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9AC4123-7987-47D3-85D6-CD13928F3683}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9AC4123-7987-47D3-85D6-CD13928F3683}.Release|Any CPU.Build.0 = Release|Any CPU + {22BDDF5C-F911-4978-B83F-981F3652BF45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22BDDF5C-F911-4978-B83F-981F3652BF45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22BDDF5C-F911-4978-B83F-981F3652BF45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22BDDF5C-F911-4978-B83F-981F3652BF45}.Release|Any CPU.Build.0 = Release|Any CPU + {0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0}.Release|Any CPU.Build.0 = Release|Any CPU + {4711320B-F98D-4CB0-BFEB-B9685B6CBCB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4711320B-F98D-4CB0-BFEB-B9685B6CBCB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4711320B-F98D-4CB0-BFEB-B9685B6CBCB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4711320B-F98D-4CB0-BFEB-B9685B6CBCB7}.Release|Any CPU.Build.0 = Release|Any CPU + {130F8ED1-A64F-48DE-BF43-18EAD19CAF63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {130F8ED1-A64F-48DE-BF43-18EAD19CAF63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {130F8ED1-A64F-48DE-BF43-18EAD19CAF63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {130F8ED1-A64F-48DE-BF43-18EAD19CAF63}.Release|Any CPU.Build.0 = Release|Any CPU + {A53FE09E-6B1C-46C0-9422-C313D14AE9E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A53FE09E-6B1C-46C0-9422-C313D14AE9E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A53FE09E-6B1C-46C0-9422-C313D14AE9E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A53FE09E-6B1C-46C0-9422-C313D14AE9E4}.Release|Any CPU.Build.0 = Release|Any CPU + {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.Build.0 = Release|Any CPU + {7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278}.Release|Any CPU.Build.0 = Release|Any CPU + {920867B4-4740-4074-9B49-14002B272A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {920867B4-4740-4074-9B49-14002B272A63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {920867B4-4740-4074-9B49-14002B272A63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {920867B4-4740-4074-9B49-14002B272A63}.Release|Any CPU.Build.0 = Release|Any CPU + {3D422738-B111-4DEE-82E1-C3A90F1133B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D422738-B111-4DEE-82E1-C3A90F1133B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D422738-B111-4DEE-82E1-C3A90F1133B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D422738-B111-4DEE-82E1-C3A90F1133B1}.Release|Any CPU.Build.0 = Release|Any CPU + {08CC528E-98D7-41D9-957D-9F9064645788}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08CC528E-98D7-41D9-957D-9F9064645788}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08CC528E-98D7-41D9-957D-9F9064645788}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08CC528E-98D7-41D9-957D-9F9064645788}.Release|Any CPU.Build.0 = Release|Any CPU + {B507D18B-770E-4581-854B-15579AC7074F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B507D18B-770E-4581-854B-15579AC7074F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B507D18B-770E-4581-854B-15579AC7074F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B507D18B-770E-4581-854B-15579AC7074F}.Release|Any CPU.Build.0 = Release|Any CPU + {178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE}.Release|Any CPU.Build.0 = Release|Any CPU + {7C4C266C-DC2A-4A48-AB87-185E284B86E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C4C266C-DC2A-4A48-AB87-185E284B86E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C4C266C-DC2A-4A48-AB87-185E284B86E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C4C266C-DC2A-4A48-AB87-185E284B86E9}.Release|Any CPU.Build.0 = Release|Any CPU + {0380623A-EC74-430B-AA59-A6D23BC5E108}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0380623A-EC74-430B-AA59-A6D23BC5E108}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0380623A-EC74-430B-AA59-A6D23BC5E108}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0380623A-EC74-430B-AA59-A6D23BC5E108}.Release|Any CPU.Build.0 = Release|Any CPU + {C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD}.Release|Any CPU.Build.0 = Release|Any CPU + {C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1}.Release|Any CPU.Build.0 = Release|Any CPU + {82CB7E17-ED5A-4D26-B116-BA7B4226E43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82CB7E17-ED5A-4D26-B116-BA7B4226E43C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82CB7E17-ED5A-4D26-B116-BA7B4226E43C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82CB7E17-ED5A-4D26-B116-BA7B4226E43C}.Release|Any CPU.Build.0 = Release|Any CPU + {102C3711-135E-446D-9A35-AEFB79993CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {102C3711-135E-446D-9A35-AEFB79993CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {102C3711-135E-446D-9A35-AEFB79993CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {102C3711-135E-446D-9A35-AEFB79993CAA}.Release|Any CPU.Build.0 = Release|Any CPU + {2B7C1441-8801-4121-ABFB-03771E9DFE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B7C1441-8801-4121-ABFB-03771E9DFE46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B7C1441-8801-4121-ABFB-03771E9DFE46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B7C1441-8801-4121-ABFB-03771E9DFE46}.Release|Any CPU.Build.0 = Release|Any CPU + {942816E3-B270-40DC-9532-C1077FF59A32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {942816E3-B270-40DC-9532-C1077FF59A32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {942816E3-B270-40DC-9532-C1077FF59A32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {942816E3-B270-40DC-9532-C1077FF59A32}.Release|Any CPU.Build.0 = Release|Any CPU + {FBB50072-33BE-4B4A-8908-E98BC0C80B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBB50072-33BE-4B4A-8908-E98BC0C80B92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBB50072-33BE-4B4A-8908-E98BC0C80B92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBB50072-33BE-4B4A-8908-E98BC0C80B92}.Release|Any CPU.Build.0 = Release|Any CPU + {D509011F-4690-4F21-BA30-E4C31799993F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D509011F-4690-4F21-BA30-E4C31799993F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D509011F-4690-4F21-BA30-E4C31799993F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D509011F-4690-4F21-BA30-E4C31799993F}.Release|Any CPU.Build.0 = Release|Any CPU + {257C64BC-BD16-4F6D-A0B9-E286A4161241}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {257C64BC-BD16-4F6D-A0B9-E286A4161241}.Debug|Any CPU.Build.0 = Debug|Any CPU + {257C64BC-BD16-4F6D-A0B9-E286A4161241}.Release|Any CPU.ActiveCfg = Release|Any CPU + {257C64BC-BD16-4F6D-A0B9-E286A4161241}.Release|Any CPU.Build.0 = Release|Any CPU + {785251E2-6E77-40E3-90C2-4DFB63D0721B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {785251E2-6E77-40E3-90C2-4DFB63D0721B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {785251E2-6E77-40E3-90C2-4DFB63D0721B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {785251E2-6E77-40E3-90C2-4DFB63D0721B}.Release|Any CPU.Build.0 = Release|Any CPU + {0521239A-6B83-414F-B3E2-0515FC70F121}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0521239A-6B83-414F-B3E2-0515FC70F121}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0521239A-6B83-414F-B3E2-0515FC70F121}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0521239A-6B83-414F-B3E2-0515FC70F121}.Release|Any CPU.Build.0 = Release|Any CPU + {44E33132-9427-4E52-B105-67A8BC2BC29E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44E33132-9427-4E52-B105-67A8BC2BC29E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44E33132-9427-4E52-B105-67A8BC2BC29E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44E33132-9427-4E52-B105-67A8BC2BC29E}.Release|Any CPU.Build.0 = Release|Any CPU + {D3008465-B344-4243-B14A-A1430E2BEC48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3008465-B344-4243-B14A-A1430E2BEC48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3008465-B344-4243-B14A-A1430E2BEC48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3008465-B344-4243-B14A-A1430E2BEC48}.Release|Any CPU.Build.0 = Release|Any CPU + {3CBA6005-B412-4D2A-8F1E-01D53D5C657E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CBA6005-B412-4D2A-8F1E-01D53D5C657E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CBA6005-B412-4D2A-8F1E-01D53D5C657E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CBA6005-B412-4D2A-8F1E-01D53D5C657E}.Release|Any CPU.Build.0 = Release|Any CPU + {15EC4A03-D172-4984-B9CA-2C73929838DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15EC4A03-D172-4984-B9CA-2C73929838DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15EC4A03-D172-4984-B9CA-2C73929838DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15EC4A03-D172-4984-B9CA-2C73929838DE}.Release|Any CPU.Build.0 = Release|Any CPU + {74C13BCC-A5A5-40FA-81E8-83DCCF760148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74C13BCC-A5A5-40FA-81E8-83DCCF760148}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74C13BCC-A5A5-40FA-81E8-83DCCF760148}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74C13BCC-A5A5-40FA-81E8-83DCCF760148}.Release|Any CPU.Build.0 = Release|Any CPU + {427382F6-3153-47A2-BBC4-88F6EA116A8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {427382F6-3153-47A2-BBC4-88F6EA116A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {427382F6-3153-47A2-BBC4-88F6EA116A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {427382F6-3153-47A2-BBC4-88F6EA116A8F}.Release|Any CPU.Build.0 = Release|Any CPU + {2BFFE9C3-E022-4B57-9E4D-0A0408424B1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BFFE9C3-E022-4B57-9E4D-0A0408424B1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BFFE9C3-E022-4B57-9E4D-0A0408424B1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BFFE9C3-E022-4B57-9E4D-0A0408424B1A}.Release|Any CPU.Build.0 = Release|Any CPU + {CA8D7141-9520-46AC-83FD-6E034AD6EBDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA8D7141-9520-46AC-83FD-6E034AD6EBDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA8D7141-9520-46AC-83FD-6E034AD6EBDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA8D7141-9520-46AC-83FD-6E034AD6EBDD}.Release|Any CPU.Build.0 = Release|Any CPU + {42FD76A3-803A-4E07-8A90-4269204B7B87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42FD76A3-803A-4E07-8A90-4269204B7B87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42FD76A3-803A-4E07-8A90-4269204B7B87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42FD76A3-803A-4E07-8A90-4269204B7B87}.Release|Any CPU.Build.0 = Release|Any CPU + {4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}.Release|Any CPU.Build.0 = Release|Any CPU + {CDD4CC0F-5493-40C2-B889-3670263888D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDD4CC0F-5493-40C2-B889-3670263888D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDD4CC0F-5493-40C2-B889-3670263888D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDD4CC0F-5493-40C2-B889-3670263888D8}.Release|Any CPU.Build.0 = Release|Any CPU + {F74AAE01-7B87-44CA-85ED-9A6307D51504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F74AAE01-7B87-44CA-85ED-9A6307D51504}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F74AAE01-7B87-44CA-85ED-9A6307D51504}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F74AAE01-7B87-44CA-85ED-9A6307D51504}.Release|Any CPU.Build.0 = Release|Any CPU + {E3F010C7-6C96-4EEA-B5FA-BF80515E195F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3F010C7-6C96-4EEA-B5FA-BF80515E195F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3F010C7-6C96-4EEA-B5FA-BF80515E195F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3F010C7-6C96-4EEA-B5FA-BF80515E195F}.Release|Any CPU.Build.0 = Release|Any CPU + {B153F98A-7DA9-4A12-A1D7-105BE9408FA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B153F98A-7DA9-4A12-A1D7-105BE9408FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B153F98A-7DA9-4A12-A1D7-105BE9408FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B153F98A-7DA9-4A12-A1D7-105BE9408FA1}.Release|Any CPU.Build.0 = Release|Any CPU + {EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Release|Any CPU.Build.0 = Release|Any CPU + {35D17AF3-FDCD-4704-969C-E82DBCC0A232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35D17AF3-FDCD-4704-969C-E82DBCC0A232}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35D17AF3-FDCD-4704-969C-E82DBCC0A232}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35D17AF3-FDCD-4704-969C-E82DBCC0A232}.Release|Any CPU.Build.0 = Release|Any CPU + {984F481B-79FF-4825-917B-944F151694BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {984F481B-79FF-4825-917B-944F151694BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {984F481B-79FF-4825-917B-944F151694BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {984F481B-79FF-4825-917B-944F151694BC}.Release|Any CPU.Build.0 = Release|Any CPU + {B12BECC4-8A58-4DBD-A5CD-144A507972BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B12BECC4-8A58-4DBD-A5CD-144A507972BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B12BECC4-8A58-4DBD-A5CD-144A507972BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B12BECC4-8A58-4DBD-A5CD-144A507972BB}.Release|Any CPU.Build.0 = Release|Any CPU + {F7A8000A-D8DA-4A1F-B0B2-9A52183F2012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7A8000A-D8DA-4A1F-B0B2-9A52183F2012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7A8000A-D8DA-4A1F-B0B2-9A52183F2012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7A8000A-D8DA-4A1F-B0B2-9A52183F2012}.Release|Any CPU.Build.0 = Release|Any CPU + {4E8DA436-8FAF-4028-8A0C-E4EEB3615972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E8DA436-8FAF-4028-8A0C-E4EEB3615972}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E8DA436-8FAF-4028-8A0C-E4EEB3615972}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E8DA436-8FAF-4028-8A0C-E4EEB3615972}.Release|Any CPU.Build.0 = Release|Any CPU + {405694F8-0051-4DAE-A991-919FAC36C7DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {405694F8-0051-4DAE-A991-919FAC36C7DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {405694F8-0051-4DAE-A991-919FAC36C7DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {405694F8-0051-4DAE-A991-919FAC36C7DA}.Release|Any CPU.Build.0 = Release|Any CPU + {2EAA690B-1395-4952-95A0-A52F929028C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EAA690B-1395-4952-95A0-A52F929028C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EAA690B-1395-4952-95A0-A52F929028C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2EAA690B-1395-4952-95A0-A52F929028C4}.Release|Any CPU.Build.0 = Release|Any CPU + {722FE012-8F23-4558-9E8F-A37C02902058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {722FE012-8F23-4558-9E8F-A37C02902058}.Debug|Any CPU.Build.0 = Debug|Any CPU + {722FE012-8F23-4558-9E8F-A37C02902058}.Release|Any CPU.ActiveCfg = Release|Any CPU + {722FE012-8F23-4558-9E8F-A37C02902058}.Release|Any CPU.Build.0 = Release|Any CPU + {79D3C6D6-6433-471D-B354-477E07CB08EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79D3C6D6-6433-471D-B354-477E07CB08EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79D3C6D6-6433-471D-B354-477E07CB08EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79D3C6D6-6433-471D-B354-477E07CB08EE}.Release|Any CPU.Build.0 = Release|Any CPU + {5A3B9F4D-E6CC-410F-B307-0E69CCA213F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A3B9F4D-E6CC-410F-B307-0E69CCA213F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A3B9F4D-E6CC-410F-B307-0E69CCA213F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A3B9F4D-E6CC-410F-B307-0E69CCA213F5}.Release|Any CPU.Build.0 = Release|Any CPU + {4CDCD854-6E06-4076-AE94-53C1C1D7F6FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CDCD854-6E06-4076-AE94-53C1C1D7F6FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CDCD854-6E06-4076-AE94-53C1C1D7F6FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CDCD854-6E06-4076-AE94-53C1C1D7F6FA}.Release|Any CPU.Build.0 = Release|Any CPU + {97062425-3379-4F8D-BFA2-D445C56C0801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97062425-3379-4F8D-BFA2-D445C56C0801}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97062425-3379-4F8D-BFA2-D445C56C0801}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97062425-3379-4F8D-BFA2-D445C56C0801}.Release|Any CPU.Build.0 = Release|Any CPU + {5B20BA13-40FF-4743-AEEE-2E3F887F50C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B20BA13-40FF-4743-AEEE-2E3F887F50C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B20BA13-40FF-4743-AEEE-2E3F887F50C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B20BA13-40FF-4743-AEEE-2E3F887F50C6}.Release|Any CPU.Build.0 = Release|Any CPU + {03EC70B8-912C-4FBE-94DD-6327F4F23021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03EC70B8-912C-4FBE-94DD-6327F4F23021}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03EC70B8-912C-4FBE-94DD-6327F4F23021}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03EC70B8-912C-4FBE-94DD-6327F4F23021}.Release|Any CPU.Build.0 = Release|Any CPU + {C037F0CE-8223-4D4A-B15F-18B7D6AA447F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C037F0CE-8223-4D4A-B15F-18B7D6AA447F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C037F0CE-8223-4D4A-B15F-18B7D6AA447F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C037F0CE-8223-4D4A-B15F-18B7D6AA447F}.Release|Any CPU.Build.0 = Release|Any CPU + {E293BB96-5054-497B-BCE5-64AF9B0457B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E293BB96-5054-497B-BCE5-64AF9B0457B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E293BB96-5054-497B-BCE5-64AF9B0457B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E293BB96-5054-497B-BCE5-64AF9B0457B1}.Release|Any CPU.Build.0 = Release|Any CPU + {FB7AF3F8-44CD-4732-8A25-A43902437B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB7AF3F8-44CD-4732-8A25-A43902437B89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB7AF3F8-44CD-4732-8A25-A43902437B89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB7AF3F8-44CD-4732-8A25-A43902437B89}.Release|Any CPU.Build.0 = Release|Any CPU + {6472B3C1-C237-49CD-82C8-821AD001096A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6472B3C1-C237-49CD-82C8-821AD001096A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6472B3C1-C237-49CD-82C8-821AD001096A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6472B3C1-C237-49CD-82C8-821AD001096A}.Release|Any CPU.Build.0 = Release|Any CPU + {4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F}.Release|Any CPU.Build.0 = Release|Any CPU + {FB0B28CA-EE88-4DBF-9E0D-E442757E2B98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB0B28CA-EE88-4DBF-9E0D-E442757E2B98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB0B28CA-EE88-4DBF-9E0D-E442757E2B98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB0B28CA-EE88-4DBF-9E0D-E442757E2B98}.Release|Any CPU.Build.0 = Release|Any CPU + {47D57848-A910-4869-8A46-84E40A985FEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47D57848-A910-4869-8A46-84E40A985FEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47D57848-A910-4869-8A46-84E40A985FEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47D57848-A910-4869-8A46-84E40A985FEE}.Release|Any CPU.Build.0 = Release|Any CPU + {8A1F9647-B773-40AB-9126-30868014AE58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A1F9647-B773-40AB-9126-30868014AE58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A1F9647-B773-40AB-9126-30868014AE58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A1F9647-B773-40AB-9126-30868014AE58}.Release|Any CPU.Build.0 = Release|Any CPU + {4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0}.Release|Any CPU.Build.0 = Release|Any CPU + {10CF8240-4276-4199-B3D1-C45F16468EBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10CF8240-4276-4199-B3D1-C45F16468EBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10CF8240-4276-4199-B3D1-C45F16468EBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10CF8240-4276-4199-B3D1-C45F16468EBD}.Release|Any CPU.Build.0 = Release|Any CPU + {39DFEFCD-7C73-450F-9A2F-7426188A890B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39DFEFCD-7C73-450F-9A2F-7426188A890B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39DFEFCD-7C73-450F-9A2F-7426188A890B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39DFEFCD-7C73-450F-9A2F-7426188A890B}.Release|Any CPU.Build.0 = Release|Any CPU + {C465BB41-9DB7-470F-BC7F-A59D2A7D6083}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C465BB41-9DB7-470F-BC7F-A59D2A7D6083}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C465BB41-9DB7-470F-BC7F-A59D2A7D6083}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C465BB41-9DB7-470F-BC7F-A59D2A7D6083}.Release|Any CPU.Build.0 = Release|Any CPU + {7779D9BD-5928-49A2-965F-537967004238}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7779D9BD-5928-49A2-965F-537967004238}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7779D9BD-5928-49A2-965F-537967004238}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7779D9BD-5928-49A2-965F-537967004238}.Release|Any CPU.Build.0 = Release|Any CPU + {AC41F335-E240-47E0-B409-AFAD1400E626}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC41F335-E240-47E0-B409-AFAD1400E626}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC41F335-E240-47E0-B409-AFAD1400E626}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC41F335-E240-47E0-B409-AFAD1400E626}.Release|Any CPU.Build.0 = Release|Any CPU + {1D420BA6-2155-4E0D-AAAF-EECC0330A38C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D420BA6-2155-4E0D-AAAF-EECC0330A38C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D420BA6-2155-4E0D-AAAF-EECC0330A38C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D420BA6-2155-4E0D-AAAF-EECC0330A38C}.Release|Any CPU.Build.0 = Release|Any CPU + {2F49E870-DAE2-4D89-98CA-46BBD91C68E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F49E870-DAE2-4D89-98CA-46BBD91C68E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F49E870-DAE2-4D89-98CA-46BBD91C68E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F49E870-DAE2-4D89-98CA-46BBD91C68E2}.Release|Any CPU.Build.0 = Release|Any CPU + {E4CEED06-B8E9-41FA-82BF-5401AE101C4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4CEED06-B8E9-41FA-82BF-5401AE101C4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4CEED06-B8E9-41FA-82BF-5401AE101C4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4CEED06-B8E9-41FA-82BF-5401AE101C4B}.Release|Any CPU.Build.0 = Release|Any CPU + {9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A}.Release|Any CPU.Build.0 = Release|Any CPU + {B4C8056F-7325-4DB1-9F09-A6F37B052192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4C8056F-7325-4DB1-9F09-A6F37B052192}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4C8056F-7325-4DB1-9F09-A6F37B052192}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4C8056F-7325-4DB1-9F09-A6F37B052192}.Release|Any CPU.Build.0 = Release|Any CPU + {D5AEBB8E-713C-4DD2-BA18-7B0B48489901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5AEBB8E-713C-4DD2-BA18-7B0B48489901}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5AEBB8E-713C-4DD2-BA18-7B0B48489901}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5AEBB8E-713C-4DD2-BA18-7B0B48489901}.Release|Any CPU.Build.0 = Release|Any CPU + {CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C}.Release|Any CPU.Build.0 = Release|Any CPU + {DEDB69A9-657F-4B8B-81A7-4ADB19664F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DEDB69A9-657F-4B8B-81A7-4ADB19664F35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DEDB69A9-657F-4B8B-81A7-4ADB19664F35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DEDB69A9-657F-4B8B-81A7-4ADB19664F35}.Release|Any CPU.Build.0 = Release|Any CPU + {2C86306D-D626-41F8-BA3C-5C9B4123CE7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C86306D-D626-41F8-BA3C-5C9B4123CE7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C86306D-D626-41F8-BA3C-5C9B4123CE7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C86306D-D626-41F8-BA3C-5C9B4123CE7D}.Release|Any CPU.Build.0 = Release|Any CPU + {2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA}.Release|Any CPU.Build.0 = Release|Any CPU + {3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Release|Any CPU.Build.0 = Release|Any CPU + {34987F45-8234-428C-AB41-783D42295C32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34987F45-8234-428C-AB41-783D42295C32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34987F45-8234-428C-AB41-783D42295C32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34987F45-8234-428C-AB41-783D42295C32}.Release|Any CPU.Build.0 = Release|Any CPU + {227DA969-291B-4749-985C-7A83523B7F53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {227DA969-291B-4749-985C-7A83523B7F53}.Debug|Any CPU.Build.0 = Debug|Any CPU + {227DA969-291B-4749-985C-7A83523B7F53}.Release|Any CPU.ActiveCfg = Release|Any CPU + {227DA969-291B-4749-985C-7A83523B7F53}.Release|Any CPU.Build.0 = Release|Any CPU + {CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Release|Any CPU.Build.0 = Release|Any CPU + {F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Release|Any CPU.Build.0 = Release|Any CPU + {A025B8D2-5D92-4023-82AB-97A672A5A132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A025B8D2-5D92-4023-82AB-97A672A5A132}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A025B8D2-5D92-4023-82AB-97A672A5A132}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A025B8D2-5D92-4023-82AB-97A672A5A132}.Release|Any CPU.Build.0 = Release|Any CPU + {5D99743B-7044-4BE9-8F7A-E195F2A3E2EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D99743B-7044-4BE9-8F7A-E195F2A3E2EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D99743B-7044-4BE9-8F7A-E195F2A3E2EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D99743B-7044-4BE9-8F7A-E195F2A3E2EC}.Release|Any CPU.Build.0 = Release|Any CPU + {E09E476C-9DF8-46AC-848E-4E7635369117}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E09E476C-9DF8-46AC-848E-4E7635369117}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E09E476C-9DF8-46AC-848E-4E7635369117}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E09E476C-9DF8-46AC-848E-4E7635369117}.Release|Any CPU.Build.0 = Release|Any CPU + {E414F7BC-215C-46D0-99EC-CD78EB31FC3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E414F7BC-215C-46D0-99EC-CD78EB31FC3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E414F7BC-215C-46D0-99EC-CD78EB31FC3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E414F7BC-215C-46D0-99EC-CD78EB31FC3C}.Release|Any CPU.Build.0 = Release|Any CPU + {8142FB8C-3D32-4062-BD95-B2F61A1A390A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8142FB8C-3D32-4062-BD95-B2F61A1A390A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8142FB8C-3D32-4062-BD95-B2F61A1A390A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8142FB8C-3D32-4062-BD95-B2F61A1A390A}.Release|Any CPU.Build.0 = Release|Any CPU + {4155336A-DC06-4885-878D-03AF5DFAF47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4155336A-DC06-4885-878D-03AF5DFAF47D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4155336A-DC06-4885-878D-03AF5DFAF47D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4155336A-DC06-4885-878D-03AF5DFAF47D}.Release|Any CPU.Build.0 = Release|Any CPU + {ADAB35CB-A34E-448D-ACBB-FA054A3B90AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADAB35CB-A34E-448D-ACBB-FA054A3B90AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADAB35CB-A34E-448D-ACBB-FA054A3B90AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADAB35CB-A34E-448D-ACBB-FA054A3B90AA}.Release|Any CPU.Build.0 = Release|Any CPU + {1B112FAC-CB57-48B6-A3D5-95456477CB8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B112FAC-CB57-48B6-A3D5-95456477CB8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B112FAC-CB57-48B6-A3D5-95456477CB8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B112FAC-CB57-48B6-A3D5-95456477CB8D}.Release|Any CPU.Build.0 = Release|Any CPU + {B84E4D98-0B10-4189-8572-F6F7B4E384B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B84E4D98-0B10-4189-8572-F6F7B4E384B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B84E4D98-0B10-4189-8572-F6F7B4E384B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B84E4D98-0B10-4189-8572-F6F7B4E384B7}.Release|Any CPU.Build.0 = Release|Any CPU + {E81EC3E4-521F-4C52-8AA0-A783847E764E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E81EC3E4-521F-4C52-8AA0-A783847E764E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E81EC3E4-521F-4C52-8AA0-A783847E764E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E81EC3E4-521F-4C52-8AA0-A783847E764E}.Release|Any CPU.Build.0 = Release|Any CPU + {49EB2864-B715-47DD-AE47-C5243C656F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49EB2864-B715-47DD-AE47-C5243C656F47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49EB2864-B715-47DD-AE47-C5243C656F47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49EB2864-B715-47DD-AE47-C5243C656F47}.Release|Any CPU.Build.0 = Release|Any CPU + {68538541-4280-46F5-BA08-99ACA8575615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68538541-4280-46F5-BA08-99ACA8575615}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68538541-4280-46F5-BA08-99ACA8575615}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68538541-4280-46F5-BA08-99ACA8575615}.Release|Any CPU.Build.0 = Release|Any CPU + {F6F93723-5BC3-4D25-A83E-25B41B6D956F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6F93723-5BC3-4D25-A83E-25B41B6D956F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6F93723-5BC3-4D25-A83E-25B41B6D956F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6F93723-5BC3-4D25-A83E-25B41B6D956F}.Release|Any CPU.Build.0 = Release|Any CPU + {109BF321-1BC6-4031-A59B-7B5375EBA8C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {109BF321-1BC6-4031-A59B-7B5375EBA8C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {109BF321-1BC6-4031-A59B-7B5375EBA8C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {109BF321-1BC6-4031-A59B-7B5375EBA8C5}.Release|Any CPU.Build.0 = Release|Any CPU + {08A78A69-913B-4C5E-BCE0-739585F82D1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08A78A69-913B-4C5E-BCE0-739585F82D1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08A78A69-913B-4C5E-BCE0-739585F82D1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08A78A69-913B-4C5E-BCE0-739585F82D1E}.Release|Any CPU.Build.0 = Release|Any CPU + {B6857FC4-97C2-4E20-B005-1FAABC574B88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6857FC4-97C2-4E20-B005-1FAABC574B88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6857FC4-97C2-4E20-B005-1FAABC574B88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6857FC4-97C2-4E20-B005-1FAABC574B88}.Release|Any CPU.Build.0 = Release|Any CPU + {B6D4AADE-3ABA-45E6-9916-2F8798412549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6D4AADE-3ABA-45E6-9916-2F8798412549}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6D4AADE-3ABA-45E6-9916-2F8798412549}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6D4AADE-3ABA-45E6-9916-2F8798412549}.Release|Any CPU.Build.0 = Release|Any CPU + {86E85013-7C71-4770-9323-18897A64F5B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86E85013-7C71-4770-9323-18897A64F5B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86E85013-7C71-4770-9323-18897A64F5B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86E85013-7C71-4770-9323-18897A64F5B2}.Release|Any CPU.Build.0 = Release|Any CPU + {014A9583-0EAA-48A4-ACBE-07DC88159E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {014A9583-0EAA-48A4-ACBE-07DC88159E13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {014A9583-0EAA-48A4-ACBE-07DC88159E13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {014A9583-0EAA-48A4-ACBE-07DC88159E13}.Release|Any CPU.Build.0 = Release|Any CPU + {AAC0C407-B4B9-4E90-99FC-2D793AC229D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AAC0C407-B4B9-4E90-99FC-2D793AC229D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AAC0C407-B4B9-4E90-99FC-2D793AC229D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AAC0C407-B4B9-4E90-99FC-2D793AC229D9}.Release|Any CPU.Build.0 = Release|Any CPU + {4C71CA88-0D04-4DDB-8906-B953908B8B8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C71CA88-0D04-4DDB-8906-B953908B8B8B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C71CA88-0D04-4DDB-8906-B953908B8B8B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C71CA88-0D04-4DDB-8906-B953908B8B8B}.Release|Any CPU.Build.0 = Release|Any CPU + {50FF92EA-8BA4-445D-AB04-E7568EE5D3FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50FF92EA-8BA4-445D-AB04-E7568EE5D3FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50FF92EA-8BA4-445D-AB04-E7568EE5D3FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50FF92EA-8BA4-445D-AB04-E7568EE5D3FE}.Release|Any CPU.Build.0 = Release|Any CPU + {1E00BE51-A1AE-447D-B6E0-F28EC12B259A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E00BE51-A1AE-447D-B6E0-F28EC12B259A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E00BE51-A1AE-447D-B6E0-F28EC12B259A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E00BE51-A1AE-447D-B6E0-F28EC12B259A}.Release|Any CPU.Build.0 = Release|Any CPU + {61F0EEB2-5ED0-4809-8EF9-0676C7A680CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61F0EEB2-5ED0-4809-8EF9-0676C7A680CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61F0EEB2-5ED0-4809-8EF9-0676C7A680CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61F0EEB2-5ED0-4809-8EF9-0676C7A680CE}.Release|Any CPU.Build.0 = Release|Any CPU + {72D54834-7ADF-4B18-A745-FCBBC255073B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72D54834-7ADF-4B18-A745-FCBBC255073B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72D54834-7ADF-4B18-A745-FCBBC255073B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72D54834-7ADF-4B18-A745-FCBBC255073B}.Release|Any CPU.Build.0 = Release|Any CPU + {8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3}.Release|Any CPU.Build.0 = Release|Any CPU + {6C0DB8F2-FB0A-4922-B8FE-177DCF37A918}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C0DB8F2-FB0A-4922-B8FE-177DCF37A918}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C0DB8F2-FB0A-4922-B8FE-177DCF37A918}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C0DB8F2-FB0A-4922-B8FE-177DCF37A918}.Release|Any CPU.Build.0 = Release|Any CPU + {D73200F6-CBB3-4BA8-B9BF-7110AAF05596}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D73200F6-CBB3-4BA8-B9BF-7110AAF05596}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D73200F6-CBB3-4BA8-B9BF-7110AAF05596}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D73200F6-CBB3-4BA8-B9BF-7110AAF05596}.Release|Any CPU.Build.0 = Release|Any CPU + {30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C}.Release|Any CPU.Build.0 = Release|Any CPU + {40D7A0A3-68BD-431E-A67A-E2A35508D55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40D7A0A3-68BD-431E-A67A-E2A35508D55D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40D7A0A3-68BD-431E-A67A-E2A35508D55D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40D7A0A3-68BD-431E-A67A-E2A35508D55D}.Release|Any CPU.Build.0 = Release|Any CPU + {8EA8C998-F81A-46E9-8C7E-C944D2503A0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EA8C998-F81A-46E9-8C7E-C944D2503A0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EA8C998-F81A-46E9-8C7E-C944D2503A0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EA8C998-F81A-46E9-8C7E-C944D2503A0A}.Release|Any CPU.Build.0 = Release|Any CPU + {47550AB9-FA06-42D6-A4B8-7DD12FE66563}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47550AB9-FA06-42D6-A4B8-7DD12FE66563}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47550AB9-FA06-42D6-A4B8-7DD12FE66563}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47550AB9-FA06-42D6-A4B8-7DD12FE66563}.Release|Any CPU.Build.0 = Release|Any CPU + {835E51CE-1E6B-4C8C-9736-8C5B61F5E08E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {835E51CE-1E6B-4C8C-9736-8C5B61F5E08E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {835E51CE-1E6B-4C8C-9736-8C5B61F5E08E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {835E51CE-1E6B-4C8C-9736-8C5B61F5E08E}.Release|Any CPU.Build.0 = Release|Any CPU + {FDAAAD2E-42A7-44EC-8971-B5277FD6D404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDAAAD2E-42A7-44EC-8971-B5277FD6D404}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDAAAD2E-42A7-44EC-8971-B5277FD6D404}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDAAAD2E-42A7-44EC-8971-B5277FD6D404}.Release|Any CPU.Build.0 = Release|Any CPU + {ED3DF100-C5DB-4334-A847-118922B28D95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED3DF100-C5DB-4334-A847-118922B28D95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED3DF100-C5DB-4334-A847-118922B28D95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED3DF100-C5DB-4334-A847-118922B28D95}.Release|Any CPU.Build.0 = Release|Any CPU + {15482834-9242-4D20-9736-9DA571A9A83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15482834-9242-4D20-9736-9DA571A9A83A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15482834-9242-4D20-9736-9DA571A9A83A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15482834-9242-4D20-9736-9DA571A9A83A}.Release|Any CPU.Build.0 = Release|Any CPU + {8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.Build.0 = Release|Any CPU + {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Release|Any CPU.Build.0 = Release|Any CPU + {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Release|Any CPU.Build.0 = Release|Any CPU + {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Release|Any CPU.Build.0 = Release|Any CPU + {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Release|Any CPU.Build.0 = Release|Any CPU + {8826831D-8733-473A-B47B-A30C3732B13D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8826831D-8733-473A-B47B-A30C3732B13D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8826831D-8733-473A-B47B-A30C3732B13D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8826831D-8733-473A-B47B-A30C3732B13D}.Release|Any CPU.Build.0 = Release|Any CPU + {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Release|Any CPU.Build.0 = Release|Any CPU + {54BBA043-317B-4A4F-B583-513D08BC25A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54BBA043-317B-4A4F-B583-513D08BC25A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54BBA043-317B-4A4F-B583-513D08BC25A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54BBA043-317B-4A4F-B583-513D08BC25A7}.Release|Any CPU.Build.0 = Release|Any CPU + {79FA2CBA-2904-4D80-A217-DCC0A38F93C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79FA2CBA-2904-4D80-A217-DCC0A38F93C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79FA2CBA-2904-4D80-A217-DCC0A38F93C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79FA2CBA-2904-4D80-A217-DCC0A38F93C4}.Release|Any CPU.Build.0 = Release|Any CPU + {E469F047-6AD0-4D2B-9900-46358DA3BC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E469F047-6AD0-4D2B-9900-46358DA3BC30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E469F047-6AD0-4D2B-9900-46358DA3BC30}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E469F047-6AD0-4D2B-9900-46358DA3BC30}.Release|Any CPU.Build.0 = Release|Any CPU + {EB9F1905-1798-4766-8347-A8D2A9DBFAED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB9F1905-1798-4766-8347-A8D2A9DBFAED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB9F1905-1798-4766-8347-A8D2A9DBFAED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB9F1905-1798-4766-8347-A8D2A9DBFAED}.Release|Any CPU.Build.0 = Release|Any CPU + {CCE5C620-E17A-4EB1-A17A-9F90311B197D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCE5C620-E17A-4EB1-A17A-9F90311B197D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCE5C620-E17A-4EB1-A17A-9F90311B197D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCE5C620-E17A-4EB1-A17A-9F90311B197D}.Release|Any CPU.Build.0 = Release|Any CPU + {F2AD691B-71B9-4B86-95BC-E020DA6B1E4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2AD691B-71B9-4B86-95BC-E020DA6B1E4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2AD691B-71B9-4B86-95BC-E020DA6B1E4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2AD691B-71B9-4B86-95BC-E020DA6B1E4A}.Release|Any CPU.Build.0 = Release|Any CPU + {76DDE71D-00BD-4BC8-AEA2-31209E2B7E05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76DDE71D-00BD-4BC8-AEA2-31209E2B7E05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76DDE71D-00BD-4BC8-AEA2-31209E2B7E05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76DDE71D-00BD-4BC8-AEA2-31209E2B7E05}.Release|Any CPU.Build.0 = Release|Any CPU + {267933BD-BFB8-4906-BA39-DF193B2FD558}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {267933BD-BFB8-4906-BA39-DF193B2FD558}.Debug|Any CPU.Build.0 = Debug|Any CPU + {267933BD-BFB8-4906-BA39-DF193B2FD558}.Release|Any CPU.ActiveCfg = Release|Any CPU + {267933BD-BFB8-4906-BA39-DF193B2FD558}.Release|Any CPU.Build.0 = Release|Any CPU + {3CBD1342-C021-49FB-933F-FAC1DAFC7B48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CBD1342-C021-49FB-933F-FAC1DAFC7B48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CBD1342-C021-49FB-933F-FAC1DAFC7B48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CBD1342-C021-49FB-933F-FAC1DAFC7B48}.Release|Any CPU.Build.0 = Release|Any CPU + {01B86C39-B0C8-48A4-949C-1C63D755B02C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01B86C39-B0C8-48A4-949C-1C63D755B02C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01B86C39-B0C8-48A4-949C-1C63D755B02C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01B86C39-B0C8-48A4-949C-1C63D755B02C}.Release|Any CPU.Build.0 = Release|Any CPU + {DD6609C7-07AC-49FD-B588-44E649D0AE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD6609C7-07AC-49FD-B588-44E649D0AE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD6609C7-07AC-49FD-B588-44E649D0AE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD6609C7-07AC-49FD-B588-44E649D0AE6E}.Release|Any CPU.Build.0 = Release|Any CPU + {856B4ACA-BD13-417F-A6E2-0F401F877189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {856B4ACA-BD13-417F-A6E2-0F401F877189}.Debug|Any CPU.Build.0 = Debug|Any CPU + {856B4ACA-BD13-417F-A6E2-0F401F877189}.Release|Any CPU.ActiveCfg = Release|Any CPU + {856B4ACA-BD13-417F-A6E2-0F401F877189}.Release|Any CPU.Build.0 = Release|Any CPU + {B52B199C-0E1C-4CE9-B066-71D26F618424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B52B199C-0E1C-4CE9-B066-71D26F618424}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B52B199C-0E1C-4CE9-B066-71D26F618424}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B52B199C-0E1C-4CE9-B066-71D26F618424}.Release|Any CPU.Build.0 = Release|Any CPU + {80F44B5B-F8FF-47FA-9A77-BE2D176B2721}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80F44B5B-F8FF-47FA-9A77-BE2D176B2721}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80F44B5B-F8FF-47FA-9A77-BE2D176B2721}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80F44B5B-F8FF-47FA-9A77-BE2D176B2721}.Release|Any CPU.Build.0 = Release|Any CPU + {DD365101-E8FC-6516-2883-B9CA024B36FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD365101-E8FC-6516-2883-B9CA024B36FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD365101-E8FC-6516-2883-B9CA024B36FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD365101-E8FC-6516-2883-B9CA024B36FA}.Release|Any CPU.Build.0 = Release|Any CPU + {C330BADD-59A0-A3CD-E839-A0D4C2C636EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C330BADD-59A0-A3CD-E839-A0D4C2C636EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C330BADD-59A0-A3CD-E839-A0D4C2C636EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C330BADD-59A0-A3CD-E839-A0D4C2C636EE}.Release|Any CPU.Build.0 = Release|Any CPU + {F1C6C6B6-5B99-5AA6-7F76-27560C111605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1C6C6B6-5B99-5AA6-7F76-27560C111605}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1C6C6B6-5B99-5AA6-7F76-27560C111605}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1C6C6B6-5B99-5AA6-7F76-27560C111605}.Release|Any CPU.Build.0 = Release|Any CPU + {459DA653-F12A-65B5-41EF-A5877B1C38BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {459DA653-F12A-65B5-41EF-A5877B1C38BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {459DA653-F12A-65B5-41EF-A5877B1C38BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {459DA653-F12A-65B5-41EF-A5877B1C38BA}.Release|Any CPU.Build.0 = Release|Any CPU + {9DD70A99-41A6-8598-553E-2B5AB6277035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DD70A99-41A6-8598-553E-2B5AB6277035}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DD70A99-41A6-8598-553E-2B5AB6277035}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DD70A99-41A6-8598-553E-2B5AB6277035}.Release|Any CPU.Build.0 = Release|Any CPU + {016CCD97-3551-B6C7-FC6C-FF1CB7F84B88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {016CCD97-3551-B6C7-FC6C-FF1CB7F84B88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {016CCD97-3551-B6C7-FC6C-FF1CB7F84B88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {016CCD97-3551-B6C7-FC6C-FF1CB7F84B88}.Release|Any CPU.Build.0 = Release|Any CPU + {F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147}.Release|Any CPU.Build.0 = Release|Any CPU + {AE00DA82-B33A-CAF7-D9CD-D5E26608741B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE00DA82-B33A-CAF7-D9CD-D5E26608741B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE00DA82-B33A-CAF7-D9CD-D5E26608741B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE00DA82-B33A-CAF7-D9CD-D5E26608741B}.Release|Any CPU.Build.0 = Release|Any CPU + {F9A0D88F-53AE-4AC7-8E15-163C34386E7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9A0D88F-53AE-4AC7-8E15-163C34386E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9A0D88F-53AE-4AC7-8E15-163C34386E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9A0D88F-53AE-4AC7-8E15-163C34386E7C}.Release|Any CPU.Build.0 = Release|Any CPU + {0FF0A04C-B580-4A56-9171-CF2988B5DE5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0FF0A04C-B580-4A56-9171-CF2988B5DE5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0FF0A04C-B580-4A56-9171-CF2988B5DE5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0FF0A04C-B580-4A56-9171-CF2988B5DE5A}.Release|Any CPU.Build.0 = Release|Any CPU + {F810C8A8-1256-440F-BAAF-7F3588291963}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F810C8A8-1256-440F-BAAF-7F3588291963}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F810C8A8-1256-440F-BAAF-7F3588291963}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F810C8A8-1256-440F-BAAF-7F3588291963}.Release|Any CPU.Build.0 = Release|Any CPU + {FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59}.Release|Any CPU.Build.0 = Release|Any CPU + {C95DE287-9D21-4DCD-9281-A060B6D99774}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C95DE287-9D21-4DCD-9281-A060B6D99774}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C95DE287-9D21-4DCD-9281-A060B6D99774}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C95DE287-9D21-4DCD-9281-A060B6D99774}.Release|Any CPU.Build.0 = Release|Any CPU + {96748DAE-D367-48C0-B64E-2F25010EAC4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96748DAE-D367-48C0-B64E-2F25010EAC4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96748DAE-D367-48C0-B64E-2F25010EAC4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96748DAE-D367-48C0-B64E-2F25010EAC4D}.Release|Any CPU.Build.0 = Release|Any CPU + {5A0063BF-EE72-E688-84C6-9E3CE0616C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A0063BF-EE72-E688-84C6-9E3CE0616C94}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A0063BF-EE72-E688-84C6-9E3CE0616C94}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A0063BF-EE72-E688-84C6-9E3CE0616C94}.Release|Any CPU.Build.0 = Release|Any CPU + {ECE61F58-1AEC-1E4F-1543-76C2242B6F70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECE61F58-1AEC-1E4F-1543-76C2242B6F70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECE61F58-1AEC-1E4F-1543-76C2242B6F70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECE61F58-1AEC-1E4F-1543-76C2242B6F70}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B63E08-8F62-34F6-FEA5-063267F1FC85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7B63E08-8F62-34F6-FEA5-063267F1FC85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7B63E08-8F62-34F6-FEA5-063267F1FC85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7B63E08-8F62-34F6-FEA5-063267F1FC85}.Release|Any CPU.Build.0 = Release|Any CPU + {7C48C1CA-7E53-4261-A477-454DD3A8402C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C48C1CA-7E53-4261-A477-454DD3A8402C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C48C1CA-7E53-4261-A477-454DD3A8402C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C48C1CA-7E53-4261-A477-454DD3A8402C}.Release|Any CPU.Build.0 = Release|Any CPU + {A54344EB-05A7-A405-5368-4A9C0A60B078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A54344EB-05A7-A405-5368-4A9C0A60B078}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A54344EB-05A7-A405-5368-4A9C0A60B078}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A54344EB-05A7-A405-5368-4A9C0A60B078}.Release|Any CPU.Build.0 = Release|Any CPU + {7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6}.Release|Any CPU.Build.0 = Release|Any CPU + {C9266D5D-3860-09C3-F566-489BBB57A534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9266D5D-3860-09C3-F566-489BBB57A534}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9266D5D-3860-09C3-F566-489BBB57A534}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9266D5D-3860-09C3-F566-489BBB57A534}.Release|Any CPU.Build.0 = Release|Any CPU + {F3DF1C3E-7319-48B1-81AB-0284853BB567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3DF1C3E-7319-48B1-81AB-0284853BB567}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3DF1C3E-7319-48B1-81AB-0284853BB567}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3DF1C3E-7319-48B1-81AB-0284853BB567}.Release|Any CPU.Build.0 = Release|Any CPU + {7D7561CB-5059-4F5F-B736-B97195B46A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D7561CB-5059-4F5F-B736-B97195B46A91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D7561CB-5059-4F5F-B736-B97195B46A91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D7561CB-5059-4F5F-B736-B97195B46A91}.Release|Any CPU.Build.0 = Release|Any CPU + {5B9CA129-16CE-4BEF-B22D-C084B38B4EDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B9CA129-16CE-4BEF-B22D-C084B38B4EDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B9CA129-16CE-4BEF-B22D-C084B38B4EDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B9CA129-16CE-4BEF-B22D-C084B38B4EDA}.Release|Any CPU.Build.0 = Release|Any CPU + {418EE258-2670-29D3-480F-EC0FD07700E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {418EE258-2670-29D3-480F-EC0FD07700E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {418EE258-2670-29D3-480F-EC0FD07700E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {418EE258-2670-29D3-480F-EC0FD07700E8}.Release|Any CPU.Build.0 = Release|Any CPU + {7984F6B6-726F-9F30-3B6F-08A90AD75A7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7984F6B6-726F-9F30-3B6F-08A90AD75A7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7984F6B6-726F-9F30-3B6F-08A90AD75A7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7984F6B6-726F-9F30-3B6F-08A90AD75A7D}.Release|Any CPU.Build.0 = Release|Any CPU + {D63FEED3-2342-7E96-4121-B0C19CF1EA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D63FEED3-2342-7E96-4121-B0C19CF1EA81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D63FEED3-2342-7E96-4121-B0C19CF1EA81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D63FEED3-2342-7E96-4121-B0C19CF1EA81}.Release|Any CPU.Build.0 = Release|Any CPU + {DED16774-635C-D781-4D5B-D1FA56EECF10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DED16774-635C-D781-4D5B-D1FA56EECF10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DED16774-635C-D781-4D5B-D1FA56EECF10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DED16774-635C-D781-4D5B-D1FA56EECF10}.Release|Any CPU.Build.0 = Release|Any CPU + {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08}.Release|Any CPU.Build.0 = Release|Any CPU + {DD11D070-F39E-1C41-1843-AE3ADBE501EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD11D070-F39E-1C41-1843-AE3ADBE501EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD11D070-F39E-1C41-1843-AE3ADBE501EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD11D070-F39E-1C41-1843-AE3ADBE501EF}.Release|Any CPU.Build.0 = Release|Any CPU + {001D0817-1EED-4C04-821E-F815F148EC90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {001D0817-1EED-4C04-821E-F815F148EC90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {001D0817-1EED-4C04-821E-F815F148EC90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {001D0817-1EED-4C04-821E-F815F148EC90}.Release|Any CPU.Build.0 = Release|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Release|Any CPU.Build.0 = Release|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Release|Any CPU.Build.0 = Release|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Release|Any CPU.Build.0 = Release|Any CPU + {5FA85E8E-3276-43DF-CC93-6A9847905166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FA85E8E-3276-43DF-CC93-6A9847905166}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FA85E8E-3276-43DF-CC93-6A9847905166}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FA85E8E-3276-43DF-CC93-6A9847905166}.Release|Any CPU.Build.0 = Release|Any CPU + {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Release|Any CPU.Build.0 = Release|Any CPU + {69419D6B-9DA5-D9BD-1D6C-61BBAE331057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69419D6B-9DA5-D9BD-1D6C-61BBAE331057}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69419D6B-9DA5-D9BD-1D6C-61BBAE331057}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69419D6B-9DA5-D9BD-1D6C-61BBAE331057}.Release|Any CPU.Build.0 = Release|Any CPU + {B4311504-B0C8-AC8D-02A5-81AD43B4087B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4311504-B0C8-AC8D-02A5-81AD43B4087B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4311504-B0C8-AC8D-02A5-81AD43B4087B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4311504-B0C8-AC8D-02A5-81AD43B4087B}.Release|Any CPU.Build.0 = Release|Any CPU + {C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9}.Release|Any CPU.Build.0 = Release|Any CPU + {9FF83836-8627-2943-3344-60319FB85B39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FF83836-8627-2943-3344-60319FB85B39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FF83836-8627-2943-3344-60319FB85B39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FF83836-8627-2943-3344-60319FB85B39}.Release|Any CPU.Build.0 = Release|Any CPU + {2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {1B5368E2-8A31-F686-3120-770BAD793962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B5368E2-8A31-F686-3120-770BAD793962}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B5368E2-8A31-F686-3120-770BAD793962}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B5368E2-8A31-F686-3120-770BAD793962}.Release|Any CPU.Build.0 = Release|Any CPU + {BFFC0787-81F4-4751-9385-B91BB8CB183A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFFC0787-81F4-4751-9385-B91BB8CB183A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFFC0787-81F4-4751-9385-B91BB8CB183A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFFC0787-81F4-4751-9385-B91BB8CB183A}.Release|Any CPU.Build.0 = Release|Any CPU + {E0EEFE73-EF05-491B-A265-E2B613D0C82F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0EEFE73-EF05-491B-A265-E2B613D0C82F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0EEFE73-EF05-491B-A265-E2B613D0C82F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0EEFE73-EF05-491B-A265-E2B613D0C82F}.Release|Any CPU.Build.0 = Release|Any CPU + {2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8}.Release|Any CPU.Build.0 = Release|Any CPU + {B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC}.Release|Any CPU.Build.0 = Release|Any CPU + {569667D0-2038-4566-9711-6B174C631063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {569667D0-2038-4566-9711-6B174C631063}.Debug|Any CPU.Build.0 = Debug|Any CPU + {569667D0-2038-4566-9711-6B174C631063}.Release|Any CPU.ActiveCfg = Release|Any CPU + {569667D0-2038-4566-9711-6B174C631063}.Release|Any CPU.Build.0 = Release|Any CPU + {7760B229-E3EA-4A60-9E32-7B2F7FB199E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7760B229-E3EA-4A60-9E32-7B2F7FB199E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7760B229-E3EA-4A60-9E32-7B2F7FB199E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7760B229-E3EA-4A60-9E32-7B2F7FB199E7}.Release|Any CPU.Build.0 = Release|Any CPU + {3672F185-59B2-490D-A00B-5CA9815909B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3672F185-59B2-490D-A00B-5CA9815909B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3672F185-59B2-490D-A00B-5CA9815909B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3672F185-59B2-490D-A00B-5CA9815909B6}.Release|Any CPU.Build.0 = Release|Any CPU + {1B9DC76D-942D-4DCC-979F-E9E56BB7073E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B9DC76D-942D-4DCC-979F-E9E56BB7073E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B9DC76D-942D-4DCC-979F-E9E56BB7073E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B9DC76D-942D-4DCC-979F-E9E56BB7073E}.Release|Any CPU.Build.0 = Release|Any CPU + {7F65C827-914D-42B1-AE26-44053AE3140F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F65C827-914D-42B1-AE26-44053AE3140F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F65C827-914D-42B1-AE26-44053AE3140F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F65C827-914D-42B1-AE26-44053AE3140F}.Release|Any CPU.Build.0 = Release|Any CPU + {1425C1AB-048F-4ABF-ACAB-793E2524F0A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1425C1AB-048F-4ABF-ACAB-793E2524F0A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1425C1AB-048F-4ABF-ACAB-793E2524F0A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1425C1AB-048F-4ABF-ACAB-793E2524F0A8}.Release|Any CPU.Build.0 = Release|Any CPU + {4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14}.Release|Any CPU.Build.0 = Release|Any CPU + {09B8B63F-972B-4055-9BAD-B2883EBA3EF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09B8B63F-972B-4055-9BAD-B2883EBA3EF0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09B8B63F-972B-4055-9BAD-B2883EBA3EF0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09B8B63F-972B-4055-9BAD-B2883EBA3EF0}.Release|Any CPU.Build.0 = Release|Any CPU + {4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99}.Release|Any CPU.Build.0 = Release|Any CPU + {0EEA73CA-D8DD-F044-045D-F070F8831E26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EEA73CA-D8DD-F044-045D-F070F8831E26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EEA73CA-D8DD-F044-045D-F070F8831E26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EEA73CA-D8DD-F044-045D-F070F8831E26}.Release|Any CPU.Build.0 = Release|Any CPU + {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.Build.0 = Release|Any CPU + {62FB9F56-221E-47D5-8B30-311A13D6A568}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62FB9F56-221E-47D5-8B30-311A13D6A568}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62FB9F56-221E-47D5-8B30-311A13D6A568}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62FB9F56-221E-47D5-8B30-311A13D6A568}.Release|Any CPU.Build.0 = Release|Any CPU + {ACEEA6F9-868B-4701-AF65-89292F656A1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACEEA6F9-868B-4701-AF65-89292F656A1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACEEA6F9-868B-4701-AF65-89292F656A1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACEEA6F9-868B-4701-AF65-89292F656A1D}.Release|Any CPU.Build.0 = Release|Any CPU + {FB12303C-7A3A-4A42-900F-C131D0FD7BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB12303C-7A3A-4A42-900F-C131D0FD7BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB12303C-7A3A-4A42-900F-C131D0FD7BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB12303C-7A3A-4A42-900F-C131D0FD7BA2}.Release|Any CPU.Build.0 = Release|Any CPU + {BAE82F6F-2528-45DF-9571-F733C31CEB1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAE82F6F-2528-45DF-9571-F733C31CEB1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAE82F6F-2528-45DF-9571-F733C31CEB1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAE82F6F-2528-45DF-9571-F733C31CEB1E}.Release|Any CPU.Build.0 = Release|Any CPU + {97C66786-03F8-4886-088E-FA1BECB1C574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97C66786-03F8-4886-088E-FA1BECB1C574}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97C66786-03F8-4886-088E-FA1BECB1C574}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97C66786-03F8-4886-088E-FA1BECB1C574}.Release|Any CPU.Build.0 = Release|Any CPU + {7B927926-0AF4-A6F2-8ABA-331A6C138EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B927926-0AF4-A6F2-8ABA-331A6C138EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B927926-0AF4-A6F2-8ABA-331A6C138EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B927926-0AF4-A6F2-8ABA-331A6C138EAC}.Release|Any CPU.Build.0 = Release|Any CPU + {C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA}.Release|Any CPU.Build.0 = Release|Any CPU + {6FCE34BF-077B-9425-CD34-FA9B2CD190FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FCE34BF-077B-9425-CD34-FA9B2CD190FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FCE34BF-077B-9425-CD34-FA9B2CD190FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FCE34BF-077B-9425-CD34-FA9B2CD190FA}.Release|Any CPU.Build.0 = Release|Any CPU + {A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889}.Release|Any CPU.Build.0 = Release|Any CPU + {107C0D30-35C1-142B-209A-29BD6BAE7DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {107C0D30-35C1-142B-209A-29BD6BAE7DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {107C0D30-35C1-142B-209A-29BD6BAE7DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {107C0D30-35C1-142B-209A-29BD6BAE7DE9}.Release|Any CPU.Build.0 = Release|Any CPU + {DB03F47B-4E3A-4484-86DC-741472AD49A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB03F47B-4E3A-4484-86DC-741472AD49A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB03F47B-4E3A-4484-86DC-741472AD49A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB03F47B-4E3A-4484-86DC-741472AD49A3}.Release|Any CPU.Build.0 = Release|Any CPU + {2DB2EADB-745A-4442-A48A-B1B721412F78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DB2EADB-745A-4442-A48A-B1B721412F78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DB2EADB-745A-4442-A48A-B1B721412F78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DB2EADB-745A-4442-A48A-B1B721412F78}.Release|Any CPU.Build.0 = Release|Any CPU + {4524F120-F72B-4373-B731-6A2D0EF633A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4524F120-F72B-4373-B731-6A2D0EF633A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4524F120-F72B-4373-B731-6A2D0EF633A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4524F120-F72B-4373-B731-6A2D0EF633A7}.Release|Any CPU.Build.0 = Release|Any CPU + {0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD}.Release|Any CPU.Build.0 = Release|Any CPU + {8880DC40-7C67-AEBC-AFD6-45094E65D01B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8880DC40-7C67-AEBC-AFD6-45094E65D01B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8880DC40-7C67-AEBC-AFD6-45094E65D01B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8880DC40-7C67-AEBC-AFD6-45094E65D01B}.Release|Any CPU.Build.0 = Release|Any CPU + {DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0}.Release|Any CPU.Build.0 = Release|Any CPU + {A076DAB1-03F6-0592-4900-5CEF38A76026}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A076DAB1-03F6-0592-4900-5CEF38A76026}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A076DAB1-03F6-0592-4900-5CEF38A76026}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A076DAB1-03F6-0592-4900-5CEF38A76026}.Release|Any CPU.Build.0 = Release|Any CPU + {9CA173D6-B883-9629-EFB3-A37D89AAEE81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CA173D6-B883-9629-EFB3-A37D89AAEE81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CA173D6-B883-9629-EFB3-A37D89AAEE81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CA173D6-B883-9629-EFB3-A37D89AAEE81}.Release|Any CPU.Build.0 = Release|Any CPU + {FDE1FE78-B568-3602-653D-2E641AD999D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDE1FE78-B568-3602-653D-2E641AD999D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDE1FE78-B568-3602-653D-2E641AD999D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDE1FE78-B568-3602-653D-2E641AD999D5}.Release|Any CPU.Build.0 = Release|Any CPU + {2F99A8DC-3A89-3004-66F2-B61158DA9F61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F99A8DC-3A89-3004-66F2-B61158DA9F61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F99A8DC-3A89-3004-66F2-B61158DA9F61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F99A8DC-3A89-3004-66F2-B61158DA9F61}.Release|Any CPU.Build.0 = Release|Any CPU + {4AC7962E-AB5E-BEE5-DC17-22A29FE73DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AC7962E-AB5E-BEE5-DC17-22A29FE73DED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AC7962E-AB5E-BEE5-DC17-22A29FE73DED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AC7962E-AB5E-BEE5-DC17-22A29FE73DED}.Release|Any CPU.Build.0 = Release|Any CPU + {E5343E6A-61DC-46E0-6A7A-9F93362AF113}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5343E6A-61DC-46E0-6A7A-9F93362AF113}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5343E6A-61DC-46E0-6A7A-9F93362AF113}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5343E6A-61DC-46E0-6A7A-9F93362AF113}.Release|Any CPU.Build.0 = Release|Any CPU + {A768070E-FF34-424C-9945-B75533E7ADD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A768070E-FF34-424C-9945-B75533E7ADD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A768070E-FF34-424C-9945-B75533E7ADD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A768070E-FF34-424C-9945-B75533E7ADD3}.Release|Any CPU.Build.0 = Release|Any CPU + {AB207B2A-C8E7-977D-98E6-66527CBB2B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB207B2A-C8E7-977D-98E6-66527CBB2B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB207B2A-C8E7-977D-98E6-66527CBB2B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB207B2A-C8E7-977D-98E6-66527CBB2B7F}.Release|Any CPU.Build.0 = Release|Any CPU + {AB981FD3-3523-CDEA-73C9-D6280400062C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB981FD3-3523-CDEA-73C9-D6280400062C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB981FD3-3523-CDEA-73C9-D6280400062C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB981FD3-3523-CDEA-73C9-D6280400062C}.Release|Any CPU.Build.0 = Release|Any CPU + {B760E50F-F5B6-1266-02A8-0056483F475B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B760E50F-F5B6-1266-02A8-0056483F475B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B760E50F-F5B6-1266-02A8-0056483F475B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B760E50F-F5B6-1266-02A8-0056483F475B}.Release|Any CPU.Build.0 = Release|Any CPU + {CDD00CAC-4A4E-FAD5-E8C3-B833C2994314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDD00CAC-4A4E-FAD5-E8C3-B833C2994314}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDD00CAC-4A4E-FAD5-E8C3-B833C2994314}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDD00CAC-4A4E-FAD5-E8C3-B833C2994314}.Release|Any CPU.Build.0 = Release|Any CPU + {56778F12-42F0-4288-B559-218FC5A3C323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56778F12-42F0-4288-B559-218FC5A3C323}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56778F12-42F0-4288-B559-218FC5A3C323}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56778F12-42F0-4288-B559-218FC5A3C323}.Release|Any CPU.Build.0 = Release|Any CPU + {6120F990-8729-DD52-5CEA-F2295528ED07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6120F990-8729-DD52-5CEA-F2295528ED07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6120F990-8729-DD52-5CEA-F2295528ED07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6120F990-8729-DD52-5CEA-F2295528ED07}.Release|Any CPU.Build.0 = Release|Any CPU + {32C35E78-BE23-2D27-F1B3-C2270E45B0C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32C35E78-BE23-2D27-F1B3-C2270E45B0C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32C35E78-BE23-2D27-F1B3-C2270E45B0C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32C35E78-BE23-2D27-F1B3-C2270E45B0C4}.Release|Any CPU.Build.0 = Release|Any CPU + {9AC112AD-18C2-359E-6696-87B814A69E63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AC112AD-18C2-359E-6696-87B814A69E63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AC112AD-18C2-359E-6696-87B814A69E63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AC112AD-18C2-359E-6696-87B814A69E63}.Release|Any CPU.Build.0 = Release|Any CPU + {B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80}.Release|Any CPU.Build.0 = Release|Any CPU + {D74CF5EA-4BE7-4F23-663A-490C29D7576A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D74CF5EA-4BE7-4F23-663A-490C29D7576A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D74CF5EA-4BE7-4F23-663A-490C29D7576A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D74CF5EA-4BE7-4F23-663A-490C29D7576A}.Release|Any CPU.Build.0 = Release|Any CPU + {73A8BAF3-10A7-1C52-7CFF-6301B730A458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73A8BAF3-10A7-1C52-7CFF-6301B730A458}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73A8BAF3-10A7-1C52-7CFF-6301B730A458}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73A8BAF3-10A7-1C52-7CFF-6301B730A458}.Release|Any CPU.Build.0 = Release|Any CPU + {CD7B8501-57B7-6C0E-472F-4E9B894ED6C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD7B8501-57B7-6C0E-472F-4E9B894ED6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD7B8501-57B7-6C0E-472F-4E9B894ED6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD7B8501-57B7-6C0E-472F-4E9B894ED6C2}.Release|Any CPU.Build.0 = Release|Any CPU + {52186445-5B56-EA32-F154-39F47D2FB235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52186445-5B56-EA32-F154-39F47D2FB235}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52186445-5B56-EA32-F154-39F47D2FB235}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52186445-5B56-EA32-F154-39F47D2FB235}.Release|Any CPU.Build.0 = Release|Any CPU + {410E0FFF-705D-4471-9E52-FF495096A945}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {410E0FFF-705D-4471-9E52-FF495096A945}.Debug|Any CPU.Build.0 = Debug|Any CPU + {410E0FFF-705D-4471-9E52-FF495096A945}.Release|Any CPU.ActiveCfg = Release|Any CPU + {410E0FFF-705D-4471-9E52-FF495096A945}.Release|Any CPU.Build.0 = Release|Any CPU + {ABCAB030-29ED-8219-F1DB-39D16098805F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABCAB030-29ED-8219-F1DB-39D16098805F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABCAB030-29ED-8219-F1DB-39D16098805F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABCAB030-29ED-8219-F1DB-39D16098805F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {BA00B3F2-199B-40E2-B0EA-0AA4F51A1C52} = {D52D5A11-78EF-4154-8298-267738A6715B} + {77BDEF2B-1A30-4E64-BC35-0DFC21091327} = {A057F430-AD93-49D9-8080-6E074AF05694} + {573B7B0E-3065-42DE-A391-EE026CE7A366} = {BA00B3F2-199B-40E2-B0EA-0AA4F51A1C52} + {FFD1E99C-49DA-4ADC-BC92-B14B51B45CAF} = {BA00B3F2-199B-40E2-B0EA-0AA4F51A1C52} + {0439B173-F41E-4CE0-A44A-CCB70328F272} = {D52D5A11-78EF-4154-8298-267738A6715B} + {3EE2D2F8-2B57-4EF7-88E8-5E4C851E66C2} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {A584D040-95AC-4422-93FF-7B80532213F0} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {76249548-4344-4CD0-A0AC-12AC54184B58} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {A5543E56-DA53-494D-A531-DA75091D46FF} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {8AC72641-30D3-4ACF-89FA-808FADC55C2E} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {AEC1E6D3-DC23-41BD-B456-3AAD26E34978} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {E6B11DE5-B5EC-4C25-BAF6-1AC9FD0409EB} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {9E72FEB9-A626-4312-892B-CDD043879758} = {D52D5A11-78EF-4154-8298-267738A6715B} + {8B09385A-719C-4B83-B61E-0ECD5D2734BD} = {9E72FEB9-A626-4312-892B-CDD043879758} + {8E569C1C-2637-4D89-804C-50FBC83948FB} = {9E72FEB9-A626-4312-892B-CDD043879758} + {5A10C02B-D12C-479C-9E7F-9A7D9DDD753D} = {9E72FEB9-A626-4312-892B-CDD043879758} + {FF1839EA-FB6B-4ED5-9804-E40427046D35} = {14CDBAD1-10C8-464A-B445-1F727C988010} + {9FE2A95F-D7A3-4305-9E12-E955EF74CF8D} = {6255DBAD-A388-4418-A5EB-C79630786028} + {6E4A0D87-C3CE-430F-A475-A6B68C116D96} = {6255DBAD-A388-4418-A5EB-C79630786028} + {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} = {D52D5A11-78EF-4154-8298-267738A6715B} + {A5851F0F-CB0D-4E29-A829-D1BDEADB807B} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {FDEECE0D-6F66-4053-948E-9AC021B97C8D} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {4DFA9E60-E9CE-4FD3-A57F-F76EF3FF4873} = {ECC8B9A9-9E92-4493-984D-2E350A49189D} + {371B293B-0CA9-4385-8EBB-5224332066D2} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {9E12ADBF-713B-4FE7-B71F-52B5078A57CE} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {47CC8F7A-681D-42B9-AE04-78453782C1B6} = {C6D62079-B3F5-4006-AA49-3BF12C4805BB} + {F595CB9F-B117-4D62-A1AE-48599927DB36} = {C6D62079-B3F5-4006-AA49-3BF12C4805BB} + {5CF403B2-47C9-4E4E-8856-0294BDD64884} = {C6D62079-B3F5-4006-AA49-3BF12C4805BB} + {059473BA-FAF9-405F-9985-33DDCA2E9F0D} = {14CDBAD1-10C8-464A-B445-1F727C988010} + {B39B5FB6-E7B9-4A13-8FFA-FC7FEED4371B} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {C8A00439-5B8D-4923-8FAA-AB75E2A786ED} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {31B03DCB-ED12-4412-867A-61E347D40D8C} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {AB984240-EF03-416F-A9B2-F5CF169E04B7} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {EBBBBD00-74B5-49CB-8C24-4FD7C2ECC415} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {65DDA934-B76B-4018-A565-CF6CEF0D6BB0} = {11CDB632-9A54-439F-8B68-32B3C775BC3A} + {376D8343-DF83-41D2-BF6E-2F5DC8DBF259} = {11CDB632-9A54-439F-8B68-32B3C775BC3A} + {6259BCB9-A302-4CE7-AF48-9283A0DFD3CB} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {1DA91161-8757-4A68-A0A1-8C94C36C9240} = {6255DBAD-A388-4418-A5EB-C79630786028} + {F4923692-D343-4318-AECA-96F580B1A563} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F135B9E8-3FFE-44E9-835B-7B6A928F4823} = {F4923692-D343-4318-AECA-96F580B1A563} + {75A6D078-C19D-4030-88CC-C2A8608FF604} = {F4923692-D343-4318-AECA-96F580B1A563} + {2D895594-3FF5-4507-853A-CB65F2DB72ED} = {F4923692-D343-4318-AECA-96F580B1A563} + {AFA3EEF5-525F-4FF7-A0D0-E8E5D2734F93} = {F4923692-D343-4318-AECA-96F580B1A563} + {0655A0FB-59E8-4A9F-BAF5-47A89377F747} = {F4923692-D343-4318-AECA-96F580B1A563} + {5FBBBA6A-D6EC-42E1-8164-15C411EC77BE} = {F4923692-D343-4318-AECA-96F580B1A563} + {F3D9B137-32DE-4018-8058-78AB17FCDF9C} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {52B5D4F7-237B-4E0A-A167-68442164F70A} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F19C8B0F-A332-4190-9ABE-95790E0AE864} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {72DCA4CF-8B95-47C9-B02A-2671953B7987} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {7DDEAEA9-E392-469C-ACB6-908C5BAD669E} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {86A67B8C-EFA0-4103-B60F-312F07C15A7A} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {F359AAA1-C854-444A-88F2-1C0D8A07F864} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {5D0ED1FC-3A7C-4531-9512-832E73AD9555} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {2BF7FB73-0C62-4ECF-99F0-0583855D2777} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {6FE7E243-2D99-4567-8786-6C9283D608EF} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {65DE28D5-DFEA-43E5-B820-BAF09A1FC4ED} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} + {D3E65610-4167-4235-9C9D-1E1FAD4C0CE6} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} + {F12F4645-C0FE-4129-8C71-65B4039DC445} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {C457FA70-8732-44B8-A018-C96D14025D4B} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {7071E78B-755B-410A-830B-AA05D7168944} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} + {87B65CBD-0FF4-4FB5-9ABC-161911A71179} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} + {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F40F88F1-CA90-4A79-B772-80E287E25982} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} + {AC3C8985-73C2-472A-8E76-A0B8786FEC3F} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} + {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} + {CC362C67-6FC1-42B3-A130-8120AA8D790C} = {D52D5A11-78EF-4154-8298-267738A6715B} + {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {BAE74ABC-1096-495F-A624-BEBFBC1896F2} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {E92A1CAA-5758-41EF-B67E-C0D394E85417} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {F18DE651-A3E4-478F-A2B5-686429729EB8} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {42309C06-C0F2-490F-931B-CF41FA1970FF} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {EC19F867-E9EA-4B26-A1E7-87AAA3EB9296} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {DC15AE5F-D20E-47E4-92A4-DBBD1BD51E91} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {14CDBAD1-10C8-464A-B445-1F727C988010} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {FCFAF1AF-B3F6-45F3-85AB-8249EB8432CC} = {14CDBAD1-10C8-464A-B445-1F727C988010} + {97B4A37E-B93E-48C9-95D5-689CB9495D8B} = {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} + {FE0F0889-C4AF-43C5-B851-B8CCC873BA2C} = {14CDBAD1-10C8-464A-B445-1F727C988010} + {B86EBB6F-A27F-4277-8265-937951A9DCB0} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {35B17218-9FB6-439E-AF73-9A1454BC923C} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {D5036D3F-1C53-47EE-BA50-AD290AE062D7} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {BD74BE00-54E4-4979-8797-E8027695F396} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {48DE251A-3482-4934-BC26-F99D2235AC9F} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} + {94B47385-E47F-4FD7-A3A9-A7AA122EFC93} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {C892CD81-50AE-49E5-BF44-A0C28A1614CC} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {EEF03CC6-1013-4AAF-BEED-BB4BA5021039} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {90E88EAC-4291-4406-8D88-EFDF61B11292} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {84868710-ECBB-4025-900A-EEB99EC49534} = {90E88EAC-4291-4406-8D88-EFDF61B11292} + {A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {D3BAA44E-8395-4E8A-AA96-6B463356C537} = {D52D5A11-78EF-4154-8298-267738A6715B} + {5BE18D72-0D02-4854-966E-745CE5DAF77F} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {73EAD4FE-B44F-44A7-904E-FFA5096D91BD} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {06D34108-01BA-4C77-A704-4DD9E6F7E32C} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {A98C939C-9F48-414A-A2D3-853BE4447397} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {A94BE05F-7DAB-461C-93E7-914CBDF4FA93} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {FBE91498-D83B-4873-A67E-0FB9D1C366F0} = {D3BAA44E-8395-4E8A-AA96-6B463356C537} + {6084D52D-775B-4A39-8CD5-AA2F362B5A61} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {D60EFB8E-F168-4EF2-8D8F-ED42EB6FB8CF} = {6084D52D-775B-4A39-8CD5-AA2F362B5A61} + {34BB9810-2983-4E55-A96A-132D32310145} = {6084D52D-775B-4A39-8CD5-AA2F362B5A61} + {4D83BDA7-2059-41C7-85AE-FEFAD5CD9498} = {6084D52D-775B-4A39-8CD5-AA2F362B5A61} + {8EF31071-3521-409D-9740-BBFBFC04C50E} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {13219C1C-23E1-4EBA-93FB-86830C93A800} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {60D0BEF2-FEAF-4066-8377-6C873CB24858} = {C6D62079-B3F5-4006-AA49-3BF12C4805BB} + {340BE5AC-68EC-41A5-9D0D-266037C58F13} = {C6D62079-B3F5-4006-AA49-3BF12C4805BB} + {BC518F26-996E-4DF0-BB44-783EB1C275D2} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {B981DD7D-7083-4C7A-9A5F-B8CFAE7B670B} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {63D1DC91-C7C7-491A-8423-B0B89F39443F} = {B981DD7D-7083-4C7A-9A5F-B8CFAE7B670B} + {1E0E82D2-F53A-4326-9E39-D7D677590543} = {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02} + {D82DB535-67FB-4712-B3EC-9A7A1EA6F7E9} = {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02} + {6C3D4C1C-4864-44A9-8649-9856ABF667FA} = {6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA} + {AD3CC5B5-366B-4E34-8E80-EC5BB68B573A} = {6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA} + {F71A0D28-397D-4094-B1C2-7925E1310676} = {6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA} + {CEAF0044-28D3-4585-B69D-D65FF6D4745E} = {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02} + {91D9F43A-BFD9-47CA-A6AD-430D1663EFF3} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {7D02D803-F9A9-492C-9B5E-454E4B258466} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {FD04A084-BB8A-4733-B9C5-FACF40342A8A} = {7D02D803-F9A9-492C-9B5E-454E4B258466} + {67A76560-D39F-4D49-B858-B476E1DFE37B} = {F4923692-D343-4318-AECA-96F580B1A563} + {DC33925B-264D-421B-96CC-46F853CBCC70} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {93317D44-835C-4F5E-B85D-580D51D5FFF4} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {DAF80936-FBEC-45AB-92DF-34966B0148FD} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {995756A1-A379-4797-89F0-87D219B5AF00} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {EB73D2CC-B1BE-471A-B76E-35F288CD0E16} = {90E88EAC-4291-4406-8D88-EFDF61B11292} + {842E19B3-8110-40FE-AAFF-D288BC928E55} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {C1319EC1-A489-482B-A343-38B52D8AB0B0} = {848F6760-9B11-4C9A-9843-9D71DD66D9DA} + {3C7A8246-DE82-4330-8697-24EF1B1C515D} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {4059F87E-9762-46C1-AEB1-B1128EA533AE} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} + {433AD1FB-2DE8-479F-B89E-A17217591538} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} + {65311EC9-7A86-4E73-A587-F06A99474EDD} = {848F6760-9B11-4C9A-9843-9D71DD66D9DA} + {CD9081C6-7CA0-4A93-9318-33E54F3ED275} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {D262405E-1C72-4F14-A799-40471BAD48DC} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {529DF802-97C4-4BF2-BE7C-39663B3D9EA3} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {BB840DEE-1F5F-45AA-A82F-4E7B7DC4F156} = {529DF802-97C4-4BF2-BE7C-39663B3D9EA3} + {19B860CA-2E1E-45CC-A5E2-ED3F2BCEAB5D} = {529DF802-97C4-4BF2-BE7C-39663B3D9EA3} + {440C9BD9-85EA-4473-AB1C-7C3562DF4915} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {23C3B247-523A-4FBF-B785-2F035E0089BD} = {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02} + {C7CF4193-6397-4450-AF42-3BACD7CF292E} = {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} + {8FE2725C-6829-4778-93BA-A53260697AFB} = {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} + {A4B972EC-9F0B-4405-9965-766FABC9B07E} = {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} + {31E60E23-FD98-4D5E-A137-2B3F2968BA09} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {25378F9D-2A66-4568-AAC6-E9282ACA3DD3} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {3FCB1BCD-34BC-4F66-968F-38DB28371D0F} = {3B96F4D8-4993-419B-BCEB-AFE4ED39449F} + {A030CD8E-61F3-4C15-B28A-C301446DDBEC} = {A5543E56-DA53-494D-A531-DA75091D46FF} + {D01D859E-4B72-478A-BABD-90F0981652D5} = {D52D5A11-78EF-4154-8298-267738A6715B} + {049E09BF-2E11-4E3B-926D-9DD6051A2DA4} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {F1BE6113-3439-45BB-8B58-20ACA4056895} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {77C2E24A-D143-44E7-86F9-AB6C5D444F63} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {D8FB1E73-6F50-4CC9-9C0E-FB73205F8DB3} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {B1DDC8AF-B0BE-46D1-A2FE-2D5219F847B5} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {8DF50094-6791-4C7C-B07D-C3E995B69C49} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {96EF6CDD-CD29-4E7B-B86A-3EBEE6AC9FDC} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {13ACF670-F109-404E-B252-2FA34A4EA061} = {D52D5A11-78EF-4154-8298-267738A6715B} + {91AE01B1-CC82-40E2-8290-B8A84C6E90D1} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {9EC33D45-CCC7-41DF-829E-6B89A640FE35} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {902D822A-52B6-481C-96C5-ECD891FF83FC} = {9EC33D45-CCC7-41DF-829E-6B89A640FE35} + {46244C99-3A0D-4D88-9F24-2B7B586ADBA4} = {CC362C67-6FC1-42B3-A130-8120AA8D790C} + {76A5564E-033B-4AA6-A22B-78B6EB134CC6} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {67DC7FA0-506A-4977-95F6-BC739B2BC4BA} = {F4923692-D343-4318-AECA-96F580B1A563} + {8DF55DAB-4C1D-46F7-9324-0050F47B3BED} = {F4923692-D343-4318-AECA-96F580B1A563} + {ABD89F39-62D9-439E-8662-BE4F36BFA04F} = {D52D5A11-78EF-4154-8298-267738A6715B} + {D4B4800F-6238-4EA9-A9BB-298D668C26C4} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {F9AC4123-7987-47D3-85D6-CD13928F3683} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {22BDDF5C-F911-4978-B83F-981F3652BF45} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {0C824BB4-81FC-4B28-B7B1-07B2B2BB70A0} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {4711320B-F98D-4CB0-BFEB-B9685B6CBCB7} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {130F8ED1-A64F-48DE-BF43-18EAD19CAF63} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {A53FE09E-6B1C-46C0-9422-C313D14AE9E4} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {995DB1CE-A2FC-4468-A521-4207FD587EC5} = {90E88EAC-4291-4406-8D88-EFDF61B11292} + {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} = {D52D5A11-78EF-4154-8298-267738A6715B} + {7D6AE2BB-7DBF-4FC8-A1F5-C004D139B278} = {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} + {920867B4-4740-4074-9B49-14002B272A63} = {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} + {3D422738-B111-4DEE-82E1-C3A90F1133B1} = {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} + {08CC528E-98D7-41D9-957D-9F9064645788} = {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} + {B507D18B-770E-4581-854B-15579AC7074F} = {63FCC71F-1CEF-44D3-B95B-23EE58DE8C95} + {178AF3DE-1C24-41A9-8CA0-64A7D85DDFFE} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {7C4C266C-DC2A-4A48-AB87-185E284B86E9} = {53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4} + {0380623A-EC74-430B-AA59-A6D23BC5E108} = {53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4} + {C6BDAB62-0B82-4ED2-8455-2FEA1F1B1EAD} = {53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4} + {C9BB4BB2-97B8-4CDE-B961-2F0A4CB5D7B1} = {53DF60C5-AE45-4FCE-9C9B-EE15F0E33BD4} + {A8F1C9FA-4F16-43F9-8CC6-CCD124154440} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {82CB7E17-ED5A-4D26-B116-BA7B4226E43C} = {A8F1C9FA-4F16-43F9-8CC6-CCD124154440} + {102C3711-135E-446D-9A35-AEFB79993CAA} = {A8F1C9FA-4F16-43F9-8CC6-CCD124154440} + {2B7C1441-8801-4121-ABFB-03771E9DFE46} = {A8F1C9FA-4F16-43F9-8CC6-CCD124154440} + {ECC8B9A9-9E92-4493-984D-2E350A49189D} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {942816E3-B270-40DC-9532-C1077FF59A32} = {848F6760-9B11-4C9A-9843-9D71DD66D9DA} + {FBB50072-33BE-4B4A-8908-E98BC0C80B92} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {83E698F6-F8CD-4604-AB80-01A203389501} = {D52D5A11-78EF-4154-8298-267738A6715B} + {D509011F-4690-4F21-BA30-E4C31799993F} = {83E698F6-F8CD-4604-AB80-01A203389501} + {257C64BC-BD16-4F6D-A0B9-E286A4161241} = {83E698F6-F8CD-4604-AB80-01A203389501} + {785251E2-6E77-40E3-90C2-4DFB63D0721B} = {83E698F6-F8CD-4604-AB80-01A203389501} + {0521239A-6B83-414F-B3E2-0515FC70F121} = {83E698F6-F8CD-4604-AB80-01A203389501} + {44E33132-9427-4E52-B105-67A8BC2BC29E} = {83E698F6-F8CD-4604-AB80-01A203389501} + {E567A760-D19A-4CAC-BD6B-BAA0CE0BBC1B} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {D3008465-B344-4243-B14A-A1430E2BEC48} = {E567A760-D19A-4CAC-BD6B-BAA0CE0BBC1B} + {3CBA6005-B412-4D2A-8F1E-01D53D5C657E} = {E567A760-D19A-4CAC-BD6B-BAA0CE0BBC1B} + {15EC4A03-D172-4984-B9CA-2C73929838DE} = {83E698F6-F8CD-4604-AB80-01A203389501} + {74C13BCC-A5A5-40FA-81E8-83DCCF760148} = {83E698F6-F8CD-4604-AB80-01A203389501} + {427382F6-3153-47A2-BBC4-88F6EA116A8F} = {83E698F6-F8CD-4604-AB80-01A203389501} + {2BFFE9C3-E022-4B57-9E4D-0A0408424B1A} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {CA8D7141-9520-46AC-83FD-6E034AD6EBDD} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {42FD76A3-803A-4E07-8A90-4269204B7B87} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} = {D52D5A11-78EF-4154-8298-267738A6715B} + {4CF6F78C-22BE-46C4-BC9B-824E8FEEF719} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {CDD4CC0F-5493-40C2-B889-3670263888D8} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {F74AAE01-7B87-44CA-85ED-9A6307D51504} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {E3F010C7-6C96-4EEA-B5FA-BF80515E195F} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {B153F98A-7DA9-4A12-A1D7-105BE9408FA1} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {EFC5C34F-81A1-4EFC-966F-50B646C54FA6} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {F3E04039-7BEE-46F8-B33B-FE13E977DCCA} = {52E60F16-6304-4E37-A220-C94D8C5D27DC} + {35D17AF3-FDCD-4704-969C-E82DBCC0A232} = {CC362C67-6FC1-42B3-A130-8120AA8D790C} + {984F481B-79FF-4825-917B-944F151694BC} = {CC362C67-6FC1-42B3-A130-8120AA8D790C} + {B12BECC4-8A58-4DBD-A5CD-144A507972BB} = {CC362C67-6FC1-42B3-A130-8120AA8D790C} + {12896A3F-5F7E-4192-8A58-E1D2527109D1} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F7A8000A-D8DA-4A1F-B0B2-9A52183F2012} = {12896A3F-5F7E-4192-8A58-E1D2527109D1} + {4E8DA436-8FAF-4028-8A0C-E4EEB3615972} = {12896A3F-5F7E-4192-8A58-E1D2527109D1} + {405694F8-0051-4DAE-A991-919FAC36C7DA} = {12896A3F-5F7E-4192-8A58-E1D2527109D1} + {5F0BB690-0FBB-455A-AE9A-8BA914AA78F6} = {D52D5A11-78EF-4154-8298-267738A6715B} + {F7103498-8B5B-4698-AACE-9E949F732E77} = {5F0BB690-0FBB-455A-AE9A-8BA914AA78F6} + {2EAA690B-1395-4952-95A0-A52F929028C4} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {722FE012-8F23-4558-9E8F-A37C02902058} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {79D3C6D6-6433-471D-B354-477E07CB08EE} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {5A3B9F4D-E6CC-410F-B307-0E69CCA213F5} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {4CDCD854-6E06-4076-AE94-53C1C1D7F6FA} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {97062425-3379-4F8D-BFA2-D445C56C0801} = {F7103498-8B5B-4698-AACE-9E949F732E77} + {5B20BA13-40FF-4743-AEEE-2E3F887F50C6} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {03EC70B8-912C-4FBE-94DD-6327F4F23021} = {83E698F6-F8CD-4604-AB80-01A203389501} + {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} = {D52D5A11-78EF-4154-8298-267738A6715B} + {C037F0CE-8223-4D4A-B15F-18B7D6AA447F} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {E293BB96-5054-497B-BCE5-64AF9B0457B1} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {FB7AF3F8-44CD-4732-8A25-A43902437B89} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {6472B3C1-C237-49CD-82C8-821AD001096A} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {4BE55D79-63E6-4335-A4FA-DFC64BA6CF2F} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {FB0B28CA-EE88-4DBF-9E0D-E442757E2B98} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {47D57848-A910-4869-8A46-84E40A985FEE} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {8A1F9647-B773-40AB-9126-30868014AE58} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {4298F0E2-AE43-433D-B5EA-3FDDEE8E49A0} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {10CF8240-4276-4199-B3D1-C45F16468EBD} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {39DFEFCD-7C73-450F-9A2F-7426188A890B} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {C465BB41-9DB7-470F-BC7F-A59D2A7D6083} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {DD1B10ED-73E2-41BE-928A-46501050FE2A} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {7779D9BD-5928-49A2-965F-537967004238} = {DD1B10ED-73E2-41BE-928A-46501050FE2A} + {AC41F335-E240-47E0-B409-AFAD1400E626} = {DD1B10ED-73E2-41BE-928A-46501050FE2A} + {1D420BA6-2155-4E0D-AAAF-EECC0330A38C} = {DD1B10ED-73E2-41BE-928A-46501050FE2A} + {59627844-A66A-46AC-B882-E8F302D0EC24} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {2F49E870-DAE2-4D89-98CA-46BBD91C68E2} = {59627844-A66A-46AC-B882-E8F302D0EC24} + {E4CEED06-B8E9-41FA-82BF-5401AE101C4B} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {9BDE2F3E-6A95-47AC-9BBC-EC8570F2925A} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {B4C8056F-7325-4DB1-9F09-A6F37B052192} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {D5AEBB8E-713C-4DD2-BA18-7B0B48489901} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {CC07A6C2-CD79-4A1E-BE65-C6444AC89C2C} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {DEDB69A9-657F-4B8B-81A7-4ADB19664F35} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {2C86306D-D626-41F8-BA3C-5C9B4123CE7D} = {83E698F6-F8CD-4604-AB80-01A203389501} + {2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {3E32DBDA-1C63-42B4-85D1-E84BBD072D89} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {87CE2F0B-0469-4C76-B325-00EA7AB94B99} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {34987F45-8234-428C-AB41-783D42295C32} = {87CE2F0B-0469-4C76-B325-00EA7AB94B99} + {227DA969-291B-4749-985C-7A83523B7F53} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C} = {87CE2F0B-0469-4C76-B325-00EA7AB94B99} + {F197F8BB-87E3-43FC-92E7-DE8E60EB22E9} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {11CDB632-9A54-439F-8B68-32B3C775BC3A} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {C6D62079-B3F5-4006-AA49-3BF12C4805BB} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {848F6760-9B11-4C9A-9843-9D71DD66D9DA} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {6255DBAD-A388-4418-A5EB-C79630786028} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {A025B8D2-5D92-4023-82AB-97A672A5A132} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {5D99743B-7044-4BE9-8F7A-E195F2A3E2EC} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {E09E476C-9DF8-46AC-848E-4E7635369117} = {3CDBA2A6-DC8A-48C5-8A6C-AF207394B43D} + {E414F7BC-215C-46D0-99EC-CD78EB31FC3C} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {8142FB8C-3D32-4062-BD95-B2F61A1A390A} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {4155336A-DC06-4885-878D-03AF5DFAF47D} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {ADAB35CB-A34E-448D-ACBB-FA054A3B90AA} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {1B112FAC-CB57-48B6-A3D5-95456477CB8D} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {B84E4D98-0B10-4189-8572-F6F7B4E384B7} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {E81EC3E4-521F-4C52-8AA0-A783847E764E} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {49EB2864-B715-47DD-AE47-C5243C656F47} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {A057F430-AD93-49D9-8080-6E074AF05694} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {68538541-4280-46F5-BA08-99ACA8575615} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {F6F93723-5BC3-4D25-A83E-25B41B6D956F} = {A057F430-AD93-49D9-8080-6E074AF05694} + {6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {77ED7922-BF30-4436-8A85-78F812583913} = {D52D5A11-78EF-4154-8298-267738A6715B} + {109BF321-1BC6-4031-A59B-7B5375EBA8C5} = {77ED7922-BF30-4436-8A85-78F812583913} + {08A78A69-913B-4C5E-BCE0-739585F82D1E} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {4FAE314C-36CB-4E3F-85B7-41D0A428B37D} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {B6857FC4-97C2-4E20-B005-1FAABC574B88} = {4FAE314C-36CB-4E3F-85B7-41D0A428B37D} + {B6D4AADE-3ABA-45E6-9916-2F8798412549} = {4FAE314C-36CB-4E3F-85B7-41D0A428B37D} + {86E85013-7C71-4770-9323-18897A64F5B2} = {4FAE314C-36CB-4E3F-85B7-41D0A428B37D} + {014A9583-0EAA-48A4-ACBE-07DC88159E13} = {4FAE314C-36CB-4E3F-85B7-41D0A428B37D} + {AAC0C407-B4B9-4E90-99FC-2D793AC229D9} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {4C71CA88-0D04-4DDB-8906-B953908B8B8B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37} + {50FF92EA-8BA4-445D-AB04-E7568EE5D3FE} = {77ED7922-BF30-4436-8A85-78F812583913} + {1E00BE51-A1AE-447D-B6E0-F28EC12B259A} = {77ED7922-BF30-4436-8A85-78F812583913} + {61F0EEB2-5ED0-4809-8EF9-0676C7A680CE} = {77ED7922-BF30-4436-8A85-78F812583913} + {72D54834-7ADF-4B18-A745-FCBBC255073B} = {77ED7922-BF30-4436-8A85-78F812583913} + {F6A9D966-0022-440B-AE27-564A74CDED48} = {D52D5A11-78EF-4154-8298-267738A6715B} + {8C99C96A-AE0C-489B-A1A0-AD8442A3B6A3} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {6C0DB8F2-FB0A-4922-B8FE-177DCF37A918} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {D73200F6-CBB3-4BA8-B9BF-7110AAF05596} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {30FB6AD7-3CC5-4A8D-B170-BDA772E6BA3C} = {848F6760-9B11-4C9A-9843-9D71DD66D9DA} + {40D7A0A3-68BD-431E-A67A-E2A35508D55D} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {8EA8C998-F81A-46E9-8C7E-C944D2503A0A} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {47550AB9-FA06-42D6-A4B8-7DD12FE66563} = {529DF802-97C4-4BF2-BE7C-39663B3D9EA3} + {835E51CE-1E6B-4C8C-9736-8C5B61F5E08E} = {F6A9D966-0022-440B-AE27-564A74CDED48} + {FDAAAD2E-42A7-44EC-8971-B5277FD6D404} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} + {ED3DF100-C5DB-4334-A847-118922B28D95} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} + {15482834-9242-4D20-9736-9DA571A9A83A} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {8A255A72-50FC-460E-9897-FA53F455580B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37} + {CED33625-A034-475B-A4C0-A4E7D1BADD10} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {E3BA2413-5755-4F61-9A7C-5D49AE9E7016} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {BF85DB7F-70C2-4804-AA57-FACE204981DA} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {893F7376-0913-43DC-AD3D-40AF5B8F9E3B} = {0439B173-F41E-4CE0-A44A-CCB70328F272} + {8826831D-8733-473A-B47B-A30C3732B13D} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72} = {83E698F6-F8CD-4604-AB80-01A203389501} + {54BBA043-317B-4A4F-B583-513D08BC25A7} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {79FA2CBA-2904-4D80-A217-DCC0A38F93C4} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {E469F047-6AD0-4D2B-9900-46358DA3BC30} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {EB9F1905-1798-4766-8347-A8D2A9DBFAED} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {CCE5C620-E17A-4EB1-A17A-9F90311B197D} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {F2AD691B-71B9-4B86-95BC-E020DA6B1E4A} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {76DDE71D-00BD-4BC8-AEA2-31209E2B7E05} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {267933BD-BFB8-4906-BA39-DF193B2FD558} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {3CBD1342-C021-49FB-933F-FAC1DAFC7B48} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E} + {01B86C39-B0C8-48A4-949C-1C63D755B02C} = {F4923692-D343-4318-AECA-96F580B1A563} + {DD6609C7-07AC-49FD-B588-44E649D0AE6E} = {F4923692-D343-4318-AECA-96F580B1A563} + {856B4ACA-BD13-417F-A6E2-0F401F877189} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {B52B199C-0E1C-4CE9-B066-71D26F618424} = {F4923692-D343-4318-AECA-96F580B1A563} + {80F44B5B-F8FF-47FA-9A77-BE2D176B2721} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F} + {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {D52D5A11-78EF-4154-8298-267738A6715B} + {DD365101-E8FC-6516-2883-B9CA024B36FA} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {C330BADD-59A0-A3CD-E839-A0D4C2C636EE} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {F1C6C6B6-5B99-5AA6-7F76-27560C111605} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {459DA653-F12A-65B5-41EF-A5877B1C38BA} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {9DD70A99-41A6-8598-553E-2B5AB6277035} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {016CCD97-3551-B6C7-FC6C-FF1CB7F84B88} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {F92EBAA6-5BCF-1B7D-FB5E-CDD9F61CA147} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {AE00DA82-B33A-CAF7-D9CD-D5E26608741B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37} + {F9A0D88F-53AE-4AC7-8E15-163C34386E7C} = {9E72FEB9-A626-4312-892B-CDD043879758} + {0FF0A04C-B580-4A56-9171-CF2988B5DE5A} = {9E72FEB9-A626-4312-892B-CDD043879758} + {F810C8A8-1256-440F-BAAF-7F3588291963} = {9E72FEB9-A626-4312-892B-CDD043879758} + {FFBE3EC6-F11B-4B7C-9BAF-AFBBB12BEF59} = {9E72FEB9-A626-4312-892B-CDD043879758} + {C95DE287-9D21-4DCD-9281-A060B6D99774} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {96748DAE-D367-48C0-B64E-2F25010EAC4D} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {A4633711-7FB6-411A-8D08-BB9A0A778046} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {5A0063BF-EE72-E688-84C6-9E3CE0616C94} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {ECE61F58-1AEC-1E4F-1543-76C2242B6F70} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {B7B63E08-8F62-34F6-FEA5-063267F1FC85} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {7C48C1CA-7E53-4261-A477-454DD3A8402C} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} + {A54344EB-05A7-A405-5368-4A9C0A60B078} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {7A8A4C74-4B5F-F352-7AC3-54F54AFC3FD6} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {C9266D5D-3860-09C3-F566-489BBB57A534} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {21542881-C560-4CBB-8AB1-CF757071A057} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {F3DF1C3E-7319-48B1-81AB-0284853BB567} = {21542881-C560-4CBB-8AB1-CF757071A057} + {7D7561CB-5059-4F5F-B736-B97195B46A91} = {21542881-C560-4CBB-8AB1-CF757071A057} + {5B9CA129-16CE-4BEF-B22D-C084B38B4EDA} = {21542881-C560-4CBB-8AB1-CF757071A057} + {418EE258-2670-29D3-480F-EC0FD07700E8} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {7984F6B6-726F-9F30-3B6F-08A90AD75A7D} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {D63FEED3-2342-7E96-4121-B0C19CF1EA81} = {6A3FF105-7E8B-4B4D-A736-1C2BAF86FDAA} + {DED16774-635C-D781-4D5B-D1FA56EECF10} = {D01D859E-4B72-478A-BABD-90F0981652D5} + {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08} = {F4923692-D343-4318-AECA-96F580B1A563} + {DD11D070-F39E-1C41-1843-AE3ADBE501EF} = {9E72FEB9-A626-4312-892B-CDD043879758} + {001D0817-1EED-4C04-821E-F815F148EC90} = {9E72FEB9-A626-4312-892B-CDD043879758} + {546E4417-5409-40F4-A125-E08329DD82BB} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {738A72FB-ED83-4127-AA3B-59BF90635F8F} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {9950639D-AA4C-4FF1-A65E-9790EB561C8A} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {5FA85E8E-3276-43DF-CC93-6A9847905166} = {9E72FEB9-A626-4312-892B-CDD043879758} + {AEEA81D6-B282-93CF-862B-9FCF1A5052F7} = {A5543E56-DA53-494D-A531-DA75091D46FF} + {69419D6B-9DA5-D9BD-1D6C-61BBAE331057} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {B4311504-B0C8-AC8D-02A5-81AD43B4087B} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {C4BDA898-00E2-D1DD-F4E8-4DFF5DDF52C9} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {9FF83836-8627-2943-3344-60319FB85B39} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {EB06B90A-D05C-486C-9787-BA5581664641} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {2A2F1DC7-6B19-9ED8-CCA7-39856F713B5D} = {EB06B90A-D05C-486C-9787-BA5581664641} + {1AE7D817-E837-4C25-9850-8AB11030713F} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {1B5368E2-8A31-F686-3120-770BAD793962} = {1AE7D817-E837-4C25-9850-8AB11030713F} + {BFFC0787-81F4-4751-9385-B91BB8CB183A} = {EB06B90A-D05C-486C-9787-BA5581664641} + {E0EEFE73-EF05-491B-A265-E2B613D0C82F} = {EB06B90A-D05C-486C-9787-BA5581664641} + {A4EF0E36-156F-4D12-A6B0-3C681A1AE6A1} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {2AAAA2BE-A9EF-4957-9A5F-5E2CE0834AF8} = {A4EF0E36-156F-4D12-A6B0-3C681A1AE6A1} + {B49BC05C-0F2A-4E09-B6D3-1EE84AE663BC} = {A4EF0E36-156F-4D12-A6B0-3C681A1AE6A1} + {569667D0-2038-4566-9711-6B174C631063} = {A4EF0E36-156F-4D12-A6B0-3C681A1AE6A1} + {7760B229-E3EA-4A60-9E32-7B2F7FB199E7} = {1AE7D817-E837-4C25-9850-8AB11030713F} + {3672F185-59B2-490D-A00B-5CA9815909B6} = {1AE7D817-E837-4C25-9850-8AB11030713F} + {2D8CA6FB-3FE7-4218-829E-0A1B36A5340D} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {1B9DC76D-942D-4DCC-979F-E9E56BB7073E} = {2D8CA6FB-3FE7-4218-829E-0A1B36A5340D} + {7F65C827-914D-42B1-AE26-44053AE3140F} = {2D8CA6FB-3FE7-4218-829E-0A1B36A5340D} + {1425C1AB-048F-4ABF-ACAB-793E2524F0A8} = {2D8CA6FB-3FE7-4218-829E-0A1B36A5340D} + {647AB3E7-2F32-43D1-AFDC-877C7412F4DA} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {4F4BC2BD-6236-4E8B-B95F-0F4D455EFE14} = {647AB3E7-2F32-43D1-AFDC-877C7412F4DA} + {09B8B63F-972B-4055-9BAD-B2883EBA3EF0} = {647AB3E7-2F32-43D1-AFDC-877C7412F4DA} + {4D2D6CAF-75C7-4A9D-9BFB-FFE7A29D0E99} = {647AB3E7-2F32-43D1-AFDC-877C7412F4DA} + {0EEA73CA-D8DD-F044-045D-F070F8831E26} = {77ED7922-BF30-4436-8A85-78F812583913} + {B6452D3F-E58C-C433-E52A-F65EE2657E01} = {77ED7922-BF30-4436-8A85-78F812583913} + {19F90E75-657C-4542-A798-8E9CE9AF3128} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {62FB9F56-221E-47D5-8B30-311A13D6A568} = {19F90E75-657C-4542-A798-8E9CE9AF3128} + {9F260C45-199D-460C-A5C0-6C2B62594DFA} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {ACEEA6F9-868B-4701-AF65-89292F656A1D} = {9F260C45-199D-460C-A5C0-6C2B62594DFA} + {FB12303C-7A3A-4A42-900F-C131D0FD7BA2} = {9F260C45-199D-460C-A5C0-6C2B62594DFA} + {BAE82F6F-2528-45DF-9571-F733C31CEB1E} = {9F260C45-199D-460C-A5C0-6C2B62594DFA} + {97C66786-03F8-4886-088E-FA1BECB1C574} = {77ED7922-BF30-4436-8A85-78F812583913} + {7B927926-0AF4-A6F2-8ABA-331A6C138EAC} = {77ED7922-BF30-4436-8A85-78F812583913} + {C45D8013-A6DD-6FC2-7FEA-F20D3373ACFA} = {77ED7922-BF30-4436-8A85-78F812583913} + {6FCE34BF-077B-9425-CD34-FA9B2CD190FA} = {77ED7922-BF30-4436-8A85-78F812583913} + {A3DFC5C8-CA0F-3161-7B9B-AC597ACBF889} = {77ED7922-BF30-4436-8A85-78F812583913} + {107C0D30-35C1-142B-209A-29BD6BAE7DE9} = {77ED7922-BF30-4436-8A85-78F812583913} + {D8AF0368-077D-4AAD-9929-43C598DE13B5} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {DB03F47B-4E3A-4484-86DC-741472AD49A3} = {D8AF0368-077D-4AAD-9929-43C598DE13B5} + {2DB2EADB-745A-4442-A48A-B1B721412F78} = {D8AF0368-077D-4AAD-9929-43C598DE13B5} + {4524F120-F72B-4373-B731-6A2D0EF633A7} = {D8AF0368-077D-4AAD-9929-43C598DE13B5} + {0DB2CBEE-66E9-C5AA-ABC7-28CE5F8B65DD} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {8880DC40-7C67-AEBC-AFD6-45094E65D01B} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {DCC20D07-E8EE-ACD7-CF8B-29BB1CD84CD0} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {A076DAB1-03F6-0592-4900-5CEF38A76026} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {9CA173D6-B883-9629-EFB3-A37D89AAEE81} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {FDE1FE78-B568-3602-653D-2E641AD999D5} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {2F99A8DC-3A89-3004-66F2-B61158DA9F61} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {4AC7962E-AB5E-BEE5-DC17-22A29FE73DED} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {E5343E6A-61DC-46E0-6A7A-9F93362AF113} = {13ACF670-F109-404E-B252-2FA34A4EA061} + {125E78AC-071D-4F82-88CE-1D7D2D0AAFF4} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {A768070E-FF34-424C-9945-B75533E7ADD3} = {125E78AC-071D-4F82-88CE-1D7D2D0AAFF4} + {AB207B2A-C8E7-977D-98E6-66527CBB2B7F} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {AB981FD3-3523-CDEA-73C9-D6280400062C} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {B760E50F-F5B6-1266-02A8-0056483F475B} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {CDD00CAC-4A4E-FAD5-E8C3-B833C2994314} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} + {F38C6E5A-1C5F-49FF-9174-95430D6C91ED} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {56778F12-42F0-4288-B559-218FC5A3C323} = {F38C6E5A-1C5F-49FF-9174-95430D6C91ED} + {A72387FE-3361-45B3-AE7A-8BB212668A85} = {D52D5A11-78EF-4154-8298-267738A6715B} + {6120F990-8729-DD52-5CEA-F2295528ED07} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {32C35E78-BE23-2D27-F1B3-C2270E45B0C4} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {9AC112AD-18C2-359E-6696-87B814A69E63} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {B4BC25CA-1A15-DA3F-7BE7-C14713F3BA80} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {D74CF5EA-4BE7-4F23-663A-490C29D7576A} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {73A8BAF3-10A7-1C52-7CFF-6301B730A458} = {A72387FE-3361-45B3-AE7A-8BB212668A85} + {CD7B8501-57B7-6C0E-472F-4E9B894ED6C2} = {77ED7922-BF30-4436-8A85-78F812583913} + {52186445-5B56-EA32-F154-39F47D2FB235} = {0A00FAF9-A96B-4BF5-8D42-15C8678F70F3} + {B856BFF0-8D0E-4C4A-97C7-5406E1B7613C} = {FAB71536-FCDB-4135-B61A-732B72FDA6A6} + {410E0FFF-705D-4471-9E52-FF495096A945} = {B856BFF0-8D0E-4C4A-97C7-5406E1B7613C} + {ABCAB030-29ED-8219-F1DB-39D16098805F} = {77ED7922-BF30-4436-8A85-78F812583913} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} + EndGlobalSection +EndGlobal diff --git a/aspnet-core/aspire/.gitignore b/aspnet-core/aspire/.gitignore new file mode 100644 index 000000000..b4e248cf9 --- /dev/null +++ b/aspnet-core/aspire/.gitignore @@ -0,0 +1,7 @@ +.aspire +wwwroot +node_modules +blobs +bin +obj +yarn.lock \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..99177cffd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorHostedService.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.AdminService; +public class AdminServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public AdminServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorModule.cs new file mode 100644 index 000000000..262f357d3 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/AdminServiceDbMigratorModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.AdminService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AdminServiceMigrationsEntityFrameworkCoreModule) + )] +public class AdminServiceDbMigratorModule : AbpModule +{ + +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj new file mode 100644 index 000000000..7d1367820 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj @@ -0,0 +1,40 @@ + + + + + + Exe + net9.0 + enable + false + LINGYUN.Abp.MicroService.AdminService + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/Program.cs new file mode 100644 index 000000000..c0a4de3e9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/Program.cs @@ -0,0 +1,43 @@ +using LINGYUN.Abp.MicroService.AdminService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; +using System; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.AdminService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.AdminService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..21dde6a90 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.AdminService; +public class AdminServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase +{ + protected IDataSeeder DataSeeder { get; } + + public AdminServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + IDataSeeder dataSeeder) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + DataSeeder = dataSeeder; + } + + protected async override Task SeedAsync(Guid? tenantId) + { + await DataSeeder.SeedAsync(tenantId); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs new file mode 100644 index 000000000..57aef9200 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.AdminService; +public class AdminServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public AdminServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContext.cs new file mode 100644 index 000000000..3c77d0d02 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContext.cs @@ -0,0 +1,79 @@ +using LINGYUN.Abp.DataProtectionManagement; +using LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore; +using LINGYUN.Abp.Saas.Editions; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Saas.Tenants; +using LINGYUN.Abp.TextTemplating; +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.PermissionManagement; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.AdminService; + +[ConnectionStringName("Default")] +public class AdminServiceMigrationsDbContext : + AbpDbContext, + ISaasDbContext, + ITextTemplatingDbContext, + IFeatureManagementDbContext, + ISettingManagementDbContext, + IPermissionManagementDbContext, + IAbpDataProtectionManagementDbContext +{ + #region Entities from the modules + + public DbSet EntityTypeInfos { get; set; } + + public DbSet PermissionGroups { get; set; } + + public DbSet Permissions { get; set; } + + public DbSet PermissionGrants { get; set; } + + public DbSet Settings { get; set; } + + public DbSet SettingDefinitionRecords { get; set; } + + public DbSet FeatureGroups { get; set; } + + public DbSet Features { get; set; } + + public DbSet FeatureValues { get; set; } + + public DbSet TextTemplates { get; set; } + + public DbSet TextTemplateDefinitions { get; set; } + + public DbSet Editions { get; set; } + + public DbSet Tenants { get; set; } + + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public AdminServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureSaas(); + modelBuilder.ConfigureTextTemplating(); + modelBuilder.ConfigureFeatureManagement(); + modelBuilder.ConfigureSettingManagement(); + modelBuilder.ConfigurePermissionManagement(); + modelBuilder.ConfigureDataProtectionManagement(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..9e08bc408 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsDbContextFactory.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.AdminService; +public class AdminServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public AdminServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new AdminServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.AdminService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..bb10e3513 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,93 @@ +using LINGYUN.Abp.Account; +using LINGYUN.Abp.Auditing; +using LINGYUN.Abp.CachingManagement; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.DataProtectionManagement; +using LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore; +using LINGYUN.Abp.FeatureManagement; +using LINGYUN.Abp.Gdpr; +using LINGYUN.Abp.Identity; +using LINGYUN.Abp.Identity.EntityFrameworkCore; +using LINGYUN.Abp.IdentityServer; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.MessageService; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.OpenIddict; +using LINGYUN.Abp.OssManagement; +using LINGYUN.Abp.ProjectManagement; +using LINGYUN.Abp.RulesEngineManagement; +using LINGYUN.Abp.Saas; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.SettingManagement; +using LINGYUN.Abp.TaskManagement; +using LINGYUN.Abp.TextTemplating; +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using LINGYUN.Abp.WebhooksManagement; +using LINGYUN.Platform; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.AdminService; + +[DependsOn( + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpAuditingApplicationContractsModule), + typeof(AbpCachingManagementApplicationContractsModule), + typeof(AbpDataProtectionManagementApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpGdprApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpIdentityServerApplicationContractsModule), + typeof(AbpLocalizationManagementApplicationContractsModule), + typeof(AbpOpenIddictApplicationContractsModule), + typeof(AbpOssManagementApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(PlatformApplicationContractModule), + typeof(AbpProjectManagementApplicationContractsModule), + typeof(AbpMessageServiceApplicationContractsModule), + typeof(AbpNotificationsApplicationContractsModule), + typeof(RulesEngineManagementApplicationContractsModule), + typeof(AbpSaasApplicationContractsModule), + typeof(TaskManagementApplicationContractsModule), + typeof(AbpTextTemplatingApplicationContractsModule), + typeof(WebhooksManagementApplicationContractsModule))] + +[DependsOn( + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpDataProtectionManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpIdentityEntityFrameworkCoreModule),// 用户角色权限需要引用包 + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpTextTemplatingEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpDataDbMigratorModule) + )] +public class AdminServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..3417e98dc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore.csproj @@ -0,0 +1,61 @@ + + + + + + + false + net9.0 + enable + LINGYUN.Abp.MicroService.AdminService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.Designer.cs new file mode 100644 index 000000000..8f2af5540 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.Designer.cs @@ -0,0 +1,1037 @@ +// +using System; +using LINGYUN.Abp.MicroService.AdminService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AdminService.Migrations +{ + [DbContext(typeof(AdminServiceMigrationsDbContext))] + [Migration("20260105085130_Initial_Admin_Service")] + partial class Initial_Admin_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityEnumInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("PropertyInfoId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("PropertyInfoId", "Name"); + + b.ToTable("AbpAuthEntityEnums", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("JavaScriptType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("JavaScriptType"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("TypeFullName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("TypeFullName"); + + b.Property("TypeInfoId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TypeInfoId", "TypeFullName"); + + b.ToTable("AbpAuthEntityProperties", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAuditEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("TypeFullName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("TypeFullName"); + + b.HasKey("Id"); + + b.HasIndex("TypeFullName"); + + b.ToTable("AbpAuthEntitites", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessedProperties") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("AccessedProperties"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EntityTypeFullName") + .HasColumnType("text"); + + b.Property("EntityTypeId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FilterGroup") + .HasColumnType("text") + .HasColumnName("FilterGroup"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Operation") + .HasColumnType("integer"); + + b.Property("OrgCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("OrgCode"); + + b.Property("OrgId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityTypeId"); + + b.ToTable("AbpAuthOrganizationUnitEntityRules", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessedProperties") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("AccessedProperties"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EntityTypeFullName") + .HasColumnType("text"); + + b.Property("EntityTypeId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FilterGroup") + .HasColumnType("text") + .HasColumnName("FilterGroup"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Operation") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("RoleName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityTypeId"); + + b.ToTable("AbpAuthRoleEntityRules", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.SubjectStrategy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Strategy") + .HasColumnType("integer"); + + b.Property("SubjectId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("SubjectId"); + + b.Property("SubjectName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("SubjectName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpAuthSubjectStrategys", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName"); + + b.ToTable("AbpEditions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisableTime") + .HasColumnType("timestamp with time zone"); + + b.Property("EditionId") + .HasColumnType("uuid"); + + b.Property("EnableTime") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("EditionId"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Content") + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Culture") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Culture"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("DisplayName"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .HasDatabaseName("IX_Tenant_Text_Template_Name"); + + b.ToTable("AbpTextTemplates", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultCultureName") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("DefaultCultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsInlineLocalized") + .HasColumnType("boolean"); + + b.Property("IsLayout") + .HasColumnType("boolean"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Layout") + .HasMaxLength(60) + .HasColumnType("character varying(60)") + .HasColumnName("Layout"); + + b.Property("LocalizationResourceName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("LocalizationResourceName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Name"); + + b.Property("RenderEngine") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("RenderEngine"); + + b.HasKey("Id"); + + b.ToTable("AbpTextTemplateDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityEnumInfo", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", "PropertyInfo") + .WithMany("Enums") + .HasForeignKey("PropertyInfoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PropertyInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "TypeInfo") + .WithMany("Properties") + .HasForeignKey("TypeInfoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") + .WithMany() + .HasForeignKey("EntityTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EntityTypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") + .WithMany() + .HasForeignKey("EntityTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EntityTypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") + .WithMany() + .HasForeignKey("EditionId"); + + b.Navigation("Edition"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.Navigation("Enums"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => + { + b.Navigation("Properties"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.cs new file mode 100644 index 000000000..6c62f64dd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/20260105085130_Initial_Admin_Service.cs @@ -0,0 +1,583 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AdminService.Migrations +{ + /// + public partial class Initial_Admin_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuthEntitites", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TypeFullName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsAuditEnabled = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthEntitites", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuthSubjectStrategys", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SubjectName = table.Column(type: "character varying(30)", maxLength: 30, nullable: false), + SubjectId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Strategy = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthSubjectStrategys", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpEditions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEditions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + IsAvailableToHost = table.Column(type: "boolean", nullable: false), + AllowedProviders = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + MultiTenancySide = table.Column(type: "smallint", nullable: false), + Providers = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + Providers = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "boolean", nullable: false), + IsEncrypted = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTextTemplateDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + IsLayout = table.Column(type: "boolean", nullable: false), + Layout = table.Column(type: "character varying(60)", maxLength: 60, nullable: true), + IsInlineLocalized = table.Column(type: "boolean", nullable: false), + DefaultCultureName = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + LocalizationResourceName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + RenderEngine = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + IsStatic = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTextTemplateDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTextTemplates", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + DisplayName = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Content = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: true), + Culture = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTextTemplates", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuthEntityProperties", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TypeFullName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + JavaScriptType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + TypeInfoId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthEntityProperties", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuthEntityProperties_AbpAuthEntitites_TypeInfoId", + column: x => x.TypeInfoId, + principalTable: "AbpAuthEntitites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpAuthOrganizationUnitEntityRules", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + OrgId = table.Column(type: "uuid", nullable: false), + OrgCode = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + IsEnabled = table.Column(type: "boolean", nullable: false), + Operation = table.Column(type: "integer", nullable: false), + FilterGroup = table.Column(type: "text", nullable: true), + EntityTypeId = table.Column(type: "uuid", nullable: false), + EntityTypeFullName = table.Column(type: "text", nullable: true), + AccessedProperties = table.Column(type: "character varying(512)", maxLength: 512, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthOrganizationUnitEntityRules", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuthOrganizationUnitEntityRules_AbpAuthEntitites_EntityT~", + column: x => x.EntityTypeId, + principalTable: "AbpAuthEntitites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpAuthRoleEntityRules", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + RoleName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + IsEnabled = table.Column(type: "boolean", nullable: false), + Operation = table.Column(type: "integer", nullable: false), + FilterGroup = table.Column(type: "text", nullable: true), + EntityTypeId = table.Column(type: "uuid", nullable: false), + EntityTypeFullName = table.Column(type: "text", nullable: true), + AccessedProperties = table.Column(type: "character varying(512)", maxLength: 512, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthRoleEntityRules", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuthRoleEntityRules_AbpAuthEntitites_EntityTypeId", + column: x => x.EntityTypeId, + principalTable: "AbpAuthEntitites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IsActive = table.Column(type: "boolean", nullable: false), + EnableTime = table.Column(type: "timestamp with time zone", nullable: true), + DisableTime = table.Column(type: "timestamp with time zone", nullable: true), + EditionId = table.Column(type: "uuid", nullable: true), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + table.ForeignKey( + name: "FK_AbpTenants_AbpEditions_EditionId", + column: x => x.EditionId, + principalTable: "AbpEditions", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpAuthEntityEnums", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), + PropertyInfoId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuthEntityEnums", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuthEntityEnums_AbpAuthEntityProperties_PropertyInfoId", + column: x => x.PropertyInfoId, + principalTable: "AbpAuthEntityProperties", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuthEntitites_TypeFullName", + table: "AbpAuthEntitites", + column: "TypeFullName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuthEntityEnums_PropertyInfoId_Name", + table: "AbpAuthEntityEnums", + columns: new[] { "PropertyInfoId", "Name" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuthEntityProperties_TypeInfoId_TypeFullName", + table: "AbpAuthEntityProperties", + columns: new[] { "TypeInfoId", "TypeFullName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuthOrganizationUnitEntityRules_EntityTypeId", + table: "AbpAuthOrganizationUnitEntityRules", + column: "EntityTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuthRoleEntityRules_EntityTypeId", + table: "AbpAuthRoleEntityRules", + column: "EntityTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEditions_DisplayName", + table: "AbpEditions", + column: "DisplayName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_EditionId", + table: "AbpTenants", + column: "EditionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_Tenant_Text_Template_Name", + table: "AbpTextTemplates", + column: "Name"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuthEntityEnums"); + + migrationBuilder.DropTable( + name: "AbpAuthOrganizationUnitEntityRules"); + + migrationBuilder.DropTable( + name: "AbpAuthRoleEntityRules"); + + migrationBuilder.DropTable( + name: "AbpAuthSubjectStrategys"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpTextTemplateDefinitions"); + + migrationBuilder.DropTable( + name: "AbpTextTemplates"); + + migrationBuilder.DropTable( + name: "AbpAuthEntityProperties"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpAuthEntitites"); + + migrationBuilder.DropTable( + name: "AbpEditions"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/AdminServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/AdminServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..4a1291c45 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/Migrations/AdminServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,1034 @@ +// +using System; +using LINGYUN.Abp.MicroService.AdminService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AdminService.Migrations +{ + [DbContext(typeof(AdminServiceMigrationsDbContext))] + partial class AdminServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityEnumInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("PropertyInfoId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("PropertyInfoId", "Name"); + + b.ToTable("AbpAuthEntityEnums", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("JavaScriptType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("JavaScriptType"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("TypeFullName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("TypeFullName"); + + b.Property("TypeInfoId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TypeInfoId", "TypeFullName"); + + b.ToTable("AbpAuthEntityProperties", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAuditEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("TypeFullName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("TypeFullName"); + + b.HasKey("Id"); + + b.HasIndex("TypeFullName"); + + b.ToTable("AbpAuthEntitites", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessedProperties") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("AccessedProperties"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EntityTypeFullName") + .HasColumnType("text"); + + b.Property("EntityTypeId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FilterGroup") + .HasColumnType("text") + .HasColumnName("FilterGroup"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Operation") + .HasColumnType("integer"); + + b.Property("OrgCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("OrgCode"); + + b.Property("OrgId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityTypeId"); + + b.ToTable("AbpAuthOrganizationUnitEntityRules", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessedProperties") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("AccessedProperties"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EntityTypeFullName") + .HasColumnType("text"); + + b.Property("EntityTypeId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FilterGroup") + .HasColumnType("text") + .HasColumnName("FilterGroup"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Operation") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("RoleName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityTypeId"); + + b.ToTable("AbpAuthRoleEntityRules", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.SubjectStrategy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Strategy") + .HasColumnType("integer"); + + b.Property("SubjectId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("SubjectId"); + + b.Property("SubjectName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("SubjectName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpAuthSubjectStrategys", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName"); + + b.ToTable("AbpEditions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisableTime") + .HasColumnType("timestamp with time zone"); + + b.Property("EditionId") + .HasColumnType("uuid"); + + b.Property("EnableTime") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("EditionId"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Content") + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Culture") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Culture"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("DisplayName"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .HasDatabaseName("IX_Tenant_Text_Template_Name"); + + b.ToTable("AbpTextTemplates", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultCultureName") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("DefaultCultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsInlineLocalized") + .HasColumnType("boolean"); + + b.Property("IsLayout") + .HasColumnType("boolean"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Layout") + .HasMaxLength(60) + .HasColumnType("character varying(60)") + .HasColumnName("Layout"); + + b.Property("LocalizationResourceName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("LocalizationResourceName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Name"); + + b.Property("RenderEngine") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("RenderEngine"); + + b.HasKey("Id"); + + b.ToTable("AbpTextTemplateDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityEnumInfo", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", "PropertyInfo") + .WithMany("Enums") + .HasForeignKey("PropertyInfoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PropertyInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "TypeInfo") + .WithMany("Properties") + .HasForeignKey("TypeInfoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") + .WithMany() + .HasForeignKey("EntityTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EntityTypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => + { + b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") + .WithMany() + .HasForeignKey("EntityTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EntityTypeInfo"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") + .WithMany() + .HasForeignKey("EditionId"); + + b.Navigation("Edition"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => + { + b.Navigation("Enums"); + }); + + modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => + { + b.Navigation("Properties"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.Configure.cs new file mode 100644 index 000000000..9317ac1a2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.Configure.cs @@ -0,0 +1,437 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.DataProtectionManagement; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Saas; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.TextTemplating; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.AntiForgery; +using Volo.Abp.Auditing; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Caching; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Features; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Identity.Localization; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.SettingManagement; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.AdminService; + +public partial class AdminServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 10; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void ConfigureTextTemplating() + { + Configure(options => + { + options.IsDynamicTemplateDefinitionStoreEnabled = true; + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.ProviderPolicies[EditionFeatureValueProvider.ProviderName] = AbpSaasPermissions.Editions.ManageFeatures; + options.ProviderPolicies[TenantFeatureValueProvider.ProviderName] = AbpSaasPermissions.Tenants.ManageFeatures; + + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.IsDynamicPermissionStoreEnabled = true; + // Rename IdentityServer.Client.ManagePermissions + // See https://github.com/abpframework/abp/blob/dev/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/AbpPermissionManagementDomainIdentityServerModule.cs + options.ProviderPolicies[ClientPermissionValueProvider.ProviderName] = "AbpOpenIddict.Applications.ManagePermissions"; + }); + } + + private void ConfigureDataProtectedManagement() + { + Configure(options => + { + //options.AddEntities(typeof(IdentityResource), new Type[] + //{ + // typeof(IdentityUser), + // typeof(IdentityRole), + // typeof(OrganizationUnit), + //}); + + //options.AddEntities(typeof(IdentityResource), new Type[] + //{ + // typeof(IdentityUser), + // typeof(IdentityRole), + // typeof(OrganizationUnit), + //}); + }); + } + + private void ConfigureSettingManagement() + { + Configure(options => + { + options.IsDynamicSettingStoreEnabled = true; + }); + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + options.AutoEventSelectors.AddNamespace("Volo.Abp.TenantManagement"); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration!); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.AdminService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get() ?? []; + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + { "AdminService", "Admin Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Admin Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + + options.Resources + .Get() + .AddVirtualJson("/Localization/Resources"); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + Configure(options => + { + options.TokenCookie.HttpOnly = false; + options.TokenCookie.SameSite = SameSiteMode.Lax; + }); + + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs new file mode 100644 index 000000000..aeb3b50fb --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs @@ -0,0 +1,157 @@ +using LINGYUN.Abp.Aliyun.SettingManagement; +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.Auditing; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.CachingManagement; +using LINGYUN.Abp.CachingManagement.StackExchangeRedis; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.DataProtectionManagement; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.FeatureManagement; +using LINGYUN.Abp.FeatureManagement.HttpApi; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.Logging.Serilog.Elasticsearch; +using LINGYUN.Abp.OssManagement.SettingManagement; +using LINGYUN.Abp.PermissionManagement; +using LINGYUN.Abp.PermissionManagement.HttpApi; +using LINGYUN.Abp.PermissionManagement.OrganizationUnits; +using LINGYUN.Abp.Saas; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.SettingManagement; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.Tencent.SettingManagement; +using LINGYUN.Abp.TextTemplating; +using LINGYUN.Abp.TextTemplating.Scriban; +using LINGYUN.Abp.WxPusher.SettingManagement; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.Data; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.Swashbuckle; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.MicroService.AdminService; + +[DependsOn( + typeof(AbpCAPEventBusModule), + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpLoggingSerilogElasticsearchModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreMvcUiMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + + // 设置管理 + typeof(AbpAliyunSettingManagementModule), + typeof(AbpTencentCloudSettingManagementModule), + // typeof(AbpWeChatSettingManagementModule), + typeof(AbpWxPusherSettingManagementModule), + typeof(AbpOssManagementSettingManagementModule), + + typeof(AbpSettingManagementApplicationModule), + typeof(AbpSettingManagementHttpApiModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpDataProtectionManagementApplicationModule), + typeof(AbpDataProtectionManagementHttpApiModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpFeatureManagementClientModule), + typeof(AbpAuditingApplicationModule), + typeof(AbpAuditingHttpApiModule), + typeof(AbpSaasApplicationModule), + typeof(AbpSaasHttpApiModule), + typeof(AbpSaasDbCheckerModule), + typeof(AbpTextTemplatingApplicationModule), + typeof(AbpTextTemplatingHttpApiModule), + typeof(AbpCachingManagementApplicationModule), + typeof(AbpCachingManagementHttpApiModule), + typeof(AbpCachingManagementStackExchangeRedisModule), + typeof(AbpPermissionManagementDomainOrganizationUnitsModule), // 组织机构权限管理 + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + + // 重写模板引擎支持外部本地化 + typeof(AbpTextTemplatingScribanModule), + + typeof(AbpIdentitySessionAspNetCoreModule), + + typeof(AdminServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpHttpClientModule), + typeof(AbpSmsPlatformModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpClaimsMappingModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAutofacModule) + )] +public partial class AdminServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigureTextTemplating(); + ConfigureSettingManagement(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureDataProtectedManagement(); + ConfigureIdentity(configuration); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); + } + + public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + await context.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/LINGYUN.Abp.MicroService.AdminService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/LINGYUN.Abp.MicroService.AdminService.csproj new file mode 100644 index 000000000..6546fa2b0 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/LINGYUN.Abp.MicroService.AdminService.csproj @@ -0,0 +1,92 @@ + + + + net9.0 + enable + enable + LINGYUN.Abp.MicroService.AdminService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Program.cs new file mode 100644 index 000000000..bcbd401f8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Program.cs @@ -0,0 +1,119 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.AdminService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Serilog; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +Log.Information("Starting AdminService Host..."); + +try +{ + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + void LogConfig(IConfiguration config, int index = 0) + { + var prefix = ""; + for (var i = 0; i < index; i++) + { + prefix = "-" + prefix; + } + var children = config.GetChildren(); + if (children.Any()) + { + foreach (var childrenConfig in children) + { + Log.Logger.Information("{prefix}Config: {key}, Value: {value}", prefix, childrenConfig.Key, childrenConfig.Value); + LogConfig(childrenConfig, index + 1); + } + } + } + + LogConfig(builder.Configuration); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "AdminService"; + options.ApplicationName = applicationName; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + // ػ + app.UseMapRequestLocalization(); + // http + app.UseCorrelationId(); + // ļϵͳ + app.MapAbpStaticAssets(); + // · + app.UseRouting(); + // + app.UseCors(); + // ֤ + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + // ⻧ + app.UseMultiTenancy(); + // Ự + app.UseAbpSession(); + // jwt + app.UseDynamicClaims(); + // Ȩ + app.UseAuthorization(); + // Swagger + app.UseSwagger(); + // Swaggerӻ + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Admin Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + // ־ + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + // · + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Properties/launchSettings.json new file mode 100644 index 000000000..577999532 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5063", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/TenantHeaderParamter.cs new file mode 100644 index 000000000..d06c39b4e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/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 LINGYUN.Abp.MicroService.AdminService; + +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 in http header", + Required = false + }); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json new file mode 100644 index 000000000..303f20166 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json @@ -0,0 +1,115 @@ +{ + "App": { + "ShowPii": true, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "AdminService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "admin", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Debug" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://elasticsearch", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.json new file mode 100644 index 000000000..b8e4da13c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.json @@ -0,0 +1,91 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.ApiGateway/ApiGatewayModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/ApiGatewayModule.cs new file mode 100644 index 000000000..abab06ca8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/ApiGatewayModule.cs @@ -0,0 +1,141 @@ +using Autofac.Core; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.WebSockets; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.ApiExploring; +using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.ApiGateway; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAutofacModule), + typeof(AbpDataModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAspNetCoreMvcWrapperModule) +)] +public class ApiGatewayModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + // 以开放端口区别 + options.SnowflakeIdOptions.WorkerId = 0; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + Configure(options => + { + options.ControllersToRemove.Add(typeof(AbpApiDefinitionController)); + options.ControllersToRemove.Add(typeof(AbpApplicationLocalizationController)); + options.ControllersToRemove.Add(typeof(AbpApplicationConfigurationController)); + options.ControllersToRemove.Add(typeof(AbpApplicationConfigurationScriptController)); + }); + + context.Services.AddAbpSwaggerGenWithOAuth( + authority: configuration["AuthServer:Authority"], + scopes: new Dictionary + { + {"Account", "Account API"}, + {"Identity", "Identity API"}, + {"IdentityServer", "Identity Server API"}, + {"BackendAdmin", "Backend Admin API"}, + {"Localization", "Localization API"}, + {"Platform", "Platform API"}, + {"RealtimeMessage", "RealtimeMessage API"}, + {"TaskManagement", "Task Management API"}, + {"Webhooks", "Webhooks API"}, + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "ApiGateway", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + }); + + context.Services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + context.Services.AddWebSockets(options => + { + + }); + context.Services.AddHttpForwarder(); + context.Services.AddTelemetryListeners(); + + context.Services + .AddReverseProxy() + .ConfigureHttpClient((context, handler) => + { + handler.ActivityHeadersPropagator = null; + }) + .LoadFromConfig(configuration.GetSection("ReverseProxy")); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Controllers/HomeController.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Controllers/HomeController.cs new file mode 100644 index 000000000..ca4b2c178 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.MicroService.ApiGateway.Controllers; + +public class HomeController : AbpControllerBase +{ + public IActionResult Index() + { + return Redirect("/swagger/index.html"); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/LINGYUN.Abp.MicroService.ApiGateway.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/LINGYUN.Abp.MicroService.ApiGateway.csproj new file mode 100644 index 000000000..b0f3acd06 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/LINGYUN.Abp.MicroService.ApiGateway.csproj @@ -0,0 +1,49 @@ + + + + Exe + net9.0 + LINGYUN.Abp.MicroService.ApiGateway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Program.cs new file mode 100644 index 000000000..8a609c39c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Program.cs @@ -0,0 +1,139 @@ +using LINGYUN.Abp.MicroService.ApiGateway; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; +using System; +using System.IO; +using System.Linq; +using Volo.Abp; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; +using Yarp.ReverseProxy.Configuration; + +Log.Information("Starting ApiGateway Host..."); + +try +{ + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + config.AddJsonFile("yarp.json", optional: true, reloadOnChange: true); + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "ApiGateway"; + options.ApplicationName = applicationName; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + if (app.Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + app.UseCorrelationId(); + app.UseCors(); + + // 认证 + app.UseAuthentication(); + // jwt + app.UseDynamicClaims(); + // 授权 + app.UseAuthorization(); + + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Open API Document"); + + var configuration = app.Services.GetRequiredService(); + var logger = app.Services.GetRequiredService>(); + var proxyConfigProvider = app.Services.GetRequiredService(); + var yarpConfig = proxyConfigProvider.GetConfig(); + + var routedClusters = yarpConfig.Clusters + .SelectMany(t => t.Destinations, + (clusterId, destination) => new { clusterId.ClusterId, destination.Value }); + + var groupedClusters = routedClusters + .GroupBy(q => q.Value.Address) + .Select(t => t.First()) + .Distinct() + .ToList(); + + foreach (var clusterGroup in groupedClusters) + { + var routeConfig = yarpConfig.Routes.FirstOrDefault(q => + q.ClusterId == clusterGroup.ClusterId); + if (routeConfig == null) + { + logger.LogWarning($"Swagger UI: Couldn't find route configuration for {clusterGroup.ClusterId}..."); + continue; + } + + if (clusterGroup.Value.Metadata != null && + clusterGroup.Value.Metadata.TryGetValue("SwaggerEndpoint", out var address) && + !address.IsNullOrWhiteSpace()) + { + options.SwaggerEndpoint($"{address}/swagger/v1/swagger.json", $"{routeConfig.RouteId} API"); + } + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]); + } + }); + + // app.UseRewriter(new RewriteOptions().AddRedirect("^(|\\|\\s+)$", "/swagger")); + + app.UseRouting(); + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseWebSockets(); + app.UseWebSocketsTelemetry(); + app.UseConfiguredEndpoints(endpoints => + { + endpoints.MapReverseProxy(); + }); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Properties/launchSettings.json new file mode 100644 index 000000000..c6a418dd1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.ApiGateway": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:60437;http://localhost:60438" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.Development.json new file mode 100644 index 000000000..249882a67 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.Development.json @@ -0,0 +1,74 @@ +{ + "App": { + "CorsOrigins": [ + "http://localhost:5666", + "http://localhost:44385", + "http://localhost:30010", + "http://localhost:30015", + "http://localhost:30020", + "http://localhost:30025", + "http://localhost:30030", + "http://localhost:30045", + "http://localhost:30050", + "http://localhost:30060" + ], + "ShowPii": true + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://localhost:9200" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Debug", + "Microsoft": "Debug", + "DotNetCore": "Warning", + "Yarp.ReverseProxy": "Debug" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.json new file mode 100644 index 000000000..893da32fd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/appsettings.json @@ -0,0 +1,80 @@ +{ + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "System": "Information", + "Microsoft": "Information", + "DotNetCore": "Information", + "Yarp.ReverseProxy": "Debug" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json new file mode 100644 index 000000000..decfd16cd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json @@ -0,0 +1,538 @@ +{ + "ReverseProxy": { + "Routes": { + "abp-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/abp/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + }, + { + "ResponseHeadersCopy": true + }, + { + "ResponseHeader": "Set-Cookie", + "Append": true + } + ] + }, + "auth-wellknown-route": { + "ClusterId": "auth-server-cluster", + "Match": { + "Path": "/.well-known/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "auth-server-route": { + "ClusterId": "auth-server-cluster", + "Match": { + "Path": "/connect/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "external-logins-route": { + "ClusterId": "auth-server-cluster", + "Match": { + "Path": "/api/account/external-logins/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "oauth-route": { + "ClusterId": "auth-server-cluster", + "Match": { + "Path": "/api/account/oauth/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "qrcode-route": { + "ClusterId": "auth-server-cluster", + "Match": { + "Path": "/api/account/qrcode/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "account-route": { + "ClusterId": "auth-server-api-cluster", + "Match": { + "Path": "/api/account/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "identity-route": { + "ClusterId": "auth-server-api-cluster", + "Match": { + "Path": "/api/identity/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "identity-server-route": { + "ClusterId": "auth-server-api-cluster", + "Match": { + "Path": "/api/identity-server/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "openiddict-route": { + "ClusterId": "auth-server-api-cluster", + "Match": { + "Path": "/api/openiddict/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "cache-management-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/caching-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "saas-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/saas/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "auditing-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/auditing/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "data-protected-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/data-protection-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "text-template-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/text-templating/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "feature-management-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/feature-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "permission-management-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/permission-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "setting-management-route": { + "ClusterId": "admin-api-cluster", + "Match": { + "Path": "/api/setting-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "localization-management-route": { + "ClusterId": "localization-api-cluster", + "Match": { + "Path": "/api/localization/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "im-route": { + "ClusterId": "messages-api-cluster", + "Match": { + "Path": "/api/im/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "notifications-route": { + "ClusterId": "messages-api-cluster", + "Match": { + "Path": "/api/notifications/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "signalr-route": { + "ClusterId": "messages-api-cluster", + "Match": { + "Path": "/signalr-hubs/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + }, + { + "RequestHeadersCopy": true + }, + { + "ResponseHeadersCopy": true + } + ] + }, + "webhooks-management-route": { + "ClusterId": "webhooks-api-cluster", + "Match": { + "Path": "/api/webhooks/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "task-management-route": { + "ClusterId": "tasks-api-cluster", + "Match": { + "Path": "/api/task-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "platform-route": { + "ClusterId": "platform-api-cluster", + "Match": { + "Path": "/api/platform/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "oss-route": { + "ClusterId": "platform-api-cluster", + "Match": { + "Path": "/api/oss-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "files-route": { + "ClusterId": "platform-api-cluster", + "Match": { + "Path": "/api/files/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, + "wechat-route": { + "ClusterId": "wechat-api-cluster", + "Match": { + "Path": "/api/wechat/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + } + }, + "Clusters": { + "auth-server-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:44385" + } + } + }, + "auth-server-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30015", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30015" + } + } + } + }, + "admin-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30010", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30010" + } + } + } + }, + "localization-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30030", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30030" + } + } + } + }, + "messages-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30020", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30020" + } + } + } + }, + "webhooks-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30045", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30045" + } + } + } + }, + "tasks-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30040", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30040" + } + } + } + }, + "platform-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30025", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30025" + } + } + } + }, + "workflow-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30050", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30050" + } + } + } + }, + "wechat-api-cluster": { + "Destinations": { + "destination1": { + "Address": "http://localhost:30060", + "Metadata": { + "SwaggerEndpoint": "http://localhost:30060" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs new file mode 100644 index 000000000..e8ba22bb0 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs @@ -0,0 +1,237 @@ +using Microsoft.Extensions.Hosting; + +var builder = DistributedApplication.CreateBuilder(args); + +// Redis +var redis = builder.AddRedis("redis") + .WithContainerName("redis") + .WithDataVolume("redis-dev"); + +// Elasticsearch +var elasticsearch = builder.AddElasticsearch("elasticsearch") + .WithContainerName("elasticsearch") + .WithDataVolume("elasticsearch-dev") + .WithEnvironment("ES_JAVA_OPTS", "-Xms2g -Xmx2g"); + +// Postgres +var postgres = builder.AddPostgres("postgres") + .WithPassword(builder.AddParameter("postgres-pwd", "123456", secret: true)) + .WithImage("postgres", "17-alpine") + .WithContainerName("postgres") + .WithDataVolume("postgres-dev"); + +var abpDb = postgres.AddDatabase("abp"); + +// RabbitMQ +var rabbitmq = builder.AddRabbitMQ("rabbitmq", + userName: builder.AddParameter("rabbitmq-username", "admin", secret: true), + password: builder.AddParameter("rabbitmq-password", "123456", secret: true)) + .WithContainerName("rabbitmq") + .WithDataVolume("rabbitmq-dev") + .WithManagementPlugin(); + +IResourceBuilder AddDotNetProject( + IDistributedApplicationBuilder builder, + string servicePrefix, + int port, + string portName, + string serviceSuffix = "Service", + string migratorSuffix = "Migrator", + IResourceBuilder? waitProject = null) + where TDbMigrator : IProjectMetadata, new() + where TProject : IProjectMetadata, new() +{ + IResourceBuilder service; + if (builder.Environment.IsDevelopment()) + { + var dbMigrator = builder + .AddProject($"{servicePrefix}{migratorSuffix}") + .WithReference(abpDb, "Default") + .WithReference(redis, "Redis") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis) + .WaitFor(abpDb) + .WithReplicas(1); + + service = builder.AddProject($"{servicePrefix}{serviceSuffix}") + .WithHttpEndpoint(port: port, name: portName) + .WithExternalHttpEndpoints() + .WithReference(abpDb, "Default") + .WithReference(redis, "Redis") + .WithReference(rabbitmq, "Rabbitmq") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis) + .WaitFor(rabbitmq) + .WaitFor(abpDb) + .WaitForCompletion(dbMigrator); + } + else + { + service = builder.AddProject($"{servicePrefix}{serviceSuffix}") + .WithHttpEndpoint(port: port, name: portName) + .WithExternalHttpEndpoints() + .WithReference(abpDb, "Default") + .WithReference(redis, "Redis") + .WithReference(rabbitmq, "Rabbitmq") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis) + .WaitFor(rabbitmq) + .WaitFor(abpDb) + .WithExplicitStart(); + } + + if (waitProject != null) + { + service.WaitFor(waitProject, WaitBehavior.WaitOnResourceUnavailable); + } + + return service; +} + +// LocalizationService +var localizationService = AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_LocalizationService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_LocalizationService>( + builder: builder, + servicePrefix: "Localization", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30030, + portName: "localization") + .WithHttpHealthCheck("/service-health"); + +// AuthServer +var authServer = AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_AuthServer_DbMigrator, + Projects.LINGYUN_Abp_MicroService_AuthServer>( + builder: builder, + servicePrefix: "Auth", + serviceSuffix: "Server", + migratorSuffix: "Migrator", + port: 44385, + portName: "auth", + waitProject: localizationService); + +// AdminService +var adminService = AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_AdminService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_AdminService>( + builder: builder, + servicePrefix: "Admin", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30010, + portName: "admin", + waitProject: authServer); + +// IdentityService +AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_AuthServer_DbMigrator, + Projects.LINGYUN_Abp_MicroService_IdentityService>( + builder: builder, + servicePrefix: "Identity", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30015, + portName: "identity", + waitProject: authServer); + +// TaskService +var taskService = AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_TaskService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_TaskService>( + builder: builder, + servicePrefix: "Task", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30040, + portName: "task", + waitProject: adminService) + .WithHttpHealthCheck("/service-health"); + +// MessageService +AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_MessageService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_MessageService>( + builder: builder, + servicePrefix: "Message", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30020, + portName: "message", + waitProject: taskService); + +// WebhookService +AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_WebhookService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_WebhookService>( + builder: builder, + servicePrefix: "Webhook", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30045, + portName: "webhook", + waitProject: taskService); + +// PlatformService +AddDotNetProject< + Projects.LINGYUN_Abp_MicroService_PlatformService_DbMigrator, + Projects.LINGYUN_Abp_MicroService_PlatformService>( + builder: builder, + servicePrefix: "Platform", + serviceSuffix: "Service", + migratorSuffix: "Migrator", + port: 30025, + portName: "platform", + waitProject: adminService); + +// WeChatService +builder.AddProject("WeChatService") + .WithHttpEndpoint(port: 30060, name: "wechat") + .WithExternalHttpEndpoints() + .WithReference(abpDb, "Default") + .WithReference(redis, "Redis") + .WithReference(rabbitmq, "Rabbitmq") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis) + .WaitFor(abpDb) + .WaitFor(rabbitmq); + +// WorkflowService +builder.AddProject("WorkflowService") + .WithHttpEndpoint(port: 30050, name: "workflow") + .WithExternalHttpEndpoints() + .WithReference(abpDb, "Default") + .WithReference(redis, "Redis") + .WithReference(rabbitmq, "Rabbitmq") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis) + .WaitFor(abpDb) + .WaitFor(rabbitmq) + .WaitFor(taskService); + +// ApiGateway +var apigateway = builder.AddProject("ApiGateway") + .WithHttpEndpoint(port: 30000, name: "gateway") + .WithExternalHttpEndpoints() + .WithReference(redis, "Redis") + .WithReference(elasticsearch, "Elasticsearch") + .WaitFor(elasticsearch) + .WaitFor(redis); + +// vben5 +builder.AddViteApp("Frontend", "../../../apps/vben5", "dev:app") + .WithHttpEndpoint(name: "frontend", env: "VITE_PORT") + .WithExternalHttpEndpoints() + .WithEnvironment("BROWSER", "none") + .WithArgs("--port", "5666") + .WithPnpm() + .WithReference(apigateway) + .WaitFor(apigateway); + +builder.Build().Run(); diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj new file mode 100644 index 000000000..013e7a8c5 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj @@ -0,0 +1,40 @@ + + + + Exe + net9.0 + enable + enable + 13c67981-84b2-4284-81fc-61ede65252c3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/Properties/launchSettings.json new file mode 100644 index 000000000..d89958c34 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/Properties/launchSettings.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17291;http://localhost:15258", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21219", + "ASPIRE_DASHBOARD_MCP_ENDPOINT_URL": "https://localhost:23177", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22076", + "OTEL_DOTNET_EXPERIMENTAL_EFCORE_ENABLE_TRACE_DB_QUERY_PARAMETERS": "true" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15258", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19236", + "ASPIRE_DASHBOARD_MCP_ENDPOINT_URL": "http://localhost:18177", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20189", + "OTEL_DOTNET_EXPERIMENTAL_EFCORE_ENABLE_TRACE_DB_QUERY_PARAMETERS": "true" + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.Development.json new file mode 100644 index 000000000..0c208ae91 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.json new file mode 100644 index 000000000..31c092aa4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorHostedService.cs new file mode 100644 index 000000000..a60c2a5a4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.AuthServer; +public class AuthServerDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public AuthServerDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorModule.cs new file mode 100644 index 000000000..1a491e8a2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/AuthServerDbMigratorModule.cs @@ -0,0 +1,11 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AuthServerMigrationsEntityFrameworkCoreModule))] +public class AuthServerDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj new file mode 100644 index 000000000..bb08747f1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj @@ -0,0 +1,42 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.AuthServer + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/Program.cs new file mode 100644 index 000000000..71a783367 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/Program.cs @@ -0,0 +1,43 @@ +using LINGYUN.Abp.MicroService.AuthServer; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.AuthServer", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.AuthServer", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs new file mode 100644 index 000000000..249ddefb4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs @@ -0,0 +1,132 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; +using IdentityPermissions = Volo.Abp.Identity.IdentityPermissions; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +public class AuthServerDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase +{ + protected IGuidGenerator GuidGenerator { get; } + protected IdentityUserManager IdentityUserManager { get; } + protected IdentityRoleManager IdentityRoleManager { get; } + protected IPermissionDataSeeder PermissionDataSeeder { get; } + + public AuthServerDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + IGuidGenerator guidGenerator, + IdentityUserManager identityUserManager, + IdentityRoleManager identityRoleManager, + IPermissionDataSeeder permissionDataSeeder) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + GuidGenerator = guidGenerator; + IdentityUserManager = identityUserManager; + IdentityRoleManager = identityRoleManager; + PermissionDataSeeder = permissionDataSeeder; + } + + protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) + { + if (!schemaMigrated) + { + return; + } + + using (CurrentTenant.Change(eventData.Id)) + { + await SeedTenantDefaultRoleAsync(eventData); + await SeedTenantAdminAsync(eventData); + } + } + + protected async virtual Task SeedTenantDefaultRoleAsync(TenantCreatedEto eventData) + { + // 默认用户 + var roleId = GuidGenerator.Create(); + var defaultRole = new IdentityRole(roleId, "Users", eventData.Id) + { + IsStatic = true, + IsPublic = true, + IsDefault = true, + }; + (await IdentityRoleManager.CreateAsync(defaultRole)).CheckErrors(); + + // 所有用户都应该具有查询用户权限, 用于IM场景 + await PermissionDataSeeder.SeedAsync( + RolePermissionValueProvider.ProviderName, + defaultRole.Name, + new string[] + { + IdentityPermissions.UserLookup.Default, + IdentityPermissions.Users.Default + }, + tenantId: eventData.Id); + } + + protected async virtual Task SeedTenantAdminAsync(TenantCreatedEto eventData) + { + const string tenantAdminUserName = "admin"; + const string tenantAdminRoleName = "admin"; + Guid tenantAdminRoleId; + if (!await IdentityRoleManager.RoleExistsAsync(tenantAdminRoleName)) + { + tenantAdminRoleId = GuidGenerator.Create(); + var tenantAdminRole = new IdentityRole(tenantAdminRoleId, tenantAdminRoleName, eventData.Id) + { + IsStatic = true, + IsPublic = true + }; + (await IdentityRoleManager.CreateAsync(tenantAdminRole)).CheckErrors(); + } + else + { + var tenantAdminRole = await IdentityRoleManager.FindByNameAsync(tenantAdminRoleName); + tenantAdminRoleId = tenantAdminRole.Id; + } + + var adminUserId = GuidGenerator.Create(); + if (eventData.Properties.TryGetValue("AdminUserId", out var userIdString) && + Guid.TryParse(userIdString, out var adminUserGuid)) + { + adminUserId = adminUserGuid; + } + var adminEmailAddress = eventData.Properties.GetOrDefault("AdminEmail") ?? "admin@abp.io"; + var adminPassword = eventData.Properties.GetOrDefault("AdminPassword") ?? "1q2w3E*"; + + var tenantAdminUser = await IdentityUserManager.FindByNameAsync(adminEmailAddress); + if (tenantAdminUser == null) + { + tenantAdminUser = new IdentityUser( + adminUserId, + tenantAdminUserName, + adminEmailAddress, + eventData.Id); + + tenantAdminUser.AddRole(tenantAdminRoleId); + + // 创建租户管理用户 + (await IdentityUserManager.CreateAsync(tenantAdminUser)).CheckErrors(); + (await IdentityUserManager.AddPasswordAsync(tenantAdminUser, adminPassword)).CheckErrors(); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs new file mode 100644 index 000000000..f7ff2434d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs @@ -0,0 +1,31 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Saas.Tenants; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +public class AuthServerDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public AuthServerDbMigrationService( + IDataSeeder dataSeeder, + IDbSchemaMigrator dbSchemaMigrator, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContext.cs new file mode 100644 index 000000000..f38674d4a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContext.cs @@ -0,0 +1,63 @@ +using LINGYUN.Abp.Gdpr; +using LINGYUN.Abp.Gdpr.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Authorizations; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.OpenIddict.Tokens; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +[ConnectionStringName("Default")] +public class AuthServerMigrationsDbContext : + AbpDbContext, + IIdentityDbContext, + IOpenIddictDbContext, + IGdprDbContext +{ + public DbSet Requests { get; set; } + + public DbSet Applications { get; set; } + + public DbSet Authorizations { get; set; } + + public DbSet Scopes { get; set; } + + public DbSet Tokens { get; set; } + + public DbSet Users { get; set; } + + public DbSet Roles { get; set; } + + public DbSet ClaimTypes { get; set; } + + public DbSet OrganizationUnits { get; set; } + + public DbSet SecurityLogs { get; set; } + + public DbSet LinkUsers { get; set; } + + public DbSet UserDelegations { get; set; } + + public DbSet Sessions { get; set; } + + public AuthServerMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureIdentity(); + modelBuilder.ConfigureOpenIddict(); + modelBuilder.ConfigureGdpr(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContextFactory.cs new file mode 100644 index 000000000..2dc16a429 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsDbContextFactory.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +public class AuthServerMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public AuthServerMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new AuthServerMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.AuthServer.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..9ecc1a3c6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,53 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Gdpr.EntityFrameworkCore; +using LINGYUN.Abp.Identity.EntityFrameworkCore; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using LINGYUN.Platform.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.Authorization; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +[DependsOn( + typeof(AbpAuthorizationModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpGdprEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpTextTemplatingEntityFrameworkCoreModule), + typeof(PlatformEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpDataDbMigratorModule) + )] +public class AuthServerMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore.csproj new file mode 100644 index 000000000..679008143 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore.csproj @@ -0,0 +1,36 @@ + + + + + + + false + net9.0 + LINGYUN.Abp.MicroService.AuthServer + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.Designer.cs new file mode 100644 index 000000000..424ab20ad --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.Designer.cs @@ -0,0 +1,1248 @@ +// +using System; +using LINGYUN.Abp.MicroService.AuthServer; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AuthServer.Migrations +{ + [DbContext(typeof(AuthServerMigrationsDbContext))] + [Migration("20260105085302_Initial_Auth_Server")] + partial class Initial_Auth_Server + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Data") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Data"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Provider"); + + b.Property("RequestId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RequestId"); + + b.ToTable("AbpGdprInfos", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprRequest", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("ReadyTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpGdprRequests", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp with time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprInfo", b => + { + b.HasOne("LINGYUN.Abp.Gdpr.GdprRequest", null) + .WithMany("Infos") + .HasForeignKey("RequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprRequest", b => + { + b.Navigation("Infos"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.cs new file mode 100644 index 000000000..3df6ef9f9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/20260105085302_Initial_Auth_Server.cs @@ -0,0 +1,739 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AuthServer.Migrations +{ + /// + public partial class Initial_Auth_Server : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Regex = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "integer", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpGdprRequests", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + ReadyTime = table.Column(type: "timestamp with time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpGdprRequests", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SourceUserId = table.Column(type: "uuid", nullable: false), + SourceTenantId = table.Column(type: "uuid", nullable: true), + TargetUserId = table.Column(type: "uuid", nullable: false), + TargetTenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + Code = table.Column(type: "character varying(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SessionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + SignedIn = table.Column(type: "timestamp with time zone", nullable: false), + LastAccessed = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SourceUserId = table.Column(type: "uuid", nullable: false), + TargetUserId = table.Column(type: "uuid", nullable: false), + StartTime = table.Column(type: "timestamp with time zone", nullable: false), + EndTime = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "boolean", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + IsActive = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "integer", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + LastPasswordChangeTime = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "text", nullable: true), + ClientType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + JsonWebKeySet = table.Column(type: "text", nullable: true), + Permissions = table.Column(type: "text", nullable: true), + PostLogoutRedirectUris = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedirectUris = table.Column(type: "text", nullable: true), + Requirements = table.Column(type: "text", nullable: true), + Settings = table.Column(type: "text", nullable: true), + ClientUri = table.Column(type: "text", nullable: true), + LogoUri = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + Descriptions = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "text", nullable: true), + Resources = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpGdprInfos", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RequestId = table.Column(type: "uuid", nullable: false), + Data = table.Column(type: "text", nullable: false), + Provider = table.Column(type: "character varying(256)", maxLength: 256, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpGdprInfos", x => x.Id); + table.ForeignKey( + name: "FK_AbpGdprInfos_AbpGdprRequests_RequestId", + column: x => x.RequestId, + principalTable: "AbpGdprRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ProviderKey = table.Column(type: "character varying(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: true), + Properties = table.Column(type: "text", nullable: true), + Scopes = table.Column(type: "text", nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_Application~", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + AuthorizationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp with time zone", nullable: true), + Payload = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedemptionDate = table.Column(type: "timestamp with time zone", nullable: true), + ReferenceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpGdprInfos_RequestId", + table: "AbpGdprInfos", + column: "RequestId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpGdprRequests_UserId", + table: "AbpGdprRequests", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Targe~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpGdprInfos"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpGdprRequests"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/AuthServerMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/AuthServerMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..a26b9a1b4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/Migrations/AuthServerMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,1245 @@ +// +using System; +using LINGYUN.Abp.MicroService.AuthServer; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AuthServer.Migrations +{ + [DbContext(typeof(AuthServerMigrationsDbContext))] + partial class AuthServerMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprInfo", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Data") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Data"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Provider"); + + b.Property("RequestId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RequestId"); + + b.ToTable("AbpGdprInfos", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprRequest", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("ReadyTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpGdprRequests", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp with time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprInfo", b => + { + b.HasOne("LINGYUN.Abp.Gdpr.GdprRequest", null) + .WithMany("Infos") + .HasForeignKey("RequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Gdpr.GdprRequest", b => + { + b.Navigation("Infos"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.Configure.cs new file mode 100644 index 000000000..74e0660f3 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.Configure.cs @@ -0,0 +1,475 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.AspNetCore.MultiTenancy; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.MicroService.AuthServer.Ui.Branding; +using LINGYUN.Abp.OpenIddict.AspNetCore.Session; +using LINGYUN.Abp.OpenIddict.LinkUser; +using LINGYUN.Abp.OpenIddict.Portal; +using LINGYUN.Abp.OpenIddict.Sms; +using LINGYUN.Abp.OpenIddict.WeChat; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.WeChat.Work; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using OpenIddict.Server; +using OpenIddict.Server.AspNetCore; +using OpenIddict.Validation.AspNetCore; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.BlobStoring; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.OpenIddict.WildcardDomains; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.SettingManagement; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +public partial class AuthServerModule +{ + private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 1; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureAuthServer() + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + //options.AddAudiences("lingyun-abp-application"); + + options.UseLocalServer(); + + options.UseAspNetCore(); + + options.UseDataProtection(); + }); + }); + } + + private void PreConfigureCertificate(IConfiguration configuration, IWebHostEnvironment environment) + { + if (!environment.IsDevelopment()) + { + PreConfigure(options => + { + options.AddDevelopmentEncryptionAndSigningCertificate = false; + }); + + PreConfigure(builder => + { + builder.AddProductionEncryptionAndSigningCertificate(configuration["App:SslFile"], configuration["App:SslPassword"]); + }); + } + + PreConfigure(builder => + { + // builder.UseDataProtection(); + + // 禁用https + builder.UseAspNetCore() + .DisableTransportSecurityRequirement(); + }); + + var wildcardDomains = configuration.GetSection("App:WildcardDomains").Get>(); + if (wildcardDomains?.Count > 0) + { + PreConfigure(options => + { + options.EnableWildcardDomainSupport = true; + options.WildcardDomainsFormat.AddIfNotContains(wildcardDomains); + }); + } + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureDataSeeder() + { + + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureSettingManagement() + { + Configure(options => + { + options.IsDynamicSettingStoreEnabled = true; + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureBranding(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("App:Branding").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + private void ConfigureIdentity(IConfiguration configuration) + { + // 增加配置文件定义,在新建租户时需要 + Configure(options => + { + var identityConfiguration = configuration.GetSection("Identity"); + if (identityConfiguration.Exists()) + { + identityConfiguration.Bind(options); + } + }); + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.IsRemoteRefreshEnabled = false; + }); + + 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 ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.AuthServer"); + }); + } + private void ConfigureLocalization() + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // options.IsEnabledForGetRequests = true; + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + var applicationConfiguration = configuration.GetSection("App:Urls:Applications"); + foreach (var appConfig in applicationConfiguration.GetChildren()) + { + options.Applications[appConfig.Key].RootUrl = appConfig["RootUrl"]; + foreach (var urlsConfig in appConfig.GetSection("Urls").GetChildren()) + { + options.Applications[appConfig.Key].Urls[urlsConfig.Key] = urlsConfig.Value; + } + } + }); + } + + private void ConfigureAuthServer(IConfiguration configuration) + { + Configure(builder => + { + builder.DisableTransportSecurityRequirement(); + }); + + Configure(options => + { + options.DisableTransportSecurityRequirement = true; + }); + + Configure(options => + { + var lifetime = configuration.GetSection("OpenIddict:Lifetime"); + options.AuthorizationCodeLifetime = lifetime.GetValue("AuthorizationCode", options.AuthorizationCodeLifetime); + options.AccessTokenLifetime = lifetime.GetValue("AccessToken", options.AccessTokenLifetime); + options.DeviceCodeLifetime = lifetime.GetValue("DeviceCode", options.DeviceCodeLifetime); + options.IdentityTokenLifetime = lifetime.GetValue("IdentityToken", options.IdentityTokenLifetime); + options.RefreshTokenLifetime = lifetime.GetValue("RefreshToken", options.RefreshTokenLifetime); + options.RefreshTokenReuseLeeway = lifetime.GetValue("RefreshTokenReuseLeeway", options.RefreshTokenReuseLeeway); + options.UserCodeLifetime = lifetime.GetValue("UserCode", options.UserCodeLifetime); + }); + } + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + + services + .AddAuthentication() + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => + { + options.ExpireTimeSpan = TimeSpan.FromDays(365); + }) + .AddJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + }); + //.AddWeChatWork(options => + //{ + // options.SignInScheme = IdentityConstants.ExternalScheme; + //}); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + + services.AddSameSiteCookiePolicy(); + } + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddOnlyDomainTenantResolver(domain); + } + }); + } + } + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void PreConfigureWrapper() + { + PreConfigure(options => + { + // http服务间调用发送不需要包装结果的请求头 + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs new file mode 100644 index 000000000..88ae4db6e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs @@ -0,0 +1,134 @@ +using LINGYUN.Abp.Account; +using LINGYUN.Abp.Account.Web.OAuth; +using LINGYUN.Abp.Account.Web.OpenIddict; +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.MultiTenancy; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.BlobStoring.OssManagement; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.Exporter.MiniExcel; +using LINGYUN.Abp.Gdpr; +using LINGYUN.Abp.Gdpr.Web; +using LINGYUN.Abp.Identity.AspNetCore.Session; +using LINGYUN.Abp.Identity.OrganizaztionUnits; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.OpenIddict.AspNetCore.Session; +using LINGYUN.Abp.OpenIddict.LinkUser; +using LINGYUN.Abp.OpenIddict.Portal; +using LINGYUN.Abp.OpenIddict.Sms; +using LINGYUN.Abp.OpenIddict.WeChat; +using LINGYUN.Abp.OpenIddict.WeChat.Work; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.MicroService.AuthServer; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAccountApplicationModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAccountWebOAuthModule), + typeof(AbpBlobStoringOssManagementModule), + typeof(AbpGdprApplicationModule), + typeof(AbpGdprHttpApiModule), + typeof(AbpGdprWebModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAutofacModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpIdentityAspNetCoreSessionModule), + typeof(AbpOpenIddictAspNetCoreSessionModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpOpenIddictSmsModule), + typeof(AbpOpenIddictWeChatModule), + typeof(AbpOpenIddictLinkUserModule), + typeof(AbpOpenIddictPortalModule), + typeof(AbpOpenIddictWeChatWorkModule), + typeof(AbpIdentityOrganizaztionUnitsModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AuthServerMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpAuditLoggingElasticsearchModule), // 放在 AbpIdentity 模块之后,避免被覆盖 + typeof(AbpLocalizationCultureMapModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpExporterMiniExcelModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpSmsPlatformModule), + typeof(AbpCAPEventBusModule) + )] +public partial class AuthServerModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureAuthServer(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureCertificate(configuration, hostingEnvironment); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureBranding(configuration); + ConfigureCaching(configuration); + ConfigureIdentity(configuration); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigureSettingManagement(); + ConfigurePermissionManagement(); + ConfigureLocalization(); + ConfigureDataSeeder(); + ConfigureUrls(configuration); + ConfigureTiming(configuration); + ConfigureAuditing(configuration); + ConfigureAuthServer(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); + } + + public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + await context.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs new file mode 100644 index 000000000..b1348bf39 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs @@ -0,0 +1,309 @@ +using Microsoft.Extensions.Configuration; +using OpenIddict.Abstractions; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; + +namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeder; + +public class AuthServerDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public static HashSet InitializeScopes = new HashSet + { + // obsolete! microservice should be allocated separately + "lingyun-abp-application", + // admin service + "ams", + // identity service + "ids", + // localization service + "lts", + // platform service + "pts", + // message service + "mgs", + // task service + "tks", + // webhook service + "wks", + // workflow service + "wfs", + // wechat service + "was" + }; + + private readonly IConfiguration _configuration; + private readonly ICurrentTenant _currentTenant; + private readonly IOpenIddictApplicationManager _applicationManager; + private readonly IOpenIddictApplicationRepository _applicationRepository; + + private readonly IPermissionDataSeeder _permissionDataSeeder; + + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IOpenIddictScopeRepository _scopeRepository; + + public AuthServerDataSeedContributor( + IConfiguration configuration, + ICurrentTenant currentTenant, + IOpenIddictScopeManager scopeManager, + IOpenIddictScopeRepository scopeRepository, + IPermissionDataSeeder permissionDataSeeder, + IOpenIddictApplicationManager applicationManager, + IOpenIddictApplicationRepository applicationRepository) + { + _configuration = configuration; + _currentTenant = currentTenant; + _scopeManager = scopeManager; + _scopeRepository = scopeRepository; + _permissionDataSeeder = permissionDataSeeder; + _applicationManager = applicationManager; + _applicationRepository = applicationRepository; + } + + public async Task SeedAsync(DataSeedContext context) + { + using (_currentTenant.Change(context.TenantId)) + { + await CreateScopeAsync(InitializeScopes); + + await CreateApplicationAsync(InitializeScopes); + } + } + + private async Task CreateScopeAsync(IEnumerable scopes) + { + foreach (var scope in scopes) + { + if (await _scopeRepository.FindByNameAsync(scope) == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor() + { + Name = scope, + DisplayName = scope + " access", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问", + [CultureInfo.GetCultureInfo("en")] = "Abp API Application Access" + }, + Resources = + { + scope + } + }); + } + } + } + + private async Task CreateApplicationAsync(IEnumerable scopes) + { + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + var vueClientId = configurationSection["VueAdmin:ClientId"]; + if (!vueClientId.IsNullOrWhiteSpace()) + { + var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/'); + + if (await _applicationRepository.FindByClientIdAsync(vueClientId) == null) + { + var application = new OpenIddictApplicationDescriptor + { + ClientId = vueClientId, + ClientSecret = configurationSection["VueAdmin:ClientSecret"], + ApplicationType = OpenIddictConstants.ApplicationTypes.Web, + ConsentType = OpenIddictConstants.ConsentTypes.Explicit, + DisplayName = "Abp Vue Admin Client", + PostLogoutRedirectUris = + { + new Uri(vueClientRootUrl + "signout-callback"), + new Uri(vueClientRootUrl) + }, + RedirectUris = + { + new Uri(vueClientRootUrl + "signin-callback"), + new Uri(vueClientRootUrl) + }, + Permissions = + { + OpenIddictConstants.Permissions.Endpoints.Authorization, + OpenIddictConstants.Permissions.Endpoints.Token, + OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, + OpenIddictConstants.Permissions.Endpoints.Introspection, + OpenIddictConstants.Permissions.Endpoints.Revocation, + OpenIddictConstants.Permissions.Endpoints.EndSession, + + OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, + OpenIddictConstants.Permissions.GrantTypes.Implicit, + OpenIddictConstants.Permissions.GrantTypes.Password, + OpenIddictConstants.Permissions.GrantTypes.RefreshToken, + OpenIddictConstants.Permissions.GrantTypes.DeviceCode, + OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, + + OpenIddictConstants.Permissions.ResponseTypes.Code, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeToken, + OpenIddictConstants.Permissions.ResponseTypes.IdToken, + OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.None, + OpenIddictConstants.Permissions.ResponseTypes.Token, + + OpenIddictConstants.Permissions.Scopes.Roles, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Phone, + } + }; + foreach (var scope in scopes) + { + application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + + await _applicationManager.CreateAsync(application); + + var vueClientPermissions = new string[1] + { + "AbpIdentity.UserLookup" + }; + await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions); + } + } + + var internalServiceClientId = configurationSection["InternalService:ClientId"]; + if (!internalServiceClientId.IsNullOrWhiteSpace()) + { + if (await _applicationRepository.FindByClientIdAsync(internalServiceClientId) == null) + { + var application = new OpenIddictApplicationDescriptor + { + ClientId = internalServiceClientId, + ClientSecret = configurationSection["InternalService:ClientSecret"], + ClientType = OpenIddictConstants.ClientTypes.Confidential, + ConsentType = OpenIddictConstants.ConsentTypes.Explicit, + ApplicationType = OpenIddictConstants.ApplicationTypes.Native, + DisplayName = "Abp Vue Admin Client", + Permissions = + { + OpenIddictConstants.Permissions.Endpoints.Authorization, + OpenIddictConstants.Permissions.Endpoints.Token, + OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, + OpenIddictConstants.Permissions.Endpoints.Introspection, + OpenIddictConstants.Permissions.Endpoints.Revocation, + OpenIddictConstants.Permissions.Endpoints.EndSession, + + OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, + OpenIddictConstants.Permissions.GrantTypes.Implicit, + OpenIddictConstants.Permissions.GrantTypes.Password, + OpenIddictConstants.Permissions.GrantTypes.RefreshToken, + OpenIddictConstants.Permissions.GrantTypes.DeviceCode, + OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, + + OpenIddictConstants.Permissions.ResponseTypes.Code, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeToken, + OpenIddictConstants.Permissions.ResponseTypes.IdToken, + OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.None, + OpenIddictConstants.Permissions.ResponseTypes.Token, + + OpenIddictConstants.Permissions.Scopes.Roles, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Phone, + } + }; + foreach (var scope in scopes) + { + application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + + await _applicationManager.CreateAsync(application); + + var internalServicePermissions = new string[2] + { + "AbpIdentity.UserLookup","AbpIdentity.Users" + }; + await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, internalServiceClientId, internalServicePermissions); + } + } + + var oauthClientId = configurationSection["VueOAuthClient:ClientId"]; + if (!oauthClientId.IsNullOrWhiteSpace()) + { + var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get>(); + + if (await _applicationRepository.FindByClientIdAsync(oauthClientId) == null) + { + var application = new OpenIddictApplicationDescriptor + { + ClientId = oauthClientId, + ClientSecret = null, + ApplicationType = OpenIddictConstants.ApplicationTypes.Web, + ConsentType = OpenIddictConstants.ConsentTypes.Implicit, + DisplayName = "OAuth Client", + PostLogoutRedirectUris = { }, + RedirectUris = { }, + Permissions = + { + OpenIddictConstants.Permissions.Endpoints.Authorization, + OpenIddictConstants.Permissions.Endpoints.Token, + OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, + OpenIddictConstants.Permissions.Endpoints.Introspection, + OpenIddictConstants.Permissions.Endpoints.Revocation, + OpenIddictConstants.Permissions.Endpoints.EndSession, + + OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, + OpenIddictConstants.Permissions.GrantTypes.RefreshToken, + + OpenIddictConstants.Permissions.ResponseTypes.Code, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.CodeToken, + OpenIddictConstants.Permissions.ResponseTypes.IdToken, + OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, + OpenIddictConstants.Permissions.ResponseTypes.None, + OpenIddictConstants.Permissions.ResponseTypes.Token, + + OpenIddictConstants.Permissions.Scopes.Roles, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Phone, + } + }; + foreach (var scope in scopes) + { + application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + + oauthClientRootUrls.ForEach(url => + { + application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/'))); + application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signout-callback")); + + application.RedirectUris.AddIfNotContains(new Uri(url)); + application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signin-callback")); + application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html")); + }); + + await _applicationManager.CreateAsync(application); + + var oauthClientPermissions = new string[1] + { + "AbpIdentity.UserLookup" + }; + await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions); + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj new file mode 100644 index 000000000..e09b3509a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj @@ -0,0 +1,98 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.AuthServer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MSBuildProjectDirectory)\package.json + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs new file mode 100644 index 000000000..3b0c754a5 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs @@ -0,0 +1,70 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class SameSiteCookiesServiceCollectionExtensions + { + public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services) + { + services.Configure(options => + { + options.MinimumSameSitePolicy = SameSiteMode.Unspecified; + options.OnAppendCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + options.OnDeleteCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + }); + + return services; + } + + private static void CheckSameSite(HttpContext httpContext, CookieOptions options) + { + if (options.SameSite == SameSiteMode.None) + { + var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); + if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent)) + { + // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1) + options.SameSite = SameSiteMode.Unspecified; + } + } + } + + private static bool DisallowsSameSiteNone(string userAgent) + { + // Cover all iOS based browsers here. This includes: + // - Safari on iOS 12 for iPhone, iPod Touch, iPad + // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad + // - Chrome on iOS 12 for iPhone, iPod Touch, iPad + // All of which are broken by SameSite=None, because they use the iOS networking stack + if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12")) + { + return true; + } + + // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes: + // - Safari on Mac OS X. + // This does not include: + // - Chrome on Mac OS X + // Because they do not use the Mac OS networking stack. + if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") && + userAgent.Contains("Version/") && userAgent.Contains("Safari")) + { + return true; + } + + // Cover Chrome 50-69, because some versions are broken by SameSite=None, + // and none in this range require it. + // Note: this covers some pre-Chromium Edge versions, + // but pre-Chromium Edge does not require SameSite=None. + if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6")) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml new file mode 100644 index 000000000..e7d74e8c0 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml @@ -0,0 +1,34 @@ +@page +@using LINGYUN.Abp.MicroService.AuthServer.Pages +@using Volo.Abp.Users +@model IndexModel +@inject ICurrentUser CurrentUser +@if (CurrentUser.IsAuthenticated) +{ +
+ + + + Logout + + +

@CurrentUser.UserName

+
@CurrentUser.Email
+
+ Roles: @CurrentUser.Roles.JoinAsString(", ") +
+ Claims:
+ @Html.Raw(CurrentUser.GetAllClaims().Select(c => $"{c.Type}={c.Value}").JoinAsString("
")) +
+
+
+
+} + +@if (!CurrentUser.IsAuthenticated) +{ +
+

+ Login +
+} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml.cs new file mode 100644 index 000000000..b96b2a1c7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/Index.cshtml.cs @@ -0,0 +1,10 @@ +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace LINGYUN.Abp.MicroService.AuthServer.Pages; + +public class IndexModel : AbpPageModel +{ + public void OnGet() + { + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/_ViewImports.cshtml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/_ViewImports.cshtml new file mode 100644 index 000000000..c1da1f5f1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Program.cs new file mode 100644 index 000000000..31b3ae68e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Program.cs @@ -0,0 +1,95 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.AuthServer; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting AuthServer Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "AuthServer"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + app.UseMapRequestLocalization(); + if (app.Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + // app.UseErrorPage(); + app.UseHsts(); + } + // app.UseHttpsRedirection(); + app.UseCookiePolicy(); + app.UseCorrelationId(); + app.MapAbpStaticAssets(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + app.UseMultiTenancy(); + app.UseAbpSession(); + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Properties/launchSettings.json new file mode 100644 index 000000000..43389a5dc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.AuthServer": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:52861;http://localhost:52862" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingOptions.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingOptions.cs new file mode 100644 index 000000000..0f0c24934 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingOptions.cs @@ -0,0 +1,10 @@ +namespace LINGYUN.Abp.MicroService.AuthServer.Ui.Branding; + +public class AccountBrandingOptions +{ + public string AppName { get; set; } + + public string LogoUrl { get; set; } + + public string LogoReverseUrl { get; set; } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingProvider.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingProvider.cs new file mode 100644 index 000000000..ebc06c8d1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/Ui/Branding/AccountBrandingProvider.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace LINGYUN.Abp.MicroService.AuthServer.Ui.Branding; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IBrandingProvider), typeof(AccountBrandingProvider))] +public class AccountBrandingProvider : IBrandingProvider, ITransientDependency +{ + private readonly AccountBrandingOptions _options; + + public AccountBrandingProvider(IOptions options) + { + _options = options.Value; + } + + public string AppName => _options.AppName ?? "MyApplication"; + + public string LogoUrl => _options.LogoUrl; + + public string LogoReverseUrl => _options.LogoReverseUrl; +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json new file mode 100644 index 000000000..e83c6e815 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json @@ -0,0 +1,185 @@ +{ + "App": { + "CorsOrigins": [ + "http://localhost:5666", + "http://localhost:30000", + "http://localhost:30010", + "http://localhost:30015", + "http://localhost:30020", + "http://localhost:30025", + "http://localhost:30030", + "http://localhost:30040", + "http://localhost:30045", + "http://localhost:30050", + "http://localhost:30060" + ], + "Urls": { + "Applications": { + "MVC": { + "RootUrl": "http://localhost:44385/", + "Urls": { + "Abp.Account.EmailConfirm": "Account/EmailConfirm", + "Abp.Account.EmailVerifyLogin": "Account/VerifyCode" + } + }, + "STS": { + "RootUrl": "http://localhost:44385/" + }, + "VueVbenAdmin": { + "RootUrl": "http://localhost:5666/", + "Urls": { + "Abp.Account.EmailConfirm": "account/email-confirm", + "Abp.Account.EmailVerifyLogin": "account/verify-code" + } + } + } + } + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "AuthServer", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "auth", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false + }, + "OpenIddict": { + "Applications": { + "VueAdmin": { + "ClientId": "vue-admin-client", + "ClientSecret": "1q2w3e*", + "RootUrl": "http://localhost:5666/" + }, + "InternalService": { + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3e*" + }, + "VueOAuthClient": { + "ClientId": "vue-oauth-client", + "RootUrls": [ + "http://localhost:5666", + "http://localhost:30010", + "http://localhost:30015", + "http://localhost:30020", + "http://localhost:30025", + "http://localhost:30030", + "http://localhost:30040", + "http://localhost:30045", + "http://localhost:30050", + "http://localhost:30060" + ] + } + } + }, + "Identity": { + "Password": { + "RequiredLength": 6, + "RequiredUniqueChars": 0, + "RequireNonAlphanumeric": false, + "RequireLowercase": false, + "RequireUppercase": false, + "RequireDigit": false + }, + "Lockout": { + "AllowedForNewUsers": false, + "LockoutDuration": 5, + "MaxFailedAccessAttempts": 5 + }, + "SignIn": { + "RequireConfirmedEmail": false, + "RequireConfirmedPhoneNumber": false + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://localhost:9200" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.json new file mode 100644 index 000000000..f76197991 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.json @@ -0,0 +1,101 @@ +{ + "App": { + "Branding": { + "AppName": "Auth Server" + }, + "SslFile": "openiddict.pfx", + "SslPassword": "e1c48393-0c43-11f0-9582-4aecacda42db" + }, + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json new file mode 100644 index 000000000..4adab4c7f --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json @@ -0,0 +1,9 @@ +{ + "version": "9.3.6", + "name": "my-app-authserver", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.3.6", + "@abp/qrcode": "9.3.6" + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Handlers/IdentitySessionAccessEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Handlers/IdentitySessionAccessEventHandler.cs new file mode 100644 index 000000000..fe3fb7f87 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Handlers/IdentitySessionAccessEventHandler.cs @@ -0,0 +1,164 @@ +using LINGYUN.Abp.Identity; +using LINGYUN.Abp.Identity.Session; +using LINGYUN.Abp.Identity.Settings; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Settings; +using Volo.Abp.Uow; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.IdentityService.Handlers; +/// +/// 会话控制事件处理器 +/// +public class IdentitySessionAccessEventHandler : + IDistributedEventHandler, + IDistributedEventHandler>, + IDistributedEventHandler>, + ITransientDependency +{ + public ILogger Logger { protected get; set; } + protected ISettingProvider SettingProvider { get; } + protected IAbpDistributedLock DistributedLock { get; } + protected IIdentitySessionCache IdentitySessionCache { get; } + protected IIdentitySessionStore IdentitySessionStore { get; } + + public IdentitySessionAccessEventHandler( + ISettingProvider settingProvider, + IAbpDistributedLock distributedLock, + IIdentitySessionCache identitySessionCache, + IIdentitySessionStore identitySessionStore) + { + SettingProvider = settingProvider; + DistributedLock = distributedLock; + IdentitySessionCache = identitySessionCache; + IdentitySessionStore = identitySessionStore; + + Logger = NullLogger.Instance; + } + + [UnitOfWork] + public async virtual Task HandleEventAsync(EntityCreatedEto eventData) + { + // 新会话创建时检查登录策略 + var lockKey = $"{nameof(IdentitySessionAccessEventHandler)}_{nameof(EntityCreatedEto)}"; + await using (var handle = await DistributedLock.TryAcquireAsync(lockKey)) + { + Logger.LogInformation($"Lock is acquired for {lockKey}"); + + if (handle == null) + { + Logger.LogInformation($"Handle is null because of the locking for : {lockKey}"); + return; + } + + await CheckConcurrentLoginStrategy(eventData.Entity); + } + } + + [UnitOfWork] + public async virtual Task HandleEventAsync(EntityDeletedEto eventData) + { + // 用户被删除, 移除所有会话 + var lockKey = $"{nameof(IdentitySessionAccessEventHandler)}_{nameof(EntityDeletedEto)}"; + await using (var handle = await DistributedLock.TryAcquireAsync(lockKey)) + { + Logger.LogInformation($"Lock is acquired for {lockKey}"); + + if (handle == null) + { + Logger.LogInformation($"Handle is null because of the locking for : {lockKey}"); + return; + } + + await IdentitySessionStore.RevokeAllAsync(eventData.Entity.Id); + } + } + + [UnitOfWork] + public async virtual Task HandleEventAsync(IdentitySessionChangeAccessedEvent eventData) + { + // 会话访问更新 + var lockKey = $"{nameof(IdentitySessionAccessEventHandler)}_{nameof(IdentitySessionChangeAccessedEvent)}"; + await using (var handle = await DistributedLock.TryAcquireAsync(lockKey)) + { + Logger.LogInformation($"Lock is acquired for {lockKey}"); + + if (handle == null) + { + Logger.LogInformation($"Handle is null because of the locking for : {lockKey}"); + return; + } + + var idetitySession = await IdentitySessionStore.FindAsync(eventData.SessionId); + if (idetitySession != null) + { + if (!eventData.IpAddresses.IsNullOrWhiteSpace()) + { + idetitySession.SetIpAddresses(eventData.IpAddresses.Split(",")); + } + idetitySession.UpdateLastAccessedTime(eventData.LastAccessed); + + await IdentitySessionStore.UpdateAsync(idetitySession); + } + else + { + // 数据库中不存在会话, 清理缓存, 后续请求会话失效 + await IdentitySessionCache.RemoveAsync(eventData.SessionId); + } + } + } + + protected async virtual Task CheckConcurrentLoginStrategy(IdentitySessionEto session) + { + // 创建一个会话后根据策略使其他会话失效 + var strategySet = await SettingProvider.GetOrNullAsync(IdentitySettingNames.Session.ConcurrentLoginStrategy); + + Logger.LogDebug($"The concurrent login strategy is: {strategySet}"); + + if (!strategySet.IsNullOrWhiteSpace() && Enum.TryParse(strategySet, true, out var strategy)) + { + switch (strategy) + { + // 限制用户相同设备 + case ConcurrentLoginStrategy.LogoutFromSameTypeDevicesLimit: + + var sameTypeDevicesCountSet = await SettingProvider.GetAsync(IdentitySettingNames.Session.LogoutFromSameTypeDevicesLimit, 1); + + Logger.LogDebug($"Clear other sessions on the device {session.Device} and save only {sameTypeDevicesCountSet} sessions."); + + await IdentitySessionStore.RevokeWithAsync( + session.UserId, + session.Device, + session.Id, + sameTypeDevicesCountSet); + break; + // 限制登录设备 + case ConcurrentLoginStrategy.LogoutFromSameTypeDevices: + + Logger.LogDebug($"Clear all other sessions on the device {session.Device}."); + + await IdentitySessionStore.RevokeAllAsync( + session.UserId, + session.Device, + session.Id); + break; + // 限制多端登录 + case ConcurrentLoginStrategy.LogoutFromAllDevices: + + Logger.LogDebug($"Clear all other user sessions."); + + await IdentitySessionStore.RevokeAllAsync( + session.UserId, + session.Id); + break; + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.Configure.cs new file mode 100644 index 000000000..33d7e661c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.Configure.cs @@ -0,0 +1,450 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.BlobStoring.OssManagement; +using LINGYUN.Abp.Identity.Session; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.OpenIddict.Permissions; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.BlobStoring; +using Volo.Abp.Caching; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.IdentityService; + +public partial class IdentityServiceModule +{ + private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 15; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureIdentity() + { + PreConfigure(builder => + { + builder.AddDefaultTokenProviders(); + }); + } + + private void ConfigureBlobStoring(IConfiguration configuration) + { + Configure(options => + { + // all container use oss management + options.Containers.ConfigureAll((containerName, containerConfiguration) => + { + // use oss management + containerConfiguration.UseOssManagement(config => + { + config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket]; + }); + }); + }); + } + + private void ConfigureDbContext() + { + // 配置Ef + Configure(options => + { + options.UseNpgsql(); + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + // Rename IdentityServer.Client.ManagePermissions + // See https://github.com/abpframework/abp/blob/dev/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/AbpPermissionManagementDomainIdentityServerModule.cs + options.ProviderPolicies[ClientPermissionValueProvider.ProviderName] = AbpOpenIddictPermissions.Applications.ManagePermissions; + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + var applicationConfiguration = configuration.GetSection("App:Urls:Applications"); + foreach (var appConfig in applicationConfiguration.GetChildren()) + { + options.Applications[appConfig.Key].RootUrl = appConfig["RootUrl"]; + foreach (var urlsConfig in appConfig.GetSection("Urls").GetChildren()) + { + options.Applications[appConfig.Key].Urls[urlsConfig.Key] = urlsConfig.Value; + } + } + }); + } + + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + options.AutoEventSelectors.AddNamespace("Volo.Abp.Identity"); + options.AutoEventSelectors.AddNamespace("Volo.Abp.OpenIddict"); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.IdentityService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity() + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + Configure(options => + { + options.IsCleanupEnabled = true; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Identity Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Identity Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs new file mode 100644 index 000000000..ad71ae28b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs @@ -0,0 +1,137 @@ +using LINGYUN.Abp.Account; +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.BlobStoring.OssManagement; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Exporter.MiniExcel; +using LINGYUN.Abp.Gdpr; +using LINGYUN.Abp.Gdpr.EntityFrameworkCore; +using LINGYUN.Abp.Gdpr.Identity; +using LINGYUN.Abp.Identity; +using LINGYUN.Abp.Identity.EntityFrameworkCore; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.OpenIddict; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.IdentityService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpAccountApplicationModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictApplicationModule), + typeof(AbpOpenIddictHttpApiModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpGdprApplicationModule), + typeof(AbpGdprHttpApiModule), + typeof(AbpGdprDomainIdentityModule), + typeof(AbpGdprEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpBlobStoringOssManagementModule), + typeof(AbpCAPEventBusModule), + typeof(AbpHttpClientModule), + typeof(AbpSmsPlatformModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpExporterMiniExcelModule), + typeof(AbpClaimsMappingModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAutofacModule) + )] +public partial class IdentityServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureIdentity(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureIdentity(); + ConfigureDbContext(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureBlobStoring(configuration); + ConfigureUrls(configuration); + ConfigureCaching(configuration); + ConfigureTiming(configuration); + ConfigureAuditing(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/LINGYUN.Abp.MicroService.IdentityService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/LINGYUN.Abp.MicroService.IdentityService.csproj new file mode 100644 index 000000000..2eb0a7475 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/LINGYUN.Abp.MicroService.IdentityService.csproj @@ -0,0 +1,84 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.IdentityService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Program.cs new file mode 100644 index 000000000..cd32d319b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Program.cs @@ -0,0 +1,105 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.IdentityService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting IdentityService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "IdentityService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + // 本地化 + app.UseMapRequestLocalization(); + // http调用链 + app.UseCorrelationId(); + // 虚拟文件系统 + app.MapAbpStaticAssets(); + // 路由 + app.UseRouting(); + // 跨域 + app.UseCors(); + // 认证 + app.UseAuthentication(); + // 多租户 + app.UseMultiTenancy(); + // 会话 + app.UseAbpSession(); + // 动态身份 + app.UseDynamicClaims(); + // 授权 + app.UseAuthorization(); + // Swagger + app.UseSwagger(); + // Swagger可视化界面 + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Identity Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + // 审计日志 + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + // 路由 + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Properties/launchSettings.json new file mode 100644 index 000000000..2f7650da1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.IdentityService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:60708;http://localhost:60709" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/TenantHeaderParamter.cs new file mode 100644 index 000000000..5b8a07b18 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.IdentityService; + +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 in http header", + Required = false + }); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json new file mode 100644 index 000000000..baa317b60 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json @@ -0,0 +1,131 @@ +{ + "App": { + "ShowPii": true, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "Urls": { + "Applications": { + "MVC": { + "RootUrl": "http://localhost:44385/", + "Urls": { + "Abp.Account.EmailConfirm": "Account/EmailConfirm", + "Abp.Account.EmailVerifyLogin": "Account/VerifyCode" + } + }, + "STS": { + "RootUrl": "http://localhost:44385/" + }, + "VueVbenAdmin": { + "RootUrl": "http://localhost:3100/", + "Urls": { + "Abp.Account.EmailConfirm": "account/email-confirm", + "Abp.Account.EmailVerifyLogin": "account/verify-code" + } + } + } + } + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "IdentityService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "ida", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "AuthServer": { + "Authority": "http://localhost:44385", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "OssManagement": { + "Bucket": "users" + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "System": "Information", + "Microsoft": "Information", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.json new file mode 100644 index 000000000..2c4961697 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.json @@ -0,0 +1,98 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "App": { + "CorsOrigins": "http://localhost:3100" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator.csproj new file mode 100644 index 000000000..4d7e77ce1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator.csproj @@ -0,0 +1,41 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.LocalizationService + + + + + + + + + + + + + + + + + + + + + + + + + Always + PreserveNewest + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..32264e9d9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.LocalizationService; +public class LocalizationServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public LocalizationServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorModule.cs new file mode 100644 index 000000000..2e00db21f --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LocalizationServiceDbMigratorModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(LocalizationServiceMigrationsEntityFrameworkCoreModule) + )] +public class LocalizationServiceDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/Program.cs new file mode 100644 index 000000000..2f99fd08c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/Program.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.MicroService.LocalizationService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.LocalizationService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.LocalizationService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..0f5313060 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore.csproj @@ -0,0 +1,29 @@ + + + + + + + false + net9.0 + LINGYUN.Abp.MicroService.LocalizationService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..fb7a5caf7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationEventHandler.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.LocalizationService; +public class LocalizationServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase +{ + public LocalizationServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationService.cs new file mode 100644 index 000000000..74c61a63a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.LocalizationService; +public class LocalizationServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public LocalizationServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContext.cs new file mode 100644 index 000000000..b78747280 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContext.cs @@ -0,0 +1,32 @@ +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +[ConnectionStringName("Default")] +public class LocalizationServiceMigrationsDbContext : + AbpDbContext, + ILocalizationDbContext +{ + public DbSet Resources { get; set; } + + public DbSet Languages { get; set; } + + public DbSet Texts { get; set; } + + public LocalizationServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureLocalization(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..fe45cbcbd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsDbContextFactory.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.MicroService.LocalizationService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.PlatformService; +public class LocalizationServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public LocalizationServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new LocalizationServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..703a29a45 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LocalizationServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,41 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +[DependsOn( + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpDataDbMigratorModule) + )] +public class LocalizationServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.Designer.cs new file mode 100644 index 000000000..04198eb70 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.Designer.cs @@ -0,0 +1,177 @@ +// +using System; +using LINGYUN.Abp.MicroService.LocalizationService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.LocalizationService.Migrations +{ + [DbContext(typeof(LocalizationServiceMigrationsDbContext))] + [Migration("20260105085421_Initial_Localization_Service")] + partial class Initial_Localization_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Language", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("CultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DisplayName"); + + b.Property("Enable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TwoLetterISOLanguageName") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("TwoLetterISOLanguageName"); + + b.Property("UiCultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("UiCultureName"); + + b.HasKey("Id"); + + b.HasIndex("CultureName"); + + b.ToTable("AbpLocalizationLanguages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Resource", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultCultureName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DefaultCultureName"); + + b.Property("Description") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DisplayName"); + + b.Property("Enable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("Name"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AbpLocalizationResources", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Text", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("CultureName"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Key"); + + b.Property("ResourceName") + .HasColumnType("text"); + + b.Property("Value") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("Key"); + + b.ToTable("AbpLocalizationTexts", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.cs new file mode 100644 index 000000000..d13afd595 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/20260105085421_Initial_Localization_Service.cs @@ -0,0 +1,100 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.LocalizationService.Migrations +{ + /// + public partial class Initial_Localization_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpLocalizationLanguages", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Enable = table.Column(type: "boolean", nullable: false, defaultValue: true), + CultureName = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + UiCultureName = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TwoLetterISOLanguageName = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLocalizationLanguages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLocalizationResources", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Enable = table.Column(type: "boolean", nullable: false, defaultValue: true), + Name = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Description = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + DefaultCultureName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLocalizationResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLocalizationTexts", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CultureName = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + Key = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ResourceName = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLocalizationTexts", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpLocalizationLanguages_CultureName", + table: "AbpLocalizationLanguages", + column: "CultureName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpLocalizationResources_Name", + table: "AbpLocalizationResources", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpLocalizationTexts_Key", + table: "AbpLocalizationTexts", + column: "Key"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpLocalizationLanguages"); + + migrationBuilder.DropTable( + name: "AbpLocalizationResources"); + + migrationBuilder.DropTable( + name: "AbpLocalizationTexts"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/LocalizationServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/LocalizationServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..21ce64bb0 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/Migrations/LocalizationServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,174 @@ +// +using System; +using LINGYUN.Abp.MicroService.LocalizationService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.LocalizationService.Migrations +{ + [DbContext(typeof(LocalizationServiceMigrationsDbContext))] + partial class LocalizationServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Language", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("CultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DisplayName"); + + b.Property("Enable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TwoLetterISOLanguageName") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("TwoLetterISOLanguageName"); + + b.Property("UiCultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("UiCultureName"); + + b.HasKey("Id"); + + b.HasIndex("CultureName"); + + b.ToTable("AbpLocalizationLanguages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Resource", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultCultureName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DefaultCultureName"); + + b.Property("Description") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("DisplayName"); + + b.Property("Enable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("Name"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AbpLocalizationResources", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Text", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("CultureName"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Key"); + + b.Property("ResourceName") + .HasColumnType("text"); + + b.Property("Value") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("Key"); + + b.ToTable("AbpLocalizationTexts", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LINGYUN.Abp.MicroService.LocalizationService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LINGYUN.Abp.MicroService.LocalizationService.csproj new file mode 100644 index 000000000..34029a43d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LINGYUN.Abp.MicroService.LocalizationService.csproj @@ -0,0 +1,67 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.LocalizationService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs new file mode 100644 index 000000000..03d3f29d4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs @@ -0,0 +1,366 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +public partial class LocalizationServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 30; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.LocalizationService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = false; + }); + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Localization Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Localization Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 默认支持的本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs new file mode 100644 index 000000000..4f8fdca08 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs @@ -0,0 +1,99 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpLocalizationManagementApplicationModule), + typeof(AbpLocalizationManagementHttpApiModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(LocalizationServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpCAPEventBusModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpHttpClientModule), + typeof(AbpSmsPlatformModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpClaimsMappingModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAutofacModule) + )] +public partial class LocalizationServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureIdentity(configuration); + ConfigureAuditing(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Program.cs new file mode 100644 index 000000000..846717202 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Program.cs @@ -0,0 +1,107 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.LocalizationService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting LocalizationService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + builder.AddServiceHealthChecks(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "LocalizationService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + app.MapServiceHealthChecks(); + + app.UseForwardedHeaders(); + // 本地化 + app.UseMapRequestLocalization(); + // http调用链 + app.UseCorrelationId(); + // 虚拟文件系统 + app.MapAbpStaticAssets(); + // 路由 + app.UseRouting(); + // 跨域 + app.UseCors(); + // 认证 + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + // 多租户 + app.UseMultiTenancy(); + // 会话 + app.UseAbpSession(); + app.UseDynamicClaims(); + // 授权 + app.UseAuthorization(); + // Swagger + app.UseSwagger(); + // Swagger可视化界面 + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Localization Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + // 审计日志 + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + // 路由 + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Properties/launchSettings.json new file mode 100644 index 000000000..6653e158b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.LocalizationService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:64094;http://localhost:64095" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthCheck.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthCheck.cs new file mode 100644 index 000000000..1782b5596 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthCheck.cs @@ -0,0 +1,35 @@ +using LINGYUN.Abp.LocalizationManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +public class ServiceHealthCheck : IHealthCheck +{ + private readonly IServiceScopeFactory _scopeFactory; + + public ServiceHealthCheck(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async virtual Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + using var scope = _scopeFactory.CreateScope(); + var repo = scope.ServiceProvider.GetRequiredService(); + + var _ = await repo.GetCountAsync(cancellationToken); + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthChecksExtenssions.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthChecksExtenssions.cs new file mode 100644 index 000000000..ea6e6fe86 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/ServiceHealthChecksExtenssions.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +internal static class ServiceHealthChecksExtenssions +{ + private const string HealthEndpointPath = "/service-health"; + private const string DefaultHealthTag = "ready"; + + public static TBuilder AddServiceHealthChecks(this TBuilder builder, string name = "Service", string tag = DefaultHealthTag) where TBuilder : IHostApplicationBuilder + { + builder.Services + .AddHealthChecks() + .AddCheck(name, tags: [tag]); + + return builder; + } + + public static WebApplication MapServiceHealthChecks(this WebApplication app, string tag = DefaultHealthTag) + { + if (app.Environment.IsDevelopment()) + { + app.MapHealthChecks(HealthEndpointPath, new HealthCheckOptions + { + Predicate = r => r.Tags.Contains(tag) + }); + } + return app; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/TenantHeaderParamter.cs new file mode 100644 index 000000000..40df63491 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.LocalizationService; + +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/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json new file mode 100644 index 000000000..65c3816b4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json @@ -0,0 +1,108 @@ +{ + "App": { + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "ShowPii": true, + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "LocalizationService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "lta", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Debug" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.json new file mode 100644 index 000000000..3c85151c7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.json @@ -0,0 +1,99 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "App": { + "CorsOrigins": "http://localhost:3100" + }, + "AllowedHosts": "*", + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/LINGYUN.Abp.MicroService.MessageService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/LINGYUN.Abp.MicroService.MessageService.DbMigrator.csproj new file mode 100644 index 000000000..81004b3ad --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/LINGYUN.Abp.MicroService.MessageService.DbMigrator.csproj @@ -0,0 +1,42 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.MessageService + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..6735df5a1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.MessageService; +public class MessageServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public MessageServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorModule.cs new file mode 100644 index 000000000..0b6279dd8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/MessageServiceDbMigratorModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.MessageService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(MessageServiceMigrationsEntityFrameworkCoreModule) + )] +public class MessageServiceDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/Program.cs new file mode 100644 index 000000000..85f22ed07 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/Program.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.MicroService.MessageService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.MessageService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.MessageService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..0b4515de4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore.csproj @@ -0,0 +1,33 @@ + + + + + + + false + net9.0 + LINGYUN.Abp.MicroService.MessageService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..380738f01 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.Notifications; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.MessageService; +public class MessageServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase +{ + protected INotificationSender NotificationSender { get; } + protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + + public MessageServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + INotificationSender notificationSender, + INotificationSubscriptionManager notificationSubscriptionManager) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + NotificationSender = notificationSender; + NotificationSubscriptionManager = notificationSubscriptionManager; + } + + protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) + { + if (!schemaMigrated) + { + return; + } + + using (CurrentTenant.Change(eventData.Id)) + { + await SendNotificationAsync(eventData); + } + } + + protected async virtual Task SendNotificationAsync(TenantCreatedEto eventData) + { + try + { + if (!eventData.Properties.TryGetValue("AdminUserId", out var userIdString) || + !Guid.TryParse(userIdString, out var adminUserId)) + { + return; + } + var adminEmailAddress = eventData.Properties.GetOrDefault("AdminEmail") ?? "admin@abp.io"; + + var tenantAdminUserIdentifier = new UserIdentifier(adminUserId, adminEmailAddress); + + // 租户管理员订阅事件 + await NotificationSubscriptionManager + .SubscribeAsync( + eventData.Id, + tenantAdminUserIdentifier, + TenantNotificationNames.NewTenantRegistered); + + Logger.LogInformation("publish new tenant notification.."); + await NotificationSender.SendNofiterAsync( + TenantNotificationNames.NewTenantRegistered, + new NotificationTemplate( + TenantNotificationNames.NewTenantRegistered, + formUser: adminEmailAddress, + data: new Dictionary + { + { "name", eventData.Name }, + { "email", adminEmailAddress }, + { "id", eventData.Id }, + }), + tenantAdminUserIdentifier, + eventData.Id, + NotificationSeverity.Success); + + Logger.LogInformation("tenant administrator subscribes to new tenant events.."); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Failed to send the tenant initialization notification."); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs new file mode 100644 index 000000000..53b74d610 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.MessageService; +public class MessageServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public MessageServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContext.cs new file mode 100644 index 000000000..c4af21f0e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContext.cs @@ -0,0 +1,61 @@ +using LINGYUN.Abp.MessageService.Chat; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using LINGYUN.Abp.MessageService.Groups; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.Notifications.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.MessageService; + +[ConnectionStringName("Default")] +public class MessageServiceMigrationsDbContext : + AbpDbContext, + INotificationsDbContext, + INotificationsDefinitionDbContext, + IMessageServiceDbContext +{ + public DbSet UserMessages { get; set; } + + public DbSet GroupMessages { get; set; } + + public DbSet UserChatFriends { get; set; } + + public DbSet UserChatSettings { get; set; } + + public DbSet GroupChatBlacks { get; set; } + + public DbSet ChatGroups { get; set; } + + public DbSet UserChatGroups { get; set; } + + public DbSet UserChatCards { get; set; } + + public DbSet UserGroupCards { get; set; } + + public DbSet NotificationDefinitionGroupRecords { get; set; } + + public DbSet NotificationDefinitionRecords { get; set; } + + public DbSet Notifications { get; set; } + + public DbSet UserNotifications { get; set; } + + public DbSet UserSubscribes { get; set; } + + public MessageServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureNotifications(); + modelBuilder.ConfigureNotificationsDefinition(); + modelBuilder.ConfigureMessageService(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..2cf989bdf --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsDbContextFactory.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.MessageService; +public class MessageServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public MessageServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new MessageServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.MessageService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..016447de6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using LINGYUN.Abp.Notifications.EntityFrameworkCore; +using LINGYUN.Abp.Quartz.PostgresSqlInstaller; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.MessageService; + +[DependsOn( + typeof(AbpQuartzPostgresSqlInstallerModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpNotificationsEntityFrameworkCoreModule), + typeof(AbpMessageServiceEntityFrameworkCoreModule), + typeof(AbpTextTemplatingEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpDataDbMigratorModule) + )] +public class MessageServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.Designer.cs new file mode 100644 index 000000000..5b2244c02 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.Designer.cs @@ -0,0 +1,759 @@ +// +using System; +using LINGYUN.Abp.MicroService.MessageService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.MessageService.Migrations +{ + [DbContext(typeof(MessageServiceMigrationsDbContext))] + [Migration("20260105085638_Initial_Message_Service")] + partial class Initial_Message_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatCard", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer"); + + b.Property("AvatarUrl") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastOnlineTime") + .HasColumnType("timestamp with time zone"); + + b.Property("NickName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Sex") + .HasColumnType("integer"); + + b.Property("Sign") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatCards", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatFriend", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Black") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DontDisturb") + .HasColumnType("boolean"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FrientId") + .HasColumnType("uuid"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("RemarkName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SpecialFocus") + .HasColumnType("boolean"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "FrientId"); + + b.ToTable("AppUserChatFriends", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowAddFriend") + .HasColumnType("boolean"); + + b.Property("AllowAnonymous") + .HasColumnType("boolean"); + + b.Property("AllowReceiveMessage") + .HasColumnType("boolean"); + + b.Property("AllowSendMessage") + .HasColumnType("boolean"); + + b.Property("RequireAddFriendValition") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatSettings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("ReceiveUserId") + .HasColumnType("uuid"); + + b.Property("SendUserName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ReceiveUserId"); + + b.ToTable("AppUserMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.ChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("AdminUserId") + .HasColumnType("uuid"); + + b.Property("AllowAnonymous") + .HasColumnType("boolean"); + + b.Property("AllowSendMessage") + .HasColumnType("boolean"); + + b.Property("AvatarUrl") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MaxUserCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Notice") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AppChatGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("ShieldUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupChatBlacks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SendUserName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId", "UserId"); + + b.ToTable("AppUserChatGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserGroupCard", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAdmin") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("NickName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SilenceEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserGroupCards", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContentType") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NotificationTypeName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Severity") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "NotificationName"); + + b.ToTable("AppNotifications", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.NotificationDefinitionGroupRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowSubscriptionToClients") + .HasColumnType("boolean"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("DisplayName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("AppNotificationDefinitionGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.NotificationDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowSubscriptionToClients") + .HasColumnType("boolean"); + + b.Property("ContentType") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("DisplayName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NotificationLifetime") + .HasColumnType("integer"); + + b.Property("NotificationType") + .HasColumnType("integer"); + + b.Property("Providers") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Template") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.ToTable("AppNotificationDefinitions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationId") + .HasDatabaseName("IX_Tenant_User_Notification_Id"); + + b.ToTable("AppUserNotifications", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.UserSubscribe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("NotificationName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasDefaultValue("/"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationName") + .IsUnique() + .HasDatabaseName("IX_Tenant_User_Notification_Name"); + + b.ToTable("AppUserSubscribes", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.cs new file mode 100644 index 000000000..0dc923f8a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/20260105085638_Initial_Message_Service.cs @@ -0,0 +1,424 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.MessageService.Migrations +{ + /// + public partial class Initial_Message_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AppChatGroups", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + AdminUserId = table.Column(type: "uuid", nullable: false), + GroupId = table.Column(type: "bigint", nullable: false), + Name = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + Tag = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + Address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Notice = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + MaxUserCount = table.Column(type: "integer", nullable: false), + AllowAnonymous = table.Column(type: "boolean", nullable: false), + AllowSendMessage = table.Column(type: "boolean", nullable: false), + Description = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + AvatarUrl = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppChatGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppGroupChatBlacks", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + GroupId = table.Column(type: "bigint", nullable: false), + ShieldUserId = table.Column(type: "uuid", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppGroupChatBlacks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppGroupMessages", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + GroupId = table.Column(type: "bigint", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + MessageId = table.Column(type: "bigint", nullable: false), + SendUserName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Content = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + Type = table.Column(type: "integer", nullable: false), + Source = table.Column(type: "integer", nullable: false), + State = table.Column(type: "smallint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppGroupMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppNotificationDefinitionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + DisplayName = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + AllowSubscriptionToClients = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppNotificationDefinitionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppNotificationDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + GroupName = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + DisplayName = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Template = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + NotificationLifetime = table.Column(type: "integer", nullable: false), + NotificationType = table.Column(type: "integer", nullable: false), + ContentType = table.Column(type: "integer", nullable: false, defaultValue: 0), + Providers = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + AllowSubscriptionToClients = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppNotificationDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppNotifications", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + Severity = table.Column(type: "smallint", nullable: false), + Type = table.Column(type: "integer", nullable: false), + ContentType = table.Column(type: "integer", nullable: false, defaultValue: 0), + NotificationId = table.Column(type: "bigint", nullable: false), + NotificationName = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + NotificationTypeName = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + ExpirationTime = table.Column(type: "timestamp with time zone", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppNotifications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatCards", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Sex = table.Column(type: "integer", nullable: false), + Sign = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + NickName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Description = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + AvatarUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + Birthday = table.Column(type: "timestamp with time zone", nullable: true), + Age = table.Column(type: "integer", nullable: false), + LastOnlineTime = table.Column(type: "timestamp with time zone", nullable: true), + State = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatCards", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatFriends", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + FrientId = table.Column(type: "uuid", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Black = table.Column(type: "boolean", nullable: false), + DontDisturb = table.Column(type: "boolean", nullable: false), + SpecialFocus = table.Column(type: "boolean", nullable: false), + RemarkName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Description = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Status = table.Column(type: "smallint", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatFriends", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatGroups", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + GroupId = table.Column(type: "bigint", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatSettings", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + AllowAnonymous = table.Column(type: "boolean", nullable: false), + AllowAddFriend = table.Column(type: "boolean", nullable: false), + RequireAddFriendValition = table.Column(type: "boolean", nullable: false), + AllowReceiveMessage = table.Column(type: "boolean", nullable: false), + AllowSendMessage = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserGroupCards", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + NickName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsAdmin = table.Column(type: "boolean", nullable: false), + SilenceEnd = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserGroupCards", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserMessages", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + ReceiveUserId = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + MessageId = table.Column(type: "bigint", nullable: false), + SendUserName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Content = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + Type = table.Column(type: "integer", nullable: false), + Source = table.Column(type: "integer", nullable: false), + State = table.Column(type: "smallint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserNotifications", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + NotificationId = table.Column(type: "bigint", nullable: false), + ReadStatus = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserNotifications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserSubscribes", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "uuid", nullable: false), + UserName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, defaultValue: "/"), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + NotificationName = table.Column(type: "character varying(255)", maxLength: 255, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserSubscribes", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AppChatGroups_TenantId_Name", + table: "AppChatGroups", + columns: new[] { "TenantId", "Name" }); + + migrationBuilder.CreateIndex( + name: "IX_AppGroupChatBlacks_TenantId_GroupId", + table: "AppGroupChatBlacks", + columns: new[] { "TenantId", "GroupId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppGroupMessages_TenantId_GroupId", + table: "AppGroupMessages", + columns: new[] { "TenantId", "GroupId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppNotifications_TenantId_NotificationName", + table: "AppNotifications", + columns: new[] { "TenantId", "NotificationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatCards_TenantId_UserId", + table: "AppUserChatCards", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatFriends_TenantId_UserId_FrientId", + table: "AppUserChatFriends", + columns: new[] { "TenantId", "UserId", "FrientId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatGroups_TenantId_GroupId_UserId", + table: "AppUserChatGroups", + columns: new[] { "TenantId", "GroupId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatSettings_TenantId_UserId", + table: "AppUserChatSettings", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserGroupCards_TenantId_UserId", + table: "AppUserGroupCards", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserMessages_TenantId_ReceiveUserId", + table: "AppUserMessages", + columns: new[] { "TenantId", "ReceiveUserId" }); + + migrationBuilder.CreateIndex( + name: "IX_Tenant_User_Notification_Id", + table: "AppUserNotifications", + columns: new[] { "TenantId", "UserId", "NotificationId" }); + + migrationBuilder.CreateIndex( + name: "IX_Tenant_User_Notification_Name", + table: "AppUserSubscribes", + columns: new[] { "TenantId", "UserId", "NotificationName" }, + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AppChatGroups"); + + migrationBuilder.DropTable( + name: "AppGroupChatBlacks"); + + migrationBuilder.DropTable( + name: "AppGroupMessages"); + + migrationBuilder.DropTable( + name: "AppNotificationDefinitionGroups"); + + migrationBuilder.DropTable( + name: "AppNotificationDefinitions"); + + migrationBuilder.DropTable( + name: "AppNotifications"); + + migrationBuilder.DropTable( + name: "AppUserChatCards"); + + migrationBuilder.DropTable( + name: "AppUserChatFriends"); + + migrationBuilder.DropTable( + name: "AppUserChatGroups"); + + migrationBuilder.DropTable( + name: "AppUserChatSettings"); + + migrationBuilder.DropTable( + name: "AppUserGroupCards"); + + migrationBuilder.DropTable( + name: "AppUserMessages"); + + migrationBuilder.DropTable( + name: "AppUserNotifications"); + + migrationBuilder.DropTable( + name: "AppUserSubscribes"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/MessageServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/MessageServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..d1b513018 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/Migrations/MessageServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,756 @@ +// +using System; +using LINGYUN.Abp.MicroService.MessageService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.MessageService.Migrations +{ + [DbContext(typeof(MessageServiceMigrationsDbContext))] + partial class MessageServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatCard", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer"); + + b.Property("AvatarUrl") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastOnlineTime") + .HasColumnType("timestamp with time zone"); + + b.Property("NickName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Sex") + .HasColumnType("integer"); + + b.Property("Sign") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatCards", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatFriend", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Black") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DontDisturb") + .HasColumnType("boolean"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FrientId") + .HasColumnType("uuid"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("RemarkName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SpecialFocus") + .HasColumnType("boolean"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "FrientId"); + + b.ToTable("AppUserChatFriends", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowAddFriend") + .HasColumnType("boolean"); + + b.Property("AllowAnonymous") + .HasColumnType("boolean"); + + b.Property("AllowReceiveMessage") + .HasColumnType("boolean"); + + b.Property("AllowSendMessage") + .HasColumnType("boolean"); + + b.Property("RequireAddFriendValition") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatSettings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("ReceiveUserId") + .HasColumnType("uuid"); + + b.Property("SendUserName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ReceiveUserId"); + + b.ToTable("AppUserMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.ChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("AdminUserId") + .HasColumnType("uuid"); + + b.Property("AllowAnonymous") + .HasColumnType("boolean"); + + b.Property("AllowSendMessage") + .HasColumnType("boolean"); + + b.Property("AvatarUrl") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MaxUserCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Notice") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AppChatGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("ShieldUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupChatBlacks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SendUserName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId", "UserId"); + + b.ToTable("AppUserChatGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserGroupCard", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAdmin") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("NickName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SilenceEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserGroupCards", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContentType") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NotificationTypeName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Severity") + .HasColumnType("smallint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "NotificationName"); + + b.ToTable("AppNotifications", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.NotificationDefinitionGroupRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowSubscriptionToClients") + .HasColumnType("boolean"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("DisplayName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("AppNotificationDefinitionGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.NotificationDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowSubscriptionToClients") + .HasColumnType("boolean"); + + b.Property("ContentType") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("DisplayName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NotificationLifetime") + .HasColumnType("integer"); + + b.Property("NotificationType") + .HasColumnType("integer"); + + b.Property("Providers") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Template") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.ToTable("AppNotificationDefinitions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationId") + .HasDatabaseName("IX_Tenant_User_Notification_Id"); + + b.ToTable("AppUserNotifications", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Notifications.UserSubscribe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("NotificationName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasDefaultValue("/"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationName") + .IsUnique() + .HasDatabaseName("IX_Tenant_User_Notification_Name"); + + b.ToTable("AppUserSubscribes", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJob.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJob.cs new file mode 100644 index 000000000..d4f1ccba9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJob.cs @@ -0,0 +1,41 @@ +using LINGYUN.Abp.Notifications; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Threading.Tasks; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.MicroService.MessageService.BackgroundJobs; + +public class NotificationPublishJob : AsyncBackgroundJob, ITransientDependency +{ + protected AbpNotificationsPublishOptions Options { get; } + protected IServiceScopeFactory ServiceScopeFactory { get; } + protected INotificationDataSerializer NotificationDataSerializer { get; } + public NotificationPublishJob( + IOptions options, + IServiceScopeFactory serviceScopeFactory, + INotificationDataSerializer notificationDataSerializer) + { + Options = options.Value; + ServiceScopeFactory = serviceScopeFactory; + NotificationDataSerializer = notificationDataSerializer; + } + + public override async Task ExecuteAsync(NotificationPublishJobArgs args) + { + var providerType = Type.GetType(args.ProviderType); + using (var scope = ServiceScopeFactory.CreateScope()) + { + if (scope.ServiceProvider.GetRequiredService(providerType) is INotificationPublishProvider publishProvider) + { + var store = scope.ServiceProvider.GetRequiredService(); + var notification = await store.GetNotificationOrNullAsync(args.TenantId, args.NotificationId); + notification.Data = NotificationDataSerializer.Serialize(notification.Data); + + await publishProvider.PublishAsync(notification, args.UserIdentifiers); + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJobArgs.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJobArgs.cs new file mode 100644 index 000000000..ac3b8bc57 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/BackgroundJobs/NotificationPublishJobArgs.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.Notifications; +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.MicroService.MessageService.BackgroundJobs; + +public class NotificationPublishJobArgs +{ + public Guid? TenantId { get; set; } + public long NotificationId { get; set; } + public string ProviderType { get; set; } + public List UserIdentifiers { get; set; } + public NotificationPublishJobArgs() + { + UserIdentifiers = new List(); + } + public NotificationPublishJobArgs(long id, string providerType, List userIdentifiers, Guid? tenantId = null) + { + NotificationId = id; + ProviderType = providerType; + UserIdentifiers = userIdentifiers; + TenantId = tenantId; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/ChatMessageEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/ChatMessageEventHandler.cs new file mode 100644 index 000000000..9e5706be8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/ChatMessageEventHandler.cs @@ -0,0 +1,61 @@ +using LINGYUN.Abp.IM; +using LINGYUN.Abp.IM.Messages; +using LINGYUN.Abp.RealTime; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Distributed +{ + public class ChatMessageEventHandler : IDistributedEventHandler>, ITransientDependency + { + /// + /// Reference to . + /// + public ILogger Logger { get; set; } + /// + /// Reference to . + /// + protected AbpIMOptions Options { get; } + + protected IMessageStore MessageStore { get; } + protected IMessageBlocker MessageBlocker { get; } + protected IMessageSenderProviderManager MessageSenderProviderManager { get; } + + public ChatMessageEventHandler( + IOptions options, + IMessageStore messageStore, + IMessageBlocker messageBlocker, + IMessageSenderProviderManager messageSenderProviderManager) + { + Options = options.Value; + MessageStore = messageStore; + MessageBlocker = messageBlocker; + MessageSenderProviderManager = messageSenderProviderManager; + + Logger = NullLogger.Instance; + } + + public async virtual Task HandleEventAsync(RealTimeEto eventData) + { + Logger.LogDebug($"Persistent chat message."); + + var message = eventData.Data; + // 消息拦截 + // 扩展敏感词汇过滤 + await MessageBlocker.InterceptAsync(message); + + await MessageStore.StoreMessageAsync(message); + + // 发送消息 + foreach (var provider in MessageSenderProviderManager.Providers) + { + Logger.LogDebug($"Sending message with provider {provider.Name}"); + await provider.SendMessageAsync(message); + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/NotificationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/NotificationEventHandler.cs new file mode 100644 index 000000000..d7ba789a6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/NotificationEventHandler.cs @@ -0,0 +1,493 @@ +using LINGYUN.Abp.MicroService.MessageService.BackgroundJobs; +using LINGYUN.Abp.MicroService.MessageService.MultiTenancy; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.Notifications.Templating; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Json; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Settings; +using Volo.Abp.TextTemplating; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Distributed +{ + /// + /// 订阅通知发布事件,统一发布消息 + /// + /// + /// 作用在于SignalR客户端只会与一台服务器建立连接, + /// 只有启用了SignlR服务端的才能真正将消息发布到客户端 + /// + public class NotificationEventHandler : + IDistributedEventHandler>, + IDistributedEventHandler>, + ITransientDependency + { + /// + /// Reference to . + /// + public ILogger Logger { get; set; } + /// + /// Reference to . + /// + protected AbpNotificationsPublishOptions Options { get; } + /// + /// Reference to . + /// + protected ISettingProvider SettingProvider { get; } + /// + /// Reference to . + /// + protected ICurrentTenant CurrentTenant { get; } + /// + /// Reference to . + /// + protected ITenantConfigurationCache TenantConfigurationCache { get; } + /// + /// Reference to . + /// + protected IJsonSerializer JsonSerializer { get; } + /// + /// Reference to . + /// + protected IBackgroundJobManager BackgroundJobManager { get; } + /// + /// Reference to . + /// + protected ITemplateRenderer TemplateRenderer { get; } + /// + /// Reference to . + /// + protected INotificationStore NotificationStore { get; } + /// + /// Reference to . + /// + protected IStringLocalizerFactory StringLocalizerFactory { get; } + /// + /// Reference to . + /// + protected INotificationDataSerializer NotificationDataSerializer { get; } + /// + /// Reference to . + /// + protected INotificationTemplateResolver NotificationTemplateResolver { get; } + /// + /// Reference to . + /// + protected INotificationDefinitionManager NotificationDefinitionManager { get; } + /// + /// Reference to . + /// + protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + /// + /// Reference to . + /// + protected INotificationPublishProviderManager NotificationPublishProviderManager { get; } + + /// + /// Initializes a new instance of the class. + /// + public NotificationEventHandler( + ICurrentTenant currentTenant, + ISettingProvider settingProvider, + ITenantConfigurationCache tenantConfigurationCache, + IJsonSerializer jsonSerializer, + ITemplateRenderer templateRenderer, + IBackgroundJobManager backgroundJobManager, + IStringLocalizerFactory stringLocalizerFactory, + IOptions options, + INotificationStore notificationStore, + INotificationDataSerializer notificationDataSerializer, + INotificationTemplateResolver notificationTemplateResolver, + INotificationDefinitionManager notificationDefinitionManager, + INotificationSubscriptionManager notificationSubscriptionManager, + INotificationPublishProviderManager notificationPublishProviderManager) + { + Options = options.Value; + TenantConfigurationCache = tenantConfigurationCache; + CurrentTenant = currentTenant; + SettingProvider = settingProvider; + JsonSerializer = jsonSerializer; + TemplateRenderer = templateRenderer; + BackgroundJobManager = backgroundJobManager; + StringLocalizerFactory = stringLocalizerFactory; + NotificationStore = notificationStore; + NotificationDataSerializer = notificationDataSerializer; + NotificationTemplateResolver = notificationTemplateResolver; + NotificationDefinitionManager = notificationDefinitionManager; + NotificationSubscriptionManager = notificationSubscriptionManager; + NotificationPublishProviderManager = notificationPublishProviderManager; + + Logger = NullLogger.Instance; + } + + [UnitOfWork] + public async virtual Task HandleEventAsync(NotificationEto eventData) + { + var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name); + if (notification == null) + { + return; + } + + var culture = eventData.Data.Culture; + if (culture.IsNullOrWhiteSpace()) + { + var cultureSet = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); + culture = cultureSet ?? CultureInfo.CurrentCulture.Name; + } + using (CultureHelper.Use(culture, culture)) + { + var result = await NotificationTemplateResolver.ResolveAsync(eventData.Data); + + if (notification.NotificationType == NotificationType.System) + { + using (CurrentTenant.Change(null)) + { + await SendToTenantAsync(null, notification, eventData, result); + + var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync(); + + foreach (var activeTenant in allActiveTenants) + { + await SendToTenantAsync(activeTenant.Id, notification, eventData, result); + } + } + } + else + { + await SendToTenantAsync(eventData.TenantId, notification, eventData, result); + } + } + } + + [UnitOfWork] + public async virtual Task HandleEventAsync(NotificationEto eventData) + { + var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name); + if (notification == null) + { + return; + } + var culture = eventData.Data.TryGetData(NotificationData.CultureKey)?.ToString(); + if (culture.IsNullOrWhiteSpace()) + { + var cultureSet = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); + culture = cultureSet ?? CultureInfo.CurrentCulture.Name; + } + using (CultureHelper.Use(culture, culture)) + { + if (notification.NotificationType == NotificationType.System) + { + using (CurrentTenant.Change(null)) + { + await SendToTenantAsync(null, notification, eventData); + + var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync(); + + foreach (var activeTenant in allActiveTenants) + { + await SendToTenantAsync(activeTenant.Id, notification, eventData); + } + } + } + else + { + await SendToTenantAsync(eventData.TenantId, notification, eventData); + } + } + } + + protected async virtual Task SendToTenantAsync( + Guid? tenantId, + NotificationDefinition notification, + NotificationEto eventData, + NotificationTemplateResolveResult templateResolveResult) + { + using (CurrentTenant.Change(tenantId)) + { + var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers); + + // 过滤用户指定提供者 + if (eventData.UseProviders.Any()) + { + providers = providers.Where(p => eventData.UseProviders.Contains(p.Name)); + } + else if (notification.Providers.Any()) + { + providers = providers.Where(p => notification.Providers.Contains(p.Name)); + } + + var notificationInfo = new NotificationInfo + { + Name = notification.Name, + TenantId = tenantId, + Severity = eventData.Severity, + Type = notification.NotificationType, + ContentType = notification.ContentType, + CreationTime = eventData.CreationTime, + Lifetime = notification.NotificationLifetime, + }; + notificationInfo.SetId(eventData.Id); + + var title = notification.DisplayName.Localize(StringLocalizerFactory); + var message = ""; + + try + { + // 由于模板通知受租户影响, 格式化失败的消息将被丢弃. + message = await TemplateRenderer.RenderAsync( + templateName: eventData.Data.Name, + // 解决序列化后的数据无法渲染模板 + model: templateResolveResult.Model ?? eventData.Data.ExtraProperties, + cultureName: eventData.Data.Culture, + globalContext: new Dictionary + { + // 模板不支持 $ 字符, 改为普通关键字 + { NotificationKeywords.Name, notification.Name }, + { NotificationKeywords.FormUser, eventData.Data.FormUser }, + { NotificationKeywords.Id, eventData.Id }, + { NotificationKeywords.Title, title.ToString() }, + { NotificationKeywords.CreationTime, eventData.CreationTime.ToString(Options.DateTimeFormat) }, + }); + } + catch (Exception ex) + { + Logger.LogWarning("Formatting template notification failed, message will be discarded, cause :{message}", ex.Message); + return; + } + + var notificationData = new NotificationData(); + notificationData.WriteStandardData( + title: title.ToString(), + message: message, + createTime: eventData.CreationTime, + formUser: eventData.Data.FormUser); + notificationData.ExtraProperties.AddIfNotContains(eventData.Data.ExtraProperties); + + notificationInfo.Data = notificationData; + + var subscriptionUsers = await GerSubscriptionUsersAsync( + notificationInfo.Name, + eventData.Users, + tenantId); + + await PersistentNotificationAsync( + notificationInfo, + subscriptionUsers, + providers); + + if (subscriptionUsers.Any()) + { + // 发布通知 + foreach (var provider in providers) + { + await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers); + } + } + } + } + + protected async virtual Task SendToTenantAsync( + Guid? tenantId, + NotificationDefinition notification, + NotificationEto eventData) + { + using (CurrentTenant.Change(tenantId)) + { + var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers); + + // 过滤用户指定提供者 + if (eventData.UseProviders.Any()) + { + providers = providers.Where(p => eventData.UseProviders.Contains(p.Name)); + } + else if (notification.Providers.Any()) + { + providers = providers.Where(p => notification.Providers.Contains(p.Name)); + } + + var notificationInfo = new NotificationInfo + { + Name = notification.Name, + CreationTime = eventData.CreationTime, + Data = eventData.Data, + Severity = eventData.Severity, + Lifetime = notification.NotificationLifetime, + TenantId = tenantId, + Type = notification.NotificationType, + ContentType = notification.ContentType, + }; + notificationInfo.SetId(eventData.Id); + + notificationInfo.Data = NotificationDataSerializer.Serialize(notificationInfo.Data); + + // 获取用户订阅 + var subscriptionUsers = await GerSubscriptionUsersAsync( + notificationInfo.Name, + eventData.Users, + tenantId); + + // 持久化通知 + await PersistentNotificationAsync( + notificationInfo, + subscriptionUsers, + providers); + + if (subscriptionUsers.Any()) + { + // 发布订阅通知 + foreach (var provider in providers) + { + await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers); + } + } + } + } + /// + /// 获取用户订阅列表 + /// + /// 通知名称 + /// 接收用户列表 + /// 租户标识 + /// 用户订阅列表 + protected async Task> GerSubscriptionUsersAsync( + string notificationName, + IEnumerable sendToUsers, + Guid? tenantId = null) + { + try + { + // 获取用户订阅列表 + var userSubscriptions = await NotificationSubscriptionManager.GetUsersSubscriptionsAsync( + tenantId, + notificationName, + sendToUsers); + + return userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName)); + } + catch (Exception ex) + { + Logger.LogWarning("Failed to get user subscription, message will not be received by the user, reason: {message}", ex.Message); + } + + return new List(); + } + /// + /// 持久化通知并返回订阅用户列表 + /// + /// 通知实体 + /// 订阅用户列表 + /// 通知发送提供者 + /// 返回订阅者列表 + protected async Task PersistentNotificationAsync( + NotificationInfo notificationInfo, + IEnumerable subscriptionUsers, + IEnumerable sendToProviders) + { + try + { + // 持久化通知 + await NotificationStore.InsertNotificationAsync(notificationInfo); + + if (!subscriptionUsers.Any()) + { + return; + } + + // 持久化用户通知 + await NotificationStore.InsertUserNotificationsAsync(notificationInfo, subscriptionUsers.Select(u => u.UserId)); + + if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne) + { + // 一次性通知取消用户订阅 + await NotificationStore.DeleteUserSubscriptionAsync( + notificationInfo.TenantId, + subscriptionUsers, + notificationInfo.Name); + } + } + catch (Exception ex) + { + Logger.LogWarning("Failed to persistent notification failed, reason: {message}", ex.Message); + + foreach (var provider in sendToProviders) + { + // 处理持久化失败进入后台队列 + await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers); + } + } + } + /// + /// 发布订阅者通知 + /// + /// 通知发布者 + /// 通知信息 + /// 订阅用户列表 + /// + protected async Task PublishToSubscriberAsync( + INotificationPublishProvider provider, + NotificationInfo notificationInfo, + IEnumerable subscriptionUsers) + { + try + { + Logger.LogDebug($"Sending notification with provider {provider.Name}"); + // 发布 + await provider.PublishAsync(notificationInfo, subscriptionUsers); + + Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); + } + catch (Exception ex) + { + Logger.LogWarning($"Send notification error with provider {provider.Name}"); + Logger.LogWarning($"Error message:{ex.Message}"); + Logger.LogDebug($"Failed to send notification {notificationInfo.Name}. Try to push notification to background job"); + // 发送失败的消息进入后台队列 + await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers); + } + } + /// + /// 处理失败的消息进入后台队列 + /// + /// + /// 注: 如果入队失败,消息将被丢弃. + /// + /// + /// + /// + /// + protected async Task ProcessingFailedToQueueAsync( + INotificationPublishProvider provider, + NotificationInfo notificationInfo, + IEnumerable subscriptionUsers) + { + try + { + // 发送失败的消息进入后台队列 + await BackgroundJobManager.EnqueueAsync( + new NotificationPublishJobArgs( + notificationInfo.GetId(), + provider.GetType().AssemblyQualifiedName, + subscriptionUsers.ToList(), + notificationInfo.TenantId)); + } + catch (Exception ex) + { + Logger.LogWarning("Failed to push to background job, notification will be discarded, error cause: {message}", ex.Message); + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/TenantSynchronizer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/TenantSynchronizer.cs new file mode 100644 index 000000000..bfa3281be --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/TenantSynchronizer.cs @@ -0,0 +1,70 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.MicroService.MessageService.MultiTenancy; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.Saas.Tenants; +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Distributed +{ + public class TenantSynchronizer : + IDistributedEventHandler>, + IDistributedEventHandler>, + IDistributedEventHandler>, + IDistributedEventHandler, + ITransientDependency + { + protected ILogger Logger { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IDbSchemaMigrator DbSchemaMigrator { get; } + protected INotificationSender NotificationSender { get; } + protected ITenantConfigurationCache TenantConfigurationCache { get; } + protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + + public TenantSynchronizer( + ICurrentTenant currentTenant, + IDbSchemaMigrator dbSchemaMigrator, + IUnitOfWorkManager unitOfWorkManager, + INotificationSender notificationSender, + ITenantConfigurationCache tenantConfigurationCache, + INotificationSubscriptionManager notificationSubscriptionManager, + ILogger logger) + { + Logger = logger; + + CurrentTenant = currentTenant; + DbSchemaMigrator = dbSchemaMigrator; + UnitOfWorkManager = unitOfWorkManager; + TenantConfigurationCache = tenantConfigurationCache; + + NotificationSender = notificationSender; + NotificationSubscriptionManager = notificationSubscriptionManager; + } + + public async virtual Task HandleEventAsync(EntityCreatedEto eventData) + { + await TenantConfigurationCache.RefreshAsync(); + } + + public async virtual Task HandleEventAsync(EntityUpdatedEto eventData) + { + await TenantConfigurationCache.RefreshAsync(); + } + + public async virtual Task HandleEventAsync(EntityDeletedEto eventData) + { + await TenantConfigurationCache.RefreshAsync(); + } + + public async virtual Task HandleEventAsync(TenantConnectionStringUpdatedEto eventData) + { + await TenantConfigurationCache.RefreshAsync(); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/UserCreateEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/UserCreateEventHandler.cs new file mode 100644 index 000000000..2fcdd30f0 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Distributed/UserCreateEventHandler.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Local; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Distributed +{ + public class UserCreateEventHandler : IDistributedEventHandler>, ITransientDependency + { + private readonly ILocalEventBus _localEventBus; + public UserCreateEventHandler( + ILocalEventBus localEventBus) + { + _localEventBus = localEventBus; + } + /// + /// 接收添加用户事件,发布本地事件 + /// + /// + /// + public async Task HandleEventAsync(EntityCreatedEto eventData) + { + var localUserCreateEventData = new EntityCreatedEventData(eventData.Entity); + + await _localEventBus.PublishAsync(localUserCreateEventData); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateJoinIMEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateJoinIMEventHandler.cs new file mode 100644 index 000000000..05d92f455 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateJoinIMEventHandler.cs @@ -0,0 +1,59 @@ +using LINGYUN.Abp.MessageService.Chat; +using LINGYUN.Abp.MessageService.Notifications; +using LINGYUN.Abp.Notifications; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; +using Volo.Abp.Uow; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Local +{ + public class UserCreateJoinIMEventHandler : ILocalEventHandler>, ITransientDependency + { + private readonly IChatDataSeeder _chatDataSeeder; + private readonly INotificationSubscriptionManager _notificationSubscriptionManager; + public UserCreateJoinIMEventHandler( + IChatDataSeeder chatDataSeeder, + INotificationSubscriptionManager notificationSubscriptionManager) + { + _chatDataSeeder = chatDataSeeder; + _notificationSubscriptionManager = notificationSubscriptionManager; + } + /// + /// 接收添加用户事件,初始化IM用户种子 + /// + /// + /// + [UnitOfWork] + public async virtual Task HandleEventAsync(EntityCreatedEventData eventData) + { + await SeedChatDataAsync(eventData.Entity); + + await SeedUserSubscriptionNotifiersAsync(eventData.Entity); + } + + protected async virtual Task SeedChatDataAsync(IUserData user) + { + await _chatDataSeeder.SeedAsync(user); + } + + protected async virtual Task SeedUserSubscriptionNotifiersAsync(IUserData user) + { + var userIdentifier = new UserIdentifier(user.Id, user.UserName); + + await _notificationSubscriptionManager + .SubscribeAsync( + user.TenantId, + userIdentifier, + MessageServiceNotificationNames.IM.FriendValidation); + + await _notificationSubscriptionManager + .SubscribeAsync( + user.TenantId, + userIdentifier, + MessageServiceNotificationNames.IM.NewFriend); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateSendWelcomeEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateSendWelcomeEventHandler.cs new file mode 100644 index 000000000..3e842936b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserCreateSendWelcomeEventHandler.cs @@ -0,0 +1,72 @@ +using LINGYUN.Abp.Notifications; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Local +{ + public class UserCreateSendWelcomeEventHandler : ILocalEventHandler>, ITransientDependency + { + private readonly INotificationSender _notificationSender; + private readonly INotificationSubscriptionManager _notificationSubscriptionManager; + public UserCreateSendWelcomeEventHandler( + INotificationSender notificationSender, + INotificationSubscriptionManager notificationSubscriptionManager + ) + { + _notificationSender = notificationSender; + _notificationSubscriptionManager = notificationSubscriptionManager; + } + + public async Task HandleEventAsync(EntityCreatedEventData eventData) + { + var userIdentifer = new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName); + // 订阅用户欢迎消息 + await SubscribeInternalNotifers(userIdentifer, eventData.Entity.TenantId); + + await _notificationSender.SendNofiterAsync( + UserNotificationNames.WelcomeToApplication, + new NotificationTemplate( + UserNotificationNames.WelcomeToApplication, + formUser: eventData.Entity.UserName, + data: new Dictionary + { + { "name", eventData.Entity.UserName }, + }), + userIdentifer, + eventData.Entity.TenantId, + NotificationSeverity.Info); + } + + private async Task SubscribeInternalNotifers(UserIdentifier userIdentifer, Guid? tenantId = null) + { + // 订阅内置通知 + await _notificationSubscriptionManager + .SubscribeAsync( + tenantId, + userIdentifer, + DefaultNotifications.SystemNotice); + await _notificationSubscriptionManager + .SubscribeAsync( + tenantId, + userIdentifer, + DefaultNotifications.OnsideNotice); + await _notificationSubscriptionManager + .SubscribeAsync( + tenantId, + userIdentifer, + DefaultNotifications.ActivityNotice); + + // 订阅用户欢迎消息 + await _notificationSubscriptionManager + .SubscribeAsync( + tenantId, + userIdentifer, + UserNotificationNames.WelcomeToApplication); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserSubscribeSessionExpirationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserSubscribeSessionExpirationEventHandler.cs new file mode 100644 index 000000000..aea56ee94 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Handlers/Local/UserSubscribeSessionExpirationEventHandler.cs @@ -0,0 +1,35 @@ +using LINGYUN.Abp.Identity.Notifications; +using LINGYUN.Abp.Notifications; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.MessageService.Handlers.Local; + +public class UserSubscribeSessionExpirationEventHandler : ILocalEventHandler>, ITransientDependency +{ + private readonly INotificationSubscriptionManager _notificationSubscriptionManager; + + public UserSubscribeSessionExpirationEventHandler(INotificationSubscriptionManager notificationSubscriptionManager) + { + _notificationSubscriptionManager = notificationSubscriptionManager; + } + + public async virtual Task HandleEventAsync(EntityCreatedEventData eventData) + { + // 新用户订阅会话过期通知 + await _notificationSubscriptionManager + .SubscribeAsync( + eventData.Entity.TenantId, + new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName), + IdentityNotificationNames.Session.ExpirationSession); + // 新用户订阅不活跃用户清理通知 + await _notificationSubscriptionManager + .SubscribeAsync( + eventData.Entity.TenantId, + new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName), + IdentityNotificationNames.IdentityUser.CleaningUpInactiveUsers); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj new file mode 100644 index 000000000..7ea73830e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj @@ -0,0 +1,97 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.MessageService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.Configure.cs new file mode 100644 index 000000000..e3a02dae8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.Configure.cs @@ -0,0 +1,493 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.MessageService.Localization; +using LINGYUN.Abp.MicroService.MessageService.BackgroundJobs; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.TextTemplating; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Quartz; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Quartz; +using Volo.Abp.Security.Claims; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.MessageService; + +public partial class MessageServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 20; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureQuartz(IConfiguration configuration) + { + PreConfigure(options => + { + // 如果使用持久化存储, 则配置quartz持久层 + if (configuration.GetSection("Quartz:UsePersistentStore").Get()) + { + var settings = configuration.GetSection("Quartz:Properties").Get>(); + if (settings != null) + { + foreach (var setting in settings) + { + options.Properties[setting.Key] = setting.Value; + } + } + + options.Configurator += (config) => + { + config.UsePersistentStore(store => + { + store.UseProperties = false; + store.UseNewtonsoftJsonSerializer(); + }); + }; + } + }); + } + + private void ConfigureBackgroundTasks(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + var applicationName = services.GetApplicationName(); + options.NodeName = applicationName; + + options.JobDispatcherSelectors.AddJob( + job => + { + job.Interval = 10; + job.MaxTryCount = 10; + job.NodeName = applicationName; + }); + }); + } + + private void ConfigureTextTemplating() + { + Configure(options => + { + options.IsDynamicTemplateDefinitionStoreEnabled = true; + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void PreConfigureSignalR(IConfiguration configuration) + { + PreConfigure(builder => + { + var redisEnabled = configuration["SignalR:Redis:IsEnabled"]; + if (redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled)) + { + builder.AddStackExchangeRedis(redis => + { + var redisConfiguration = configuration["SignalR:Redis:Configuration"]; + if (!redisConfiguration.IsNullOrEmpty()) + { + redis.ConnectionFactory = async (writer) => + { + return await ConnectionMultiplexer.ConnectAsync(redisConfiguration); + }; + } + }); + } + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.MessageService"); + }); + } + + private void ConfigureNotifications() + { + Configure(options => + { + // 宿主项目启用动态通知 + options.IsDynamicNotificationsStoreEnabled = true; + options.SaveStaticNotificationsToDatabase = true; + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Message Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Message Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + + options.Resources + .Get() + .AddVirtualJson("/Localization/Resources"); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + if (context.Token.IsNullOrWhiteSpace()) + { + var accessToken = context.Request.Query["access_token"]; + if (!accessToken.IsNullOrEmpty()) + { + context.Token = accessToken; + } + } + return Task.CompletedTask; + } + }; + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs new file mode 100644 index 000000000..5445db5cd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs @@ -0,0 +1,166 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.BackgroundTasks.DistributedLocking; +using LINGYUN.Abp.BackgroundTasks.ExceptionHandling; +using LINGYUN.Abp.BackgroundTasks.Quartz; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Notifications; +using LINGYUN.Abp.Features.LimitValidation.Redis; +using LINGYUN.Abp.Identity.EntityFrameworkCore; +using LINGYUN.Abp.Identity.Notifications; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Identity.WeChat; +using LINGYUN.Abp.Identity.WeChat.Work; +using LINGYUN.Abp.IM.SignalR; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.MessageService; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.Notifications.Common; +using LINGYUN.Abp.Notifications.Emailing; +using LINGYUN.Abp.Notifications.EntityFrameworkCore; +using LINGYUN.Abp.Notifications.Jobs; +using LINGYUN.Abp.Notifications.SignalR; +using LINGYUN.Abp.Notifications.Sms; +using LINGYUN.Abp.Notifications.Templating; +using LINGYUN.Abp.Notifications.WeChat.MiniProgram; +using LINGYUN.Abp.Notifications.WeChat.Work; +using LINGYUN.Abp.Notifications.WxPusher; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using LINGYUN.Abp.TextTemplating.Scriban; +using LINGYUN.Abp.WeChat.Official.Handlers; +using LINGYUN.Abp.WeChat.Work.Handlers; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.MessageService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpMessageServiceApplicationModule), + typeof(AbpMessageServiceHttpApiModule), + typeof(AbpNotificationsApplicationModule), + typeof(AbpNotificationsHttpApiModule), + typeof(AbpIdentityWeChatModule), + typeof(AbpIdentityWeChatWorkModule), + typeof(AbpBackgroundTasksQuartzModule), + typeof(AbpBackgroundTasksDistributedLockingModule), + typeof(AbpBackgroundTasksExceptionHandlingModule), + typeof(TaskManagementEntityFrameworkCoreModule), + typeof(AbpMessageServiceEntityFrameworkCoreModule), + typeof(AbpNotificationsEntityFrameworkCoreModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpTextTemplatingEntityFrameworkCoreModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(MessageServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpBackgroundWorkersModule), + typeof(AbpIMSignalRModule), + typeof(AbpNotificationsJobsModule), + typeof(AbpNotificationsCommonModule), + typeof(AbpNotificationsSmsModule), + typeof(AbpNotificationsEmailingModule), + typeof(AbpNotificationsSignalRModule), + typeof(AbpNotificationsWxPusherModule), + typeof(AbpNotificationsWeChatMiniProgramModule), + typeof(AbpNotificationsWeChatWorkModule), + typeof(AbpNotificationsExceptionHandlingModule), + typeof(AbpNotificationsTemplatingModule), + typeof(AbpWeChatWorkHandlersModule), + typeof(AbpWeChatOfficialHandlersModule), + typeof(AbpIdentityNotificationsModule), + + // 重写模板引擎支持外部本地化 + typeof(AbpTextTemplatingScribanModule), + + typeof(AbpCAPEventBusModule), + typeof(AbpFeaturesValidationRedisModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpSmsPlatformModule), + typeof(AbpHttpClientModule), + typeof(AbpClaimsMappingModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAutofacModule) + )] +public partial class MessageServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureQuartz(configuration); + PreConfigureSignalR(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureNotifications(); + ConfigureTextTemplating(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureIdentity(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureBackgroundTasks(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/ITenantConfigurationCache.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/ITenantConfigurationCache.cs new file mode 100644 index 000000000..f9f8d02a3 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/ITenantConfigurationCache.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.MessageService.MultiTenancy; + +public interface ITenantConfigurationCache +{ + Task RefreshAsync(); + + Task> GetTenantsAsync(); +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCache.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCache.cs new file mode 100644 index 000000000..ab9e4ec67 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCache.cs @@ -0,0 +1,62 @@ +using LINGYUN.Abp.Saas.Tenants; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.MessageService.MultiTenancy; + +public class TenantConfigurationCache : ITenantConfigurationCache, ITransientDependency +{ + protected ITenantRepository TenantRepository { get; } + protected IDistributedCache TenantCache { get; } + + public TenantConfigurationCache( + ITenantRepository tenantRepository, + IDistributedCache tenantCache) + { + TenantRepository = tenantRepository; + TenantCache = tenantCache; + } + + public async virtual Task RefreshAsync() + { + var cacheKey = GetCacheKey(); + + await TenantCache.RemoveAsync(cacheKey); + } + + public async virtual Task> GetTenantsAsync() + { + return (await GetForCacheItemAsync()).Tenants; + } + + protected async virtual Task GetForCacheItemAsync() + { + var cacheKey = GetCacheKey(); + var cacheItem = await TenantCache.GetAsync(cacheKey); + if (cacheItem == null) + { + var allActiveTenants = await TenantRepository.GetListAsync(); + + cacheItem = new TenantConfigurationCacheItem( + allActiveTenants + .Where(t => t.IsActive) + .Select(t => new TenantConfiguration(t.Id, t.Name) + { + IsActive = t.IsActive, + }).ToList()); + + await TenantCache.SetAsync(cacheKey, cacheItem); + } + + return cacheItem; + } + + protected virtual string GetCacheKey() + { + return "_Abp_Tenant_Configuration"; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCacheItem.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCacheItem.cs new file mode 100644 index 000000000..8504783cb --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MultiTenancy/TenantConfigurationCacheItem.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.MessageService.MultiTenancy; + +[IgnoreMultiTenancy] +public class TenantConfigurationCacheItem +{ + public List Tenants { get; set; } + + public TenantConfigurationCacheItem() + { + Tenants = new List(); + } + + public TenantConfigurationCacheItem(List tenants) + { + Tenants = tenants; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Program.cs new file mode 100644 index 000000000..3a660d399 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Program.cs @@ -0,0 +1,105 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.MessageService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting MessageService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "MessageService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + // 本地化 + app.UseMapRequestLocalization(); + // http调用链 + app.UseCorrelationId(); + // 虚拟文件系统 + app.MapAbpStaticAssets(); + // 路由 + app.UseRouting(); + // 跨域 + app.UseCors(); + // 认证 + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + // 多租户 + app.UseMultiTenancy(); + // 会话 + app.UseAbpSession(); + app.UseDynamicClaims(); + // 授权 + app.UseAuthorization(); + // Swagger + app.UseSwagger(); + // Swagger可视化界面 + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Message Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + // 审计日志 + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + // 路由 + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Properties/launchSettings.json new file mode 100644 index 000000000..9cbc1f040 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.MessageService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:63618;http://localhost:63619" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/TenantHeaderParamter.cs new file mode 100644 index 000000000..b78b7ef01 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.MessageService; + +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/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json new file mode 100644 index 000000000..25080e466 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json @@ -0,0 +1,153 @@ +{ + "App": { + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "Forwarded": { + "ForwardedHeaders": 5, + "KnownProxies": [ + "localhost" + ] + }, + "ShowPii": true, + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Features": { + "Validation": { + "Redis": { + "Configuration": "localhost,defaultDatabase=8", + "InstanceName": "LINGYUN.Abp.Application" + } + } + }, + "Redis": { + "IsEnabled": true, + "Configuration": "localhost,defaultDatabase=8", + "InstanceName": "LINGYUN.Abp.Application" + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "SignalR": { + "Redis": { + "IsEnabled": true, + "Configuration": "localhost,defaultDatabase=13,channelPrefix=abp-realtime-channel" + } + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "Quartz": { + "UsePersistentStore": true, + "Properties": { + "quartz.jobStore.dataSource": "tkm", + "quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz", + "quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate,Quartz", + "quartz.dataSource.tkm.connectionStringName": "Default", + "quartz.dataSource.tkm.provider": "Npgsql", + "quartz.jobStore.clustered": "true", + "quartz.serializer.type": "json", + "quartz.scheduler.instanceName": "MessageService", + "quartz.scheduler.instanceId": "3c36620a-d8c5-4c89-9828-78f33547751d" + } + }, + "Notifications": { + "WeChat": { + "WeApp": { + "DefaultWeAppState": "formal" + } + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "MessageService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "msg", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft.EntityFrameworkCore": "Warning", + "DotNetCore.CAP": "Debug", + "System": "Warning", + "Microsoft": "Warning", + "Microsoft.AspNetCore.SignalR": "Debug", + "Microsoft.AspNetCore.Http.Connections": "Debug" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.json new file mode 100644 index 000000000..3c85151c7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.json @@ -0,0 +1,99 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "App": { + "CorsOrigins": "http://localhost:3100" + }, + "AllowedHosts": "*", + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/LINGYUN.Abp.MicroService.PlatformService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/LINGYUN.Abp.MicroService.PlatformService.DbMigrator.csproj new file mode 100644 index 000000000..1c60e106a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/LINGYUN.Abp.MicroService.PlatformService.DbMigrator.csproj @@ -0,0 +1,42 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.PlatformService + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..974e4b64d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.PlatformService; +public class PlatformServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public PlatformServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorModule.cs new file mode 100644 index 000000000..0fb56cf52 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/PlatformServiceDbMigratorModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(PlatformServiceMigrationsEntityFrameworkCoreModule) + )] +public class PlatformServiceDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/Program.cs new file mode 100644 index 000000000..702b614d2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/Program.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.MicroService.PlatformService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.PlatformService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.PlatformService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..ae3d3a24b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj @@ -0,0 +1,30 @@ + + + + + + + false + net9.0 + LINGYUN.Abp.MicroService.PlatformService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.Designer.cs new file mode 100644 index 000000000..9ace94eae --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.Designer.cs @@ -0,0 +1,1331 @@ +// +using System; +using LINGYUN.Abp.MicroService.PlatformService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.PlatformService.Migrations +{ + [DbContext(typeof(PlatformServiceMigrationsDbContext))] + [Migration("20260106000241_Initial_Platform_Service")] + partial class Initial_Platform_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Name"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AppPlatformDatas", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowBeNull") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataId") + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DefaultValue"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Name"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DataId"); + + b.HasIndex("Name"); + + b.ToTable("AppPlatformDataItems", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.Feedback", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Category"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformFeedbacks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("FeedbackId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Url"); + + b.HasKey("Id"); + + b.HasIndex("FeedbackId"); + + b.ToTable("AppPlatformFeedbackAttachments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Capacity") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Capacity"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("FeedbackId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("FeedbackId"); + + b.ToTable("AppPlatformFeedbackComments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Layouts.Layout", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Path") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("Redirect") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Redirect"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformLayouts", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.Menu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(23) + .HasColumnType("character varying(23)") + .HasColumnName("Code"); + + b.Property("Component") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Component"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsPublic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("Path") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("Redirect") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Redirect"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.RoleMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("RoleName"); + + b.Property("Startup") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleName", "MenuId"); + + b.ToTable("AppPlatformRoleMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.UserFavoriteMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AliasName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("AliasName"); + + b.Property("Color") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Color"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("Icon") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Icon"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "MenuId"); + + b.ToTable("AppPlatformUserFavoriteMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.UserMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("Startup") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "MenuId"); + + b.ToTable("AppPlatformUserMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BodyTransferEncoding") + .HasColumnType("integer"); + + b.Property("CC") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("CC"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeliveryNotificationOptions") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("From") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("From"); + + b.Property("IsBodyHtml") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Normalize") + .HasColumnType("boolean"); + + b.Property("Priority") + .HasColumnType("integer"); + + b.Property("Provider") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Provider"); + + b.Property("Reason") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Reason"); + + b.Property("Receiver") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Receiver"); + + b.Property("SendCount") + .HasColumnType("integer"); + + b.Property("SendTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Sender") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Sender"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Subject"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformEmailMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BlobName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("BlobName"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Name"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("AppPlatformEmailMessageAttachments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageHeader", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Key") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Key"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("AppPlatformEmailMessageHeaders", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.SmsMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Provider") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Provider"); + + b.Property("Reason") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Reason"); + + b.Property("Receiver") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Receiver"); + + b.Property("SendCount") + .HasColumnType("integer"); + + b.Property("SendTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Sender") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Sender"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformSmsMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.Package", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Authors") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Authors"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Description"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("ForceUpdate") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("Note") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Note"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Version"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Version"); + + b.ToTable("AppPlatformPackages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.PackageBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Authors") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Authors"); + + b.Property("ContentType") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ContentType"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DownloadCount") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("License") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("License"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("PackageId") + .HasColumnType("uuid"); + + b.Property("SHA256") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SHA256"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Summary") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Summary"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Url") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Url"); + + b.HasKey("Id"); + + b.HasIndex("PackageId", "Name"); + + b.ToTable("AppPlatformPackageBlobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Portal.Enterprise", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Address"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("EnglishName") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("EnglishName"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LegalMan") + .HasMaxLength(60) + .HasColumnType("character varying(60)") + .HasColumnName("LegalMan"); + + b.Property("Logo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Logo"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("OrganizationCode") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("OrganizationCode"); + + b.Property("RegistrationCode") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("RegistrationCode"); + + b.Property("RegistrationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TaxCode") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("TaxCode"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformEnterprises", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b => + { + b.HasOne("LINGYUN.Platform.Datas.Data", null) + .WithMany("Items") + .HasForeignKey("DataId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackAttachment", b => + { + b.HasOne("LINGYUN.Platform.Feedbacks.Feedback", null) + .WithMany("Attachments") + .HasForeignKey("FeedbackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackComment", b => + { + b.HasOne("LINGYUN.Platform.Feedbacks.Feedback", null) + .WithMany("Comments") + .HasForeignKey("FeedbackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageAttachment", b => + { + b.HasOne("LINGYUN.Platform.Messages.EmailMessage", null) + .WithMany("Attachments") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageHeader", b => + { + b.HasOne("LINGYUN.Platform.Messages.EmailMessage", null) + .WithMany("Headers") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.PackageBlob", b => + { + b.HasOne("LINGYUN.Platform.Packages.Package", "Package") + .WithMany("Blobs") + .HasForeignKey("PackageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Package"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.Feedback", b => + { + b.Navigation("Attachments"); + + b.Navigation("Comments"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessage", b => + { + b.Navigation("Attachments"); + + b.Navigation("Headers"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.Package", b => + { + b.Navigation("Blobs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.cs new file mode 100644 index 000000000..ecb3ba10e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/20260106000241_Initial_Platform_Service.cs @@ -0,0 +1,583 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.PlatformService.Migrations +{ + /// + public partial class Initial_Platform_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AppPlatformDatas", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(30)", maxLength: 30, nullable: false), + Code = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + IsStatic = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformDatas", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformEmailMessages", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + From = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Subject = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + IsBodyHtml = table.Column(type: "boolean", nullable: false), + CC = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + Normalize = table.Column(type: "boolean", nullable: false), + Priority = table.Column(type: "integer", nullable: true), + BodyTransferEncoding = table.Column(type: "integer", nullable: true), + DeliveryNotificationOptions = table.Column(type: "integer", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + Sender = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Provider = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Receiver = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + Content = table.Column(type: "text", nullable: false), + SendTime = table.Column(type: "timestamp with time zone", nullable: true), + SendCount = table.Column(type: "integer", nullable: false), + Status = table.Column(type: "integer", nullable: false), + Reason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformEmailMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformEnterprises", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + EnglishName = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + Logo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + Address = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + LegalMan = table.Column(type: "character varying(60)", maxLength: 60, nullable: true), + TaxCode = table.Column(type: "character varying(40)", maxLength: 40, nullable: true), + OrganizationCode = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + RegistrationCode = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + RegistrationDate = table.Column(type: "timestamp with time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformEnterprises", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformFeedbacks", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Content = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Category = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Status = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformFeedbacks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformLayouts", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Framework = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DataId = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + Path = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "text", nullable: true), + Redirect = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformLayouts", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformMenus", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Framework = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Code = table.Column(type: "character varying(23)", maxLength: 23, nullable: false), + Component = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + ParentId = table.Column(type: "uuid", nullable: true), + LayoutId = table.Column(type: "uuid", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + Path = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "text", nullable: true), + Redirect = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformMenus", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformPackages", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Note = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + Version = table.Column(type: "character varying(30)", maxLength: 30, nullable: false), + Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + ForceUpdate = table.Column(type: "boolean", nullable: false), + Authors = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Level = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformPackages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformRoleMenus", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + MenuId = table.Column(type: "uuid", nullable: false), + RoleName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Startup = table.Column(type: "boolean", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformRoleMenus", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformSmsMessages", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + Sender = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Provider = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Receiver = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + Content = table.Column(type: "text", nullable: false), + SendTime = table.Column(type: "timestamp with time zone", nullable: true), + SendCount = table.Column(type: "integer", nullable: false), + Status = table.Column(type: "integer", nullable: false), + Reason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformSmsMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformUserFavoriteMenus", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + MenuId = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + AliasName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Color = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + Framework = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Path = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Icon = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformUserFavoriteMenus", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformUserMenus", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + MenuId = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + Startup = table.Column(type: "boolean", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformUserMenus", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformDataItems", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(30)", maxLength: 30, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DefaultValue = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + AllowBeNull = table.Column(type: "boolean", nullable: false, defaultValue: true), + IsStatic = table.Column(type: "boolean", nullable: false), + ValueType = table.Column(type: "integer", nullable: false), + DataId = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformDataItems", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformDataItems_AppPlatformDatas_DataId", + column: x => x.DataId, + principalTable: "AppPlatformDatas", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformEmailMessageAttachments", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + MessageId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + BlobName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Size = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformEmailMessageAttachments", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformEmailMessageAttachments_AppPlatformEmailMessages~", + column: x => x.MessageId, + principalTable: "AppPlatformEmailMessages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformEmailMessageHeaders", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + MessageId = table.Column(type: "uuid", nullable: false), + Key = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformEmailMessageHeaders", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformEmailMessageHeaders_AppPlatformEmailMessages_Mes~", + column: x => x.MessageId, + principalTable: "AppPlatformEmailMessages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformFeedbackAttachments", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Url = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Size = table.Column(type: "bigint", nullable: false), + FeedbackId = table.Column(type: "uuid", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformFeedbackAttachments", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformFeedbackAttachments_AppPlatformFeedbacks_Feedbac~", + column: x => x.FeedbackId, + principalTable: "AppPlatformFeedbacks", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformFeedbackComments", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Capacity = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Content = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + FeedbackId = table.Column(type: "uuid", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformFeedbackComments", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformFeedbackComments_AppPlatformFeedbacks_FeedbackId", + column: x => x.FeedbackId, + principalTable: "AppPlatformFeedbacks", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AppPlatformPackageBlobs", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + PackageId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Url = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + Size = table.Column(type: "bigint", nullable: true), + Summary = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true), + License = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + Authors = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ContentType = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SHA256 = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DownloadCount = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppPlatformPackageBlobs", x => x.Id); + table.ForeignKey( + name: "FK_AppPlatformPackageBlobs_AppPlatformPackages_PackageId", + column: x => x.PackageId, + principalTable: "AppPlatformPackages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformDataItems_DataId", + table: "AppPlatformDataItems", + column: "DataId"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformDataItems_Name", + table: "AppPlatformDataItems", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformDatas_Name", + table: "AppPlatformDatas", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformEmailMessageAttachments_MessageId", + table: "AppPlatformEmailMessageAttachments", + column: "MessageId"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformEmailMessageHeaders_MessageId", + table: "AppPlatformEmailMessageHeaders", + column: "MessageId"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformFeedbackAttachments_FeedbackId", + table: "AppPlatformFeedbackAttachments", + column: "FeedbackId"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformFeedbackComments_FeedbackId", + table: "AppPlatformFeedbackComments", + column: "FeedbackId"); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformPackageBlobs_PackageId_Name", + table: "AppPlatformPackageBlobs", + columns: new[] { "PackageId", "Name" }); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformPackages_Name_Version", + table: "AppPlatformPackages", + columns: new[] { "Name", "Version" }); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformRoleMenus_RoleName_MenuId", + table: "AppPlatformRoleMenus", + columns: new[] { "RoleName", "MenuId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformUserFavoriteMenus_UserId_MenuId", + table: "AppPlatformUserFavoriteMenus", + columns: new[] { "UserId", "MenuId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppPlatformUserMenus_UserId_MenuId", + table: "AppPlatformUserMenus", + columns: new[] { "UserId", "MenuId" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AppPlatformDataItems"); + + migrationBuilder.DropTable( + name: "AppPlatformEmailMessageAttachments"); + + migrationBuilder.DropTable( + name: "AppPlatformEmailMessageHeaders"); + + migrationBuilder.DropTable( + name: "AppPlatformEnterprises"); + + migrationBuilder.DropTable( + name: "AppPlatformFeedbackAttachments"); + + migrationBuilder.DropTable( + name: "AppPlatformFeedbackComments"); + + migrationBuilder.DropTable( + name: "AppPlatformLayouts"); + + migrationBuilder.DropTable( + name: "AppPlatformMenus"); + + migrationBuilder.DropTable( + name: "AppPlatformPackageBlobs"); + + migrationBuilder.DropTable( + name: "AppPlatformRoleMenus"); + + migrationBuilder.DropTable( + name: "AppPlatformSmsMessages"); + + migrationBuilder.DropTable( + name: "AppPlatformUserFavoriteMenus"); + + migrationBuilder.DropTable( + name: "AppPlatformUserMenus"); + + migrationBuilder.DropTable( + name: "AppPlatformDatas"); + + migrationBuilder.DropTable( + name: "AppPlatformEmailMessages"); + + migrationBuilder.DropTable( + name: "AppPlatformFeedbacks"); + + migrationBuilder.DropTable( + name: "AppPlatformPackages"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/PlatformServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/PlatformServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..7a696a9fa --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/Migrations/PlatformServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,1328 @@ +// +using System; +using LINGYUN.Abp.MicroService.PlatformService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.PlatformService.Migrations +{ + [DbContext(typeof(PlatformServiceMigrationsDbContext))] + partial class PlatformServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Name"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AppPlatformDatas", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowBeNull") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataId") + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DefaultValue"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Description"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Name"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DataId"); + + b.HasIndex("Name"); + + b.ToTable("AppPlatformDataItems", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.Feedback", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Category"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformFeedbacks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("FeedbackId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Url"); + + b.HasKey("Id"); + + b.HasIndex("FeedbackId"); + + b.ToTable("AppPlatformFeedbackAttachments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Capacity") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Capacity"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("FeedbackId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("FeedbackId"); + + b.ToTable("AppPlatformFeedbackComments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Layouts.Layout", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Path") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("Redirect") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Redirect"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformLayouts", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.Menu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(23) + .HasColumnType("character varying(23)") + .HasColumnName("Code"); + + b.Property("Component") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Component"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsPublic") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("Path") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("Redirect") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Redirect"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.RoleMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("RoleName"); + + b.Property("Startup") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleName", "MenuId"); + + b.ToTable("AppPlatformRoleMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.UserFavoriteMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AliasName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("AliasName"); + + b.Property("Color") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Color"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("Framework") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Framework"); + + b.Property("Icon") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Icon"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Path"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "MenuId"); + + b.ToTable("AppPlatformUserFavoriteMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Menus.UserMenu", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MenuId") + .HasColumnType("uuid"); + + b.Property("Startup") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "MenuId"); + + b.ToTable("AppPlatformUserMenus", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BodyTransferEncoding") + .HasColumnType("integer"); + + b.Property("CC") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("CC"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeliveryNotificationOptions") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("From") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("From"); + + b.Property("IsBodyHtml") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Normalize") + .HasColumnType("boolean"); + + b.Property("Priority") + .HasColumnType("integer"); + + b.Property("Provider") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Provider"); + + b.Property("Reason") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Reason"); + + b.Property("Receiver") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Receiver"); + + b.Property("SendCount") + .HasColumnType("integer"); + + b.Property("SendTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Sender") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Sender"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Subject"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformEmailMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BlobName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("BlobName"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Name"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("AppPlatformEmailMessageAttachments", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageHeader", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Key") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Key"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("AppPlatformEmailMessageHeaders", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.SmsMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Provider") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Provider"); + + b.Property("Reason") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Reason"); + + b.Property("Receiver") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Receiver"); + + b.Property("SendCount") + .HasColumnType("integer"); + + b.Property("SendTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Sender") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Sender"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformSmsMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.Package", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Authors") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Authors"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Description"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("ForceUpdate") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("Note") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Note"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("Version"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Version"); + + b.ToTable("AppPlatformPackages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.PackageBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Authors") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Authors"); + + b.Property("ContentType") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ContentType"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DownloadCount") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("License") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("License"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("PackageId") + .HasColumnType("uuid"); + + b.Property("SHA256") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SHA256"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Summary") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("Summary"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Url") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Url"); + + b.HasKey("Id"); + + b.HasIndex("PackageId", "Name"); + + b.ToTable("AppPlatformPackageBlobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Portal.Enterprise", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Address"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("EnglishName") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("EnglishName"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LegalMan") + .HasMaxLength(60) + .HasColumnType("character varying(60)") + .HasColumnName("LegalMan"); + + b.Property("Logo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("Logo"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Name"); + + b.Property("OrganizationCode") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("OrganizationCode"); + + b.Property("RegistrationCode") + .HasMaxLength(30) + .HasColumnType("character varying(30)") + .HasColumnName("RegistrationCode"); + + b.Property("RegistrationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TaxCode") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("TaxCode"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("AppPlatformEnterprises", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b => + { + b.HasOne("LINGYUN.Platform.Datas.Data", null) + .WithMany("Items") + .HasForeignKey("DataId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackAttachment", b => + { + b.HasOne("LINGYUN.Platform.Feedbacks.Feedback", null) + .WithMany("Attachments") + .HasForeignKey("FeedbackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.FeedbackComment", b => + { + b.HasOne("LINGYUN.Platform.Feedbacks.Feedback", null) + .WithMany("Comments") + .HasForeignKey("FeedbackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageAttachment", b => + { + b.HasOne("LINGYUN.Platform.Messages.EmailMessage", null) + .WithMany("Attachments") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessageHeader", b => + { + b.HasOne("LINGYUN.Platform.Messages.EmailMessage", null) + .WithMany("Headers") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.PackageBlob", b => + { + b.HasOne("LINGYUN.Platform.Packages.Package", "Package") + .WithMany("Blobs") + .HasForeignKey("PackageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Package"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Feedbacks.Feedback", b => + { + b.Navigation("Attachments"); + + b.Navigation("Comments"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Messages.EmailMessage", b => + { + b.Navigation("Attachments"); + + b.Navigation("Headers"); + }); + + modelBuilder.Entity("LINGYUN.Platform.Packages.Package", b => + { + b.Navigation("Blobs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..b987094fe --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs @@ -0,0 +1,100 @@ +using LINGYUN.Abp.Saas.Tenants; +using LINGYUN.Abp.UI.Navigation; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Features; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.PlatformService; +public class PlatformServiceDbMigrationEventHandler : + EfCoreDatabaseMigrationEventHandlerBase, + IDistributedEventHandler +{ + protected IEnumerable NavigationSeedContributors { get; } + protected INavigationProvider NavigationProvider { get; } + protected IFeatureChecker FeatureChecker { get; } + protected IConfiguration Configuration { get; } + public PlatformServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + IFeatureChecker featureChecker, + IConfiguration configuration, + INavigationProvider navigationProvider, + IEnumerable navigationSeedContributors) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + FeatureChecker = featureChecker; + Configuration = configuration; + NavigationProvider = navigationProvider; + NavigationSeedContributors = navigationSeedContributors; + } + + protected async override Task SeedAsync(Guid? tenantId) + { + using (CurrentTenant.Change(tenantId)) + { + var menus = await NavigationProvider.GetAllAsync(); + + var multiTenancySides = CurrentTenant.IsAvailable + ? MultiTenancySides.Tenant + : MultiTenancySides.Host; + + var seedContext = new NavigationSeedContext(menus, multiTenancySides); + + foreach (var contributor in NavigationSeedContributors) + { + await contributor.SeedAsync(seedContext); + } + } + } + + public async virtual Task HandleEventAsync(TenantDeletedEto eventData) + { + var hostDefaultConnectionString = Configuration.GetConnectionString(ConnectionStrings.DefaultConnectionStringName); + using (CurrentTenant.Change(eventData.Id)) + { + // 需要回收策略为回收且存在默认连接字符串且默认连接字符串与宿主不同 + if (eventData.Strategy == RecycleStrategy.Recycle && !eventData.DefaultConnectionString.IsNullOrWhiteSpace()) + { + var hostConnection = new DbConnectionStringBuilder() + { + ConnectionString = hostDefaultConnectionString, + }; + var tenantConnection = new DbConnectionStringBuilder() + { + ConnectionString = eventData.DefaultConnectionString, + }; + if (hostConnection.EquivalentTo(tenantConnection)) + { + return; + } + + using var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true); + var buildr = new DbContextOptionsBuilder(); + buildr.UseNpgsql(eventData.DefaultConnectionString); + await using var dbConnection = new DbContext(buildr.Options); + if ((await dbConnection.Database.GetAppliedMigrationsAsync()).Any()) + { + await dbConnection.Database.EnsureDeletedAsync(); + } + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs new file mode 100644 index 000000000..e8f51a089 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.PlatformService; +public class PlatformServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public PlatformServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContext.cs new file mode 100644 index 000000000..67209d167 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContext.cs @@ -0,0 +1,55 @@ +using LINGYUN.Platform.Datas; +using LINGYUN.Platform.EntityFrameworkCore; +using LINGYUN.Platform.Layouts; +using LINGYUN.Platform.Menus; +using LINGYUN.Platform.Messages; +using LINGYUN.Platform.Packages; +using LINGYUN.Platform.Portal; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +[ConnectionStringName("Default")] +public class PlatformServiceMigrationsDbContext : + AbpDbContext, + IPlatformDbContext +{ + public DbSet Menus { get; set; } + + public DbSet Layouts { get; set; } + + public DbSet RoleMenus { get; set; } + + public DbSet UserMenus { get; set; } + + public DbSet UserFavoriteMenus { get; set; } + + public DbSet Datas { get; set; } + + public DbSet DataItems { get; set; } + + public DbSet Packages { get; set; } + + public DbSet PackageBlobs { get; set; } + + public DbSet Enterprises { get; set; } + + public DbSet EmailMessages { get; set; } + + public DbSet SmsMessages { get; set; } + + public PlatformServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigurePlatform(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..1695dc611 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsDbContextFactory.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +public class PlatformServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public PlatformServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new PlatformServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.PlatformService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..f361163fd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,43 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.UI.Navigation; +using LINGYUN.Platform.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +[DependsOn( + typeof(AbpUINavigationModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(PlatformEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpDataDbMigratorModule) + )] +public class PlatformServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/BackgroundWorkers/OssObjectTempCleanupBackgroundWorker.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/BackgroundWorkers/OssObjectTempCleanupBackgroundWorker.cs new file mode 100644 index 000000000..c17321df2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/BackgroundWorkers/OssObjectTempCleanupBackgroundWorker.cs @@ -0,0 +1,69 @@ +using LINGYUN.Abp.MicroService.PlatformService.MultiTenancy; +using LINGYUN.Abp.OssManagement; +using Microsoft.Extensions.Options; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.DistributedLocking; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.MicroService.PlatformService.BackgroundWorkers; + +public class OssObjectTempCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase +{ + protected ICurrentTenant CurrentTenant { get; } + protected IAbpDistributedLock DistributedLock { get; } + protected ITenantConfigurationCache TenantConfigurationCache { get; } + + public OssObjectTempCleanupBackgroundWorker( + AbpAsyncTimer timer, + IServiceScopeFactory serviceScopeFactory, + IOptionsMonitor cleanupOptions, + IAbpDistributedLock distributedLock, + ICurrentTenant currentTenant, + ITenantConfigurationCache tenantConfigurationCache) + : base(timer, serviceScopeFactory) + { + CurrentTenant = currentTenant; + DistributedLock = distributedLock; + TenantConfigurationCache = tenantConfigurationCache; + timer.Period = cleanupOptions.CurrentValue.CleanupPeriod; + } + + protected async override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await using var handle = await DistributedLock.TryAcquireAsync(nameof(OssObjectTempCleanupBackgroundWorker)); + + Logger.LogInformation($"Lock is acquired for {nameof(OssObjectTempCleanupBackgroundWorker)}"); + + if (handle != null) + { + using (CurrentTenant.Change(null)) + { + await ExecuteCleanService(workerContext); + + var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync(); + + foreach (var activeTenant in allActiveTenants) + { + using (CurrentTenant.Change(activeTenant.Id, activeTenant.Name)) + { + await ExecuteCleanService(workerContext); + } + } + } + + Logger.LogInformation($"Lock is released for {nameof(OssObjectTempCleanupBackgroundWorker)}"); + return; + } + + Logger.LogInformation($"Handle is null because of the locking for : {nameof(OssObjectTempCleanupBackgroundWorker)}"); + } + + private async static Task ExecuteCleanService(PeriodicBackgroundWorkerContext workerContext) + { + await workerContext + .ServiceProvider + .GetRequiredService() + .CleanAsync(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj new file mode 100644 index 000000000..206c44ab1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj @@ -0,0 +1,88 @@ + + + + net9.0 + enable + enable + LINGYUN.Abp.MicroService.PlatformService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/ITenantConfigurationCache.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/ITenantConfigurationCache.cs new file mode 100644 index 000000000..1b6c5cf69 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/ITenantConfigurationCache.cs @@ -0,0 +1,8 @@ +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.PlatformService.MultiTenancy; + +public interface ITenantConfigurationCache +{ + Task> GetTenantsAsync(); +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCache.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCache.cs new file mode 100644 index 000000000..bd881db3d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCache.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.Saas.Tenants; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.PlatformService.MultiTenancy; + +public class TenantConfigurationCache : ITenantConfigurationCache, ITransientDependency +{ + protected ITenantRepository TenantRepository { get; } + protected IDistributedCache TenantCache { get; } + + public TenantConfigurationCache( + ITenantRepository tenantRepository, + IDistributedCache tenantCache) + { + TenantRepository = tenantRepository; + TenantCache = tenantCache; + } + + public async virtual Task> GetTenantsAsync() + { + return (await GetForCacheItemAsync()).Tenants; + } + + protected async virtual Task GetForCacheItemAsync() + { + var cacheKey = "_Abp_Tenant_Configuration"; + var cacheItem = await TenantCache.GetAsync(cacheKey); + if (cacheItem == null) + { + var allActiveTenants = await TenantRepository.GetListAsync(); + + cacheItem = new TenantConfigurationCacheItem( + allActiveTenants + .Where(t => t.IsActive) + .Select(t => new TenantConfiguration(t.Id, t.Name) + { + IsActive = t.IsActive, + }).ToList()); + + await TenantCache.SetAsync(cacheKey, cacheItem); + } + + return cacheItem; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCacheItem.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCacheItem.cs new file mode 100644 index 000000000..8bd0abd3d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/MultiTenancy/TenantConfigurationCacheItem.cs @@ -0,0 +1,19 @@ +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.PlatformService.MultiTenancy; + +[IgnoreMultiTenancy] +public class TenantConfigurationCacheItem +{ + public List Tenants { get; set; } + + public TenantConfigurationCacheItem() + { + Tenants = new List(); + } + + public TenantConfigurationCacheItem(List tenants) + { + Tenants = tenants; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.Configure.cs new file mode 100644 index 000000000..3516883a4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.Configure.cs @@ -0,0 +1,437 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Aliyun; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MailKit; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.Sms; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +public partial class PlatformServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别,应在0-31之间 + options.SnowflakeIdOptions.WorkerId = 25; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureKestrelServer() + { + Configure(options => + { + options.Limits.MaxRequestBodySize = null; + options.Limits.MaxRequestBufferSize = null; + }); + } + + private void ConfigureExceptionHandling() + { + Configure(options => + { + // 是否发送错误详情 + options.SendExceptionsDetailsToClients = false; + options.SendStackTraceToClients = false; + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + options.IsEnabledForIntegrationServices = true; + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration!); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.PlatformService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get() ?? []; + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + { configuration["AuthServer:Audience"]!, "Platform Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Platform Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Query["access_token"]; + var path = context.HttpContext.Request.Path; + if (!string.IsNullOrEmpty(accessToken) && + (path.StartsWithSegments("/api/files"))) + { + context.Token = accessToken; + } + return Task.CompletedTask; + } + }; + }); + + // services.AddAlwaysAllowAuthorization(); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } + + private void ConfigurePlatformModule(IServiceCollection services) + { + Configure(options => + { + // 允许第三方调用集成服务 + options.ExposeIntegrationServices = true; + }); + // 用于消息中心邮件集中发送 + services.Replace(ServiceDescriptor.Transient()); + + services.AddKeyedTransient("DefaultEmailSender"); + + // 用于消息中心短信集中发送 + services.Replace(ServiceDescriptor.Transient()); + services.AddKeyedSingleton("DefaultSmsSender"); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs new file mode 100644 index 000000000..2d4cc5590 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs @@ -0,0 +1,166 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Features.LimitValidation.Redis; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.MicroService.PlatformService.BackgroundWorkers; +using LINGYUN.Abp.Notifications; +using LINGYUN.Abp.OssManagement; +using LINGYUN.Abp.OssManagement.Aliyun; +using LINGYUN.Abp.OssManagement.FileSystem; +using LINGYUN.Abp.OssManagement.Imaging; +using LINGYUN.Abp.OssManagement.Minio; +using LINGYUN.Abp.OssManagement.Nexus; +using LINGYUN.Abp.OssManagement.SettingManagement; +using LINGYUN.Abp.OssManagement.Tencent; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Aliyun; +using LINGYUN.Abp.UI.Navigation.VueVbenAdmin5; +using LINGYUN.Platform; +using LINGYUN.Platform.EntityFrameworkCore; +using LINGYUN.Platform.HttpApi; +using LINGYUN.Platform.Theme.VueVbenAdmin; +using Microsoft.Extensions.Options; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.Data; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Identity; +using Volo.Abp.Imaging; +using Volo.Abp.MailKit; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.MicroService.PlatformService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpUINavigationVueVbenAdmin5Module), + typeof(PlatformThemeVueVbenAdminModule), + typeof(AbpOssManagementAliyunModule), // 阿里云存储提供者模块 + typeof(AbpOssManagementTencentModule), // 腾讯云存储提供者模块 + typeof(AbpOssManagementNexusModule), // Nexus存储提供者模块 + typeof(AbpOssManagementMinioModule), // Minio存储提供者模块 + typeof(AbpOssManagementFileSystemModule),// 本地文件系统提供者模块 + typeof(AbpOssManagementImagingModule), // 对象存储图形处理模块 + typeof(AbpOssManagementApplicationModule), + typeof(AbpOssManagementHttpApiModule), + typeof(AbpOssManagementSettingManagementModule), + typeof(AbpImagingImageSharpModule), + typeof(PlatformApplicationModule), + typeof(PlatformHttpApiModule), + typeof(PlatformEntityFrameworkCoreModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(PlatformServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpNotificationsModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpCAPEventBusModule), + typeof(AbpFeaturesValidationRedisModule), + // typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块 + // typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块 + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpHttpClientModule), + typeof(AbpMailKitModule), + typeof(AbpAliyunSmsModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpClaimsMappingModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAutofacModule) + )] +public partial class PlatformServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreForwardedHeaders(); + PreConfigureFeature(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureKestrelServer(); + ConfigureExceptionHandling(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureIdentity(configuration); + ConfigureAuditing(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLocking(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + + ConfigurePlatformModule(context.Services); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); + } + + public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + await context.ServiceProvider + .GetRequiredService() + .SeedAsync(); + + var options = context.ServiceProvider.GetRequiredService>().Value; + if (options.IsCleanupEnabled) + { + await context.ServiceProvider + .GetRequiredService() + .AddAsync(context.ServiceProvider.GetRequiredService()); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Program.cs new file mode 100644 index 000000000..53ef7e07e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Program.cs @@ -0,0 +1,99 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.PlatformService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Serilog; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting PlatformService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "PlatformService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + // ػ + app.UseMapRequestLocalization(); + // http + app.UseCorrelationId(); + // ļϵͳ + app.MapAbpStaticAssets(); + // · + app.UseRouting(); + // + app.UseCors(); + // ֤ + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + // ⻧ + app.UseMultiTenancy(); + // Ự + app.UseAbpSession(); + app.UseDynamicClaims(); + // Ȩ + app.UseAuthorization(); + // Swagger + app.UseSwagger(); + // Swaggerӻ + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Platform Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + // ־ + app.UseAuditing(); + // ¼Ϣ + app.UseAbpSerilogEnrichers(); + // · + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Properties/launchSettings.json new file mode 100644 index 000000000..e2cc6bcb3 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5099", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/TenantHeaderParamter.cs new file mode 100644 index 000000000..8a2fe808d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/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 LINGYUN.Abp.MicroService.PlatformService; + +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/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json new file mode 100644 index 000000000..b106d6cea --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json @@ -0,0 +1,140 @@ +{ + "App": { + "TrackingEntitiesChanged": true, + "Forwarded": { + "ForwardedHeaders": 5, + "KnownProxies": [ + "localhost" + ] + }, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "ShowPii": true, + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "RemoteServices": { + "AbpIdentity": { + "BaseUrl": "http://localhost:30015/", + "IdentityClient": "InternalServiceClient" + } + }, + "IdentityClients": { + "InternalServiceClient": { + "Authority": "http://localhost:44385/", + "RequireHttps": false, + "GrantType": "client_credentials", + "Scope": "lingyun-abp-application", + "ClientId": "internal-service-client", + "ClientSecret": "1q2w3e*" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "Features": { + "Validation": { + "Redis": { + "Configuration": "localhost,defaultDatabase=8", + "InstanceName": "LINGYUN.Abp.Application" + } + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "PlatformService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "plt", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "OssManagement": { + "Provider": "FileSystem", + "FileSystem": { + "Bucket": "blobs", + "AppendContainerNameToBasePath": true + } + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.json new file mode 100644 index 000000000..4c9e40bd6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.json @@ -0,0 +1,105 @@ +{ + "Aspire": { + "StackExchange": { + "Redis": { + "ConfigurationOptions": { + "ConnectRetry": 5 + } + } + } + }, + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "AllowedHosts": "*", + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/Extensions.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/Extensions.cs new file mode 100644 index 000000000..c8e23fafd --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/Extensions.cs @@ -0,0 +1,199 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; +using System; + +namespace Microsoft.Extensions.Hosting; + +// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// This project should be referenced by each service project in your solution. +// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults +public static class Extensions +{ + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; + + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.ConfigureOpenTelemetry(); + + builder.ReplaceDefaultConfiguration(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services + .AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddSource(builder.Environment.ApplicationName) + .AddAspNetCoreInstrumentation(tracing => + // Exclude health check requests from tracing + tracing.Filter = context => + !context.Request.Path.StartsWithSegments(HealthEndpointPath) + && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath) + ) + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation() + .AddCapInstrumentation() + .AddEntityFrameworkCoreInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + public static TBuilder ReplaceDefaultConfiguration(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.AddRedisClient("redis"); + builder.AddRabbitMQClient("rabbitmq"); + builder.AddElasticsearchClient("elasticsearch"); + + // CAP PostgreSql + builder.Configuration["CAP:PostgreSql:ConnectionString"] = builder.Configuration.GetConnectionString("Default"); + + // CAP RabbitMQ + builder.Configuration["CAP:RabbitMQ:HostName"] = builder.Configuration["RABBITMQ_HOST"]; + builder.Configuration["CAP:RabbitMQ:UserName"] = builder.Configuration["RABBITMQ_USERNAME"]; + builder.Configuration["CAP:RabbitMQ:Password"] = builder.Configuration["RABBITMQ_PASSWORD"]; + builder.Configuration["CAP:RabbitMQ:Port"] = builder.Configuration["RABBITMQ_PORT"]; + + // Abp RabbitMQ + builder.Configuration["RabbitMQ:Default:HostName"] = builder.Configuration["RABBITMQ_HOST"]; + builder.Configuration["RabbitMQ:Default:UserName"] = builder.Configuration["RABBITMQ_USERNAME"]; + builder.Configuration["RabbitMQ:Default:Password"] = builder.Configuration["RABBITMQ_PASSWORD"]; + builder.Configuration["RabbitMQ:Default:Port"] = builder.Configuration["RABBITMQ_PORT"]; + + // Elsa RabbitMQ + builder.Configuration["Elsa:Rebus:RabbitMQ:Connection"] = builder.Configuration.GetConnectionString("RabbitMQ"); + + // Redis + var redisConnectionString = builder.Configuration.GetConnectionString("Redis"); + builder.Configuration["Redis:Configuration"] = $"{redisConnectionString},defaultDatabase=10"; + + // DistributedLock + builder.Configuration["DistributedLock:Redis:Configuration"] = $"{redisConnectionString},defaultDatabase=11"; + + // Features + builder.Configuration["Features:Validation:Redis:Configuration"] = $"{redisConnectionString},defaultDatabase=12"; + + // SignalR + builder.Configuration["SignalR:Redis:Configuration"] = $"{redisConnectionString},defaultDatabase=13,channelPrefix=abp-realtime-channel"; + + // Elasticsearch + var elasticSearchUrl = builder.Configuration.GetConnectionString("Elasticsearch"); + var serialogEsConfig = builder.Configuration.GetSection("Serilog:WriteTo"); + + void ReplaceElasticsearchLogging(IConfiguration configuration) + { + foreach (var config in configuration.GetChildren()) + { + if (string.Equals(config["Name"], "Async", StringComparison.InvariantCultureIgnoreCase)) + { + var configureArgs = config.GetSection("Args:configure"); + ReplaceElasticsearchLogging(configureArgs); + } + if (string.Equals(config["Name"], "Elasticsearch", StringComparison.InvariantCultureIgnoreCase)) + { + config["Args:nodeUris"] = elasticSearchUrl; + } + } + } + + if (serialogEsConfig.Exists()) + { + ReplaceElasticsearchLogging(serialogEsConfig); + } + builder.Configuration["Elasticsearch:NodeUris"] = elasticSearchUrl; + + return builder; + } + + private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks(HealthEndpointPath); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/LINGYUN.Abp.MicroService.ServiceDefaults.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/LINGYUN.Abp.MicroService.ServiceDefaults.csproj new file mode 100644 index 000000000..1dbc33319 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ServiceDefaults/LINGYUN.Abp.MicroService.ServiceDefaults.csproj @@ -0,0 +1,28 @@ + + + + net9.0 + enable + enable + true + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/LINGYUN.Abp.MicroService.TaskService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/LINGYUN.Abp.MicroService.TaskService.DbMigrator.csproj new file mode 100644 index 000000000..4d522d65e --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/LINGYUN.Abp.MicroService.TaskService.DbMigrator.csproj @@ -0,0 +1,42 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.TaskService + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/Program.cs new file mode 100644 index 000000000..6f4690586 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/Program.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.MicroService.TaskService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.TaskService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.TaskService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..9a01af443 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.TaskService; +public class TaskServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public TaskServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorModule.cs new file mode 100644 index 000000000..c8d8b98a2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/TaskServiceDbMigratorModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.TaskService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(TaskServiceMigrationsEntityFrameworkCoreModule) + )] +public class TaskServiceDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/appsettings.json new file mode 100644 index 000000000..38212c579 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..b13bc6f23 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore.csproj @@ -0,0 +1,29 @@ + + + + + + + net9.0 + LINGYUN.Abp.MicroService.TaskService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.Designer.cs new file mode 100644 index 000000000..195ca5b9d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.Designer.cs @@ -0,0 +1,281 @@ +// +using System; +using LINGYUN.Abp.MicroService.TaskService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.TaskService.Migrations +{ + [DbContext(typeof(TaskServiceMigrationsDbContext))] + [Migration("20260106000509_Initial_Task_Service")] + partial class Initial_Task_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobAction", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("JobId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("JobId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.Property("Paramters") + .HasColumnType("text") + .HasColumnName("Paramters"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("TK_BackgroundJobActions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Args") + .HasColumnType("text") + .HasColumnName("Args"); + + b.Property("BeginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("Cron"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Description"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Group"); + + b.Property("Interval") + .HasColumnType("integer"); + + b.Property("IsAbandoned") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("JobType") + .HasColumnType("integer"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastRunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockTimeOut") + .HasColumnType("integer"); + + b.Property("MaxCount") + .HasColumnType("integer"); + + b.Property("MaxTryCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.Property("NextRunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("NodeName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("NodeName"); + + b.Property("Priority") + .HasColumnType("integer"); + + b.Property("Result") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Result"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerCount") + .HasColumnType("integer"); + + b.Property("TryCount") + .HasColumnType("integer"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Type"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Group"); + + b.ToTable("TK_BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Exception") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Exception"); + + b.Property("JobGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("JobGroup"); + + b.Property("JobId") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("JobId"); + + b.Property("JobName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("JobName"); + + b.Property("JobType") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("JobType"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Message"); + + b.Property("RunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("JobGroup", "JobName"); + + b.ToTable("TK_BackgroundJobLogs", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.cs new file mode 100644 index 000000000..9f66eb4fc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/20260106000509_Initial_Task_Service.cs @@ -0,0 +1,128 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.TaskService.Migrations +{ + /// + public partial class Initial_Task_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "TK_BackgroundJobActions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + JobId = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + Paramters = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TK_BackgroundJobActions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TK_BackgroundJobLogs", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TenantId = table.Column(type: "uuid", nullable: true), + JobId = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + JobName = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + JobGroup = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + JobType = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: true), + Message = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: true), + RunTime = table.Column(type: "timestamp with time zone", nullable: false), + Exception = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TK_BackgroundJobLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TK_BackgroundJobs", + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Group = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Type = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: false), + Result = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: true), + Args = table.Column(type: "text", nullable: true), + Status = table.Column(type: "integer", nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + LockTimeOut = table.Column(type: "integer", nullable: false), + BeginTime = table.Column(type: "timestamp with time zone", nullable: false), + EndTime = table.Column(type: "timestamp with time zone", nullable: true), + LastRunTime = table.Column(type: "timestamp with time zone", nullable: true), + NextRunTime = table.Column(type: "timestamp with time zone", nullable: true), + JobType = table.Column(type: "integer", nullable: false), + Cron = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Source = table.Column(type: "integer", nullable: false), + Priority = table.Column(type: "integer", nullable: false), + TriggerCount = table.Column(type: "integer", nullable: false), + TryCount = table.Column(type: "integer", nullable: false), + MaxTryCount = table.Column(type: "integer", nullable: false), + MaxCount = table.Column(type: "integer", nullable: false), + Interval = table.Column(type: "integer", nullable: false), + IsAbandoned = table.Column(type: "boolean", nullable: false), + NodeName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TK_BackgroundJobs", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_TK_BackgroundJobActions_Name", + table: "TK_BackgroundJobActions", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_TK_BackgroundJobLogs_JobGroup_JobName", + table: "TK_BackgroundJobLogs", + columns: new[] { "JobGroup", "JobName" }); + + migrationBuilder.CreateIndex( + name: "IX_TK_BackgroundJobs_Name_Group", + table: "TK_BackgroundJobs", + columns: new[] { "Name", "Group" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TK_BackgroundJobActions"); + + migrationBuilder.DropTable( + name: "TK_BackgroundJobLogs"); + + migrationBuilder.DropTable( + name: "TK_BackgroundJobs"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/TaskServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/TaskServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..ab483b443 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/Migrations/TaskServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,278 @@ +// +using System; +using LINGYUN.Abp.MicroService.TaskService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.TaskService.Migrations +{ + [DbContext(typeof(TaskServiceMigrationsDbContext))] + partial class TaskServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobAction", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("JobId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("JobId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.Property("Paramters") + .HasColumnType("text") + .HasColumnName("Paramters"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("TK_BackgroundJobActions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Args") + .HasColumnType("text") + .HasColumnName("Args"); + + b.Property("BeginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("Cron"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("Description"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Group"); + + b.Property("Interval") + .HasColumnType("integer"); + + b.Property("IsAbandoned") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("JobType") + .HasColumnType("integer"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastRunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockTimeOut") + .HasColumnType("integer"); + + b.Property("MaxCount") + .HasColumnType("integer"); + + b.Property("MaxTryCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("Name"); + + b.Property("NextRunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("NodeName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("NodeName"); + + b.Property("Priority") + .HasColumnType("integer"); + + b.Property("Result") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Result"); + + b.Property("Source") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerCount") + .HasColumnType("integer"); + + b.Property("TryCount") + .HasColumnType("integer"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Type"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Group"); + + b.ToTable("TK_BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Exception") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Exception"); + + b.Property("JobGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("JobGroup"); + + b.Property("JobId") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("JobId"); + + b.Property("JobName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("JobName"); + + b.Property("JobType") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("JobType"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("Message"); + + b.Property("RunTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("JobGroup", "JobName"); + + b.ToTable("TK_BackgroundJobLogs", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..57c56163c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs @@ -0,0 +1,151 @@ +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.BackgroundTasks.Internal; +using LINGYUN.Abp.Saas.Tenants; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.TaskService; +public class TaskServiceDbMigrationEventHandler : + EfCoreDatabaseMigrationEventHandlerBase, + IDistributedEventHandler> +{ + protected AbpBackgroundTasksOptions Options { get; } + protected IJobStore JobStore { get; } + protected IJobScheduler JobScheduler { get; } + + public TaskServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + IJobStore jobStore, + IJobScheduler jobScheduler, + IOptions options) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + JobStore = jobStore; + JobScheduler = jobScheduler; + Options = options.Value; + } + + public async Task HandleEventAsync(EntityDeletedEto eventData) + { + // 租户删除时移除轮询作业 + var pollingJob = BuildPollingJobInfo(eventData.Entity.Id, eventData.Entity.Name); + await JobScheduler.RemoveAsync(pollingJob); + await JobStore.RemoveAsync(pollingJob.Id); + + var cleaningJob = BuildCleaningJobInfo(eventData.Entity.Id, eventData.Entity.Name); + await JobScheduler.RemoveAsync(cleaningJob); + await JobStore.RemoveAsync(cleaningJob.Id); + + var checkingJob = BuildCheckingJobInfo(eventData.Entity.Id, eventData.Entity.Name); + await JobScheduler.RemoveAsync(checkingJob); + await JobStore.RemoveAsync(checkingJob.Id); + } + + protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) + { + if (!schemaMigrated) + { + return; + } + + await QueueBackgroundJobAsync(eventData); + } + + protected async virtual Task QueueBackgroundJobAsync(TenantCreatedEto eventData) + { + var pollingJob = BuildPollingJobInfo(eventData.Id, eventData.Name); + await JobStore.StoreAsync(pollingJob); + await JobScheduler.QueueAsync(pollingJob); + + var cleaningJob = BuildCleaningJobInfo(eventData.Id, eventData.Name); + await JobStore.StoreAsync(cleaningJob); + await JobScheduler.QueueAsync(cleaningJob); + + var checkingJob = BuildCheckingJobInfo(eventData.Id, eventData.Name); + await JobStore.StoreAsync(checkingJob); + await JobScheduler.QueueAsync(checkingJob); + } + + protected virtual JobInfo BuildPollingJobInfo(Guid tenantId, string tenantName) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Polling", + Name = nameof(BackgroundPollingJob), + Group = "Polling", + Description = "Polling tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobFetchCronExpression, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + LockTimeOut = Options.JobFetchLockTimeOut, + TenantId = tenantId, + Type = typeof(BackgroundPollingJob).AssemblyQualifiedName, + }; + } + + protected virtual JobInfo BuildCleaningJobInfo(Guid tenantId, string tenantName) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Cleaning", + Name = nameof(BackgroundCleaningJob), + Group = "Cleaning", + Description = "Cleaning tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobCleanCronExpression, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + TenantId = tenantId, + Type = typeof(BackgroundCleaningJob).AssemblyQualifiedName, + }; + } + + protected virtual JobInfo BuildCheckingJobInfo(Guid tenantId, string tenantName) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Checking", + Name = nameof(BackgroundCheckingJob), + Group = "Checking", + Description = "Checking tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobCheckCronExpression, + LockTimeOut = Options.JobCheckLockTimeOut, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + TenantId = tenantId, + Type = typeof(BackgroundCheckingJob).AssemblyQualifiedName, + }; + } +} + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationService.cs new file mode 100644 index 000000000..1e405fa78 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.TaskService; +public class TaskServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public TaskServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContext.cs new file mode 100644 index 000000000..e6f830da9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContext.cs @@ -0,0 +1,32 @@ +using LINGYUN.Abp.TaskManagement; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.TaskService; + +[ConnectionStringName("Default")] +public class TaskServiceMigrationsDbContext : + AbpDbContext, + ITaskManagementDbContext +{ + public DbSet BackgroundJobInfos { get; set; } + + public DbSet BackgroundJobLogs { get; set; } + + public DbSet BackgroundJobAction { get; set; } + + public TaskServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureTaskManagement(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..c06cde564 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsDbContextFactory.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.TaskService; +public class TaskServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public TaskServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new TaskServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.TaskService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..321d29450 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,43 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Quartz.PostgresSqlInstaller; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.TaskService; + +[DependsOn( + typeof(AbpQuartzPostgresSqlInstallerModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(TaskManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule) + )] +public class TaskServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj new file mode 100644 index 000000000..970eb117c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj @@ -0,0 +1,80 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.TaskService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Program.cs new file mode 100644 index 000000000..fe86697ef --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Program.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.MicroService.TaskService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting TaskService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + builder.AddServiceHealthChecks(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "TaskService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + app.MapServiceHealthChecks(); + + app.UseForwardedHeaders(); + app.UseAbpRequestLocalization(); + app.MapAbpStaticAssets(); + app.UseCorrelationId(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + app.UseMultiTenancy(); + app.UseDynamicClaims(); + app.UseAuthorization(); + app.UseSwagger(); + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Task Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Properties/launchSettings.json new file mode 100644 index 000000000..daece9a1a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.TaskService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:49512;http://localhost:49513" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthCheck.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthCheck.cs new file mode 100644 index 000000000..91c0745bb --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthCheck.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Quartz; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.MicroService.TaskService; + +public class ServiceHealthCheck : IHealthCheck +{ + private readonly IScheduler _scheduler; + private readonly IServiceProvider _serviceProvider; + private readonly Func> _factory; + + public ServiceHealthCheck(IScheduler scheduler) + { + _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler)); + } + + public ServiceHealthCheck(IServiceProvider serviceProvider, Func> factory) + { + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _factory = factory ?? throw new ArgumentNullException(nameof(factory)); + } + + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + var scheduler = _scheduler ?? await _factory(_serviceProvider); + + if (scheduler.IsStarted) + { + return HealthCheckResult.Healthy(); + } + + return HealthCheckResult.Unhealthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthChecksExtenssions.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthChecksExtenssions.cs new file mode 100644 index 000000000..ca0badb28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/ServiceHealthChecksExtenssions.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace LINGYUN.Abp.MicroService.TaskService; + +internal static class ServiceHealthChecksExtenssions +{ + private const string HealthEndpointPath = "/service-health"; + private const string DefaultHealthTag = "ready"; + + public static TBuilder AddServiceHealthChecks(this TBuilder builder, string name = "Service", string tag = DefaultHealthTag) where TBuilder : IHostApplicationBuilder + { + builder.Services + .AddHealthChecks() + .AddCheck(name, tags: [tag]); + + return builder; + } + + public static WebApplication MapServiceHealthChecks(this WebApplication app, string tag = DefaultHealthTag) + { + if (app.Environment.IsDevelopment()) + { + app.MapHealthChecks(HealthEndpointPath, new HealthCheckOptions + { + Predicate = r => r.Tags.Contains(tag) + }); + } + return app; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.Configure.cs new file mode 100644 index 000000000..c10f5235d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.Configure.cs @@ -0,0 +1,424 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Identity.Client; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Quartz; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Quartz; +using Volo.Abp.Security.Claims; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.TaskService; + +public partial class TaskServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别 + options.SnowflakeIdOptions.WorkerId = 27; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureQuartz(IConfiguration configuration) + { + PreConfigure(options => + { + // 如果使用持久化存储, 则配置quartz持久层 + if (configuration.GetSection("Quartz:UsePersistentStore").Get()) + { + var settings = configuration.GetSection("Quartz:Properties").Get>(); + if (settings != null) + { + foreach (var setting in settings) + { + options.Properties[setting.Key] = setting.Value; + } + } + + options.Configurator += (config) => + { + config.UsePersistentStore(store => + { + store.UseProperties = false; + store.UseNewtonsoftJsonSerializer(); + }); + }; + } + }); + } + + private void ConfigureBackgroundTasks() + { + Configure(options => + { + options.JobCleanEnabled = true; + options.JobFetchEnabled = true; + options.JobCheckEnabled = true; + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + options.ApplicationName = configuration["ApplicationName"]; + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.TaskService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Task Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Task Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.cs new file mode 100644 index 000000000..42e80af93 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.cs @@ -0,0 +1,121 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.BackgroundTasks.DistributedLocking; +using LINGYUN.Abp.BackgroundTasks.ExceptionHandling; +using LINGYUN.Abp.BackgroundTasks.Jobs; +using LINGYUN.Abp.BackgroundTasks.Notifications; +using LINGYUN.Abp.BackgroundTasks.Quartz; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.OssManagement; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.TaskManagement; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.DistributedLocking; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.TaskService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpDistributedLockingModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpOssManagementHttpApiClientModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpBackgroundTasksJobsModule), + typeof(AbpBackgroundTasksQuartzModule), + typeof(AbpBackgroundTasksDistributedLockingModule), + typeof(AbpBackgroundTasksExceptionHandlingModule), + typeof(AbpBackgroundTasksNotificationsModule), + typeof(TaskManagementApplicationModule), + typeof(TaskManagementHttpApiModule), + typeof(TaskManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(TaskServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpSmsPlatformModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpSwashbuckleModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpClaimsMappingModule), + typeof(AbpCAPEventBusModule), + typeof(AbpAutofacModule) + )] +public partial class TaskServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureQuartz(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureBackgroundTasks(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureIdentity(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLock(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TenantHeaderParamter.cs new file mode 100644 index 000000000..3114d4324 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.TaskService; + +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/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json new file mode 100644 index 000000000..a1a6a7b70 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json @@ -0,0 +1,145 @@ +{ + "App": { + "ShowPii": true, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "TaskService", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "tsk", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "Quartz": { + "UsePersistentStore": true, + "Properties": { + "quartz.jobStore.dataSource": "tkm", + "quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz", + "quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate,Quartz", + "quartz.dataSource.tkm.connectionStringName": "Default", + "quartz.dataSource.tkm.provider": "Npgsql", + "quartz.jobStore.clustered": "true", + "quartz.serializer.type": "json" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RemoteServices": { + "AbpOssManagement": { + "BaseUrl": "http://localhost:30025", + "IdentityClient": "InternalServiceClient", + "UseCurrentAccessToken": false + }, + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "IdentityClients": { + "InternalServiceClient": { + "Authority": "http://localhost:44385", + "RequireHttps": false, + "GrantType": "client_credentials", + "Scope": "lingyun-abp-application", + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3e*" + } + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "Scopes": "lingyun-abp-application", + "SwaggerClientId": "InternalServiceClient", + "SwaggerClientSecret": "1q2w3E*", + "MapInboundClaims": false, + "RequireHttpsMetadata": false + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "Microsoft.EntityFrameworkCore": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.json new file mode 100644 index 000000000..06dfdddfc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.json @@ -0,0 +1,99 @@ +{ + "App": { + "CorsOrigins": "http://localhost:3100" + }, + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "AllowedHosts": "*", + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.WeChatService/LINGYUN.Abp.MicroService.WeChatService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/LINGYUN.Abp.MicroService.WeChatService.csproj new file mode 100644 index 000000000..e0b6adc3f --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/LINGYUN.Abp.MicroService.WeChatService.csproj @@ -0,0 +1,80 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.WeChatService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Program.cs new file mode 100644 index 000000000..26501397a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Program.cs @@ -0,0 +1,76 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.WeChatService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +Log.Information("Starting WeChatService Host..."); + +var builder = WebApplication.CreateBuilder(args); +builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + +builder.AddServiceDefaults(); + +await builder.AddApplicationAsync(options => +{ + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "WeChatService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); +}); + +var app = builder.Build(); + +await app.InitializeApplicationAsync(); + +app.MapDefaultEndpoints(); + +app.UseForwardedHeaders(); +app.UseMapRequestLocalization(); +app.UseCorrelationId(); +app.MapAbpStaticAssets(); +app.UseRouting(); +app.UseCors(); +app.UseAuthentication(); +app.UseJwtTokenMiddleware(); +app.UseMultiTenancy(); +app.UseAbpSession(); +app.UseDynamicClaims(); +app.UseAuthorization(); +app.UseSwagger(); +app.UseAbpSwaggerUI(options => +{ + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Wechat Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); +}); +app.UseAuditing(); +app.UseAbpSerilogEnrichers(); +app.UseConfiguredEndpoints(); + +await app.RunAsync(); \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Properties/launchSettings.json new file mode 100644 index 000000000..4d8c504b6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.WeChatService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:52666;http://localhost:52667" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/TenantHeaderParamter.cs new file mode 100644 index 000000000..a4efd101c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.WeChatService; + +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 in http header", + Required = false + }); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs new file mode 100644 index 000000000..e449d229a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs @@ -0,0 +1,417 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Security.Claims; +using Volo.Abp.SettingManagement; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.WeChatService; + +public partial class WeChatServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别 + options.SnowflakeIdOptions.WorkerId = 11; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(sqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(sqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void ConfigureDbContext() + { + // 配置Ef + Configure(options => + { + options.UseNpgsql(); + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + var applicationConfiguration = configuration.GetSection("App:Urls:Applications"); + foreach (var appConfig in applicationConfiguration.GetChildren()) + { + options.Applications[appConfig.Key].RootUrl = appConfig["RootUrl"]; + foreach (var urlsConfig in appConfig.GetSection("Urls").GetChildren()) + { + options.Applications[appConfig.Key].Urls[urlsConfig.Key] = urlsConfig.Value; + } + } + }); + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.WeChatService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Wechat Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Wechat Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.IsDynamicPermissionStoreEnabled = true; + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureSettingManagement() + { + Configure(options => + { + options.IsDynamicSettingStoreEnabled = true; + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.cs new file mode 100644 index 000000000..199a2ec20 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.cs @@ -0,0 +1,128 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Http.Client.Wrapper; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Identity.WeChat.Work; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.WeChat.MiniProgram; +using LINGYUN.Abp.WeChat.Official; +using LINGYUN.Abp.WeChat.SettingManagement; +using LINGYUN.Abp.WeChat.Work; +using LINGYUN.Abp.WeChat.Work.Contacts; +using LINGYUN.Abp.WeChat.Work.ExternalContact; +using LINGYUN.Abp.WeChat.Work.Handlers; +using LINGYUN.Abp.WeChat.Work.OA; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.MailKit; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.WeChatService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpWeChatWorkApplicationModule), + typeof(AbpWeChatWorkHttpApiModule), + typeof(AbpWeChatWorkContactModule), + typeof(AbpWeChatWorkExternalContactModule), + typeof(AbpWeChatWorkOAModule), + typeof(AbpWeChatWorkHandlersModule), + typeof(AbpWeChatOfficialApplicationModule), + typeof(AbpWeChatOfficialHttpApiModule), + typeof(AbpWeChatMiniProgramModule), + typeof(AbpIdentityWeChatWorkModule), + typeof(AbpWeChatSettingManagementModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpCAPEventBusModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpDistributedLockingModule), + typeof(AbpSwashbuckleModule), + typeof(AbpHttpClientWrapperModule), + typeof(AbpMailKitModule), + typeof(AbpClaimsMappingModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpAutofacModule) + )] +public partial class WeChatServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureDbContext(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigureSettingManagement(); + ConfigurePermissionManagement(); + ConfigureUrls(configuration); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureIdentity(configuration); + ConfigureMultiTenancy(configuration); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLock(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json new file mode 100644 index 000000000..c92ea8829 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json @@ -0,0 +1,127 @@ +{ + "App": { + "ShowPii": true, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "OpenTelemetry": { + "IsEnabled": true, + "ZipKin": { + "Endpoint": "http://localhost:9411/api/v2/spans" + } + }, + "RemoteServices": {}, + "IdentityClients": { + "InternalServiceClient": { + "Authority": "http://localhost:44385", + "RequireHttps": false, + "GrantType": "client_credentials", + "Scope": "lingyun-abp-application", + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3E*" + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "WeChatService", + "GroupNamePrefix": "Dev", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10 + }, + "MySql": { + "TableNamePrefix": "wechat", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "InternalServiceClient", + "SwaggerClientSecret": "1q2w3E*" + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.json new file mode 100644 index 000000000..f7f8d8154 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.json @@ -0,0 +1,96 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "AllowedHosts": "*", + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/LINGYUN.Abp.MicroService.WebhookService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/LINGYUN.Abp.MicroService.WebhookService.DbMigrator.csproj new file mode 100644 index 000000000..0822913eb --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/LINGYUN.Abp.MicroService.WebhookService.DbMigrator.csproj @@ -0,0 +1,42 @@ + + + + + + Exe + net9.0 + enable + enable + false + LINGYUN.Abp.MicroService.WebhookService + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/Program.cs new file mode 100644 index 000000000..55b4d4fdc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/Program.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.MicroService.WebhookService; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"; + +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("LINGYUN.Abp.MicroService.WebhookService", LogEventLevel.Debug) +#else + .MinimumLevel.Override("LINGYUN.Abp.MicroService.WebhookService", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate)) + .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate)) + .CreateLogger(); + +try +{ + var builder = Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + await builder.RunConsoleAsync(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorHostedService.cs new file mode 100644 index 000000000..490a2893b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorHostedService.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.MicroService.WebhookService; +public class WebhookServiceDbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public WebhookServiceDbMigratorHostedService( + IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using var application = await AbpApplicationFactory + .CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + }); + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .CheckAndApplyDatabaseMigrationsAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorModule.cs new file mode 100644 index 000000000..58877fc8c --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/WebhookServiceDbMigratorModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(WebhookServiceMigrationsEntityFrameworkCoreModule) + )] +public class WebhookServiceDbMigratorModule : AbpModule +{ +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/appsettings.json new file mode 100644 index 000000000..df80b3a21 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Server=localhost;Port=63983;Database=abp;User Id=root;Password=123456;SslMode=None" + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/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/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..8b0c720f7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore.csproj @@ -0,0 +1,32 @@ + + + + + + + false + net9.0 + LINGYUN.Abp.MicroService.WebhookService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.Designer.cs new file mode 100644 index 000000000..9cb440ae8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.Designer.cs @@ -0,0 +1,263 @@ +// +using System; +using LINGYUN.Abp.MicroService.WebhookService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.WebhookService.Migrations +{ + [DbContext(typeof(WebhookServiceMigrationsDbContext))] + [Migration("20260106003313_Initial_Webhook_Service")] + partial class Initial_Webhook_Service + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("RequiredFeatures") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpWebhooksWebhooks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookEventRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("Data") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Data"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("WebhookName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("WebhookName"); + + b.HasKey("Id"); + + b.ToTable("AbpWebhooksEvents", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpWebhooksWebhookGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("RequestHeaders") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("RequestHeaders"); + + b.Property("Response") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Response"); + + b.Property("ResponseHeaders") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("ResponseHeaders"); + + b.Property("ResponseStatusCode") + .HasColumnType("integer"); + + b.Property("SendExactSameData") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("WebhookEventId") + .HasColumnType("uuid"); + + b.Property("WebhookSubscriptionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WebhookEventId"); + + b.ToTable("AbpWebhooksSendAttempts", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Description"); + + b.Property("Headers") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Headers"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Secret") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Secret"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("TimeoutDuration") + .HasColumnType("integer"); + + b.Property("WebhookUri") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("WebhookUri"); + + b.Property("Webhooks") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Webhooks"); + + b.HasKey("Id"); + + b.ToTable("AbpWebhooksSubscriptions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", b => + { + b.HasOne("LINGYUN.Abp.WebhooksManagement.WebhookEventRecord", "WebhookEvent") + .WithOne() + .HasForeignKey("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", "WebhookEventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebhookEvent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.cs new file mode 100644 index 000000000..4694966a9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/20260106003313_Initial_Webhook_Service.cs @@ -0,0 +1,154 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.WebhookService.Migrations +{ + /// + public partial class Initial_Webhook_Service : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpWebhooksEvents", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + WebhookName = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Data = table.Column(type: "text", maxLength: 2147483647, nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + DeletionTime = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpWebhooksEvents", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpWebhooksSubscriptions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + WebhookUri = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Secret = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + IsActive = table.Column(type: "boolean", nullable: false), + Webhooks = table.Column(type: "text", maxLength: 2147483647, nullable: true), + Headers = table.Column(type: "text", maxLength: 2147483647, nullable: true), + Description = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: true), + TimeoutDuration = table.Column(type: "integer", nullable: true), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpWebhooksSubscriptions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpWebhooksWebhookGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpWebhooksWebhookGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpWebhooksWebhooks", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsEnabled = table.Column(type: "boolean", nullable: false), + RequiredFeatures = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpWebhooksWebhooks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpWebhooksSendAttempts", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + WebhookEventId = table.Column(type: "uuid", nullable: false), + WebhookSubscriptionId = table.Column(type: "uuid", nullable: false), + Response = table.Column(type: "text", maxLength: 2147483647, nullable: true), + ResponseStatusCode = table.Column(type: "integer", nullable: true), + RequestHeaders = table.Column(type: "text", maxLength: 2147483647, nullable: true), + ResponseHeaders = table.Column(type: "text", maxLength: 2147483647, nullable: true), + SendExactSameData = table.Column(type: "boolean", nullable: false), + CreationTime = table.Column(type: "timestamp with time zone", nullable: false), + LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpWebhooksSendAttempts", x => x.Id); + table.ForeignKey( + name: "FK_AbpWebhooksSendAttempts_AbpWebhooksEvents_WebhookEventId", + column: x => x.WebhookEventId, + principalTable: "AbpWebhooksEvents", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpWebhooksSendAttempts_WebhookEventId", + table: "AbpWebhooksSendAttempts", + column: "WebhookEventId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpWebhooksWebhookGroups_Name", + table: "AbpWebhooksWebhookGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpWebhooksWebhooks_GroupName", + table: "AbpWebhooksWebhooks", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpWebhooksWebhooks_Name", + table: "AbpWebhooksWebhooks", + column: "Name", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpWebhooksSendAttempts"); + + migrationBuilder.DropTable( + name: "AbpWebhooksSubscriptions"); + + migrationBuilder.DropTable( + name: "AbpWebhooksWebhookGroups"); + + migrationBuilder.DropTable( + name: "AbpWebhooksWebhooks"); + + migrationBuilder.DropTable( + name: "AbpWebhooksEvents"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/WebhookServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/WebhookServiceMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..c5cbfedf4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/Migrations/WebhookServiceMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,260 @@ +// +using System; +using LINGYUN.Abp.MicroService.WebhookService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.WebhookService.Migrations +{ + [DbContext(typeof(WebhookServiceMigrationsDbContext))] + partial class WebhookServiceMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("RequiredFeatures") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpWebhooksWebhooks", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookEventRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("Data") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Data"); + + b.Property("DeletionTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("WebhookName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("WebhookName"); + + b.HasKey("Id"); + + b.ToTable("AbpWebhooksEvents", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpWebhooksWebhookGroups", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("RequestHeaders") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("RequestHeaders"); + + b.Property("Response") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Response"); + + b.Property("ResponseHeaders") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("ResponseHeaders"); + + b.Property("ResponseStatusCode") + .HasColumnType("integer"); + + b.Property("SendExactSameData") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("WebhookEventId") + .HasColumnType("uuid"); + + b.Property("WebhookSubscriptionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WebhookEventId"); + + b.ToTable("AbpWebhooksSendAttempts", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Description"); + + b.Property("Headers") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Headers"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Secret") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("Secret"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("TimeoutDuration") + .HasColumnType("integer"); + + b.Property("WebhookUri") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("WebhookUri"); + + b.Property("Webhooks") + .HasMaxLength(2147483647) + .HasColumnType("text") + .HasColumnName("Webhooks"); + + b.HasKey("Id"); + + b.ToTable("AbpWebhooksSubscriptions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", b => + { + b.HasOne("LINGYUN.Abp.WebhooksManagement.WebhookEventRecord", "WebhookEvent") + .WithOne() + .HasForeignKey("LINGYUN.Abp.WebhooksManagement.WebhookSendRecord", "WebhookEventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebhookEvent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs new file mode 100644 index 000000000..834214234 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; +using Volo.Abp.Data; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EntityFrameworkCore.Migrations; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.WebhookService; +public class WebhookServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase +{ + public WebhookServiceDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory, + IDataSeeder dataSeeder) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationService.cs new file mode 100644 index 000000000..1562a1f3a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationService.cs @@ -0,0 +1,26 @@ +using LINGYUN.Abp.Data.DbMigrator; +using Microsoft.Extensions.Logging; +using System; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MicroService.WebhookService; +public class WebhookServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency +{ + public WebhookServiceDbMigrationService( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + : base( + ConnectionStringNameAttribute.GetConnStringName(), + unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) + { + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContext.cs new file mode 100644 index 000000000..77aa9b167 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContext.cs @@ -0,0 +1,32 @@ +using LINGYUN.Abp.WebhooksManagement; +using LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +[ConnectionStringName("Default")] +public class WebhookServiceMigrationsDbContext : + AbpDbContext, + IWebhooksManagementDbContext +{ + public DbSet WebhookSendRecord { get; set; } + + public DbSet WebhookGroupDefinitionRecords { get; set; } + + public DbSet WebhookDefinitionRecords { get; set; } + + public WebhookServiceMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureWebhooksManagement(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContextFactory.cs new file mode 100644 index 000000000..6fc917ec5 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsDbContextFactory.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System.IO; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +public class WebhookServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory +{ + public WebhookServiceMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(connectionString); + + return new WebhookServiceMigrationsDbContext(builder!.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.WebhookService.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..cfb43e18b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceMigrationsEntityFrameworkCoreModule.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Quartz.PostgresSqlInstaller; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +[DependsOn( + typeof(AbpQuartzPostgresSqlInstallerModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(WebhooksManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(TaskManagementEntityFrameworkCoreModule), + typeof(AbpDataDbMigratorModule) + )] +public class WebhookServiceMigrationsEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.UseNpgsql(); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Handlers/WebhooksEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Handlers/WebhooksEventHandler.cs new file mode 100644 index 000000000..2f1d16dae --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Handlers/WebhooksEventHandler.cs @@ -0,0 +1,117 @@ +using LINGYUN.Abp.Webhooks; +using LINGYUN.Abp.Webhooks.EventBus; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.WebhookService.Handlers; + +public class WebhooksEventHandler : + IDistributedEventHandler, + ITransientDependency +{ + public IWebhookEventStore WebhookEventStore { get; set; } + + private readonly ICurrentTenant _currentTenant; + private readonly IBackgroundJobManager _backgroundJobManager; + private readonly IWebhookSubscriptionManager _webhookSubscriptionManager; + + public WebhooksEventHandler( + IWebhookSubscriptionManager webhookSubscriptionManager, + ICurrentTenant currentTenant, + IBackgroundJobManager backgroundJobManager) + { + _currentTenant = currentTenant; + _backgroundJobManager = backgroundJobManager; + _webhookSubscriptionManager = webhookSubscriptionManager; + + WebhookEventStore = NullWebhookEventStore.Instance; + } + + public async virtual Task HandleEventAsync(WebhooksEventData eventData) + { + var subscriptions = await _webhookSubscriptionManager + .GetAllSubscriptionsOfTenantsIfFeaturesGrantedAsync( + eventData.TenantIds, + eventData.WebhookName); + + await PublishAsync(eventData.WebhookName, eventData.Data, subscriptions, eventData.SendExactSameData, eventData.Headers); + } + + protected async virtual Task PublishAsync( + string webhookName, + string data, + List webhookSubscriptions, + bool sendExactSameData = false, + WebhookHeader headers = null) + { + if (webhookSubscriptions.IsNullOrEmpty()) + { + return; + } + + var subscriptionsGroupedByTenant = webhookSubscriptions.GroupBy(x => x.TenantId); + + foreach (var subscriptionGroupedByTenant in subscriptionsGroupedByTenant) + { + var webhookInfo = await SaveAndGetWebhookAsync(subscriptionGroupedByTenant.Key, webhookName, data); + + foreach (var webhookSubscription in subscriptionGroupedByTenant) + { + var headersToSend = webhookSubscription.Headers; + if (headers != null) + { + if (headers.UseOnlyGivenHeaders)//do not use the headers defined in subscription + { + headersToSend = headers.Headers; + } + else + { + //use the headers defined in subscription. If additional headers has same header, use additional headers value. + foreach (var additionalHeader in headers.Headers) + { + headersToSend[additionalHeader.Key] = additionalHeader.Value; + } + } + } + + await _backgroundJobManager.EnqueueAsync(new WebhookSenderArgs + { + TenantId = webhookSubscription.TenantId, + WebhookEventId = webhookInfo.Id, + Data = webhookInfo.Data, + WebhookName = webhookInfo.WebhookName, + WebhookSubscriptionId = webhookSubscription.Id, + Headers = headersToSend, + Secret = webhookSubscription.Secret, + WebhookUri = webhookSubscription.WebhookUri, + SendExactSameData = sendExactSameData + }); + } + } + } + + protected async virtual Task SaveAndGetWebhookAsync( + Guid? tenantId, + string webhookName, + string data) + { + var webhookInfo = new WebhookEvent + { + WebhookName = webhookName, + Data = data, + TenantId = tenantId + }; + + var webhookId = await WebhookEventStore.InsertAndGetIdAsync(webhookInfo); + webhookInfo.Id = webhookId; + + return webhookInfo; + } +} + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/LINGYUN.Abp.MicroService.WebhookService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/LINGYUN.Abp.MicroService.WebhookService.csproj new file mode 100644 index 000000000..8571b3f4b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/LINGYUN.Abp.MicroService.WebhookService.csproj @@ -0,0 +1,75 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.WebhookService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Program.cs new file mode 100644 index 000000000..3f7c390a9 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Program.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.WebhookService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +try +{ + Log.Information("Starting WebhookService Host..."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + + builder.AddServiceDefaults(); + + await builder.AddApplicationAsync(options => + { + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "WebhookService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); + }); + + var app = builder.Build(); + + await app.InitializeApplicationAsync(); + + app.MapDefaultEndpoints(); + + app.UseForwardedHeaders(); + app.UseMapRequestLocalization(); + app.UseCorrelationId(); + app.MapAbpStaticAssets(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseJwtTokenMiddleware(); + app.UseMultiTenancy(); + app.UseAbpSession(); + app.UseDynamicClaims(); + app.UseAuthorization(); + app.UseSwagger(); + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Webhook Service API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); + }); + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); +} +finally +{ + await Log.CloseAndFlushAsync(); +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Properties/launchSettings.json new file mode 100644 index 000000000..8260d0bf6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.WebhookService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:61131;http://localhost:61132" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/TenantHeaderParamter.cs new file mode 100644 index 000000000..880e6d65a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +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/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.Configure.cs new file mode 100644 index 000000000..ba99da581 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.Configure.cs @@ -0,0 +1,469 @@ +using DotNetCore.CAP; +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Webhooks; +using LINGYUN.Abp.Webhooks.BackgroundJobs; +using LINGYUN.Abp.WebhooksManagement; +using LINGYUN.Abp.Wrapper; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Quartz; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.Caching; +using Volo.Abp.FeatureManagement; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Http.Client; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Quartz; +using Volo.Abp.Security.Claims; +using Volo.Abp.SettingManagement; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +public partial class WebhookServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别 + options.SnowflakeIdOptions.WorkerId = 28; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(sqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(sqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureQuartz(IConfiguration configuration) + { + PreConfigure(options => + { + // 如果使用持久化存储, 则配置quartz持久层 + if (configuration.GetSection("Quartz:UsePersistentStore").Get()) + { + var settings = configuration.GetSection("Quartz:Properties").Get>(); + if (settings != null) + { + foreach (var setting in settings) + { + options.Properties[setting.Key] = setting.Value; + } + } + + options.Configurator += (config) => + { + config.UsePersistentStore(store => + { + store.UseProperties = false; + store.UseNewtonsoftJsonSerializer(); + }); + }; + } + }); + } + + private void ConfigureBackgroundTasks(IServiceCollection services, IConfiguration configuration) + { + var webhooksOptions = services.ExecutePreConfiguredActions(); + + Configure(options => + { + var applicationName = services.GetApplicationName(); + options.NodeName = applicationName; + + options.JobDispatcherSelectors.AddJob( + job => + { + job.NodeName = applicationName; + // 需要间隔时长控制 + job.Interval = 10; + job.MaxCount = webhooksOptions.MaxSendAttemptCount; + job.MaxTryCount = webhooksOptions.MaxSendAttemptCount; + // 需要锁定作业 + job.LockTimeOut = webhooksOptions.TimeoutDuration.TotalSeconds.To(); + if (webhooksOptions.IsAutomaticSubscriptionDeactivationEnabled) + { + job.MaxCount = webhooksOptions.MaxConsecutiveFailCountBeforeDeactivateSubscription; + } + }); + //options.JobDispatcherSelectors.AddNamespace( + // "LINGYUN.Abp.Webhooks.BackgroundJobs", + // job => + // { + // // more + // }); + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.WebhookService"); + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get() ?? []; + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Webhook Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Webhook Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureFeatureManagement() + { + Configure(options => + { + options.IsDynamicFeatureStoreEnabled = true; + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.IsDynamicPermissionStoreEnabled = true; + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureSettingManagement() + { + Configure(options => + { + options.IsDynamicSettingStoreEnabled = true; + }); + } + + private void ConfigureWebhooks(IServiceCollection services) + { + Configure(options => + { + // 宿主应用中启用动态webhook + options.IsDynamicWebhookStoreEnabled = true; + }); + + // 宿主应用中使用默认发布者 + services.Replace(ServiceDescriptor.Transient()); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureWrapper() + { + Configure(options => + { + options.IsEnabled = true; + }); + } + + private void PreConfigureWrapper() + { + // 服务间调用不包装 + PreConfigure(options => + { + options.ProxyClientActions.Add( + (_, _, client) => + { + client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.cs new file mode 100644 index 000000000..fcf372978 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/WebhookServiceModule.cs @@ -0,0 +1,111 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.BackgroundTasks.DistributedLocking; +using LINGYUN.Abp.BackgroundTasks.ExceptionHandling; +using LINGYUN.Abp.BackgroundTasks.Quartz; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Dapr.Client.Wrapper; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Http.Client.Wrapper; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.Webhooks.EventBus; +using LINGYUN.Abp.Webhooks.Identity; +using LINGYUN.Abp.Webhooks.Saas; +using LINGYUN.Abp.WebhooksManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Modularity; +using Volo.Abp.Swashbuckle; + +namespace LINGYUN.Abp.MicroService.WebhookService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(WebhooksManagementApplicationModule), + typeof(WebhooksManagementHttpApiModule), + typeof(AbpWebhooksIdentityModule), + typeof(AbpWebhooksSaasModule), + typeof(AbpWebhooksEventBusModule), + typeof(AbpBackgroundTasksQuartzModule), + typeof(AbpBackgroundTasksDistributedLockingModule), + typeof(AbpBackgroundTasksExceptionHandlingModule), + typeof(WebhookServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpCAPEventBusModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpDistributedLockingModule), + typeof(AbpSwashbuckleModule), + typeof(AbpHttpClientWrapperModule), + typeof(AbpDaprClientWrapperModule), + typeof(AbpClaimsMappingModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpSmsPlatformModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpAutofacModule) + )] +public partial class WebhookServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigureWrapper(); + PreConfigureFeature(); + PreForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureQuartz(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureWrapper(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigureFeatureManagement(); + ConfigureSettingManagement(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureIdentity(configuration); + ConfigureMultiTenancy(configuration); + ConfigureWebhooks(context.Services); + ConfigureJsonSerializer(configuration); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureDistributedLock(context.Services, configuration); + ConfigureBackgroundTasks(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json new file mode 100644 index 000000000..1ed9cdc44 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json @@ -0,0 +1,145 @@ +{ + "App": { + "ShowPii": true, + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "OpenTelemetry": { + "IsEnabled": true, + "ZipKin": { + "Endpoint": "http://localhost:9411/api/v2/spans" + } + }, + "RemoteServices": { + "Platform": { + "BaseUrl": "http://localhost:30025", + "UseCurrentAccessToken": false + } + }, + "IdentityClients": { + "InternalServiceClient": { + "Authority": "http://localhost:44385", + "RequireHttps": false, + "GrantType": "client_credentials", + "Scope": "lingyun-abp-application", + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3E*" + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "WebhookService", + "GroupNamePrefix": "Dev", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10 + }, + "PostgreSql": { + "TableNamePrefix": "wkm", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "Quartz": { + "UsePersistentStore": true, + "Properties": { + "quartz.jobStore.dataSource": "tkm", + "quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz", + "quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate,Quartz", + "quartz.dataSource.tkm.connectionStringName": "Default", + "quartz.dataSource.tkm.provider": "Npgsql", + "quartz.jobStore.clustered": "true", + "quartz.serializer.type": "json", + "quartz.scheduler.instanceName": "WebhookService", + "quartz.scheduler.instanceId": "35bdbf8d-8c51-479b-970d-f09e6093b1ce" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "SwaggerClientId": "vue-oauth-client" + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.json new file mode 100644 index 000000000..f1576a0f6 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.json @@ -0,0 +1,96 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "AllowedHosts": "*", + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.WorkflowService/LINGYUN.Abp.MicroService.WorkflowService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/LINGYUN.Abp.MicroService.WorkflowService.csproj new file mode 100644 index 000000000..29ddc9df3 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/LINGYUN.Abp.MicroService.WorkflowService.csproj @@ -0,0 +1,88 @@ + + + + + + net9.0 + LINGYUN.Abp.MicroService.WorkflowService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_Host.cshtml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_Host.cshtml new file mode 100644 index 000000000..4b74acc72 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_Host.cshtml @@ -0,0 +1,42 @@ +@page "/" +@inject IConfiguration Configuration; +@{ + var serverUrl = Configuration["Elsa:Server:BaseUrl"]; +} + + + + + + Elsa Workflows + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_ViewImports.cshtml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_ViewImports.cshtml new file mode 100644 index 000000000..ca9c771ea --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Pages/_ViewImports.cshtml @@ -0,0 +1,2 @@ +@using Microsoft.Extensions.Configuration +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Program.cs new file mode 100644 index 000000000..42b511467 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Program.cs @@ -0,0 +1,78 @@ +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.MicroService.WorkflowService; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using System; +using System.IO; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +Log.Information("Starting WorkflowService Host..."); + +var builder = WebApplication.CreateBuilder(args); +builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + +builder.AddServiceDefaults(); + +await builder.AddApplicationAsync(options => +{ + var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "WorkflowService"; + AbpSerilogEnrichersConsts.ApplicationName = applicationName; + options.ApplicationName = applicationName; + + var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); +}); + +var app = builder.Build(); + +await app.InitializeApplicationAsync(); + +app.MapDefaultEndpoints(); + +app.UseForwardedHeaders(); +// 本地化 +app.UseMapRequestLocalization(); +app.UseCorrelationId(); +app.MapAbpStaticAssets(); +app.UseRouting(); +app.UseCors(); +app.UseAuthentication(); +app.UseJwtTokenMiddleware(); +app.UseMultiTenancy(); +app.UseAbpSession(); +app.UseDynamicClaims(); +app.UseAuthorization(); +app.UseSwagger(); +app.UseAbpSwaggerUI(options => +{ + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API"); + + var configuration = app.Configuration; + options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + options.OAuthScopes(configuration["AuthServer:Audience"]); +}); +app.UseAuditing(); +app.UseAbpSerilogEnrichers(); +app.UseConfiguredEndpoints(); +app.UseHttpActivities(); + +await app.RunAsync(); \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Properties/launchSettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Properties/launchSettings.json new file mode 100644 index 000000000..264506df1 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "LINGYUN.Abp.MicroService.WorkflowService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:50943;http://localhost:50944" + } + } +} \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/TenantHeaderParamter.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/TenantHeaderParamter.cs new file mode 100644 index 000000000..e57d616e7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/TenantHeaderParamter.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.WorkflowService; + +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 in http header", + Required = false + }); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.Configure.cs new file mode 100644 index 000000000..33a6e0fe7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.Configure.cs @@ -0,0 +1,508 @@ +using DotNetCore.CAP; +using Elsa; +using Elsa.Options; +using Elsa.Rebus.RabbitMq; +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.BlobStoring.OssManagement; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Quartz; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.AntiForgery; +using Volo.Abp.Auditing; +using Volo.Abp.BlobStoring; +using Volo.Abp.Caching; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.GlobalFeatures; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Quartz; +using Volo.Abp.Security.Claims; +using Volo.Abp.Threading; +using Volo.Abp.Timing; +using Volo.Abp.VirtualFileSystem; +using ConsoleStartup = Elsa.Activities.Console.Startup; +using EmailStartup = Elsa.Activities.Email.Startup; +using HttpStartup = Elsa.Activities.Http.Startup; +using JavaScriptStartup = Elsa.Scripting.JavaScript.Startup; +using TemporalQuartzStartup = Elsa.Activities.Temporal.Quartz.Startup; +using UserTaskStartup = Elsa.Activities.UserTask.Startup; +using WebhooksListEndpoint = Elsa.Webhooks.Api.Endpoints.List; +using WebhooksStartup = Elsa.Activities.Webhooks.Startup; + +namespace LINGYUN.Abp.MicroService.WorkflowService; + +public partial class WorkflowServiceModule +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + private void PreConfigureFeature() + { + OneTimeRunner.Run(() => + { + GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); + }); + } + + private void PreConfigureForwardedHeaders() + { + } + + private void PreConfigureApp(IConfiguration configuration) + { + PreConfigure(options => + { + // 以开放端口区别 + options.SnowflakeIdOptions.WorkerId = 29; + options.SnowflakeIdOptions.WorkerIdBits = 5; + options.SnowflakeIdOptions.DatacenterId = 1; + }); + + if (configuration.GetValue("App:ShowPii")) + { + IdentityModelEventSource.ShowPII = true; + } + } + + + private void PreConfigureCAP(IConfiguration configuration) + { + PreConfigure(options => + { + options + .UsePostgreSql(mySqlOptions => + { + configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); + }) + .UseRabbitMQ(rabbitMQOptions => + { + configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); + }) + .UseDashboard(); + }); + } + + private void PreConfigureQuartz(IConfiguration configuration) + { + PreConfigure(options => + { + // 如果使用持久化存储, 则配置quartz持久层 + if (configuration.GetSection("Quartz:UsePersistentStore").Get()) + { + var settings = configuration.GetSection("Quartz:Properties").Get>(); + if (settings != null) + { + foreach (var setting in settings) + { + options.Properties[setting.Key] = setting.Value; + } + } + + options.Configurator += (config) => + { + config.UsePersistentStore(store => + { + store.UseProperties = false; + store.UseNewtonsoftJsonSerializer(); + }); + }; + } + }); + } + + private void ConfigureBackgroundTasks(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.NodeName = services.GetApplicationName(); + }); + } + + private void PreConfigureElsa(IServiceCollection services, IConfiguration configuration) + { + var elsaSection = configuration.GetSection("Elsa"); + var startups = new[] + { + typeof(ConsoleStartup), + typeof(HttpStartup), + typeof(UserTaskStartup), + typeof(TemporalQuartzStartup), + typeof(EmailStartup), + typeof(JavaScriptStartup), + typeof(WebhooksStartup), + }; + + PreConfigure(elsa => + { + elsa + .AddActivitiesFrom() + .AddWorkflowsFrom() + .AddFeatures(startups, configuration) + .ConfigureWorkflowChannels(options => elsaSection.GetSection("WorkflowChannels").Bind(options)) + .UseRabbitMq(elsaSection["Rebus:RabbitMQ:Connection"]); + + elsa.DistributedLockingOptionsBuilder + .UseProviderFactory(sp => name => + { + var provider = sp.GetRequiredService(); + + return provider.CreateLock(name); + }); + }); + + services.AddNotificationHandlersFrom(); + + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(WebhooksListEndpoint).Assembly); + }); + } + + private void ConfigureEndpoints(IServiceCollection services) + { + // 不需要 + //Configure(options => + //{ + // options.EndpointConfigureActions.Add( + // (context) => + // { + // context.Endpoints.MapFallbackToPage("/_Host"); + // }); + //}); + var preActions = services.GetPreConfigureActions(); + + services.AddAbpApiVersioning(options => + { + options.ReportApiVersions = true; + options.AssumeDefaultVersionWhenUnspecified = true; + + //options.ApiVersionReader = new HeaderApiVersionReader("api-version"); //Supports header too + //options.ApiVersionReader = new MediaTypeApiVersionReader(); //Supports accept header too + }, mvcOptions => + { + mvcOptions.ConfigureAbp(preActions.Configure()); + }); + } + + private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration) + { + var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; + if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) + { + services.AddSingleton(sp => + { + var connectionMultiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); + }); + } + } + + private void ConfigureBlobStoring(IServiceCollection services, IConfiguration configuration) + { + var preActions = services.GetPreConfigureActions(); + Configure(options => + { + preActions.Configure(options); + //options.Containers.Configure((containerConfiguration) => + //{ + // containerConfiguration.UseOssManagement(config => + // { + // config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket] ?? "workflow"; + // }); + //}); + options.Containers.ConfigureAll((_, containerConfiguration) => + { + containerConfiguration.UseOssManagement(config => + { + config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket] ?? "workflow"; + }); + }); + }); + } + + private void ConfigureDbContext() + { + // 配置Ef + Configure(options => + { + options.UseNpgsql(); + }); + } + + private void ConfigureJsonSerializer(IConfiguration configuration) + { + // 统一时间日期格式 + Configure(options => + { + var jsonConfiguration = configuration.GetSection("Json"); + if (jsonConfiguration.Exists()) + { + jsonConfiguration.Bind(options); + } + }); + // 中文序列化的编码问题 + Configure(options => + { + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + + private void ConfigureAuditing(IConfiguration configuration) + { + Configure(options => + { + // 是否启用实体变更记录 + var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; + if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || + (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) + { + options.EntityHistorySelectors.AddAllEntities(); + } + }); + } + + private void ConfigureTiming(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("Clock").Bind(options); + }); + } + + private void ConfigureCaching(IConfiguration configuration) + { + Configure(options => + { + configuration.GetSection("DistributedCache").Bind(options); + }); + + Configure(options => + { + var redisConfig = ConfigurationOptions.Parse(options.Configuration); + options.ConfigurationOptions = redisConfig; + options.InstanceName = configuration["Redis:InstanceName"]; + }); + } + + private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + options.ExposeIntegrationServices = true; + }); + } + + private void ConfigureVirtualFileSystem() + { + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MicroService.WorkflowService"); + }); + } + + private void ConfigurePermissionManagement() + { + Configure(options => + { + options.IsDynamicPermissionStoreEnabled = true; + options.SaveStaticPermissionsToDatabase = false; + }); + } + + private void ConfigureMultiTenancy(IConfiguration configuration) + { + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + var tenantResolveCfg = configuration.GetSection("App:Domains"); + if (tenantResolveCfg.Exists()) + { + Configure(options => + { + var domains = tenantResolveCfg.Get(); + foreach (var domain in domains) + { + options.AddDomainTenantResolver(domain); + } + }); + } + } + + private void ConfigureIdentity(IConfiguration configuration) + { + Configure(options => + { + options.IsDynamicClaimsEnabled = true; + options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; + + }); + } + + private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) + { + // Swagger + services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"], + new Dictionary + { + { configuration["AuthServer:Audience"], "Workflow Service API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Workflow Service API", Version = "v1", + Contact = new OpenApiContact + { + Name = "colin", + Email = "colin.in@foxmail.com", + Url = new Uri("https://github.com/colinin") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") + } + }); + 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(); + }); + } + + private void ConfigureLocalization() + { + // 支持本地化语言类型 + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + Configure(options => + { + var zhHansCultureMapInfo = new CultureMapInfo + { + TargetCulture = "zh-Hans", + SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } + }; + + options.CulturesMaps.Add(zhHansCultureMapInfo); + options.UiCulturesMaps.Add(zhHansCultureMapInfo); + }); + + Configure(options => + { + options.SaveStaticLocalizationsToDatabase = true; + }); + } + + private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) + { + Configure(options => + { + options.AutoValidate = false; + }); + + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddAbpJwtBearer(options => + { + configuration.GetSection("AuthServer").Bind(options); + + var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get>(); + if (validIssuers?.Count > 0) + { + options.TokenValidationParameters.ValidIssuers = validIssuers; + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + } + var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get>(); + if (validAudiences?.Count > 0) + { + options.TokenValidationParameters.ValidAudiences = validAudiences; + } + }); + + services + .AddDataProtection() + .SetApplicationName("LINGYUN.Abp.Application") + .PersistKeysToStackExchangeRedis(() => + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + + return redis.GetDatabase(); + }, + "LINGYUN.Abp.Application:DataProtection:Protection-Keys"); + } + + private void ConfigureCors(IServiceCollection services, IConfiguration configuration) + { + services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + var corsOrigins = configuration.GetSection("App:CorsOrigins").Get>(); + if (corsOrigins == null || corsOrigins.Count == 0) + { + corsOrigins = configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToList() ?? new List(); + } + builder + .WithOrigins(corsOrigins + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .WithAbpWrapExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.cs new file mode 100644 index 000000000..ac581493a --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/WorkflowServiceModule.cs @@ -0,0 +1,136 @@ +using LINGYUN.Abp.AspNetCore.HttpOverrides; +using LINGYUN.Abp.AspNetCore.Mvc.Localization; +using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Authorization.OrganizationUnits; +using LINGYUN.Abp.BackgroundTasks.DistributedLocking; +using LINGYUN.Abp.BackgroundTasks.ExceptionHandling; +using LINGYUN.Abp.BackgroundTasks.Quartz; +using LINGYUN.Abp.BlobStoring.OssManagement; +using LINGYUN.Abp.Claims.Mapping; +using LINGYUN.Abp.Data.DbMigrator; +using LINGYUN.Abp.Elsa; +using LINGYUN.Abp.Elsa.Activities; +using LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql; +using LINGYUN.Abp.Elsa.Notifications; +using LINGYUN.Abp.Emailing.Platform; +using LINGYUN.Abp.EventBus.CAP; +using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.Http.Client.Wrapper; +using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; +using LINGYUN.Abp.Quartz.PostgresSqlInstaller; +using LINGYUN.Abp.Saas.EntityFrameworkCore; +using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.Sms.Platform; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using Volo.Abp; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.NewtonsoftJson; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Swashbuckle; +using Volo.Abp.TextTemplating.Scriban; + +namespace LINGYUN.Abp.MicroService.WorkflowService; + +[DependsOn( + typeof(AbpSerilogEnrichersApplicationModule), + typeof(AbpSerilogEnrichersUniqueIdModule), + typeof(AbpAuditLoggingElasticsearchModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpBlobStoringOssManagementModule), + typeof(AbpElsaModule), + typeof(AbpElsaServerModule), + typeof(AbpElsaActivitiesModule), + typeof(AbpElsaNotificationsModule), + typeof(AbpEmailingExceptionHandlingModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpAspNetCoreMvcLocalizationModule), + typeof(AbpBackgroundTasksQuartzModule), + typeof(AbpBackgroundTasksDistributedLockingModule), + typeof(AbpBackgroundTasksExceptionHandlingModule), + typeof(AbpQuartzPostgresSqlInstallerModule), + typeof(TaskManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), + typeof(AbpElsaEntityFrameworkCorePostgreSqlModule), + typeof(AbpAuthorizationOrganizationUnitsModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpTextTemplatingScribanModule), + typeof(AbpDataDbMigratorModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpSwashbuckleModule), + typeof(AbpCAPEventBusModule), + typeof(AbpLocalizationCultureMapModule), + typeof(AbpHttpClientWrapperModule), + typeof(AbpAspNetCoreMvcWrapperModule), + typeof(AbpSmsPlatformModule), + typeof(AbpEmailingPlatformModule), + typeof(AbpClaimsMappingModule), + typeof(AbpAspNetCoreMvcNewtonsoftModule), + typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpIdentitySessionAspNetCoreModule), + typeof(AbpAutofacModule) + )] +public partial class WorkflowServiceModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + var configuration = context.Services.GetConfiguration(); + + PreConfigureFeature(); + PreConfigureForwardedHeaders(); + PreConfigureApp(configuration); + PreConfigureCAP(configuration); + PreConfigureQuartz(configuration); + PreConfigureElsa(context.Services, configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + ConfigureDbContext(); + ConfigureLocalization(); + ConfigureVirtualFileSystem(); + ConfigurePermissionManagement(); + ConfigureTiming(configuration); + ConfigureCaching(configuration); + ConfigureAuditing(configuration); + ConfigureIdentity(configuration); + ConfigureMultiTenancy(configuration); + ConfigureEndpoints(context.Services); + ConfigureMvc(context.Services, configuration); + ConfigureCors(context.Services, configuration); + ConfigureSwagger(context.Services, configuration); + ConfigureBlobStoring(context.Services, configuration); + ConfigureDistributedLock(context.Services, configuration); + ConfigureBackgroundTasks(context.Services, configuration); + ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); + + context.Services.AddRazorPages(); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json new file mode 100644 index 000000000..88291655b --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json @@ -0,0 +1,214 @@ +{ + "App": { + "CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], + "ShowPii": true, + "RefreshClaimsUrl": "http://localhost:30015" + }, + "Auditing": { + "AllEntitiesSelector": true + }, + "DistributedCache": { + "HideErrors": true, + "KeyPrefix": "LINGYUN.Abp.Application", + "GlobalCacheEntryOptions": { + "SlidingExpiration": "30:00:00", + "AbsoluteExpirationRelativeToNow": "60:00:00" + } + }, + "ConnectionStrings": { + "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "Quartz": { + "UsePersistentStore": true, + "Properties": { + "quartz.jobStore.dataSource": "tkm", + "quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz", + "quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate,Quartz", + "quartz.dataSource.tkm.connectionStringName": "Default", + "quartz.dataSource.tkm.provider": "Npgsql", + "quartz.jobStore.clustered": "true", + "quartz.serializer.type": "json", + "quartz.scheduler.instanceName": "WorkflowService", + "quartz.scheduler.instanceId": "212c489d-cb5d-4e0a-bde9-80d4a29d379b" + } + }, + "Elsa": { + "Features": { + "DefaultPersistence": { + "Enabled": true, + "ConnectionStringIdentifier": "Default", + "YesSql": { + "MySql": { + "Enabled": true + } + }, + "EntityFrameworkCore": { + "MySql": { + "Enabled": true + } + } + }, + "Console": true, + "Http": true, + "Email": true, + "TemporalQuartz": true, + "JavaScriptActivities": true, + "UserTask": true, + "Conductor": true, + "Telnyx": true, + "BlobStoring": true, + "Emailing": true, + "Notification": true, + "Sms": true, + "IM": true, + "PublishWebhook": true, + "Webhooks": { + "Enabled": true, + "ConnectionStringIdentifier": "Default", + "YesSql": { + "MySql": { + "Enabled": true + } + }, + "EntityFrameworkCore": { + "MySql": { + "Enabled": true + } + } + }, + "WorkflowSettings": { + "Enabled": true, + "ConnectionStringIdentifier": "Default", + "YesSql": { + "MySql": { + "Enabled": true + } + }, + "EntityFrameworkCore": { + "MySql": { + "Enabled": true + } + } + } + }, + "Rebus": { + "RabbitMQ": { + "Connection": "amqp://admin:123456@localhost:5672/" + } + }, + "Server": { + "BaseUrl": "http://localhost:30035" + } + }, + "RemoteServices": { + "AbpOssManagement": { + "BaseUrl": "http://localhost:30025", + "IdentityClient": "InternalServiceClient", + "UseCurrentAccessToken": false + } + }, + "IdentityClients": { + "InternalServiceClient": { + "Authority": "http://localhost:44385", + "RequireHttps": false, + "GrantType": "client_credentials", + "Scope": "lingyun-abp-application", + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3E*" + } + }, + "OssManagement": { + "Bucket": "workflow" + }, + "DistributedLock": { + "IsEnabled": true, + "Redis": { + "Configuration": "localhost,defaultDatabase=13" + } + }, + "CAP": { + "EventBus": { + "DefaultGroupName": "WorkflowService", + "GroupNamePrefix": "Dev", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10, + "CollectorCleaningInterval": 3600000 + }, + "PostgreSql": { + "TableNamePrefix": "wf", + "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "RabbitMQ": { + "HostName": "localhost", + "Port": 5672, + "UserName": "admin", + "Password": "123456", + "ExchangeName": "LINGYUN.Abp.Application", + "VirtualHost": "/" + } + }, + "Redis": { + "Configuration": "localhost,defaultDatabase=10", + "InstanceName": "LINGYUN.Abp.Application" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "Audience": "lingyun-abp-application", + "MapInboundClaims": false, + "RequireHttpsMetadata": false, + "Scopes": "lingyun-abp-application", + "ElsaClientId": "InternalServiceClient", + "SwaggerClientId": "vue-oauth-client" + }, + "Logging": { + "Serilog": { + "Elasticsearch": { + "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" + } + } + }, + "AuditLogging": { + "Elasticsearch": { + "IndexPrefix": "abp.dev.auditing" + } + }, + "Elasticsearch": { + "NodeUris": "http://elasticsearch" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] + } + } + ] + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.json new file mode 100644 index 000000000..b862514d8 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.json @@ -0,0 +1,99 @@ +{ + "Clock": { + "Kind": "Local" + }, + "Forwarded": { + "ForwardedHeaders": "XForwardedFor,XForwardedProto" + }, + "StringEncryption": { + "DefaultPassPhrase": "s46c5q55nxpeS8Ra", + "InitVectorBytes": "s83ng0abvd02js84", + "DefaultSalt": "sf&5)s3#" + }, + "Json": { + "OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss", + "InputDateTimeFormats": [ + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-ddTHH:mm:ss" + ] + }, + "SkyWalking": { + "Enable": false + }, + "AllowedHosts": "*", + "Hosting": { + "BasePath": "" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "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/aspire/LINGYUN.Abp.MicroService.sln b/aspnet-core/aspire/LINGYUN.Abp.MicroService.sln new file mode 100644 index 000000000..bb9961bc4 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11205.157 d18.0 +MinimumVisualStudioVersion = 17.8.0.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MicroService.AppHost", "LINGYUN.Abp.MicroService.AppHost\LINGYUN.Abp.MicroService.AppHost.csproj", "{2A40357F-C4E8-4E0E-BA48-1A59E6D4460A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MicroService.ServiceDefaults", "LINGYUN.Abp.MicroService.ServiceDefaults\LINGYUN.Abp.MicroService.ServiceDefaults.csproj", "{E162F21A-C926-4498-8E21-6BA9B1FC2D21}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C5EF1B59-A579-4C91-A39C-6C8BAD682BCC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{83B54E57-4B39-4148-9627-B4F7E2837015}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solution Items", "{8CB7982A-E7C2-4372-908E-506D2C36A1C6}" + ProjectSection(SolutionItems) = preProject + ..\..\common.props = ..\..\common.props + ..\..\common.secrets.props = ..\..\common.secrets.props + ..\..\configureawait.props = ..\..\configureawait.props + ..\..\Directory.Build.props = ..\..\Directory.Build.props + ..\..\Directory.Packages.props = ..\..\Directory.Packages.props + ..\..\NuGet.Config = ..\..\NuGet.Config + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AdminService.EntityFrameworkCore", "modules\admin\LINGYUN.Abp.AdminService.EntityFrameworkCore\LINGYUN.Abp.AdminService.EntityFrameworkCore.csproj", "{35A7AEE2-B063-462F-A697-BB657BC7F1B3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AdminService.DbMigrator", "modules\admin\LINGYUN.Abp.AdminService.DbMigrator\LINGYUN.Abp.AdminService.DbMigrator.csproj", "{1F486166-9FA4-CDCC-3B75-AA22474413EB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AdminService.HttpApi.Host", "modules\admin\LINGYUN.Abp.AdminService.HttpApi.Host\LINGYUN.Abp.AdminService.HttpApi.Host.csproj", "{A48B8B69-D827-9079-97BA-D338F439C722}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A40357F-C4E8-4E0E-BA48-1A59E6D4460A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A40357F-C4E8-4E0E-BA48-1A59E6D4460A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A40357F-C4E8-4E0E-BA48-1A59E6D4460A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A40357F-C4E8-4E0E-BA48-1A59E6D4460A}.Release|Any CPU.Build.0 = Release|Any CPU + {E162F21A-C926-4498-8E21-6BA9B1FC2D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E162F21A-C926-4498-8E21-6BA9B1FC2D21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E162F21A-C926-4498-8E21-6BA9B1FC2D21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E162F21A-C926-4498-8E21-6BA9B1FC2D21}.Release|Any CPU.Build.0 = Release|Any CPU + {35A7AEE2-B063-462F-A697-BB657BC7F1B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35A7AEE2-B063-462F-A697-BB657BC7F1B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35A7AEE2-B063-462F-A697-BB657BC7F1B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35A7AEE2-B063-462F-A697-BB657BC7F1B3}.Release|Any CPU.Build.0 = Release|Any CPU + {1F486166-9FA4-CDCC-3B75-AA22474413EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F486166-9FA4-CDCC-3B75-AA22474413EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F486166-9FA4-CDCC-3B75-AA22474413EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F486166-9FA4-CDCC-3B75-AA22474413EB}.Release|Any CPU.Build.0 = Release|Any CPU + {A48B8B69-D827-9079-97BA-D338F439C722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A48B8B69-D827-9079-97BA-D338F439C722}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A48B8B69-D827-9079-97BA-D338F439C722}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A48B8B69-D827-9079-97BA-D338F439C722}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2A40357F-C4E8-4E0E-BA48-1A59E6D4460A} = {C5EF1B59-A579-4C91-A39C-6C8BAD682BCC} + {E162F21A-C926-4498-8E21-6BA9B1FC2D21} = {C5EF1B59-A579-4C91-A39C-6C8BAD682BCC} + {83B54E57-4B39-4148-9627-B4F7E2837015} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {35A7AEE2-B063-462F-A697-BB657BC7F1B3} = {83B54E57-4B39-4148-9627-B4F7E2837015} + {1F486166-9FA4-CDCC-3B75-AA22474413EB} = {83B54E57-4B39-4148-9627-B4F7E2837015} + {A48B8B69-D827-9079-97BA-D338F439C722} = {83B54E57-4B39-4148-9627-B4F7E2837015} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E1DDDCF9-54EE-4F7D-9EFE-9EB972654692} + EndGlobalSection +EndGlobal diff --git a/aspnet-core/aspire/README.md b/aspnet-core/aspire/README.md new file mode 100644 index 000000000..5e5d0d441 --- /dev/null +++ b/aspnet-core/aspire/README.md @@ -0,0 +1,19 @@ +## 先决条件 + +请参考 [Aspire Docs](https://aspire.dev/get-started/prerequisites/) 检查运行所需环境. + +## 安装CLI + +请参考 [Aspire Docs](https://aspire.dev/get-started/install-cli/) 安装Aspire CLI. + +## 启动Aspire + +```shell +aspire run +``` + +## 注意事项 + +- 仅用于学习 [Aspire](https://aspire.dev/docs/) 请勿用于生产环境! +- 项目默认启用 [Elasticsearch](https://aspire.dev/integrations/databases/elasticsearch/) 作为审计日志及系统运行日志存储, 请视本机情况酌情修改启动参数,避免OOM! +- 多个项目在启动时初始化Quartz, 就算做了健康检查, 某些情况下还是会造成数据库锁争用, 在仪表盘中重启对应服务即可. \ No newline at end of file diff --git a/aspnet-core/framework/common/LINGYUN.Abp.Data.DbMigrator/LINGYUN/Abp/Data/DbMigrator/EfCoreRuntimeDbMigratorBase.cs b/aspnet-core/framework/common/LINGYUN.Abp.Data.DbMigrator/LINGYUN/Abp/Data/DbMigrator/EfCoreRuntimeDbMigratorBase.cs index 7055b90c0..76edc2c67 100644 --- a/aspnet-core/framework/common/LINGYUN.Abp.Data.DbMigrator/LINGYUN/Abp/Data/DbMigrator/EfCoreRuntimeDbMigratorBase.cs +++ b/aspnet-core/framework/common/LINGYUN.Abp.Data.DbMigrator/LINGYUN/Abp/Data/DbMigrator/EfCoreRuntimeDbMigratorBase.cs @@ -73,7 +73,7 @@ public abstract class EfCoreRuntimeDbMigratorBase : EfCoreRuntimeDat new AppliedDatabaseMigrationsEto { DatabaseName = DatabaseName, - TenantId = null + TenantId = tenantId } ); } diff --git a/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs b/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs index 2b977113a..67619eaed 100644 --- a/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs +++ b/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs @@ -109,16 +109,7 @@ public class AbpTelemetryOpenTelemetryModule : AbpModule }; }); tracing.AddCapInstrumentation(); - tracing.AddEntityFrameworkCoreInstrumentation(efcore => - { - efcore.SetDbStatementForText = configuration.GetValue( - "OpenTelemetry:EntityFrameworkCore:SetDbStatementForText", - efcore.SetDbStatementForText); - - efcore.SetDbStatementForStoredProcedure = configuration.GetValue( - "OpenTelemetry:EntityFrameworkCore:SetDbStatementForStoredProcedure", - efcore.SetDbStatementForStoredProcedure); - }); + tracing.AddEntityFrameworkCoreInstrumentation(); if (configuration.GetValue("OpenTelemetry:Console:IsEnabled", false)) { diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/LY.MicroService.BackendAdmin.DbMigrator.csproj b/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/LY.MicroService.BackendAdmin.DbMigrator.csproj index a9781c84d..9aec2aafa 100644 --- a/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/LY.MicroService.BackendAdmin.DbMigrator.csproj +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/LY.MicroService.BackendAdmin.DbMigrator.csproj @@ -51,4 +51,10 @@ + + + PreserveNewest + + + diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/appsettings.json b/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/appsettings.json index 5134cd6f5..848a0f83b 100644 --- a/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/appsettings.json +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.DbMigrator/appsettings.json @@ -1,9 +1,6 @@ { "ConnectionStrings": { - "Default": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456;SslMode=None", - "Platform": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456;SslMode=None", - "Identity": "Server=127.0.0.1;Database=AuthServer-V70;User Id=root;Password=123456;SslMode=None", - "Realtime": "Server=127.0.0.1;Database=Messages-V70;User Id=root;Password=123456;SslMode=None" + "Default": "Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None" }, "StringEncryption": { "DefaultPassPhrase": "s46c5q55nxpeS8Ra", diff --git a/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/LY.MicroService.Platform.DbMigrator.csproj b/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/LY.MicroService.Platform.DbMigrator.csproj index 227b766b0..5309dbd8c 100644 --- a/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/LY.MicroService.Platform.DbMigrator.csproj +++ b/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/LY.MicroService.Platform.DbMigrator.csproj @@ -37,4 +37,10 @@ + + + PreserveNewest + + + diff --git a/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/appsettings.json b/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/appsettings.json index 5134cd6f5..848a0f83b 100644 --- a/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/appsettings.json +++ b/aspnet-core/migrations/LY.MicroService.Platform.DbMigrator/appsettings.json @@ -1,9 +1,6 @@ { "ConnectionStrings": { - "Default": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456;SslMode=None", - "Platform": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456;SslMode=None", - "Identity": "Server=127.0.0.1;Database=AuthServer-V70;User Id=root;Password=123456;SslMode=None", - "Realtime": "Server=127.0.0.1;Database=Messages-V70;User Id=root;Password=123456;SslMode=None" + "Default": "Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None" }, "StringEncryption": { "DefaultPassPhrase": "s46c5q55nxpeS8Ra", diff --git a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Permissions/AbpOpenIddictPermissions.cs b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Permissions/AbpOpenIddictPermissions.cs index fc0061843..ff2ce37d4 100644 --- a/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Permissions/AbpOpenIddictPermissions.cs +++ b/aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Permissions/AbpOpenIddictPermissions.cs @@ -1,36 +1,36 @@ -namespace LINGYUN.Abp.OpenIddict.Permissions; - -public class AbpOpenIddictPermissions -{ - public const string GroupName = "AbpOpenIddict"; - - public static class Applications - { - public const string Default = GroupName + ".Applications"; - public const string Create = Default + ".Create"; - public const string Update = Default + ".Update"; - public const string Delete = Default + ".Delete"; - public const string ManagePermissions = Default + ".ManagePermissions"; - public const string ManageSecret = Default + ".ManageSecret"; - } - +namespace LINGYUN.Abp.OpenIddict.Permissions; + +public class AbpOpenIddictPermissions +{ + public const string GroupName = "AbpOpenIddict"; + + public static class Applications + { + public const string Default = GroupName + ".Applications"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + public const string ManagePermissions = Default + ".ManagePermissions"; + public const string ManageSecret = Default + ".ManageSecret"; + } + public static class Authorizations { public const string Default = GroupName + ".Authorizations"; public const string Delete = Default + ".Delete"; - } - + } + public static class Scopes { - public const string Default = GroupName + ".Scopes"; - public const string Create = Default + ".Create"; - public const string Update = Default + ".Update"; + public const string Default = GroupName + ".Scopes"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; public const string Delete = Default + ".Delete"; - } - + } + public static class Tokens { public const string Default = GroupName + ".Tokens"; public const string Delete = Default + ".Delete"; - } -} + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs index d485da99d..8d42fe2bf 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs @@ -1,25 +1,25 @@ -using System; +using System; using Volo.Abp.BlobStoring; -namespace LINGYUN.Abp.BlobStoring.OssManagement; - -public static class OssManagementBlobContainerConfigurationExtensions -{ - public static OssManagementBlobProviderConfiguration GetOssManagementConfiguration( - this BlobContainerConfiguration containerConfiguration) - { - return new OssManagementBlobProviderConfiguration(containerConfiguration); - } - - public static BlobContainerConfiguration UseOssManagement( - this BlobContainerConfiguration containerConfiguration, - Action fileSystemConfigureAction) - { - containerConfiguration.ProviderType = typeof(OssManagementBlobProvider); - containerConfiguration.NamingNormalizers.TryAdd(); - - fileSystemConfigureAction(new OssManagementBlobProviderConfiguration(containerConfiguration)); - - return containerConfiguration; - } -} +namespace LINGYUN.Abp.BlobStoring.OssManagement; + +public static class OssManagementBlobContainerConfigurationExtensions +{ + public static OssManagementBlobProviderConfiguration GetOssManagementConfiguration( + this BlobContainerConfiguration containerConfiguration) + { + return new OssManagementBlobProviderConfiguration(containerConfiguration); + } + + public static BlobContainerConfiguration UseOssManagement( + this BlobContainerConfiguration containerConfiguration, + Action fileSystemConfigureAction) + { + containerConfiguration.ProviderType = typeof(OssManagementBlobProvider); + containerConfiguration.NamingNormalizers.TryAdd(); + + fileSystemConfigureAction(new OssManagementBlobProviderConfiguration(containerConfiguration)); + + return containerConfiguration; + } +} diff --git a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/FodyWeavers.xml b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/FodyWeavers.xml new file mode 100644 index 000000000..00e1d9a1c --- /dev/null +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/FodyWeavers.xsd b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/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/project/LINGYUN.Abp.ProjectManagement.Application/LINGYUN.Abp.ProjectManagement.Application.csproj b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application/LINGYUN.Abp.ProjectManagement.Application.csproj index fecf1c653..cb558d516 100644 --- a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application/LINGYUN.Abp.ProjectManagement.Application.csproj +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Application/LINGYUN.Abp.ProjectManagement.Application.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net9.0 diff --git a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/FodyWeavers.xml b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/FodyWeavers.xml new file mode 100644 index 000000000..00e1d9a1c --- /dev/null +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/FodyWeavers.xsd b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/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/project/LINGYUN.Abp.ProjectManagement.Domain/LINGYUN.Abp.ProjectManagement.Domain.csproj b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain/LINGYUN.Abp.ProjectManagement.Domain.csproj index 63d98c5a8..cea0de9c5 100644 --- a/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain/LINGYUN.Abp.ProjectManagement.Domain.csproj +++ b/aspnet-core/modules/project/LINGYUN.Abp.ProjectManagement.Domain/LINGYUN.Abp.ProjectManagement.Domain.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net9.0 diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlInstaller/LINGYUN/Abp/Quartz/SqlInstaller/AbpQuartzSqlInstallerModule.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlInstaller/LINGYUN/Abp/Quartz/SqlInstaller/AbpQuartzSqlInstallerModule.cs index e38669fed..6363b4bd3 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlInstaller/LINGYUN/Abp/Quartz/SqlInstaller/AbpQuartzSqlInstallerModule.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlInstaller/LINGYUN/Abp/Quartz/SqlInstaller/AbpQuartzSqlInstallerModule.cs @@ -19,44 +19,38 @@ public class AbpQuartzSqlInstallerModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - if (!context.Services.IsDataMigrationEnvironment()) + var abpQuartzOptions = context.Services.ExecutePreConfiguredActions(); + Configure(options => { - var abpQuartzOptions = context.Services.ExecutePreConfiguredActions(); - Configure(options => + foreach (var settingKey in abpQuartzOptions.Properties.AllKeys) { - foreach (var settingKey in abpQuartzOptions.Properties.AllKeys) - { - options[settingKey] = abpQuartzOptions.Properties[settingKey]; - } + options[settingKey] = abpQuartzOptions.Properties[settingKey]; + } - if (abpQuartzOptions.Properties[StdSchedulerFactory.PropertyJobStoreType] == null) - { - var defaultJobStoreType = typeof(RAMJobStore).AssemblyQualifiedNameWithoutVersion(); + if (abpQuartzOptions.Properties[StdSchedulerFactory.PropertyJobStoreType] == null) + { + var defaultJobStoreType = typeof(RAMJobStore).AssemblyQualifiedNameWithoutVersion(); - options[StdSchedulerFactory.PropertyJobStoreType] = defaultJobStoreType; - abpQuartzOptions.Properties[StdSchedulerFactory.PropertyJobStoreType] = defaultJobStoreType; - } - }); - } + options[StdSchedulerFactory.PropertyJobStoreType] = defaultJobStoreType; + abpQuartzOptions.Properties[StdSchedulerFactory.PropertyJobStoreType] = defaultJobStoreType; + } + }); } public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context) { - if (!context.ServiceProvider.IsDataMigrationEnvironment()) + var configuration = context.ServiceProvider.GetRequiredService(); + if (configuration.GetValue("Quartz:UsePersistentStore", false)) { - var configuration = context.ServiceProvider.GetRequiredService(); - if (configuration.GetValue("Quartz:UsePersistentStore", false)) - { - var driverDelegateType = configuration[$"Quartz:Properties:quartz.jobStore.driverDelegateType"]; - // 初始化 Quartz 数据库 - var installs = context.ServiceProvider.GetServices(); + var driverDelegateType = configuration[$"Quartz:Properties:quartz.jobStore.driverDelegateType"]; + // 初始化 Quartz 数据库 + var installs = context.ServiceProvider.GetServices(); - foreach (var install in installs) + foreach (var install in installs) + { + if (install.CanInstall(driverDelegateType)) { - if (install.CanInstall(driverDelegateType)) - { - await install.InstallAsync(); - } + await install.InstallAsync(); } } } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/ITaskManagementDbContext.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/ITaskManagementDbContext.cs index 268adb1fb..398796a6b 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/ITaskManagementDbContext.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/ITaskManagementDbContext.cs @@ -8,5 +8,6 @@ namespace LINGYUN.Abp.TaskManagement.EntityFrameworkCore; public interface ITaskManagementDbContext :IEfCoreDbContext { DbSet BackgroundJobInfos { get; } + DbSet BackgroundJobLogs { get; } DbSet BackgroundJobAction { get; } } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs index 9804d3de3..eb1226863 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs @@ -8,6 +8,7 @@ namespace LINGYUN.Abp.TaskManagement.EntityFrameworkCore; public class TaskManagementDbContext : AbpDbContext, ITaskManagementDbContext { public DbSet BackgroundJobInfos { get; set; } + public DbSet BackgroundJobLogs { get; set; } public DbSet BackgroundJobAction { get; set; } public TaskManagementDbContext(