From c4b5ea6eaf345e22b5599e304b11ad45e459ffcd Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Sun, 21 Feb 2021 11:28:07 +0800 Subject: [PATCH] Ali cloud dynamic configuration;Configuration menu bug fixes --- aspnet-core/LINGYUN.MicroService.All.sln | 9 +- aspnet-core/LINGYUN.MicroService.Common.sln | 56 +++++- aspnet-core/LINGYUN.MicroService.Platform.sln | 30 +++ .../LINGYUN.Abp.Aliyun.csproj | 3 +- .../LINYUN/Abp/Aliyun/AbpAliyunException.cs | 21 ++ ...liyunCloudModule.cs => AbpAliyunModule.cs} | 8 +- .../LINYUN/Abp/Aliyun/AcsClientFactory.cs | 32 ++++ .../AliyunBasicSessionCredentialsCacheItem.cs | 31 +++ .../LINYUN/Abp/Aliyun/AliyunClientFactory.cs | 180 ++++++++++++++++++ .../LINYUN/Abp/Aliyun/IAcsClientFactory.cs | 15 ++ .../Abp/Aliyun/Localization/Resources/en.json | 18 ++ .../Localization/Resources/zh-Hans.json | 18 ++ .../Abp/Aliyun/Settings/AliyunSettingNames.cs | 32 +++- .../Aliyun/Settings/AliyunSettingProvider.cs | 81 ++++++++ .../cloud-aliyun/LINGYUN.Abp.Aliyun/README.md | 31 +++ .../LINGYUN.Abp.BlobStoring.Aliyun.csproj | 2 +- .../Aliyun/AbpBlobStoringAliyunModule.cs | 4 +- .../BlobStoring/Aliyun/AliyunBlobProvider.cs | 43 ++--- .../BlobStoring/Aliyun/IOssClientFactory.cs | 15 ++ .../BlobStoring/Aliyun/OssClientFactory.cs | 50 +++++ .../LINGYUN.Abp.BlobStoring.Aliyun/README.md | 6 +- .../LINGYUN.Abp.Sms.Aliyun.csproj | 5 +- .../Abp/Sms/Aliyun/AbpAliyunSmsModule.cs | 15 +- .../Abp/Sms/Aliyun/AliyunSmsException.cs | 22 +-- .../LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs | 38 ---- .../LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs | 87 +++++---- .../Localization/Resources/zh-Hans.json | 14 ++ .../Aliyun/Settings/AliyunSmsSettingNames.cs | 43 +++++ .../Settings/AliyunSmsSettingProvider.cs | 74 +++++++ .../common/LINGYUN.Abp.Sms.Aliyun/README.md | 40 ++-- .../AbpEncryptionConsoleModule.cs | 12 ++ .../LINGYUN.Abp.Encryption.Console.csproj | 12 ++ .../LINGYUN.Abp.Encryption.Console/Program.cs | 42 ++++ .../Datas/DataDictionaryDataSeeder.cs | 35 ++-- .../Platform/Menus/IRoleMenuRepository.cs | 7 +- .../Platform/Menus/IUserMenuRepository.cs | 7 +- .../LINGYUN/Platform/Menus/MenuManager.cs | 66 +++++-- .../LINGYUN/Platform/Menus/RoleMenu.cs | 2 + .../LINGYUN/Platform/Menus/UserMenu.cs | 2 + .../Platform/PlatformDataSeedContributor.cs | 41 ++-- .../Platform/Routes/RouteDataSeeder.cs | 4 +- .../EntityFrameworkCore/PlatformDbContext.cs | 4 +- .../Menus/EfCoreRoleMenuRepository.cs | 34 ++-- .../Menus/EfCoreUserMenuRepository.cs | 38 ++-- .../LINGYUN.Abp.Aliyun.Tests.csproj | 18 ++ .../LINGYUN/Abp/Aliyun/AbpAliyunTestBase.cs | 8 + .../LINGYUN/Abp/Aliyun/AbpAliyunTestModule.cs | 24 +++ ...INGYUN.Abp.BlobStoring.Aliyun.Tests.csproj | 1 + .../Aliyun/AbpBlobStoringAliyunTestModule.cs | 32 ++-- .../AbpEntityFrameworkCoreTestModule.cs | 4 + .../EfCoreLoggerFactory.cs | 52 +++++ .../LINGYUN.Abp.Sms.Aliyun.Tests.csproj | 18 ++ .../Abp/Sms/Aliyun/AbpAliyunSmsTestBase.cs | 8 + .../Abp/Sms/Aliyun/AbpAliyunSmsTestModule.cs | 13 ++ .../Abp/Sms/Aliyun/AliyunSmsSenderTests.cs | 43 +++++ .../LINGYUN.Platform.Domain.Tests.csproj | 22 +++ .../Platform/PlatformDomainTestModule.cs | 40 ++++ .../LINGYUN/Platform/PlatformTestsConsts.cs | 17 ++ .../Platform/PlatformTestsDataBuilder.cs | 65 +++++++ ....Platform.EntityFrameworkCore.Tests.csproj | 24 +++ .../PlatformEntityFrameworkCoreTestBase.cs | 9 + .../PlatformEntityFrameworkCoreTestModule.cs | 14 ++ .../Menus/EfCoreUserMenuRepositoryTests.cs | 68 +++++++ 63 files changed, 1502 insertions(+), 307 deletions(-) create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunException.cs rename aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/{AbpAliyunCloudModule.cs => AbpAliyunModule.cs} (76%) create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AcsClientFactory.cs create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunClientFactory.cs create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/IAcsClientFactory.cs create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs create mode 100644 aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IOssClientFactory.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/OssClientFactory.cs delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingNames.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingProvider.cs create mode 100644 aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/AbpEncryptionConsoleModule.cs create mode 100644 aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/LINGYUN.Abp.Encryption.Console.csproj create mode 100644 aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/Program.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN.Abp.Aliyun.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreLoggerFactory.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN.Abp.Sms.Aliyun.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AliyunSmsSenderTests.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN.Platform.Domain.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformDomainTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsConsts.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsDataBuilder.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN.Platform.EntityFrameworkCore.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/Menus/EfCoreUserMenuRepositoryTests.cs diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index d3f477df8..21a4ff369 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -125,8 +125,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "te 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.Aliyun.Authorization", "modules\common\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj", "{F3AE9617-983D-4940-B5EB-35E3580C0B0F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application.Contracts", "modules\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\message\LINGYUN.Abp.MessageService.Application\LINGYUN.Abp.MessageService.Application.csproj", "{AB984240-EF03-416F-A9B2-F5CF169E04B7}" @@ -465,10 +463,6 @@ Global {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 - {F3AE9617-983D-4940-B5EB-35E3580C0B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F3AE9617-983D-4940-B5EB-35E3580C0B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F3AE9617-983D-4940-B5EB-35E3580C0B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F3AE9617-983D-4940-B5EB-35E3580C0B0F}.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 @@ -773,10 +767,9 @@ Global {F595CB9F-B117-4D62-A1AE-48599927DB36} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} {5CF403B2-47C9-4E4E-8856-0294BDD64884} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} {8A22674D-151D-474E-8C99-9D991C0D8297} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} - {059473BA-FAF9-405F-9985-33DDCA2E9F0D} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {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} - {F3AE9617-983D-4940-B5EB-35E3580C0B0F} = {14CDBAD1-10C8-464A-B445-1F727C988010} {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} diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln index 8d06dfc9e..28916cf62 100644 --- a/aspnet-core/LINGYUN.MicroService.Common.sln +++ b/aspnet-core/LINGYUN.MicroService.Common.sln @@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Sign EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.SignalR.JwtToken", "modules\common\LINGYUN.Abp.AspNetCore.SignalR\LINGYUN.Abp.AspNetCore.SignalR.JwtToken.csproj", "{304D06E6-41EC-4DCB-AEAE-DBEEC75F9ADC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Authorization", "modules\common\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj", "{58777534-1AEF-4D1B-807C-1070D6CB1D48}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs", "modules\common\LINGYUN.Abp.BackgroundJobs\LINGYUN.Abp.BackgroundJobs.csproj", "{FFC21AA5-8DCF-4514-95F0-9A1D428095F8}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs.Hangfire", "modules\common\LINGYUN.Abp.BackgroundJobs.Hangfire\LINGYUN.Abp.BackgroundJobs.Hangfire.csproj", "{492710E6-EEF5-4390-A474-8FB2412ECBE5}" @@ -95,7 +93,23 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.SettingM EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{D119C919-230B-4614-9A06-98586635DBFC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Core", "modules\common\LINGYUN.Abp.Core\LINGYUN.Abp.Core.csproj", "{A7A28D6C-6EDB-4615-8899-7DE1D435B750}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Core", "modules\common\LINGYUN.Abp.Core\LINGYUN.Abp.Core.csproj", "{A7A28D6C-6EDB-4615-8899-7DE1D435B750}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun", "modules\cloud-aliyun\LINGYUN.Abp.Aliyun\LINGYUN.Abp.Aliyun.csproj", "{17A8455F-D413-4664-AEFA-1ECAE9ED4B19}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{B86C21A4-73B7-471E-B73A-B4B905EC9435}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{3BAA3D38-96C2-4C4C-B790-AE2997BFDE25}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BlobStoring.Aliyun.Tests", "tests\LINGYUN.Abp.BlobStoring.Aliyun.Tests\LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj", "{2E35CB93-2E9C-4EE1-845F-72A40271648E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "console", "console", "{8D2AD50B-DD4B-48A2-88EC-0E8E8236D883}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Encryption.Console", "modules\console\LINGYUN.Abp.Encryption.Console\LINGYUN.Abp.Encryption.Console.csproj", "{8FB74B18-CA5C-4DC3-8DFA-600133A05712}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Aliyun.Tests", "tests\LINGYUN.Abp.Aliyun.Tests\LINGYUN.Abp.Aliyun.Tests.csproj", "{3DBF0975-B09D-49CA-9AF8-69175EDB9D52}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Sms.Aliyun.Tests", "tests\LINGYUN.Abp.Sms.Aliyun.Tests\LINGYUN.Abp.Sms.Aliyun.Tests.csproj", "{93DD5A05-B67A-4E11-BB56-F6B4E7F1489C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -123,10 +137,6 @@ Global {304D06E6-41EC-4DCB-AEAE-DBEEC75F9ADC}.Debug|Any CPU.Build.0 = Debug|Any CPU {304D06E6-41EC-4DCB-AEAE-DBEEC75F9ADC}.Release|Any CPU.ActiveCfg = Release|Any CPU {304D06E6-41EC-4DCB-AEAE-DBEEC75F9ADC}.Release|Any CPU.Build.0 = Release|Any CPU - {58777534-1AEF-4D1B-807C-1070D6CB1D48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58777534-1AEF-4D1B-807C-1070D6CB1D48}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58777534-1AEF-4D1B-807C-1070D6CB1D48}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58777534-1AEF-4D1B-807C-1070D6CB1D48}.Release|Any CPU.Build.0 = Release|Any CPU {FFC21AA5-8DCF-4514-95F0-9A1D428095F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FFC21AA5-8DCF-4514-95F0-9A1D428095F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {FFC21AA5-8DCF-4514-95F0-9A1D428095F8}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -255,6 +265,30 @@ Global {A7A28D6C-6EDB-4615-8899-7DE1D435B750}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7A28D6C-6EDB-4615-8899-7DE1D435B750}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7A28D6C-6EDB-4615-8899-7DE1D435B750}.Release|Any CPU.Build.0 = Release|Any CPU + {17A8455F-D413-4664-AEFA-1ECAE9ED4B19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17A8455F-D413-4664-AEFA-1ECAE9ED4B19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17A8455F-D413-4664-AEFA-1ECAE9ED4B19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17A8455F-D413-4664-AEFA-1ECAE9ED4B19}.Release|Any CPU.Build.0 = Release|Any CPU + {3BAA3D38-96C2-4C4C-B790-AE2997BFDE25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BAA3D38-96C2-4C4C-B790-AE2997BFDE25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BAA3D38-96C2-4C4C-B790-AE2997BFDE25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BAA3D38-96C2-4C4C-B790-AE2997BFDE25}.Release|Any CPU.Build.0 = Release|Any CPU + {2E35CB93-2E9C-4EE1-845F-72A40271648E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E35CB93-2E9C-4EE1-845F-72A40271648E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E35CB93-2E9C-4EE1-845F-72A40271648E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E35CB93-2E9C-4EE1-845F-72A40271648E}.Release|Any CPU.Build.0 = Release|Any CPU + {8FB74B18-CA5C-4DC3-8DFA-600133A05712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FB74B18-CA5C-4DC3-8DFA-600133A05712}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FB74B18-CA5C-4DC3-8DFA-600133A05712}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FB74B18-CA5C-4DC3-8DFA-600133A05712}.Release|Any CPU.Build.0 = Release|Any CPU + {3DBF0975-B09D-49CA-9AF8-69175EDB9D52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3DBF0975-B09D-49CA-9AF8-69175EDB9D52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DBF0975-B09D-49CA-9AF8-69175EDB9D52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3DBF0975-B09D-49CA-9AF8-69175EDB9D52}.Release|Any CPU.Build.0 = Release|Any CPU + {93DD5A05-B67A-4E11-BB56-F6B4E7F1489C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93DD5A05-B67A-4E11-BB56-F6B4E7F1489C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93DD5A05-B67A-4E11-BB56-F6B4E7F1489C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93DD5A05-B67A-4E11-BB56-F6B4E7F1489C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -266,7 +300,6 @@ Global {824CB367-383B-48B2-972D-33923438A9A0} = {B91F26C5-B148-4094-B5F1-71E5F945DBED} {E9AEC9D6-1FE7-4B00-BAC5-2C3D4B63CCA2} = {E2E7A062-0ABB-41B4-8220-60228446D2C2} {304D06E6-41EC-4DCB-AEAE-DBEEC75F9ADC} = {E2E7A062-0ABB-41B4-8220-60228446D2C2} - {58777534-1AEF-4D1B-807C-1070D6CB1D48} = {7F18BCA5-35BD-41FB-8EFF-801B56E5E414} {FFC21AA5-8DCF-4514-95F0-9A1D428095F8} = {086BE5BE-8594-4DA7-8819-935FEF76DABD} {492710E6-EEF5-4390-A474-8FB2412ECBE5} = {086BE5BE-8594-4DA7-8819-935FEF76DABD} {CCF1EB86-29BD-4531-BB27-C9111CC67570} = {7F18BCA5-35BD-41FB-8EFF-801B56E5E414} @@ -306,6 +339,13 @@ Global {D0717513-2CEE-4AD5-A1DA-A08EA5DE6DD6} = {22C61434-D29A-4376-AD56-F5089F3E617A} {D119C919-230B-4614-9A06-98586635DBFC} = {22C61434-D29A-4376-AD56-F5089F3E617A} {A7A28D6C-6EDB-4615-8899-7DE1D435B750} = {086BE5BE-8594-4DA7-8819-935FEF76DABD} + {17A8455F-D413-4664-AEFA-1ECAE9ED4B19} = {7F18BCA5-35BD-41FB-8EFF-801B56E5E414} + {3BAA3D38-96C2-4C4C-B790-AE2997BFDE25} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {2E35CB93-2E9C-4EE1-845F-72A40271648E} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {8D2AD50B-DD4B-48A2-88EC-0E8E8236D883} = {02EA4E78-5891-43BC-944F-3E52FEE032E4} + {8FB74B18-CA5C-4DC3-8DFA-600133A05712} = {8D2AD50B-DD4B-48A2-88EC-0E8E8236D883} + {3DBF0975-B09D-49CA-9AF8-69175EDB9D52} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {93DD5A05-B67A-4E11-BB56-F6B4E7F1489C} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} diff --git a/aspnet-core/LINGYUN.MicroService.Platform.sln b/aspnet-core/LINGYUN.MicroService.Platform.sln index cfcf24033..4d6f304f3 100644 --- a/aspnet-core/LINGYUN.MicroService.Platform.sln +++ b/aspnet-core/LINGYUN.MicroService.Platform.sln @@ -39,6 +39,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{8CDB EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{CF0EBF60-EDC7-47FF-BCD7-C2B16407B590}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{CCEFF583-4EEE-433F-8568-9E64166B41FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{B2C0271C-3FE6-4C45-B162-4DE00E542A55}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Platform.EntityFrameworkCore.Tests", "tests\LINGYUN.Platform.EntityFrameworkCore.Tests\LINGYUN.Platform.EntityFrameworkCore.Tests.csproj", "{263C49A9-34B9-449B-ABBC-D328210C023D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Platform.Domain.Tests", "tests\LINGYUN.Platform.Domain.Tests\LINGYUN.Platform.Domain.Tests.csproj", "{C60A06F2-0F4C-483F-BE2B-B103F0D726CE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -97,6 +107,22 @@ Global {CF0EBF60-EDC7-47FF-BCD7-C2B16407B590}.Debug|Any CPU.Build.0 = Debug|Any CPU {CF0EBF60-EDC7-47FF-BCD7-C2B16407B590}.Release|Any CPU.ActiveCfg = Release|Any CPU {CF0EBF60-EDC7-47FF-BCD7-C2B16407B590}.Release|Any CPU.Build.0 = Release|Any CPU + {FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC}.Release|Any CPU.Build.0 = Release|Any CPU + {B2C0271C-3FE6-4C45-B162-4DE00E542A55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2C0271C-3FE6-4C45-B162-4DE00E542A55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2C0271C-3FE6-4C45-B162-4DE00E542A55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2C0271C-3FE6-4C45-B162-4DE00E542A55}.Release|Any CPU.Build.0 = Release|Any CPU + {263C49A9-34B9-449B-ABBC-D328210C023D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {263C49A9-34B9-449B-ABBC-D328210C023D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {263C49A9-34B9-449B-ABBC-D328210C023D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {263C49A9-34B9-449B-ABBC-D328210C023D}.Release|Any CPU.Build.0 = Release|Any CPU + {C60A06F2-0F4C-483F-BE2B-B103F0D726CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C60A06F2-0F4C-483F-BE2B-B103F0D726CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C60A06F2-0F4C-483F-BE2B-B103F0D726CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C60A06F2-0F4C-483F-BE2B-B103F0D726CE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -118,6 +144,10 @@ Global {C616C167-E5DF-4141-98BE-F98C58890122} = {C7D0EB39-3418-4A7C-AD94-FAB76F023E88} {8CDB2F58-9541-4FB2-8A37-079C5E6A1689} = {15BDA03E-DE8E-46E4-96A8-CA3F2872E812} {CF0EBF60-EDC7-47FF-BCD7-C2B16407B590} = {8CDB2F58-9541-4FB2-8A37-079C5E6A1689} + {FC3E5BA0-C650-4EA2-8400-0A864D0EFEAC} = {CCEFF583-4EEE-433F-8568-9E64166B41FE} + {B2C0271C-3FE6-4C45-B162-4DE00E542A55} = {CCEFF583-4EEE-433F-8568-9E64166B41FE} + {263C49A9-34B9-449B-ABBC-D328210C023D} = {CCEFF583-4EEE-433F-8568-9E64166B41FE} + {C60A06F2-0F4C-483F-BE2B-B103F0D726CE} = {CCEFF583-4EEE-433F-8568-9E64166B41FE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {03D3B66F-8926-4C00-B7AB-A21761EC859E} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj index 331d270b8..040db79cd 100644 --- a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj @@ -20,7 +20,8 @@ - + + diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunException.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunException.cs new file mode 100644 index 000000000..510c5a040 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunException.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Logging; +using Volo.Abp; +using Volo.Abp.ExceptionHandling; +using Volo.Abp.Logging; + +namespace LINYUN.Abp.Aliyun +{ + public class AbpAliyunException : AbpException, IHasErrorCode, IHasLogLevel + { + public LogLevel LogLevel { get; set; } + + public string Code { get; } + + public AbpAliyunException(string code, string message) + : base(message) + { + Code = code; + LogLevel = LogLevel.Warning; + } + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunCloudModule.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunModule.cs similarity index 76% rename from aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunCloudModule.cs rename to aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunModule.cs index 80d744bb3..ed462d06a 100644 --- a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunCloudModule.cs +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AbpAliyunModule.cs @@ -1,21 +1,25 @@ using LINYUN.Abp.Aliyun.Localization; +using Volo.Abp.Caching; using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Modularity; +using Volo.Abp.Settings; using Volo.Abp.VirtualFileSystem; namespace LINGYUN.Abp.Aliyun { [DependsOn( + typeof(AbpCachingModule), + typeof(AbpSettingsModule), typeof(AbpJsonModule), typeof(AbpLocalizationModule))] - public class AbpAliyunCloudModule : AbpModule + public class AbpAliyunModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => { - options.FileSets.AddEmbedded(); + options.FileSets.AddEmbedded(); }); Configure(options => diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AcsClientFactory.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AcsClientFactory.cs new file mode 100644 index 000000000..277732303 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AcsClientFactory.cs @@ -0,0 +1,32 @@ +using Aliyun.Acs.Core; +using Aliyun.Acs.Core.Auth; +using Aliyun.Acs.Core.Profile; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace LINYUN.Abp.Aliyun +{ + public class AcsClientFactory : AliyunClientFactory, IAcsClientFactory, ITransientDependency + { + public AcsClientFactory( + ISettingProvider settingProvider, + IDistributedCache cache) + : base(settingProvider, cache) + { + } + + protected override IAcsClient GetClient(string regionId, string accessKeyId, string accessKeySecret) + { + return new DefaultAcsClient( + DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret)); + } + + protected override IAcsClient GetSecurityTokenClient(string regionId, string accessKeyId, string accessKeySecret, string securityToken) + { + var profile = DefaultProfile.GetProfile(regionId); + var credentials = new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken); + return new DefaultAcsClient(profile, credentials); + } + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs new file mode 100644 index 000000000..7d135ce34 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs @@ -0,0 +1,31 @@ +using System; + +namespace LINYUN.Abp.Aliyun +{ + [Serializable] + public class AliyunBasicSessionCredentialsCacheItem + { + private readonly static string _cacheKey; + public static string CacheKey => _cacheKey; + public string AccessKeyId { get; set; } + public string AccessKeySecret { get; set; } + public string SecurityToken { get; set; } + + static AliyunBasicSessionCredentialsCacheItem() + { + _cacheKey = Guid.NewGuid().ToString("N"); + } + + public AliyunBasicSessionCredentialsCacheItem() + { + + } + + public AliyunBasicSessionCredentialsCacheItem(string accessKeyId, string accessKeySecret, string securityToken) + { + AccessKeyId = accessKeyId; + AccessKeySecret = accessKeySecret; + SecurityToken = securityToken; + } + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunClientFactory.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunClientFactory.cs new file mode 100644 index 000000000..95912462c --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/AliyunClientFactory.cs @@ -0,0 +1,180 @@ +using Aliyun.Acs.Core; +using Aliyun.Acs.Core.Auth.Sts; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Core.Profile; +using LINYUN.Abp.Aliyun.Settings; +using Microsoft.Extensions.Caching.Distributed; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Caching; +using Volo.Abp.Settings; + +namespace LINYUN.Abp.Aliyun +{ + /// + /// 阿里云通用客户端构建工厂 + /// + /// + public abstract class AliyunClientFactory + { + protected ISettingProvider SettingProvider { get; } + protected IDistributedCache Cache { get; } + public AliyunClientFactory( + ISettingProvider settingProvider, + IDistributedCache cache) + { + Cache = cache; + SettingProvider = settingProvider; + } + + public virtual async Task CreateAsync() + { + var regionId = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId); + var accessKey = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId); + var accessKeySecret = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret); + + Check.NotNullOrWhiteSpace(regionId, AliyunSettingNames.Authorization.RegionId); + Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId); + Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret); + + if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService)) + { + var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId); + + return GetSecurityTokenClient(regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken); + } + + return GetClient(regionId, accessKey, accessKeySecret); + } + + protected abstract TClient GetClient(string regionId, string accessKeyId, string accessKeySecret); + + protected abstract TClient GetSecurityTokenClient(string regionId, string accessKeyId, string accessKeySecret, string securityToken); + + protected virtual async Task GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId) + { + var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey); + if (cacheItem == null) + { + var roleArn = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn); + var roleSession = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName); + Check.NotNullOrWhiteSpace(roleArn, AliyunSettingNames.Authorization.RamRoleArn); + + var policy = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.Policy); + var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000); + + var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); + var request = new AssumeRoleRequest + { + AcceptFormat = FormatType.JSON, + RoleArn = roleArn, + RoleSessionName = roleSession, + DurationSeconds = durationSeconds, + Policy = policy.IsNullOrWhiteSpace() ? null : policy + }; + + var client = new DefaultAcsClient(profile); + var response = client.GetAcsResponse(request); + + cacheItem = new AliyunBasicSessionCredentialsCacheItem( + response.Credentials.AccessKeyId, + response.Credentials.AccessKeySecret, + response.Credentials.SecurityToken); + + await Cache.SetAsync( + AliyunBasicSessionCredentialsCacheItem.CacheKey, + cacheItem, + new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(durationSeconds - 10) + }); + } + + return cacheItem; + } + } + /// + /// 阿里云通用客户端构建工厂 + /// + /// 客户端类型 + /// 客户端参数类型 + public abstract class AliyunClientFactory + { + protected ISettingProvider SettingProvider { get; } + protected IDistributedCache Cache { get; } + public AliyunClientFactory( + ISettingProvider settingProvider, + IDistributedCache cache) + { + Cache = cache; + SettingProvider = settingProvider; + } + + public virtual async Task CreateAsync(TConfiguration configuration) + { + var regionId = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId); + var accessKey = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId); + var accessKeySecret = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret); + + Check.NotNullOrWhiteSpace(regionId, AliyunSettingNames.Authorization.RegionId); + Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId); + Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret); + + if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService)) + { + var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId); + + return GetSecurityTokenClient(configuration, regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken); + } + + return GetClient(configuration, regionId, accessKey, accessKeySecret); + } + + protected abstract TClient GetClient(TConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret); + + protected abstract TClient GetSecurityTokenClient(TConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret, string securityToken); + + protected virtual async Task GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId) + { + var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey); + if (cacheItem == null) + { + var roleArn = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn); + var roleSession = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName); + Check.NotNullOrWhiteSpace(roleArn, AliyunSettingNames.Authorization.RamRoleArn); + + var policy = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.Policy); + var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000); + + var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); + var request = new AssumeRoleRequest + { + AcceptFormat = FormatType.JSON, + RoleArn = roleArn, + RoleSessionName = roleSession, + DurationSeconds = durationSeconds, + Policy = policy.IsNullOrWhiteSpace() ? null : policy + }; + + var client = new DefaultAcsClient(profile); + var response = client.GetAcsResponse(request); + + cacheItem = new AliyunBasicSessionCredentialsCacheItem( + response.Credentials.AccessKeyId, + response.Credentials.AccessKeySecret, + response.Credentials.SecurityToken); + + await Cache.SetAsync( + AliyunBasicSessionCredentialsCacheItem.CacheKey, + cacheItem, + new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(durationSeconds - 10) + }); + } + + return cacheItem; + } + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/IAcsClientFactory.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/IAcsClientFactory.cs new file mode 100644 index 000000000..fd2b84838 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/IAcsClientFactory.cs @@ -0,0 +1,15 @@ +using Aliyun.Acs.Core; +using System.Threading.Tasks; + +namespace LINYUN.Abp.Aliyun +{ + public interface IAcsClientFactory + { + /// + /// 构造一个通用的Acs客户端调用 + /// 通过CommonRequest调用可以不需要集成其他SDK包 + /// + /// + Task CreateAsync(); + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/en.json b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/en.json index a9c8dcc3f..19cf0fdf0 100644 --- a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/en.json +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/en.json @@ -1,5 +1,23 @@ { "culture": "en", "texts": { + "DisplayName:Authorization": "Authorization", + "Description:Authorization": "Authorization", + "DisplayName:RegionId": "Region Id", + "Description:RegionId": "Region Id", + "DisplayName:AccessKeyId": "AccessKey Id", + "Description:AccessKeyId": "AccessKey Id", + "DisplayName:AccessKeySecret": "AccessKey Secret", + "Description:AccessKeySecret": "AccessKey Secret", + "DisplayName:UseSecurityTokenService": "Use STS Token", + "Description:UseSecurityTokenService": "Use STS Token", + "DisplayName:RamRoleArn": "Ram Role Arn", + "Description:RamRoleArn": "Ram Role Arn", + "DisplayName:RoleSessionName": "Role Session Name", + "Description:RoleSessionName": "Role Session Name", + "DisplayName:DurationSeconds": "Duration Seconds,in seconds", + "Description:DurationSeconds": "Duration Seconds,in seconds", + "DisplayName:Policy": "Policy", + "Description:Policy": "Policy" } } \ No newline at end of file diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/zh-Hans.json b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/zh-Hans.json index c5ad81326..20e7c54e4 100644 --- a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Localization/Resources/zh-Hans.json @@ -1,5 +1,23 @@ { "culture": "zh-Hans", "texts": { + "DisplayName:Authorization": "阿里云身份认证凭据", + "Description:Authorization": "阿里云身份认证凭据", + "DisplayName:RegionId": "地域ID", + "Description:RegionId": "正在使用的地域ID", + "DisplayName:AccessKeyId": "AccessKey Id", + "Description:AccessKeyId": "访问密钥标识", + "DisplayName:AccessKeySecret": "AccessKey Secret", + "Description:AccessKeySecret": "访问密钥", + "DisplayName:UseSecurityTokenService": "使用STS Token访问", + "Description:UseSecurityTokenService": "使用STS Token访问", + "DisplayName:RamRoleArn": "角色全局资源描述符", + "Description:RamRoleArn": "格式:acs:ram::$accountID:role/$roleName/$RoleSessionName,详情见阿里云访问控制API", + "DisplayName:RoleSessionName": "角色的临时身份", + "Description:RoleSessionName": "此参数用来区分不同的令牌,可用于用户级别的访问审计", + "DisplayName:DurationSeconds": "过期时间,单位为秒。", + "Description:DurationSeconds": "过期时间最小值为900秒,默认3600秒", + "DisplayName:Policy": "权限策略", + "Description:Policy": "生成STS Token时可以指定一个额外的权限策略,以进一步限制STS Token的权限" } } \ No newline at end of file diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs index 7eb67fe3a..edc985e08 100644 --- a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs @@ -10,10 +10,38 @@ public class Authorization { public const string Prefix = AliyunSettingNames.Prefix + ".Authorization"; - + /// + /// 地域ID + /// + public const string RegionId = Prefix + ".RegionId"; + /// + /// RAM账号的AccessKey ID + /// public const string AccessKeyId = Prefix + ".AccessKeyId"; - + /// + /// RAM账号的AccessKey Secret + /// public const string AccessKeySecret = Prefix + ".AccessKeySecret"; + /// + /// 使用STS Token访问 + /// + public const string UseSecurityTokenService = Prefix + ".UseSecurityTokenService"; + /// + /// 使用RAM子账号的AssumeRole方式访问 + /// + public const string RamRoleArn = Prefix + ".RamRoleArn"; + /// + /// 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计 + /// + public const string RoleSessionName = Prefix + ".RoleSessionName"; + /// + /// 过期时间,单位为秒。 + /// + public const string DurationSeconds = Prefix + ".DurationSeconds"; + /// + /// 权限策略。 + /// + public const string Policy = Prefix + ".Policy"; } } } diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs new file mode 100644 index 000000000..2e4f081b4 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/LINYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs @@ -0,0 +1,81 @@ +using LINYUN.Abp.Aliyun.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace LINYUN.Abp.Aliyun.Settings +{ + public class AliyunSettingProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + context.Add(CreateAliyunSettings()); + } + + private SettingDefinition[] CreateAliyunSettings() + { + return new SettingDefinition[] + { + new SettingDefinition( + AliyunSettingNames.Authorization.AccessKeyId, + displayName: L("DisplayName:AccessKeyId"), + description: L("Description:AccessKeyId"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSettingNames.Authorization.AccessKeySecret, + displayName: L("DisplayName:AccessKeySecret"), + description: L("Description:AccessKeySecret"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSettingNames.Authorization.DurationSeconds, + defaultValue: "3000", + displayName: L("DisplayName:DurationSeconds"), + description: L("Description:DurationSeconds"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSettingNames.Authorization.Policy, + displayName: L("DisplayName:Policy"), + description: L("Description:Policy"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSettingNames.Authorization.RamRoleArn, + displayName: L("DisplayName:RamRoleArn"), + description: L("Description:RamRoleArn"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSettingNames.Authorization.RegionId, + displayName: L("DisplayName:RegionId"), + description: L("Description:RegionId"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSettingNames.Authorization.RoleSessionName, + displayName: L("DisplayName:RoleSessionName"), + description: L("Description:RoleSessionName"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSettingNames.Authorization.UseSecurityTokenService, + defaultValue: true.ToString(), + displayName: L("DisplayName:UseSecurityTokenService"), + description: L("Description:UseSecurityTokenService"), + isVisibleToClients: false + ), + }; + } + + private ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md new file mode 100644 index 000000000..6cb396563 --- /dev/null +++ b/aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md @@ -0,0 +1,31 @@ +# LINGYUN.Abp.Aliyun + +阿里云sdk集成 + +参照:https://help.aliyun.com/document_detail/28763.html + +## 配置使用 + +模块按需引用 + +```csharp +[DependsOn(typeof(AbpAliyunModule))] +public class YouProjectModule : AbpModule +{ + // other +} +``` +## 配置项说明 + +* AliyunSettingNames.Authorization.RegionId 可选,区域,默认 default +* AliyunSettingNames.Authorization.AccessKeyId 必须,阿里云RAM账号的AccessKey ID +* AliyunSettingNames.Authorization.AccessKeySecret 必须,RAM账号的AccessKey Secret +* AliyunSettingNames.Authorization.UseSecurityTokenService 可选,建议,使用STS Token访问,按照阿里云文档,建议使用Sts Token访问API,默认false +* AliyunSettingNames.Authorization.RamRoleArn 可选,启用Sts Token之后必须配置,阿里云RAM角色ARN +* AliyunSettingNames.Authorization.RoleSessionName 可选,启用Sts Token之后的用户自定义令牌名称,用于访问审计 +* AliyunSettingNames.Authorization.DurationSeconds 可选,用户令牌的过期时间,单位为秒,默认3000 +* AliyunSettingNames.Authorization.Policy 可选,权限策略,为json字符串 + +## 其他 + +网络因素在高并发下可能会出现预期外的异常,考虑使用二级缓存 diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj index 5bd8a4d4e..6f523955f 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj @@ -14,7 +14,7 @@ - + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs index 8930d080d..3da8694e0 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs @@ -1,4 +1,4 @@ -using LINGYUN.Abp.Aliyun.Authorization; +using LINGYUN.Abp.Aliyun; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System.Collections.Generic; @@ -9,7 +9,7 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun { [DependsOn( typeof(AbpBlobStoringModule), - typeof(AbpAliyunAuthorizationModule))] + typeof(AbpAliyunModule))] public class AbpBlobStoringAliyunModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs index 8499ae806..7a4ba3da7 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs @@ -1,6 +1,4 @@ using Aliyun.OSS; -using LINGYUN.Abp.Aliyun.Authorization; -using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.IO; @@ -12,25 +10,24 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun { public class AliyunBlobProvider : BlobProviderBase, ITransientDependency { - protected AbpAliyunOptions Options { get; } + protected IOssClientFactory OssClientFactory { get; } protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; } public AliyunBlobProvider( - IOptions options, + IOssClientFactory ossClientFactory, IAliyunBlobNameCalculator aliyunBlobNameCalculator) { - Options = options.Value; + OssClientFactory = ossClientFactory; AliyunBlobNameCalculator = aliyunBlobNameCalculator; } public override async Task DeleteAsync(BlobProviderDeleteArgs args) { + var ossClient = await GetOssClientAsync(args); var blobName = AliyunBlobNameCalculator.Calculate(args); - if (await BlobExistsAsync(args, blobName)) + if (await BlobExistsAsync(ossClient, args, blobName)) { - var ossClient = GetOssClient(args); - return ossClient.DeleteObject(GetBucketName(args), blobName).DeleteMarker; } @@ -39,21 +36,22 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun public override async Task ExistsAsync(BlobProviderExistsArgs args) { + var ossClient = await GetOssClientAsync(args); var blobName = AliyunBlobNameCalculator.Calculate(args); - return await BlobExistsAsync(args, blobName); + return await BlobExistsAsync(ossClient, args, blobName); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { + var ossClient = await GetOssClientAsync(args); var blobName = AliyunBlobNameCalculator.Calculate(args); - if (!await BlobExistsAsync(args, blobName)) + if (!await BlobExistsAsync(ossClient, args, blobName)) { return null; } - var ossClient = GetOssClient(args); var ossObject = ossClient.GetObject(GetBucketName(args), blobName); var memoryStream = new MemoryStream(); await ossObject.Content.CopyToAsync(memoryStream); @@ -62,20 +60,20 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun public override async Task SaveAsync(BlobProviderSaveArgs args) { + var ossClient = await GetOssClientAsync(args); var blobName = AliyunBlobNameCalculator.Calculate(args); var configuration = args.Configuration.GetAliyunConfiguration(); // 先检查Bucket if (configuration.CreateBucketIfNotExists) { - await CreateBucketIfNotExists(args, configuration.CreateBucketReferer); + await CreateBucketIfNotExists(ossClient, args, configuration.CreateBucketReferer); } var bucketName = GetBucketName(args); - var ossClient = GetOssClient(args); // 是否已存在 - if (await BlobExistsAsync(args, blobName)) + if (await BlobExistsAsync(ossClient, args, blobName)) { // 是否覆盖 if (!args.OverrideExisting) @@ -92,18 +90,17 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun ossClient.PutObject(bucketName, blobName, args.BlobStream); } - protected virtual OssClient GetOssClient(BlobProviderArgs args) + protected virtual async Task GetOssClientAsync(BlobProviderArgs args) { var configuration = args.Configuration.GetAliyunConfiguration(); - var ossClient = new OssClient(configuration.Endpoint, Options.AccessKeyId, Options.AccessKeySecret); + var ossClient = await OssClientFactory.CreateAsync(configuration); return ossClient; } - protected virtual async Task CreateBucketIfNotExists(BlobProviderArgs args, IList refererList = null) + protected virtual async Task CreateBucketIfNotExists(IOss ossClient, BlobProviderArgs args, IList refererList = null) { - if (! await BucketExistsAsync(args)) + if (! await BucketExistsAsync(ossClient, args)) { - var ossClient = GetOssClient(args); var bucketName = GetBucketName(args); var request = new CreateBucketRequest(bucketName) @@ -124,10 +121,9 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun } } - private async Task BlobExistsAsync(BlobProviderArgs args, string blobName) + private async Task BlobExistsAsync(IOss ossClient, BlobProviderArgs args, string blobName) { - var ossClient = GetOssClient(args); - var bucketExists = await BucketExistsAsync(args); + var bucketExists = await BucketExistsAsync(ossClient, args); if (bucketExists) { var objectExists = ossClient.DoesObjectExist(GetBucketName(args), blobName); @@ -137,9 +133,8 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun return false; } - private Task BucketExistsAsync(BlobProviderArgs args) + private Task BucketExistsAsync(IOss ossClient, BlobProviderArgs args) { - var ossClient = GetOssClient(args); var bucketExists = ossClient.DoesBucketExist(GetBucketName(args)); return Task.FromResult(bucketExists); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IOssClientFactory.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IOssClientFactory.cs new file mode 100644 index 000000000..6299df543 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IOssClientFactory.cs @@ -0,0 +1,15 @@ +using Aliyun.OSS; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.BlobStoring.Aliyun +{ + public interface IOssClientFactory + { + /// + /// 通过配置信息构建Oss客户端调用 + /// + /// + /// + Task CreateAsync(AliyunBlobProviderConfiguration configuration); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/OssClientFactory.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/OssClientFactory.cs new file mode 100644 index 000000000..2446c3269 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/OssClientFactory.cs @@ -0,0 +1,50 @@ +using Aliyun.OSS; +using LINYUN.Abp.Aliyun; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.BlobStoring.Aliyun +{ + public class OssClientFactory : AliyunClientFactory, IOssClientFactory, ITransientDependency + { + public OssClientFactory( + ISettingProvider settingProvider, + IDistributedCache cache) + : base(settingProvider, cache) + { + } + /// + /// 普通方式构建Oss客户端 + /// + /// + /// + /// + /// + /// + protected override IOss GetClient(AliyunBlobProviderConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret) + { + return new OssClient( + configuration.Endpoint, + accessKeyId, + accessKeySecret); + } + /// + /// 通过用户安全令牌构建Oss客户端 + /// + /// + /// + /// + /// + /// + /// + protected override IOss GetSecurityTokenClient(AliyunBlobProviderConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret, string securityToken) + { + return new OssClient( + configuration.Endpoint, + accessKeyId, + accessKeySecret, + securityToken); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/README.md b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/README.md index 13f724716..7973666c7 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/README.md +++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/README.md @@ -4,17 +4,13 @@ abp框架对象存储提供者**IBlobProvider**的阿里云实现 ## 配置使用 -模块按需引用,需要引用阿里云公共基础认证模块 +模块按需引用 事先定义**appsettings.json**文件 ```json { "Aliyun": { - "Auth": { - "AccessKeyId": "你的阿里云访问标识", - "AccessKeySecret": "你的阿里云访问密钥" - }, "OSS": { "BucketName": "你定义的BucketName", "Endpoint": "http://oss-cn-shanghai.aliyuncs.com", diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj index 59e8c7874..f38b82743 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj @@ -19,14 +19,11 @@ - - - - + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs index cad4c903a..fa606577f 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs @@ -1,7 +1,6 @@ -using LINGYUN.Abp.Aliyun.Authorization; +using LINGYUN.Abp.Aliyun; +using LINYUN.Abp.Aliyun.Localization; using LINYUN.Abp.Sms.Aliyun.Localization; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Sms; @@ -10,17 +9,12 @@ using Volo.Abp.VirtualFileSystem; namespace LINYUN.Abp.Sms.Aliyun { [DependsOn( - typeof(AbpSmsModule), - typeof(AbpJsonModule), - typeof(AbpLocalizationModule), - typeof(AbpAliyunAuthorizationModule))] + typeof(AbpSmsModule), + typeof(AbpAliyunModule))] public class AbpAliyunSmsModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - var configuration = context.Services.GetConfiguration(); - Configure(configuration.GetSection("Aliyun:Sms")); - Configure(options => { options.FileSets.AddEmbedded(); @@ -30,6 +24,7 @@ namespace LINYUN.Abp.Sms.Aliyun { options.Resources .Add("en") + .AddBaseTypes(typeof(AliyunResource)) .AddVirtualJson("/LINYUN/Abp/Sms/Aliyun/Localization/Resources"); }); } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsException.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsException.cs index 9b8795eed..7e80ff3bd 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsException.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsException.cs @@ -1,28 +1,12 @@ -using Microsoft.Extensions.Logging; -using Volo.Abp; -using Volo.Abp.ExceptionHandling; -using Volo.Abp.Localization; -using Volo.Abp.Logging; +using LINYUN.Abp.Aliyun; namespace LINYUN.Abp.Sms.Aliyun { - public class AliyunSmsException : AbpException, IHasErrorCode, ILocalizeErrorMessage, IHasLogLevel + public class AliyunSmsException : AbpAliyunException { public AliyunSmsException(string code, string message) - :base(message) + :base(code, message) { - Code = code; - LogLevel = LogLevel.Warning; - } - - public LogLevel LogLevel { get; set; } - - public string Code { get; } - - public string LocalizeMessage(LocalizationContext context) - { - return AliyunSmsResponse.GetErrorMessage(Code, Message) - .Localize(context.LocalizerFactory); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs deleted file mode 100644 index 19f3e04a4..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace LINYUN.Abp.Sms.Aliyun -{ - public class AliyunSmsOptions - { - /// - /// 区域Id - /// - public string RegionId { get; set; } = "default"; - /// - /// 阿里云sms服务域名 - /// - public string Domain { get; set; } = "dysmsapi.aliyuncs.com"; - /// - /// 调用方法名称 - /// - public string ActionName { get; set; } = "SendSms"; - /// - /// 默认版本号 - /// - public string Version { get; set; } = "2017-05-25"; - /// - /// 默认签名 - /// - public string DefaultSignName { get; set; } - /// - /// 默认短信模板号 - /// - public string DefaultTemplateCode { get; set; } - /// - /// 开发人员号码,当应用处于开发模式时,默认所有信息都会发送到此号码 - /// - public string DeveloperPhoneNumber { get; set; } = "13800138000"; - /// - /// 展示错误给客户端 - /// - public bool VisableErrorToClient { get; set; } = false; - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs index 51d1df128..695eb9d80 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs @@ -1,19 +1,17 @@ using Aliyun.Acs.Core; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Http; -using Aliyun.Acs.Core.Profile; -using LINGYUN.Abp.Aliyun.Authorization; -using LINYUN.Abp.Sms.Aliyun.Localization; +using LINYUN.Abp.Aliyun; +using LINYUN.Abp.Sms.Aliyun.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Options; using System; using System.Text; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; +using Volo.Abp.Settings; using Volo.Abp.Sms; namespace LINYUN.Abp.Sms.Aliyun @@ -22,69 +20,71 @@ namespace LINYUN.Abp.Sms.Aliyun [ExposeServices(typeof(ISmsSender), typeof(AliyunSmsSender))] public class AliyunSmsSender : ISmsSender { - protected AbpAliyunOptions AuthOptions { get; } - protected AliyunSmsOptions Options { get; } protected IJsonSerializer JsonSerializer { get; } - protected IHostEnvironment Environment { get; } + protected ISettingProvider SettingProvider { get; } protected IServiceProvider ServiceProvider { get; } + protected IAcsClientFactory AcsClientFactory { get; } public AliyunSmsSender( - IHostEnvironment environment, IJsonSerializer jsonSerializer, + ISettingProvider settingProvider, IServiceProvider serviceProvider, - IOptions options, - IOptions authOptions) + IAcsClientFactory acsClientFactory) { - Options = options.Value; - AuthOptions = authOptions.Value; - - Environment = environment; JsonSerializer = jsonSerializer; + SettingProvider = settingProvider; ServiceProvider = serviceProvider; + AcsClientFactory = acsClientFactory; } - public Task SendAsync(SmsMessage smsMessage) + public virtual async Task SendAsync(SmsMessage smsMessage) { + var domain = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.Domain); + var action = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.ActionName); + var version = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.Version); + + Check.NotNullOrWhiteSpace(domain, AliyunSmsSettingNames.Sms.Domain); + Check.NotNullOrWhiteSpace(action, AliyunSmsSettingNames.Sms.ActionName); + Check.NotNullOrWhiteSpace(version, AliyunSmsSettingNames.Sms.Version); + CommonRequest request = new CommonRequest { Method = MethodType.POST, - Domain = Options.Domain, - Action = Options.ActionName, - Version = Options.Version + Domain = domain, + Action = action, + Version = version }; - TryAddTemplateCode(request, smsMessage); - TryAddSignName(request, smsMessage); - TryAddSendPhone(request, smsMessage); + await TryAddTemplateCodeAsync(request, smsMessage); + await TryAddSignNameAsync(request, smsMessage); + await TryAddSendPhoneAsync(request, smsMessage); + TryAddTemplateParam(request, smsMessage); try { - IClientProfile profile = DefaultProfile.GetProfile(Options.RegionId, AuthOptions.AccessKeyId, AuthOptions.AccessKeySecret); - IAcsClient client = new DefaultAcsClient(profile); + var client = await AcsClientFactory.CreateAsync(); CommonResponse response = client.GetCommonResponse(request); var responseContent = Encoding.Default.GetString(response.HttpResponse.Content); var aliyunResponse = JsonSerializer.Deserialize(responseContent); if (!aliyunResponse.IsSuccess()) { - if (Options.VisableErrorToClient) + if (await SettingProvider.IsTrueAsync(AliyunSmsSettingNames.Sms.VisableErrorToClient)) { - throw new AliyunSmsException(aliyunResponse.Code, aliyunResponse.Message); + throw new UserFriendlyException(aliyunResponse.Code, aliyunResponse.Message); } - throw new AbpException($"Text message sending failed, code:{aliyunResponse.Code}, message:{aliyunResponse.Message}!"); + throw new AliyunSmsException(aliyunResponse.Code, $"Text message sending failed, code:{aliyunResponse.Code}, message:{aliyunResponse.Message}!"); } } catch(ServerException se) { - throw new AbpException("Sending text messages to aliyun server is abnormal", se); + throw new AliyunSmsException(se.ErrorCode, $"Sending text messages to aliyun server is abnormal,type: {se.ErrorType}, error: {se.ErrorMessage}"); } catch(ClientException ce) { - throw new AbpException("A client exception occurred in sending SMS messages", ce); + throw new AliyunSmsException(ce.ErrorCode, $"A client exception occurred in sending SMS messages,type: {ce.ErrorType}, error: {ce.ErrorMessage}"); } - - return Task.CompletedTask; } - private void TryAddTemplateCode(CommonRequest request, SmsMessage smsMessage) + private async Task TryAddTemplateCodeAsync(CommonRequest request, SmsMessage smsMessage) { if (smsMessage.Properties.TryGetValue("TemplateCode", out object template) && template != null) { @@ -93,12 +93,13 @@ namespace LINYUN.Abp.Sms.Aliyun } else { - Check.NotNullOrWhiteSpace(Options.DefaultTemplateCode, nameof(Options.DefaultTemplateCode)); - request.AddQueryParameters("TemplateCode", Options.DefaultTemplateCode); + var defaultTemplateCode = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.DefaultTemplateCode); + Check.NotNullOrWhiteSpace(defaultTemplateCode, "TemplateCode"); + request.AddQueryParameters("TemplateCode", defaultTemplateCode); } } - private void TryAddSignName(CommonRequest request, SmsMessage smsMessage) + private async Task TryAddSignNameAsync(CommonRequest request, SmsMessage smsMessage) { if (smsMessage.Properties.TryGetValue("SignName", out object signName) && signName != null) { @@ -107,21 +108,23 @@ namespace LINYUN.Abp.Sms.Aliyun } else { - Check.NotNullOrWhiteSpace(Options.DefaultSignName, nameof(Options.DefaultSignName)); - request.AddQueryParameters("SignName", Options.DefaultSignName); + var defaultSignName = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.DefaultSignName); + Check.NotNullOrWhiteSpace(defaultSignName, "SignName"); + request.AddQueryParameters("SignName", defaultSignName); } } - private void TryAddSendPhone(CommonRequest request, SmsMessage smsMessage) + private async Task TryAddSendPhoneAsync(CommonRequest request, SmsMessage smsMessage) { - if (Environment.IsDevelopment()) + if (smsMessage.PhoneNumber.IsNullOrWhiteSpace()) { + var defaultPhoneNumber = await SettingProvider.GetOrNullAsync(AliyunSmsSettingNames.Sms.DefaultPhoneNumber); // check phone number length... Check.NotNullOrWhiteSpace( - Options.DeveloperPhoneNumber, - nameof(Options.DeveloperPhoneNumber), + defaultPhoneNumber, + AliyunSmsSettingNames.Sms.DefaultPhoneNumber, maxLength: 11, minLength: 11); - request.AddQueryParameters("PhoneNumbers", Options.DeveloperPhoneNumber); + request.AddQueryParameters("PhoneNumbers", defaultPhoneNumber); } else { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json index f2ba1b6a5..61a23fb63 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json @@ -1,6 +1,20 @@ { "culture": "zh-Hans", "texts": { + "DisplayName:ActionName": "阿里云身份认证凭据", + "Description:ActionName": "阿里云身份认证凭据", + "DisplayName:DefaultSignName": "地域ID", + "Description:DefaultSignName": "正在使用的地域ID", + "DisplayName:DefaultTemplateCode": "AccessKey Id", + "Description:DefaultTemplateCode": "访问密钥标识", + "DisplayName:DeveloperPhoneNumber": "AccessKey Secret", + "Description:DeveloperPhoneNumber": "访问密钥", + "DisplayName:Domain": "阿里云sms服务域名", + "Description:Domain": "使用STS Token访问", + "DisplayName:Version": "角色全局资源描述符", + "Description:Version": "格式:acs:ram::$accountID:role/$roleName/$RoleSessionName,详情见阿里云访问控制API", + "DisplayName:RoleSessionName": "角色全局资源描述符", + "Description:RoleSessionName": "格式:acs:ram::$accountID:role/$roleName/$RoleSessionName,详情见阿里云访问控制API", "SendMessageFailed": "发送短信错误:{0}", "SMS_SIGNATURE_SCENE_ILLEGAL": "短信所使用签名场景非法", "DENY_IP_RANGE": "源IP地址所在的地区被禁用", diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingNames.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingNames.cs new file mode 100644 index 000000000..8496a3c75 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingNames.cs @@ -0,0 +1,43 @@ +using LINYUN.Abp.Aliyun.Settings; + +namespace LINYUN.Abp.Sms.Aliyun.Settings +{ + public static class AliyunSmsSettingNames + { + /// + /// 短信服务 + /// + public class Sms + { + public const string Prefix = AliyunSettingNames.Prefix + ".Sms"; + /// + /// 阿里云sms服务域名 + /// + public const string Domain = Prefix + ".Domain"; + /// + /// 调用方法名称 + /// + public const string ActionName = Prefix + ".ActionName"; + /// + /// 默认版本号 + /// + public const string Version = Prefix + ".Version"; + /// + /// 默认签名 + /// + public const string DefaultSignName = Prefix + ".DefaultSignName"; + /// + /// 默认短信模板号 + /// + public const string DefaultTemplateCode = Prefix + ".DefaultTemplateCode"; + /// + /// 默认号码 + /// + public const string DefaultPhoneNumber = Prefix + ".DefaultPhoneNumber"; + /// + /// 展示错误给客户端 + /// + public const string VisableErrorToClient = Prefix + ".VisableErrorToClient"; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingProvider.cs new file mode 100644 index 000000000..f575101f1 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Settings/AliyunSmsSettingProvider.cs @@ -0,0 +1,74 @@ +using LINYUN.Abp.Aliyun.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace LINYUN.Abp.Sms.Aliyun.Settings +{ + public class AliyunSmsSettingProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + context.Add(CreateAliyunSettings()); + } + + private SettingDefinition[] CreateAliyunSettings() + { + return new SettingDefinition[] + { + new SettingDefinition( + AliyunSmsSettingNames.Sms.ActionName, + defaultValue: "SendSms", + displayName: L("DisplayName:ActionName"), + description: L("Description:ActionName"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.DefaultSignName, + displayName: L("DisplayName:DefaultSignName"), + description: L("Description:DefaultSignName"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.DefaultTemplateCode, + displayName: L("DisplayName:DefaultTemplateCode"), + description: L("Description:DefaultTemplateCode"), + isVisibleToClients: false, + isEncrypted: true + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.DefaultPhoneNumber, + displayName: L("DisplayName:DefaultPhoneNumber"), + description: L("Description:DefaultPhoneNumber"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.Domain, + defaultValue: "dysmsapi.aliyuncs.com", + displayName: L("DisplayName:Domain"), + description: L("Description:Domain"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.Version, + defaultValue: "2017-05-25", + displayName: L("DisplayName:Version"), + description: L("Description:Version"), + isVisibleToClients: false + ), + new SettingDefinition( + AliyunSmsSettingNames.Sms.VisableErrorToClient, + defaultValue: false.ToString(), + displayName: L("DisplayName:VisableErrorToClient"), + description: L("Description:VisableErrorToClient"), + isVisibleToClients: false + ) + }; + } + + private ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/README.md b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/README.md index 110feb919..d3377eda8 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/README.md +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/README.md @@ -4,30 +4,7 @@ abp框架短信发送接口**ISmsSender**的阿里云实现 ## 配置使用 -模块按需引用,需要引用阿里云公共基础认证模块 - -事先定义**appsettings.json**文件 - -```json -{ - "Aliyun": { - "Auth": { - "AccessKeyId": "你的阿里云访问标识", - "AccessKeySecret": "你的阿里云访问密钥" - }, - "Sms": { - "RegionId": "cn-hangzhou", - "Domain": "dysmsapi.aliyuncs.com", - "Version": "2017-05-25", - "DefaultSignName": "你的阿里云短信签名,SmsMessage.Properties[SignName]不存在则使用DefaultSignName", - "DefaultTemplateCode": "你的阿里云短信模板,SmsMessage.Properties[TemplateCode]不存在则使用DefaultTemplateCode", - "DeveloperPhoneNumber": "这是用于在开发模式下的短信号码,用于统一接收短信", - "VisableErrorToClient": true - } - } -} - -``` +模块按需引用 ```csharp [DependsOn(typeof(AbpAliyunSmsModule))] @@ -35,4 +12,17 @@ public class YouProjectModule : AbpModule { // other } -``` \ No newline at end of file +``` +## 配置项说明 + +* AliyunSettingNames.Sms.Domain 可选,阿里云sms服务域名,默认 dysmsapi.aliyuncs.com +* AliyunSettingNames.Sms.ActionName 必须,调用方法名称,默认 SendSms +* AliyunSettingNames.Sms.Version 必须,R默认版本号,默认 2017-05-25 +* AliyunSettingNames.Sms.DefaultSignName 可选,默认签名,当用户调用未传递签名时,默认使用的短信签名 +* AliyunSettingNames.Sms.DefaultTemplateCode 可选,默认短信模板号,,当用户调用未传递短信模板时,默认使用的短信模板 +* AliyunSettingNames.Sms.DefaultPhoneNumber 可选,默认发送号码,当用户调用未传递接收者号码时,默认使用的接收人号码 +* AliyunSettingNames.Sms.VisableErrorToClient 可选,展示错误给客户端,当调用短信接口出现错误时,是否返回错误明细给客户端,默认 false + +## 其他 + +网络因素在高并发下可能会出现预期外的异常,考虑使用二级缓存 diff --git a/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/AbpEncryptionConsoleModule.cs b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/AbpEncryptionConsoleModule.cs new file mode 100644 index 000000000..9f4f8ed21 --- /dev/null +++ b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/AbpEncryptionConsoleModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; +using Volo.Abp.Security; + +namespace LINGYUN.Abp.Encryption.Console +{ + [DependsOn( + typeof(AbpSecurityModule))] + public class AbpEncryptionConsoleModule : AbpModule + { + + } +} diff --git a/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/LINGYUN.Abp.Encryption.Console.csproj b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/LINGYUN.Abp.Encryption.Console.csproj new file mode 100644 index 000000000..4a444eaff --- /dev/null +++ b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/LINGYUN.Abp.Encryption.Console.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/Program.cs b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/Program.cs new file mode 100644 index 000000000..f5daec401 --- /dev/null +++ b/aspnet-core/modules/console/LINGYUN.Abp.Encryption.Console/Program.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using Volo.Abp; +using Volo.Abp.Security.Encryption; +using static System.Console; + +namespace LINGYUN.Abp.Encryption.Console +{ + class Program + { + static void Main(string[] args) + { + WriteLine("Hello World!"); + + var application = AbpApplicationFactory.Create(); + + application.Initialize(); + + WriteLine("D:解密 E:加密"); + + var opt = ReadLine(); + bool en = false; + if ("E".Equals(opt, StringComparison.InvariantCultureIgnoreCase)) + { + en = true; + WriteLine("请输入需要加密的字符串"); + } + else + { + WriteLine("请输入需要解密的字符串"); + } + + var sourceChr = ReadLine(); + var encryptionService = application.ServiceProvider.GetRequiredService(); + WriteLine(en ? encryptionService.Encrypt(sourceChr) : encryptionService.Decrypt(sourceChr)); + + application.Shutdown(); + + ReadKey(); + } + } +} diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs index cbcaabbef..747a2f986 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs @@ -3,18 +3,22 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; namespace LINGYUN.Platform.Datas { public class DataDictionaryDataSeeder : IDataDictionaryDataSeeder, ITransientDependency { + protected ICurrentTenant CurrentTenant { get; } protected IGuidGenerator GuidGenerator { get; } protected IDataRepository DataRepository { get; } public DataDictionaryDataSeeder( + ICurrentTenant currentTenant, IGuidGenerator guidGenerator, IDataRepository dataRepository) { + CurrentTenant = currentTenant; GuidGenerator = guidGenerator; DataRepository = dataRepository; } @@ -28,23 +32,26 @@ namespace LINGYUN.Platform.Datas Guid? tenantId = null, CancellationToken cancellationToken = default) { - var data = await DataRepository.FindByNameAsync(name, cancellationToken: cancellationToken); - - if (data == null) + using (CurrentTenant.Change(tenantId)) { - data = new Data( - GuidGenerator.Create(), - name, - code, - displayName, - description, - parentId, - tenantId); + var data = await DataRepository.FindByNameAsync(name, cancellationToken: cancellationToken); - data = await DataRepository.InsertAsync(data); - } + if (data == null) + { + data = new Data( + GuidGenerator.Create(), + name, + code, + displayName, + description, + parentId, + tenantId); - return data; + data = await DataRepository.InsertAsync(data); + } + + return data; + } } } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs index 816c24924..39021a203 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs @@ -20,9 +20,12 @@ namespace LINGYUN.Platform.Menus string menuName, CancellationToken cancellationToken = default); - Task SetRoleMenusAsync( + Task> GetListByRoleNameAsync( string roleName, - IEnumerable menuIds, + CancellationToken cancellationToken = default); + + Task InsertAsync( + IEnumerable roleMenus, CancellationToken cancellationToken = default); } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs index 28b2c8ced..a9c82b393 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs @@ -20,9 +20,12 @@ namespace LINGYUN.Platform.Menus string menuName, CancellationToken cancellationToken = default); - Task SetMemberMenusAsync( + Task> GetListByUserIdAsync( Guid userId, - IEnumerable menuIds, + CancellationToken cancellationToken = default); + + Task InsertAsync( + IEnumerable userMenus, CancellationToken cancellationToken = default); } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs index a6ef79151..5ea2b9af2 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs @@ -11,6 +11,9 @@ namespace LINGYUN.Platform.Menus { public class MenuManager : DomainService { + private IUnitOfWorkManager _unitOfWorkManager; + protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + protected IMenuRepository MenuRepository { get; } protected IUserMenuRepository UserMenuRepository { get; } protected IRoleMenuRepository RoleMenuRepository { get; } @@ -68,6 +71,7 @@ namespace LINGYUN.Platform.Menus return menu; } + [UnitOfWork] public virtual async Task UpdateAsync(Menu menu) { await ValidateMenuAsync(menu); @@ -117,27 +121,50 @@ namespace LINGYUN.Platform.Menus } } - public virtual async Task SetUserMenusAsync(Guid userId, IEnumerable menuIds) + public virtual async Task UserHasInMenuAsync(Guid userId, string menuName) { - await UserMenuRepository.SetMemberMenusAsync(userId, menuIds); + var menu = await MenuRepository.FindByNameAsync(menuName); + return false; } - [UnitOfWork] - public virtual async Task SetRoleMenusAsync(string roleName, IEnumerable menuIds) + public virtual async Task SetUserMenusAsync(Guid userId, IEnumerable menuIds) { - await RoleMenuRepository.SetRoleMenusAsync(roleName, menuIds); + using (var unitOfWork = UnitOfWorkManager.Begin()) + { + var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId); + + // 移除不存在的菜单 + // TODO: 升级框架版本解决未能删除不需要菜单的问题 + userMenus.RemoveAll(x => !menuIds.Contains(x.MenuId)); + + var adds = menuIds.Where(menuId => !userMenus.Any(x => x.MenuId == menuId)); + if (adds.Any()) + { + var addInMenus = adds.Select(menuId => new UserMenu(GuidGenerator.Create(), menuId, userId, CurrentTenant.Id)); + await UserMenuRepository.InsertAsync(addInMenus); + } + + await unitOfWork.SaveChangesAsync(); + } } - protected virtual async Task ValidateMenuAsync(Menu menu) + public virtual async Task SetRoleMenusAsync(string roleName, IEnumerable menuIds) { - var siblings = (await FindChildrenAsync(menu.ParentId)) - .Where(x => x.Id != menu.Id) - .ToList(); - - if (siblings.Any(ou => ou.Name == menu.Name)) + using (var unitOfWork = UnitOfWorkManager.Begin()) { - throw new BusinessException(PlatformErrorCodes.DuplicateMenu) - .WithData("Name", menu.Name); + var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName); + + // 移除不存在的菜单 + roleMenus.RemoveAll(x => !menuIds.Contains(x.MenuId)); + + var adds = menuIds.Where(menuId => !roleMenus.Any(x => x.MenuId == menuId)); + if (adds.Any()) + { + var addInMenus = adds.Select(menuId => new RoleMenu(GuidGenerator.Create(), menuId, roleName, CurrentTenant.Id)); + await RoleMenuRepository.InsertAsync(addInMenus); + } + + await unitOfWork.SaveChangesAsync(); } } @@ -187,5 +214,18 @@ namespace LINGYUN.Platform.Menus var menu = await MenuRepository.GetAsync(id); return menu?.Code; } + + protected virtual async Task ValidateMenuAsync(Menu menu) + { + var siblings = (await FindChildrenAsync(menu.ParentId)) + .Where(x => x.Id != menu.Id) + .ToList(); + + if (siblings.Any(x => x.Name == menu.Name)) + { + throw new BusinessException(PlatformErrorCodes.DuplicateMenu) + .WithData("Name", menu.Name); + } + } } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/RoleMenu.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/RoleMenu.cs index 7c6c07df1..cf27cbc4f 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/RoleMenu.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/RoleMenu.cs @@ -18,9 +18,11 @@ namespace LINGYUN.Platform.Menus protected RoleMenu() { } public RoleMenu( + Guid id, Guid menuId, string roleName, Guid? tenantId = null) + : base(id) { MenuId = menuId; RoleName = roleName; diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/UserMenu.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/UserMenu.cs index ff039ccd5..1777d641b 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/UserMenu.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/UserMenu.cs @@ -18,9 +18,11 @@ namespace LINGYUN.Platform.Menus protected UserMenu() { } public UserMenu( + Guid id, Guid menuId, Guid userId, Guid? tenantId = null) + : base(id) { MenuId = menuId; UserId = userId; diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs index 39552529f..16a965012 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs @@ -9,11 +9,13 @@ using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; namespace LINGYUN.Platform { public class PlatformDataSeedContributor : IDataSeedContributor, ITransientDependency { + protected ICurrentTenant CurrentTenant { get; } protected IGuidGenerator GuidGenerator { get; } protected IRouteDataSeeder RouteDataSeeder { get; } protected IDataDictionaryDataSeeder DataDictionaryDataSeeder { get; } @@ -21,12 +23,14 @@ namespace LINGYUN.Platform protected ILayoutRepository LayoutRepository { get; } public PlatformDataSeedContributor( + ICurrentTenant currentTenant, IRouteDataSeeder routeDataSeeder, IMenuRepository menuRepository, ILayoutRepository layoutRepository, IGuidGenerator guidGenerator, IDataDictionaryDataSeeder dataDictionaryDataSeeder) { + CurrentTenant = currentTenant; GuidGenerator = guidGenerator; RouteDataSeeder = routeDataSeeder; MenuRepository = menuRepository; @@ -36,23 +40,26 @@ namespace LINGYUN.Platform public virtual async Task SeedAsync(DataSeedContext context) { - var data = await SeedDefaultDataDictionaryAsync(context.TenantId); - // 预置 - var layout = await SeedDefaultLayoutAsync(data); - // 首页 - await SeedHomeMenuAsync(layout, data); - // 管理菜单预置菜单数据 - await SeedAdminMenuAsync(layout, data); - // saas菜单数据 - await SeedSaasMenuAsync(layout, data); - // 身份资源菜单数据 - await SeedIdentityServerMenuAsync(layout, data); - // 审计日志菜单数据 - await SeedAuditingMenuAsync(layout, data); - // 布局容器预置菜单数据 - await SeedContainerMenuAsync(layout, data); - // 网关管理菜单数据 - await SeedApiGatewayMenuAsync(layout, data); + using (CurrentTenant.Change(context.TenantId)) + { + var data = await SeedDefaultDataDictionaryAsync(context.TenantId); + // 预置 + var layout = await SeedDefaultLayoutAsync(data); + // 首页 + await SeedHomeMenuAsync(layout, data); + // 管理菜单预置菜单数据 + await SeedAdminMenuAsync(layout, data); + // saas菜单数据 + await SeedSaasMenuAsync(layout, data); + // 身份资源菜单数据 + await SeedIdentityServerMenuAsync(layout, data); + // 审计日志菜单数据 + await SeedAuditingMenuAsync(layout, data); + // 布局容器预置菜单数据 + await SeedContainerMenuAsync(layout, data); + // 网关管理菜单数据 + await SeedApiGatewayMenuAsync(layout, data); + } } private async Task SeedDefaultDataDictionaryAsync(Guid? tenantId) diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs index f44680e3b..c5ec6a1a7 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs @@ -117,7 +117,7 @@ namespace LINGYUN.Platform.Routes { if (! await RoleMenuRepository.RoleHasInMenuAsync(roleName, menu.Name, cancellationToken)) { - var roleMenu = new RoleMenu(menu.Id, roleName, tenantId); + var roleMenu = new RoleMenu(GuidGenerator.Create(), menu.Id, roleName, tenantId); await RoleMenuRepository.InsertAsync(roleMenu); var childrens = await MenuRepository.GetChildrenAsync(menu.Id); @@ -136,7 +136,7 @@ namespace LINGYUN.Platform.Routes { if (!await UserMenuRepository.UserHasInMenuAsync(userId, menu.Name, cancellationToken)) { - var userMenu = new UserMenu(menu.Id, userId, tenantId); + var userMenu = new UserMenu(GuidGenerator.Create(), menu.Id, userId, tenantId); await UserMenuRepository.InsertAsync(userMenu); var childrens = await MenuRepository.GetChildrenAsync(menu.Id); diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContext.cs b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContext.cs index 95b86e43e..9bba7f23b 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContext.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContext.cs @@ -25,9 +25,9 @@ namespace LINGYUN.Platform.EntityFrameworkCore protected override void OnModelCreating(ModelBuilder builder) { - base.OnModelCreating(builder); - builder.ConfigurePlatform(); + + base.OnModelCreating(builder); } } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs index 7c9c8c8f3..cf75e0628 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs @@ -18,6 +18,17 @@ namespace LINGYUN.Platform.Menus { } + public virtual async Task> GetListByRoleNameAsync(string roleName, CancellationToken cancellationToken = default) + { + return await DbSet.Where(x => x.RoleName.Equals(roleName)) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task InsertAsync(IEnumerable roleMenus, CancellationToken cancellationToken = default) + { + await DbSet.AddRangeAsync(roleMenus, GetCancellationToken(cancellationToken)); + } + public virtual async Task RoleHasInMenuAsync( string roleName, string menuName, @@ -33,28 +44,5 @@ namespace LINGYUN.Platform.Menus .AnyAsync(x => x.RoleName == roleName, GetCancellationToken(cancellationToken)); } - - public virtual async Task SetRoleMenusAsync( - string roleName, - IEnumerable menuIds, - CancellationToken cancellationToken = default) - { - var hasInMenus = await DbSet - .Where(x => x.RoleName == roleName) - .ToArrayAsync(GetCancellationToken(cancellationToken)); - - var removes = hasInMenus.Where(x => !menuIds.Contains(x.MenuId)); - if (removes.Any()) - { - DbContext.RemoveRange(removes); - } - - var adds = menuIds.Where(menuId => !hasInMenus.Any(x => x.MenuId == menuId)); - if (adds.Any()) - { - var addInMenus = adds.Select(menuId => new RoleMenu(menuId, roleName, CurrentTenant.Id)); - await DbContext.AddRangeAsync(addInMenus, GetCancellationToken(cancellationToken)); - } - } } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs index 5b5f31810..fde688520 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs @@ -23,38 +23,28 @@ namespace LINGYUN.Platform.Menus string menuName, CancellationToken cancellationToken = default) { - var menuQuery = DbContext.Set().Where(x => x.Name == menuName); - return await - (from roleMenu in DbSet - join menu in menuQuery - on roleMenu.MenuId equals menu.Id - select roleMenu) - .AnyAsync(x => x.UserId == userId, + (from userMenu in DbContext.Set() + join menu in DbContext.Set() + on userMenu.MenuId equals menu.Id + where userMenu.UserId.Equals(userId) + select menu) + .AnyAsync( + x => x.Name.Equals(menuName), GetCancellationToken(cancellationToken)); } - public virtual async Task SetMemberMenusAsync( + public virtual async Task> GetListByUserIdAsync( Guid userId, - IEnumerable menuIds, CancellationToken cancellationToken = default) { - var hasInMenus = await DbSet - .Where(x => x.UserId == userId) - .ToArrayAsync(GetCancellationToken(cancellationToken)); - - var removes = hasInMenus.Where(x => !menuIds.Contains(x.MenuId)); - if (removes.Any()) - { - DbContext.RemoveRange(removes); - } + return await DbSet.Where(x => x.UserId.Equals(userId)) + .ToListAsync(GetCancellationToken(cancellationToken)); + } - var adds = menuIds.Where(menuId => !hasInMenus.Any(x => x.MenuId == menuId)); - if (adds.Any()) - { - var addInMenus = adds.Select(menuId => new UserMenu(menuId, userId, CurrentTenant.Id)); - await DbContext.AddRangeAsync(addInMenus, GetCancellationToken(cancellationToken)); - } + public virtual async Task InsertAsync(IEnumerable userMenus, CancellationToken cancellationToken = default) + { + await DbSet.AddRangeAsync(userMenus, GetCancellationToken(cancellationToken)); } } } diff --git a/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN.Abp.Aliyun.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN.Abp.Aliyun.Tests.csproj new file mode 100644 index 000000000..b2a8887e9 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN.Abp.Aliyun.Tests.csproj @@ -0,0 +1,18 @@ + + + + net5.0 + + false + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestBase.cs new file mode 100644 index 000000000..6bd428176 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestBase.cs @@ -0,0 +1,8 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Aliyun +{ + public class AbpAliyunTestBase : AbpTestsBase + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestModule.cs new file mode 100644 index 000000000..9dfae1732 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN/Abp/Aliyun/AbpAliyunTestModule.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.Tests; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Aliyun +{ + [DependsOn( + typeof(AbpAliyunModule), + typeof(AbpTestsBaseModule))] + public class AbpAliyunTestModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configurationOptions = new AbpConfigurationBuilderOptions + { + BasePath = @"D:\Projects\Development\Abp\Aliyun", + EnvironmentName = "Development" + }; + + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions)); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj index 5c7c5f750..526c4954d 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs index 4333b987f..ee777eede 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs @@ -1,19 +1,20 @@ using Aliyun.OSS; -using LINGYUN.Abp.Tests; +using LINGYUN.Abp.Aliyun; +using LINYUN.Abp.Aliyun.Settings; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using System; using Volo.Abp; using Volo.Abp.Autofac; using Volo.Abp.BlobStoring; using Volo.Abp.Modularity; +using Volo.Abp.Security.Encryption; namespace LINGYUN.Abp.BlobStoring.Aliyun { [DependsOn( typeof(AbpBlobStoringModule), typeof(AbpBlobStoringAliyunModule), - typeof(AbpTestsBaseModule), + typeof(AbpAliyunTestModule), typeof(AbpAutofacModule) )] public class AbpBlobStoringAliyunTestModule : AbpModule @@ -23,25 +24,22 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun private string _accessKeySecret; private string _endPoint; - public override void PreConfigureServices(ServiceConfigurationContext context) - { - var configurationOptions = new AbpConfigurationBuilderOptions - { - BasePath = @"D:\Projects\Development\Abp\BlobStoring\Aliyun", - EnvironmentName = "Development" - }; + private IConfiguration _configuration; - context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions)); + public override void ConfigureServices(ServiceConfigurationContext context) + { + _configuration = context.Services.GetConfiguration(); } - public override void ConfigureServices(ServiceConfigurationContext context) + public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var configuration = context.Services.GetConfiguration(); + _endPoint = _configuration[AliyunBlobProviderConfigurationNames.Endpoint]; + _bucketName = _configuration[AliyunBlobProviderConfigurationNames.BucketName]; + + var encryptionService = context.ServiceProvider.GetRequiredService(); - _endPoint = configuration[AliyunBlobProviderConfigurationNames.Endpoint]; - _bucketName = configuration[AliyunBlobProviderConfigurationNames.BucketName]; - _accessKeyId = configuration["Aliyun:Auth:AccessKeyId"]; - _accessKeySecret = configuration["Aliyun:Auth:AccessKeySecret"]; + _accessKeyId = encryptionService.Decrypt(_configuration["Settings:" + AliyunSettingNames.Authorization.AccessKeyId]); + _accessKeySecret = encryptionService.Decrypt(_configuration["Settings:" + AliyunSettingNames.Authorization.AccessKeySecret]); } public override void OnApplicationShutdown(ApplicationShutdownContext context) diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index 099e9a89d..cf6b484e4 100644 --- a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -23,6 +23,10 @@ namespace LINGYUN.Abp.EntityFrameworkCore.Tests { options.Configure(abpDbContextConfigurationContext => { + abpDbContextConfigurationContext.DbContextOptions.EnableDetailedErrors(); + abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging(); + abpDbContextConfigurationContext.DbContextOptions.UseEFCoreLogger(); + abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName); }); }); diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreLoggerFactory.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreLoggerFactory.cs new file mode 100644 index 000000000..6b4a90a6c --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreLoggerFactory.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using System; +using System.Diagnostics; + +namespace LINGYUN.Abp.EntityFrameworkCore.Tests +{ + public class EfCoreLoggerFactory : ILoggerFactory + { + public void AddProvider(ILoggerProvider provider) + { + } + + public ILogger CreateLogger(string categoryName) + { + return new EfCoreLogger(categoryName);//创建EFLogger类的实例 + } + + public void Dispose() + { + + } + } + + public class EfCoreLogger : ILogger + { + private readonly string _categoryName; + + public EfCoreLogger(string categoryName) => this._categoryName = categoryName; + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + var logContent = formatter(state, exception); + + Debug.WriteLine(""); + // Console.ForegroundColor = logLevel == LogLevel.Warning || logLevel == LogLevel.Error ? ConsoleColor.Red : ConsoleColor.Green; + Debug.WriteLine(logContent); + } + + public IDisposable BeginScope(TState state) => null; + } + + public static class EFCoreLoggerExtensions + { + public static DbContextOptionsBuilder UseEFCoreLogger(this DbContextOptionsBuilder builder) + { + return builder.UseLoggerFactory(new EfCoreLoggerFactory()); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN.Abp.Sms.Aliyun.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN.Abp.Sms.Aliyun.Tests.csproj new file mode 100644 index 000000000..1a82a03df --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN.Abp.Sms.Aliyun.Tests.csproj @@ -0,0 +1,18 @@ + + + + net5.0 + + false + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestBase.cs new file mode 100644 index 000000000..bd7d69da0 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestBase.cs @@ -0,0 +1,8 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Sms.Aliyun +{ + public class AbpAliyunTestBase : AbpTestsBase + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestModule.cs new file mode 100644 index 000000000..5cb689f41 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AbpAliyunSmsTestModule.cs @@ -0,0 +1,13 @@ +using LINGYUN.Abp.Aliyun; +using LINYUN.Abp.Sms.Aliyun; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Sms.Aliyun +{ + [DependsOn( + typeof(AbpAliyunTestModule), + typeof(AbpAliyunSmsModule))] + public class AbpAliyunSmsTestModule : AbpModule + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AliyunSmsSenderTests.cs b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AliyunSmsSenderTests.cs new file mode 100644 index 000000000..4fca262d9 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Sms.Aliyun.Tests/LINGYUN/Abp/Sms/Aliyun/AliyunSmsSenderTests.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.Configuration; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Sms; +using Xunit; + +namespace LINGYUN.Abp.Sms.Aliyun +{ + public class AliyunSmsSenderTests : AbpAliyunTestBase + { + protected ISmsSender SmsSender { get; } + protected IConfiguration Configuration { get; } + + public AliyunSmsSenderTests() + { + SmsSender = GetRequiredService(); + Configuration = GetRequiredService(); + } + + /// + /// 阿里云短信测试 + /// + /// + /// + [Theory] + [InlineData("123456")] + public async Task Send_Test(string code) + { + var signName = Configuration["Aliyun:Sms:Sender:SignName"]; + var phone = Configuration["Aliyun:Sms:Sender:PhoneNumber"]; + var template = Configuration["Aliyun:Sms:Sender:TemplateCode"]; + + await SmsSender.SendAsync( + signName, + template, + phone, + new Dictionary + { + { "code", code } + }); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN.Platform.Domain.Tests.csproj b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN.Platform.Domain.Tests.csproj new file mode 100644 index 000000000..91ba94467 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN.Platform.Domain.Tests.csproj @@ -0,0 +1,22 @@ + + + + net5.0 + + false + + + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformDomainTestModule.cs b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformDomainTestModule.cs new file mode 100644 index 000000000..4fc231f73 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformDomainTestModule.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace LINGYUN.Platform +{ + [DependsOn( + typeof(PlatformDomainModule) + )] + public class PlatformDomainTestModule : AbpModule + { + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + var dataSeeder = scope.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(async () => + { + // Ԥ + await dataSeeder.SeedAsync(); + // Ԥ⻧ + await dataSeeder.SeedAsync(PlatformTestsConsts.TenantId); + }); + AsyncHelper.RunSync(async () => + { + await scope.ServiceProvider + .GetRequiredService() + .BuildAsync(); + }); + } + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsConsts.cs b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsConsts.cs new file mode 100644 index 000000000..300992990 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsConsts.cs @@ -0,0 +1,17 @@ +using System; + +namespace LINGYUN.Platform +{ + public static class PlatformTestsConsts + { + public static Guid User1Id { get; } = Guid.NewGuid(); + + public static Guid User2Id { get; } = Guid.NewGuid(); + + public static Guid TenantId { get; } = Guid.NewGuid(); + + public static string Role1Name { get; } = "TestRole1"; + + public static string Role2Name { get; } = "TestRole2"; + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsDataBuilder.cs b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsDataBuilder.cs new file mode 100644 index 000000000..6d25dc4fb --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.Domain.Tests/LINGYUN/Platform/PlatformTestsDataBuilder.cs @@ -0,0 +1,65 @@ +using LINGYUN.Platform.Menus; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace LINGYUN.Platform +{ + public class PlatformTestsDataBuilder : ITransientDependency + { + private readonly ICurrentTenant _currentTenant; + + private readonly MenuManager _menuManager; + private readonly IMenuRepository _menuRepository; + + public PlatformTestsDataBuilder( + ICurrentTenant currentTenant, + MenuManager menuManager, + IMenuRepository menuRepository) + { + _currentTenant = currentTenant; + + _menuManager = menuManager; + _menuRepository = menuRepository; + } + + [UnitOfWork] + public async Task BuildAsync() + { + var adminMenu = await _menuRepository.FindByNameAsync("admin"); + + var saasMenu = await _menuRepository.FindByNameAsync("saas"); + await SetRoleMenusAsync(PlatformTestsConsts.Role1Name, new Guid[] { saasMenu.Id }); + await SetRoleMenusAsync(PlatformTestsConsts.Role2Name, new Guid[] { adminMenu.Id, saasMenu.Id }); + + await SetUserMenusAsync(PlatformTestsConsts.User1Id, new Guid[] { saasMenu.Id }); + + + using (_currentTenant.Change(PlatformTestsConsts.TenantId)) + { + var tenantAdminMenu = await _menuRepository.FindByNameAsync("admin"); + await SetUserMenusAsync(PlatformTestsConsts.User2Id, new Guid[] { tenantAdminMenu.Id }); + await SetRoleMenusAsync(PlatformTestsConsts.Role1Name, new Guid[] { tenantAdminMenu.Id }); + } + } + + private async Task SetUserMenusAsync(Guid userId, IEnumerable menusIds) + { + await _menuManager + .SetUserMenusAsync( + userId, + menusIds); + } + + private async Task SetRoleMenusAsync(string roleName, IEnumerable menusIds) + { + await _menuManager + .SetRoleMenusAsync( + roleName, + menusIds); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN.Platform.EntityFrameworkCore.Tests.csproj b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN.Platform.EntityFrameworkCore.Tests.csproj new file mode 100644 index 000000000..43b6775a5 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN.Platform.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,24 @@ + + + + net5.0 + + false + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestBase.cs b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestBase.cs new file mode 100644 index 000000000..9b4461df1 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestBase.cs @@ -0,0 +1,9 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Platform.EntityFrameworkCore +{ + public class PlatformEntityFrameworkCoreTestBase : AbpTestsBase + { + + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestModule.cs b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestModule.cs new file mode 100644 index 000000000..f10539f66 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/EntityFrameworkCore/PlatformEntityFrameworkCoreTestModule.cs @@ -0,0 +1,14 @@ +using LINGYUN.Abp.EntityFrameworkCore.Tests; +using Volo.Abp.Modularity; + +namespace LINGYUN.Platform.EntityFrameworkCore +{ + [DependsOn( + typeof(PlatformDomainTestModule), + typeof(PlatformEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreTestModule) + )] + public class PlatformEntityFrameworkCoreTestModule : AbpModule + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/Menus/EfCoreUserMenuRepositoryTests.cs b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/Menus/EfCoreUserMenuRepositoryTests.cs new file mode 100644 index 000000000..4d97a3d8b --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Platform.EntityFrameworkCore.Tests/LINGYUN/Platform/Menus/EfCoreUserMenuRepositoryTests.cs @@ -0,0 +1,68 @@ +using LINGYUN.Platform.EntityFrameworkCore; +using Shouldly; +using System; +using System.Threading.Tasks; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace LINGYUN.Platform.Menus +{ + public class EfCoreUserMenuRepositoryTests : PlatformEntityFrameworkCoreTestBase + { + protected ICurrentTenant CurrentTenant { get; } + protected IUserMenuRepository Repository { get; } + protected IMenuRepository MenuRepository { get; } + protected MenuManager MenuManager { get; } + + public EfCoreUserMenuRepositoryTests() + { + MenuManager = GetRequiredService(); + Repository = GetRequiredService(); + MenuRepository = GetRequiredService(); + + CurrentTenant = GetRequiredService(); + } + + [Fact] + public async Task UserHasInMenuAsync_Test() + { + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User1Id, "saas")).ShouldBeTrue(); + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "admin")).ShouldBeFalse(); + + using (CurrentTenant.Change(PlatformTestsConsts.TenantId)) + { + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "admin")).ShouldBeTrue(); + } + } + + [Fact] + public async Task SetMemberMenusAsync_Test() + { + var adminMenu = await MenuRepository.FindByNameAsync("admin"); + var saasMenu = await MenuRepository.FindByNameAsync("saas"); + + await MenuManager.SetUserMenusAsync(PlatformTestsConsts.User1Id, new Guid[] { adminMenu.Id}); + await MenuManager.SetUserMenusAsync(PlatformTestsConsts.User2Id, new Guid[] { adminMenu.Id, saasMenu.Id }); + + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User1Id, "admin")).ShouldBeTrue(); + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "admin")).ShouldBeTrue(); + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "saas")).ShouldBeTrue(); + + using (CurrentTenant.Change(PlatformTestsConsts.TenantId)) + { + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User1Id, "admin")).ShouldBeFalse(); + + var tenantSaasMenu = await MenuRepository.FindByNameAsync("saas"); + + var ss = await Repository.GetListByUserIdAsync(PlatformTestsConsts.User2Id); + + await MenuManager.SetUserMenusAsync(PlatformTestsConsts.User2Id, new Guid[] { tenantSaasMenu.Id }); + + var ss1 = await Repository.GetListByUserIdAsync(PlatformTestsConsts.User2Id); + + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "admin")).ShouldBeFalse(); + (await Repository.UserHasInMenuAsync(PlatformTestsConsts.User2Id, "saas")).ShouldBeTrue(); + } + } + } +}