Browse Source

Merge pull request #973 from colinin/rel-8.2.0

Rel 8.2.0
pull/988/head
yx lin 1 year ago
committed by GitHub
parent
commit
b49d2a891d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .github/workflows/publish.yml
  2. 4
      .github/workflows/release.yml
  3. 22
      Directory.Packages.props
  4. 2
      apps/vue/src/api/abp/localization/index.ts
  5. 23
      apps/vue/src/api/account/profiles/index.ts
  6. 5
      apps/vue/src/api/account/profiles/model/index.ts
  7. 2
      apps/vue/src/api/auditing/security-logs/index.ts
  8. 2
      apps/vue/src/api/identity/claims/index.ts
  9. 2
      apps/vue/src/api/identity/organization-units/index.ts
  10. 27
      apps/vue/src/api/identity/sessions/index.ts
  11. 16
      apps/vue/src/api/identity/sessions/model/index.ts
  12. 2
      apps/vue/src/api/localization/languages/index.ts
  13. 2
      apps/vue/src/api/messages/friends/index.ts
  14. 2
      apps/vue/src/api/messages/groups/index.ts
  15. 4
      apps/vue/src/api/multi-tenancy/tenants/index.ts
  16. 208
      apps/vue/src/layouts/default/header/components/notify/NoticeList.vue
  17. 126
      apps/vue/src/layouts/default/header/components/notify/index.vue
  18. 17
      apps/vue/src/layouts/default/header/components/notify/useNotifications.ts
  19. 16
      apps/vue/src/layouts/default/header/components/user-dropdown/index.vue
  20. 61
      apps/vue/src/views/account/security-logs/index.vue
  21. 141
      apps/vue/src/views/account/sessions/index.vue
  22. 150
      apps/vue/src/views/identity/user/components/SessionModal.vue
  23. 13
      apps/vue/src/views/identity/user/components/UserTable.vue
  24. 1
      apps/vue/types/abp.d.ts
  25. 248
      aspnet-core/LINGYUN.MicroService.All.sln
  26. 63
      aspnet-core/LINGYUN.MicroService.SingleProject.sln
  27. 17
      aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln
  28. 16
      aspnet-core/LINGYUN.MicroService.Workflow.sln
  29. 7
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj
  30. 23
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs
  31. 21
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs
  32. 171
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs
  33. 633
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs
  34. 441
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs
  35. 9
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs
  36. 9
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs
  37. 9
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexNameNormalizer.cs
  38. 155
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs
  39. 23
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs
  40. 39
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexNameNormalizer.cs
  41. 5
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj
  42. 31
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs
  43. 27
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs
  44. 289
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs
  45. 223
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs
  46. 9
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj
  47. 25
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs
  48. 176
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs
  49. 59
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs
  50. 27
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs
  51. 149
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs
  52. 67
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultEntityChangeStore.cs
  53. 133
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs
  54. 89
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs
  55. 11
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeWithUsername.cs
  56. 55
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs
  57. 99
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs
  58. 67
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IEntityChangeStore.cs
  59. 95
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs
  60. 83
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs
  61. 27
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs
  62. 5
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/LINGYUN.Abp.Authentication.QQ.csproj
  63. 53
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/LINGYUN/Abp/Authentication/QQ/AbpQQClaimTypes.cs
  64. 279
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthHandler.cs
  65. 73
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthOptions.cs
  66. 101
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQAuthenticationExtensions.cs
  67. 15
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/BytesExtensions.cs
  68. 15
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/StringExtensions.cs
  69. 79
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/Text/Json/JsonElementExtensions.cs
  70. 5
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/LINGYUN.Abp.Authentication.WeChat.csproj
  71. 455
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs
  72. 61
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs
  73. 25
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs
  74. 103
      aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
  75. 9
      aspnet-core/framework/authorization/LINGYUN.Abp.Authorization.OrganizationUnits/LINGYUN.Abp.Authorization.OrganizationUnits.csproj
  76. 2
      aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj
  77. 5
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN.Abp.Aliyun.SettingManagement.csproj
  78. 49
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AbpAliyunSettingManagementModule.cs
  79. 333
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingAppService.cs
  80. 47
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingController.cs
  81. 27
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingPermissionDefinitionProvider.cs
  82. 11
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingPermissionNames.cs
  83. 7
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/IAliyunSettingAppService.cs
  84. 7
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj
  85. 21
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AbpAliyunException.cs
  86. 39
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AbpAliyunModule.cs
  87. 39
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AcsClientFactory.cs
  88. 43
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs
  89. 271
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AliyunClientFactory.cs
  90. 19
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/IAcsClientFactory.cs
  91. 9
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Localization/AliyunResource.cs
  92. 147
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs
  93. 399
      aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs
  94. 7
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN.Abp.BlobStoring.Tencent.csproj
  95. 29
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/DefaultTencentBlobNameCalculator.cs
  96. 9
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/ITencentBlobNameCalculator.cs
  97. 29
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobContainerConfigurationExtensions.cs
  98. 99
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobNamingNormalizer.cs
  99. 101
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfiguration.cs
  100. 47
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfigurationNames.cs

2
.github/workflows/publish.yml

@ -2,7 +2,7 @@ name: "Publish"
on: on:
push: push:
branches: [ rel-8.1.3 ] branches: [ rel-8.2.0 ]
env: env:
DOTNET_VERSION: "8.0.200" DOTNET_VERSION: "8.0.200"

4
.github/workflows/release.yml

@ -2,7 +2,7 @@ name: "Tagged Release"
on: on:
push: push:
branches: [ rel-8.1.3 ] branches: [ rel-8.2.0 ]
jobs: jobs:
tagged-release: tagged-release:
@ -14,4 +14,4 @@ jobs:
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false prerelease: false
automatic_release_tag: "8.1.3" automatic_release_tag: "8.2.0"

22
Directory.Packages.props

@ -2,17 +2,16 @@
<PropertyGroup> <PropertyGroup>
<DotNetCoreCAPPackageVersion>8.1.1</DotNetCoreCAPPackageVersion> <DotNetCoreCAPPackageVersion>8.1.1</DotNetCoreCAPPackageVersion>
<ElsaPackageVersion>2.14.1</ElsaPackageVersion> <ElsaPackageVersion>2.14.1</ElsaPackageVersion>
<VoloAbpPackageVersion>8.1.3</VoloAbpPackageVersion> <VoloAbpPackageVersion>8.2.0</VoloAbpPackageVersion>
<LINGYUNAbpPackageVersion>8.1.3</LINGYUNAbpPackageVersion> <LINGYUNAbpPackageVersion>8.2.0</LINGYUNAbpPackageVersion>
<MicrosoftExtensionsPackageVersion>8.0.0</MicrosoftExtensionsPackageVersion> <MicrosoftExtensionsPackageVersion>8.0.0</MicrosoftExtensionsPackageVersion>
<MicrosoftAspNetCorePackageVersion>8.0.0</MicrosoftAspNetCorePackageVersion> <MicrosoftAspNetCorePackageVersion>8.0.0</MicrosoftAspNetCorePackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>8.0.0</MicrosoftEntityFrameworkCorePackageVersion> <MicrosoftEntityFrameworkCorePackageVersion>8.0.0</MicrosoftEntityFrameworkCorePackageVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<!-- Abp Framework --> <!-- Abp Framework -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="3.0.5" /> <PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="3.2.0" />
<PackageVersion Include="Volo.Abp.Core" Version="$(VoloAbpPackageVersion)" /> <PackageVersion Include="Volo.Abp.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application" Version="$(VoloAbpPackageVersion)" /> <PackageVersion Include="Volo.Abp.Account.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> <PackageVersion Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
@ -133,10 +132,9 @@
<PackageVersion Include="Volo.Abp.Users.Domain.Shared" Version="$(VoloAbpPackageVersion)" /> <PackageVersion Include="Volo.Abp.Users.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Validation" Version="$(VoloAbpPackageVersion)" /> <PackageVersion Include="Volo.Abp.Validation" Version="$(VoloAbpPackageVersion)" />
</ItemGroup> </ItemGroup>
<!-- .NET --> <!-- .NET -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageVersion Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="$(MicrosoftAspNetCorePackageVersion)" />
@ -152,9 +150,8 @@
<PackageVersion Include="Microsoft.Extensions.Http" Version="$(MicrosoftExtensionsPackageVersion)" /> <PackageVersion Include="Microsoft.Extensions.Http" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="$(MicrosoftExtensionsPackageVersion)" /> <PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(MicrosoftExtensionsPackageVersion)" /> <PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsPackageVersion)" /> <PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
</ItemGroup> </ItemGroup>
<!-- Elsa --> <!-- Elsa -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="Elsa" Version="$(ElsaPackageVersion)" /> <PackageVersion Include="Elsa" Version="$(ElsaPackageVersion)" />
@ -172,7 +169,6 @@
<PackageVersion Include="Elsa.Webhooks.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" /> <PackageVersion Include="Elsa.Webhooks.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.WorkflowSettings.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" /> <PackageVersion Include="Elsa.WorkflowSettings.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" />
</ItemGroup> </ItemGroup>
<!-- DotNetCore.CAP --> <!-- DotNetCore.CAP -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="DotNetCore.CAP" Version="$(DotNetCoreCAPPackageVersion)" /> <PackageVersion Include="DotNetCore.CAP" Version="$(DotNetCoreCAPPackageVersion)" />
@ -181,7 +177,6 @@
<PackageVersion Include="DotNetCore.CAP.OpenTelemetry" Version="$(DotNetCoreCAPPackageVersion)" /> <PackageVersion Include="DotNetCore.CAP.OpenTelemetry" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.RabbitMQ" Version="$(DotNetCoreCAPPackageVersion)" /> <PackageVersion Include="DotNetCore.CAP.RabbitMQ" Version="$(DotNetCoreCAPPackageVersion)" />
</ItemGroup> </ItemGroup>
<!-- Serilog --> <!-- Serilog -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="Serilog" Version="3.1.1" /> <PackageVersion Include="Serilog" Version="3.1.1" />
@ -198,7 +193,6 @@
<PackageVersion Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" /> <PackageVersion Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<!-- Test --> <!-- Test -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="coverlet.collector" Version="6.0.0" /> <PackageVersion Include="coverlet.collector" Version="6.0.0" />
@ -210,13 +204,11 @@
<PackageVersion Include="xunit.extensibility.execution" Version="2.6.1" /> <PackageVersion Include="xunit.extensibility.execution" Version="2.6.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.3" /> <PackageVersion Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup> </ItemGroup>
<!-- Fody --> <!-- Fody -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" /> <PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.8.0" /> <PackageVersion Include="Fody" Version="6.8.0" />
</ItemGroup> </ItemGroup>
<!-- Other --> <!-- Other -->
<ItemGroup> <ItemGroup>
<PackageVersion Include="aliyun-net-sdk-core" Version="1.5.10" /> <PackageVersion Include="aliyun-net-sdk-core" Version="1.5.10" />
@ -228,7 +220,7 @@
<PackageVersion Include="DistributedLock.Core" Version="1.0.5" /> <PackageVersion Include="DistributedLock.Core" Version="1.0.5" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.2" /> <PackageVersion Include="DistributedLock.Redis" Version="1.0.2" />
<PackageVersion Include="Hangfire.MySqlStorage" Version="2.0.3" /> <PackageVersion Include="Hangfire.MySqlStorage" Version="2.0.3" />
<PackageVersion Include="HangFire.SqlServer" Version="1.8.6" /> <PackageVersion Include="HangFire.SqlServer" Version="1.8.14" />
<PackageVersion Include="IdentityModel" Version="6.2.0" /> <PackageVersion Include="IdentityModel" Version="6.2.0" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" /> <PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="Markdig" Version="0.34.0" /> <PackageVersion Include="Markdig" Version="0.34.0" />
@ -236,6 +228,8 @@
<PackageVersion Include="NEST" Version="7.15.1" /> <PackageVersion Include="NEST" Version="7.15.1" />
<PackageVersion Include="NRules" Version="0.9.2" /> <PackageVersion Include="NRules" Version="0.9.2" />
<PackageVersion Include="Ocelot.Provider.Polly" Version="20.0.0" /> <PackageVersion Include="Ocelot.Provider.Polly" Version="20.0.0" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="5.5.0" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="5.5.0" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" /> <PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.8.1" /> <PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.8.1" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" /> <PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" />

2
apps/vue/src/api/abp/localization/index.ts

@ -5,7 +5,7 @@ export const GetAsyncByInput = (input: {
onlyDynamics?: boolean; onlyDynamics?: boolean;
}) => { }) => {
return defHttp.get<ApplicationLocalizationDto>({ return defHttp.get<ApplicationLocalizationDto>({
url: 'api/abp/application-localization"', url: '/api/abp/application-localization"',
params: input, params: input,
}); });
}; };

23
apps/vue/src/api/account/profiles/index.ts

@ -12,7 +12,9 @@ import {
AuthenticatorDto, AuthenticatorDto,
VerifyAuthenticatorCodeInput, VerifyAuthenticatorCodeInput,
AuthenticatorRecoveryCodeDto, AuthenticatorRecoveryCodeDto,
GetUserSessionsInput,
} from './model'; } from './model';
import { IdentitySessionDto } from '../../identity/sessions/model';
export const get = () => { export const get = () => {
return defHttp.get<MyProfile>({ return defHttp.get<MyProfile>({
@ -92,4 +94,25 @@ export const resetAuthenticator = () => {
return defHttp.post<void>({ return defHttp.post<void>({
url: '/api/account/my-profile/reset-authenticator', url: '/api/account/my-profile/reset-authenticator',
}); });
}
/**
*
* @param { GetUserSessionsInput } input
* @returns { Promise<PagedResultDto<IdentitySessionDto>> }
*/
export const getSessions = (input?: GetUserSessionsInput): Promise<PagedResultDto<IdentitySessionDto>> => {
return defHttp.get<PagedResultDto<IdentitySessionDto>>({
url: '/api/account/my-profile/sessions',
params: input,
});
};
/**
*
* @param { string } sessionId id
* @returns { Promise<void> }
*/
export const revokeSession = (sessionId: string): Promise<void> => {
return defHttp.delete<void>({
url: `/api/account/my-profile/sessions/${sessionId}/revoke`,
});
} }

5
apps/vue/src/api/account/profiles/model/index.ts

@ -60,4 +60,9 @@ interface Profile extends ExtensibleObject, IHasConcurrencyStamp {
export interface VerifyAuthenticatorCodeInput { export interface VerifyAuthenticatorCodeInput {
authenticatorCode: string; authenticatorCode: string;
} }
export interface GetUserSessionsInput extends PagedAndSortedResultRequestDto {
device?: string;
clientId?: string;
}

2
apps/vue/src/api/auditing/security-logs/index.ts

@ -15,7 +15,7 @@ export const getById = (id: string) => {
export const getList = (input: GetSecurityLogPagedRequest) => { export const getList = (input: GetSecurityLogPagedRequest) => {
return defHttp.get<PagedResultDto<SecurityLog>>({ return defHttp.get<PagedResultDto<SecurityLog>>({
url: 'api/auditing/security-log', url: '/api/auditing/security-log',
params: input, params: input,
}); });
}; };

2
apps/vue/src/api/identity/claims/index.ts

@ -29,7 +29,7 @@ export const update = (id: string, input: UpdateIdentityClaimType) => {
export const getById = (id: string) => { export const getById = (id: string) => {
return defHttp.get<IdentityClaimType>({ return defHttp.get<IdentityClaimType>({
url: `'/api/identity/claim-types/${id}'`, url: `/api/identity/claim-types/${id}'`,
}); });
}; };

2
apps/vue/src/api/identity/organization-units/index.ts

@ -88,7 +88,7 @@ export const getAll = () => {
export const move = (id: string, parentId?: string) => { export const move = (id: string, parentId?: string) => {
return defHttp.put<void>({ return defHttp.put<void>({
url: `api/identity/organization-units/${id}/move`, url: `/api/identity/organization-units/${id}/move`,
data: { data: {
parentId: parentId, parentId: parentId,
}, },

27
apps/vue/src/api/identity/sessions/index.ts

@ -0,0 +1,27 @@
import { defHttp } from '/@/utils/http/axios';
import {
IdentitySessionDto,
GetUserSessionsInput
} from './model';
/**
*
* @param { GetUserSessionsInput } input
* @returns { Promise<PagedResultDto<IdentitySessionDto>> }
*/
export const getSessions = (input?: GetUserSessionsInput): Promise<PagedResultDto<IdentitySessionDto>> => {
return defHttp.get<PagedResultDto<IdentitySessionDto>>({
url: '/api/identity/sessions',
params: input,
});
};
/**
*
* @param { string } sessionId id
* @returns { Promise<void> }
*/
export const revokeSession = (sessionId: string): Promise<void> => {
return defHttp.delete<void>({
url: `/api/identity/sessions/${sessionId}/revoke`,
});
}

16
apps/vue/src/api/identity/sessions/model/index.ts

@ -0,0 +1,16 @@
export interface IdentitySessionDto extends EntityDto<string> {
sessionId: string;
device: string;
deviceInfo: string;
userId: string;
clientId?: string;
ipAddresses?: string;
signedIn: Date;
lastAccessed?: Date;
}
export interface GetUserSessionsInput extends PagedAndSortedResultRequestDto {
userId?: string;
device?: string;
clientId?: string;
}

2
apps/vue/src/api/localization/languages/index.ts

@ -16,7 +16,7 @@ export const getByName = (name: string) => {
export const create = (input: LanguageCreate) => { export const create = (input: LanguageCreate) => {
return defHttp.post<Language>({ return defHttp.post<Language>({
url: '/api/abp/localization/languages', url: '/api/localization/languages',
data: input, data: input,
}); });
}; };

2
apps/vue/src/api/messages/friends/index.ts

@ -9,7 +9,7 @@ import {
export const create = (input: FriendCreateRequest) => { export const create = (input: FriendCreateRequest) => {
return defHttp.post<void>({ return defHttp.post<void>({
url: 'api/im/my-friends', url: '/api/im/my-friends',
data: input, data: input,
}); });
}; };

2
apps/vue/src/api/messages/groups/index.ts

@ -10,6 +10,6 @@ export const search = (input: GroupSearchRequest) => {
export const getById = (groupId: string) => { export const getById = (groupId: string) => {
return defHttp.get<Group>({ return defHttp.get<Group>({
url: `'/api/im/groups/${groupId}`, url: `/api/im/groups/${groupId}`,
}); });
}; };

4
apps/vue/src/api/multi-tenancy/tenants/index.ts

@ -3,12 +3,12 @@ import { FindTenantResult } from './model';
export const findTenantByName = (name: string) => { export const findTenantByName = (name: string) => {
return defHttp.get<FindTenantResult>({ return defHttp.get<FindTenantResult>({
url: `api/abp/multi-tenancy/tenants/by-name/${name}` url: `/api/abp/multi-tenancy/tenants/by-name/${name}`
}); });
}; };
export const findTenantById = (id: string) => { export const findTenantById = (id: string) => {
return defHttp.get<FindTenantResult>({ return defHttp.get<FindTenantResult>({
url: `api/abp/multi-tenancy/tenants/by-id/${id}` url: `/api/abp/multi-tenancy/tenants/by-id/${id}`
}); });
}; };

208
apps/vue/src/layouts/default/header/components/notify/NoticeList.vue

@ -1,11 +1,11 @@
<template> <template>
<a-list :class="prefixCls" bordered :pagination="getPagination"> <List :class="prefixCls" bordered :pagination="getPagination">
<template v-for="item in getData" :key="item.id"> <template v-for="item in getData" :key="item.id">
<a-list-item class="list-item"> <ListItem class="list-item">
<a-list-item-meta> <ListItemMeta>
<template #title> <template #title>
<div class="title"> <div class="title">
<a-typography-paragraph <TypographyParagraph
@click="handleTitleClick(item)" @click="handleTitleClick(item)"
style="width: 100%; margin-bottom: 0 !important" style="width: 100%; margin-bottom: 0 !important"
:style="{ cursor: isTitleClickable ? 'pointer' : '' }" :style="{ cursor: isTitleClickable ? 'pointer' : '' }"
@ -18,22 +18,22 @@
:content="item.title" :content="item.title"
/> />
<div class="extra" v-if="item.extra"> <div class="extra" v-if="item.extra">
<a-tag class="tag" :color="item.color"> <Tag class="tag" :color="item.color">
{{ item.extra }} {{ item.extra }}
</a-tag> </Tag>
</div> </div>
</div> </div>
</template> </template>
<template #avatar> <template #avatar>
<a-avatar v-if="item.avatar" class="avatar" :src="item.avatar" /> <Avatar v-if="item.avatar" class="avatar" :src="item.avatar" />
<span v-else> {{ item.avatar }}</span> <span v-else> {{ item.avatar }}</span>
</template> </template>
<template #description> <template #description>
<div> <div>
<div class="description" v-if="item.description"> <div class="description" v-if="item.description">
<a-typography-paragraph <TypographyParagraph
@click="handleContentClick(item)" @click="handleContentClick(item)"
style="width: 100%; margin-bottom: 0 !important" style="width: 100%; margin-bottom: 0 !important"
:style="{ cursor: isContentClickable ? 'pointer' : '' }" :style="{ cursor: isContentClickable ? 'pointer' : '' }"
@ -50,129 +50,109 @@
</div> </div>
</div> </div>
</template> </template>
</a-list-item-meta> </ListItemMeta>
</a-list-item> </ListItem>
</template> </template>
<template #footer> <template #footer>
<slot name="footer"></slot> <slot name="footer"></slot>
</template> </template>
</a-list> </List>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, PropType, ref, watch, unref } from 'vue'; import { computed, PropType, ref, watchEffect, unref } from 'vue';
import { ListItem } from './data'; import { ListItem } from './data';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { List, Avatar, Tag, Typography } from 'ant-design-vue'; import { List, Avatar, Tag, Typography } from 'ant-design-vue';
import { NotificationContentType } from '/@/api/messages/notifications/model'; import { NotificationContentType } from '/@/api/messages/notifications/model';
import { isNumber } from '/@/utils/is'; import { isNumber } from '/@/utils/is';
export default defineComponent({
components: { const TypographyParagraph = Typography.Paragraph;
[Avatar.name]: Avatar, const ListItem = List.Item;
[List.name]: List, const ListItemMeta = List.Item.Meta;
[List.Item.name]: List.Item,
AListItemMeta: List.Item.Meta, const emits = defineEmits(['update:currentPage']);
ATypographyParagraph: Typography.Paragraph, const props = defineProps({
[Tag.name]: Tag, list: {
type: Array as PropType<ListItem[]>,
default: () => [],
}, },
props: { pageSize: {
list: { type: [Boolean, Number] as PropType<Boolean | Number>,
type: Array as PropType<ListItem[]>, default: 5,
default: () => [],
},
pageSize: {
type: [Boolean, Number] as PropType<Boolean | Number>,
default: 5,
},
currentPage: {
type: Number,
default: 1,
},
titleRows: {
type: Number,
default: 1,
},
descRows: {
type: Number,
default: 2,
},
onTitleClick: {
type: Function as PropType<(Recordable) => void>,
},
onContentClick: {
type: Function as PropType<(Recordable) => void>,
},
}, },
emits: ['update:currentPage'], currentPage: {
setup(props, { emit }) { type: Number,
const { prefixCls } = useDesign('header-notify-list'); default: 1,
const current = ref(props.currentPage || 1); },
const getData = computed(() => { titleRows: {
const { pageSize, list } = props; type: Number,
if (pageSize === false) return []; default: 1,
let size = isNumber(pageSize) ? pageSize : 10; },
return list.slice(size * (unref(current) - 1), size * unref(current)); descRows: {
}); type: Number,
const getContent = computed(() => { default: 2,
return (item: ListItem) => { },
switch (item.contentType) { onTitleClick: {
default: type: Function as PropType<(Recordable) => void>,
case NotificationContentType.Text: },
return item.description; onContentClick: {
case NotificationContentType.Html: type: Function as PropType<(Recordable) => void>,
case NotificationContentType.Json: }
case NotificationContentType.Markdown: });
return item.title;
}
};
});
watch(
() => props.currentPage,
(v) => {
current.value = v;
},
);
const isTitleClickable = computed(() => !!props.onTitleClick);
const isContentClickable = computed(() => !!props.onContentClick);
const getPagination = computed(() => {
const { list, pageSize } = props;
if (pageSize === false) return false;
const size = isNumber(pageSize) ? pageSize : 5;
if (size > 0 && list && list.length > size) {
return {
total: list.length,
pageSize: size,
//size: 'small',
current: unref(current),
onChange(page) {
current.value = page;
emit('update:currentPage', page);
},
};
} else {
return false;
}
});
function handleTitleClick(item: ListItem) {
props.onTitleClick && props.onTitleClick(item);
}
function handleContentClick(item: ListItem) { const { prefixCls } = useDesign('header-notify-list');
props.onContentClick && props.onContentClick(item); const current = ref(props.currentPage || 1);
const getData = computed(() => {
const { pageSize, list } = props;
if (pageSize === false) return [];
let size = isNumber(pageSize) ? pageSize : 10;
return list.slice(size * (unref(current) - 1), size * unref(current));
});
const getContent = computed(() => {
return (item: ListItem) => {
switch (item.contentType) {
default:
case NotificationContentType.Text:
return item.description;
case NotificationContentType.Html:
case NotificationContentType.Json:
case NotificationContentType.Markdown:
return item.title;
} }
};
});
watchEffect(() => {
current.value = props.currentPage;
});
const isTitleClickable = computed(() => !!props.onTitleClick);
const isContentClickable = computed(() => !!props.onContentClick);
const getPagination = computed(() => {
const { list, pageSize } = props;
if (pageSize === false) return false;
const size = isNumber(pageSize) ? pageSize : 5;
if (size > 0 && list && list.length > size) {
return { return {
prefixCls, total: list.length,
getPagination, pageSize: size,
getData, //size: 'small',
getContent, current: unref(current),
handleTitleClick, onChange(page) {
isTitleClickable, current.value = page;
handleContentClick, emits('update:currentPage', page);
isContentClickable, },
}; };
}, } else {
return false;
}
}); });
function handleTitleClick(item: ListItem) {
props.onTitleClick && props.onTitleClick(item);
}
function handleContentClick(item: ListItem) {
props.onContentClick && props.onContentClick(item);
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-header-notify-list'; @prefix-cls: ~'@{namespace}-header-notify-list';

126
apps/vue/src/layouts/default/header/components/notify/index.vue

@ -1,6 +1,6 @@
<template> <template>
<div :class="prefixCls"> <div :class="prefixCls">
<Badge :count="count" dot :numberStyle="numberStyle"> <Badge :count="count" dot :numberStyle="{}">
<BellOutlined @click="showDrawer" /> <BellOutlined @click="showDrawer" />
</Badge> </Badge>
<Drawer <Drawer
@ -39,44 +39,11 @@
</TabPane> </TabPane>
</Tabs> </Tabs>
</Drawer> </Drawer>
<!-- <Popover title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`">
<Badge :count="count" dot :numberStyle="numberStyle">
<BellOutlined />
</Badge>
<template #content>
<Tabs>
<TabPane :key="notifierRef.key" :tab="notifierRef.name">
<NoticeList :list="notifierRef.list" @title-click="readNotifer" />
</TabPane>
<TabPane :key="messageRef.key" :tab="messageRef.name">
<NoticeList :list="messageRef.list">
<template #footer>
<ButtonGroup style="width: 100%">
<Button
:disabled="messageRef.list.length === 0"
style="width: 50%"
type="link"
@click="clearMessage"
>清空消息</Button
>
<Button style="width: 50%" type="link" @click="handleShowMessages"
>查看更多</Button
>
</ButtonGroup>
</template>
</NoticeList>
</TabPane>
<TabPane :key="tasksRef.key" :tab="tasksRef.name">
<NoticeList :list="tasksRef.list" />
</TabPane>
</Tabs>
</template>
</Popover> -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref } from 'vue'; import { computed, ref } from 'vue';
import { Button, Drawer, Popover, Tabs, Badge } from 'ant-design-vue'; import { Button, Drawer, Tabs, Badge } from 'ant-design-vue';
import { BellOutlined } from '@ant-design/icons-vue'; import { BellOutlined } from '@ant-design/icons-vue';
import NoticeList from './NoticeList.vue'; import NoticeList from './NoticeList.vue';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
@ -85,67 +52,40 @@
import { useMessages } from './useMessages'; import { useMessages } from './useMessages';
import { useNotifications } from './useNotifications'; import { useNotifications } from './useNotifications';
export default defineComponent({ const ButtonGroup = Button.Group;
components: { const TabPane = Tabs.TabPane;
Button,
ButtonGroup: Button.Group,
Drawer,
Popover,
BellOutlined,
Tabs,
TabPane: Tabs.TabPane,
Badge,
NoticeList,
},
setup() {
const { prefixCls } = useDesign('header-notify');
const go = useGo();
const open = ref(false);
const { tasksRef } = useTasks();
const { messageRef, clearMessage } = useMessages();
const { notifierRef, readNotifer } = useNotifications();
// const listData = ref(tabListData);
const count = computed(() => { const { prefixCls } = useDesign('header-notify');
let count = 0; const go = useGo();
count += notifierRef.value.list.length; const open = ref(false);
count += messageRef.value.list.length; const { tasksRef } = useTasks();
count += tasksRef.value.list.length; const { messageRef, clearMessage } = useMessages();
return count; const { notifierRef, readNotifer } = useNotifications();
}); // const listData = ref(tabListData);
function handleShowMessages() { const count = computed(() => {
console.log('handleShowMessages'); let count = 0;
go('/sys/chat?type=chat-message'); count += notifierRef.value.list.length;
} count += messageRef.value.list.length;
count += tasksRef.value.list.length;
return count;
});
function handleShowNotifications() { function handleShowMessages() {
console.log('handleShowNotifications'); console.log('handleShowMessages');
open.value = false; go('/sys/chat?type=chat-message');
go('/messages/notifications'); }
}
function showDrawer() { function handleShowNotifications() {
console.log('showDrawer'); console.log('handleShowNotifications');
open.value = true; open.value = false;
} go('/messages/notifications');
}
return { function showDrawer() {
prefixCls, console.log('showDrawer');
count, open.value = true;
numberStyle: {}, }
open,
showDrawer,
notifierRef,
readNotifer,
messageRef,
clearMessage,
tasksRef,
handleShowMessages,
handleShowNotifications,
};
},
});
</script> </script>
<style lang="less"> <style lang="less">
@prefix-cls: ~'@{namespace}-header-notify'; @prefix-cls: ~'@{namespace}-header-notify';

17
apps/vue/src/layouts/default/header/components/notify/useNotifications.ts

@ -44,6 +44,10 @@ export function useNotifications() {
}); });
function onNotifyReceived(notificationInfo: NotificationInfo, notifer?: boolean) { function onNotifyReceived(notificationInfo: NotificationInfo, notifer?: boolean) {
if (notificationInfo.type === NotificationType.ServiceCallback) {
emitter.emit(NotifyEventEnum.NOTIFICATIONS_SERVICE_CALLBACK, notificationInfo);
return;
}
const { data } = notificationInfo; const { data } = notificationInfo;
let title = data.extraProperties.title; let title = data.extraProperties.title;
let message = data.extraProperties.message; let message = data.extraProperties.message;
@ -83,16 +87,9 @@ export function useNotifications() {
contentType: notificationInfo.contentType, contentType: notificationInfo.contentType,
}; };
if (notifer && notificationInfo.type !== NotificationType.ServiceCallback) { notifer && _notification(notifier, notificationInfo.severity);
_notification(notifier, notificationInfo.severity); emitter.emit(NotifyEventEnum.NOTIFICATIONS_RECEVIED, notificationInfo);
} notifierRef.value.list.push(notifier);
if (notificationInfo.type === NotificationType.ServiceCallback) {
emitter.emit(NotifyEventEnum.NOTIFICATIONS_SERVICE_CALLBACK, notificationInfo);
} else {
emitter.emit(NotifyEventEnum.NOTIFICATIONS_RECEVIED, notificationInfo);
notifierRef.value.list.push(notifier);
}
} }

16
apps/vue/src/layouts/default/header/components/user-dropdown/index.vue

@ -26,6 +26,11 @@
:text="t('AbpAuditLogging.SecurityLog')" :text="t('AbpAuditLogging.SecurityLog')"
icon="ant-design:security-scan-outlined" icon="ant-design:security-scan-outlined"
/> />
<MenuItem
key="sessions"
:text="t('AbpIdentity.IdentitySessions')"
icon="carbon:prompt-session"
/>
<MenuDivider /> <MenuDivider />
<MenuItem <MenuItem
v-if="getUseLockPage" v-if="getUseLockPage"
@ -42,6 +47,7 @@
</template> </template>
</Dropdown> </Dropdown>
<LockAction @register="register" /> <LockAction @register="register" />
<SessionModal @register="registerSessionModal" />
<SecurityLogsModal @register="registerSecurityLogsModal" /> <SecurityLogsModal @register="registerSecurityLogsModal" />
</template> </template>
<script lang="ts"> <script lang="ts">
@ -67,7 +73,7 @@
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
type MenuEvent = 'logout' | 'doc' | 'lock' | 'setting' | 'center' | 'security-logs'; type MenuEvent = 'logout' | 'doc' | 'lock' | 'setting' | 'center' | 'sessions' | 'security-logs';
export default defineComponent({ export default defineComponent({
name: 'UserDropdown', name: 'UserDropdown',
@ -77,6 +83,9 @@
MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')), MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
MenuDivider: Menu.Divider, MenuDivider: Menu.Divider,
LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')), LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
SessionModal: createAsyncComponent(
() => import('/@/views/account/sessions/index.vue'),
),
SecurityLogsModal: createAsyncComponent( SecurityLogsModal: createAsyncComponent(
() => import('/@/views/account/security-logs/index.vue'), () => import('/@/views/account/security-logs/index.vue'),
), ),
@ -107,6 +116,7 @@
}); });
const [register, { openModal }] = useModal(); const [register, { openModal }] = useModal();
const [registerSessionModal, { openModal: openSessionModal }] = useModal();
const [registerSecurityLogsModal, { openModal: openSecurityLogsModal }] = useModal(); const [registerSecurityLogsModal, { openModal: openSecurityLogsModal }] = useModal();
function handleLock() { function handleLock() {
@ -140,6 +150,9 @@
case 'center': case 'center':
go('/account/center'); go('/account/center');
break; break;
case 'sessions':
openSessionModal(true, {});
break;
case 'security-logs': case 'security-logs':
openSecurityLogsModal(true, {}); openSecurityLogsModal(true, {});
break; break;
@ -154,6 +167,7 @@
getShowDoc, getShowDoc,
register, register,
getUseLockPage, getUseLockPage,
registerSessionModal,
registerSecurityLogsModal, registerSecurityLogsModal,
}; };
}, },

61
apps/vue/src/views/account/security-logs/index.vue

@ -9,45 +9,23 @@
:can-fullscreen="false" :can-fullscreen="false"
:show-ok-btn="false" :show-ok-btn="false"
> >
<Card style="height: 100%"> <div :style="getContentStyle" ref="contentWrapRef">
<div :style="getContentStyle" ref="contentWrapRef"> <ScrollContainer ref="contentScrollRef">
<ScrollContainer ref="contentScrollRef"> <template v-for="securityLog in securityLogs" :key="securityLog.id">
<template v-for="securityLog in securityLogs" :key="securityLog.id"> <Card hoverable style="height: 100%; margin-bottom: 15px;">
<CardGrid> <Descriptions bordered size="small" :column="1">
<Form <DescriptionItem :label="L('ApplicationName')">{{ securityLog.applicationName }}</DescriptionItem>
layout="horizontal" <DescriptionItem :label="L('Identity')">{{ securityLog.identity }}</DescriptionItem>
:colon="false" <DescriptionItem :label="L('Actions')">{{ securityLog.action }}</DescriptionItem>
:model="securityLog" <DescriptionItem :label="L('ClientId')">{{ securityLog.clientId }}</DescriptionItem>
:labelCol="{ span: 4 }" <DescriptionItem :label="L('ClientIpAddress')">{{ securityLog.clientIpAddress }}</DescriptionItem>
:wrapperCol="{ span: 16 }" <DescriptionItem :label="L('BrowserInfo')">{{ formatToDateTime(securityLog.browserInfo) }}</DescriptionItem>
> <DescriptionItem :label="L('CreationTime')">{{ formatToDateTime(securityLog.creationTime) }}</DescriptionItem>
<FormItem labelAlign="left" :label="L('ApplicationName')"> </Descriptions>
<span>{{ securityLog.applicationName }}</span> </Card>
</FormItem> </template>
<FormItem labelAlign="left" :label="L('Identity')"> </ScrollContainer>
<span>{{ securityLog.identity }}</span> </div>
</FormItem>
<FormItem labelAlign="left" :label="L('Actions')">
<span>{{ securityLog.action }}</span>
</FormItem>
<FormItem labelAlign="left" :label="L('ClientId')">
<span>{{ securityLog.clientId }}</span>
</FormItem>
<FormItem labelAlign="left" :label="L('ClientIpAddress')">
<span>{{ securityLog.clientIpAddress }}</span>
</FormItem>
<FormItem labelAlign="left" :label="L('BrowserInfo')">
<span>{{ securityLog.browserInfo }}</span>
</FormItem>
<FormItem labelAlign="left" :label="L('CreationTime')">
<span>{{ formatToDateTime(securityLog.creationTime) }}</span>
</FormItem>
</Form>
</CardGrid>
</template>
</ScrollContainer>
</div>
</Card>
<template #footer> <template #footer>
<APagination <APagination
ref="paginationRef" ref="paginationRef"
@ -63,7 +41,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { CSSProperties } from 'vue'; import type { CSSProperties } from 'vue';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { Card, Form, Pagination } from 'ant-design-vue'; import { Card, Descriptions, Pagination } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { ScrollContainer } from '/@/components/Container'; import { ScrollContainer } from '/@/components/Container';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -74,9 +52,8 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { formatToDateTime } from '/@/utils/dateUtil'; import { formatToDateTime } from '/@/utils/dateUtil';
const CardGrid = Card.Grid;
const FormItem = Form.Item;
const APagination = Pagination; const APagination = Pagination;
const DescriptionItem = Descriptions.Item;
const props = defineProps({ const props = defineProps({
autoContentHeight: { autoContentHeight: {

141
apps/vue/src/views/account/sessions/index.vue

@ -0,0 +1,141 @@
<template>
<BasicModal
v-bind="$attrs"
@register="registerModal"
:width="800"
:height="500"
:title="L('IdentitySessions')"
:mask-closable="false"
:can-fullscreen="false"
:show-ok-btn="false"
>
<div :style="getContentStyle" ref="contentWrapRef" class="session">
<ScrollContainer ref="contentScrollRef">
<template v-for="identitySession in identitySessions" :key="identitySession.id">
<Card style="height: 100%">
<template #title>
<div class="session__tile">
<span>{{ identitySession.device }}</span>
<div style="padding-left: 5px;">
<Tag
v-if="identitySession.sessionId === abpStore.getApplication.currentUser.sessionId"
color="#87d068"
>{{ L('CurrentSession') }}</Tag>
</div>
</div>
</template>
<Descriptions bordered size="small" :column="1">
<DescriptionItem :label="L('DisplayName:SessionId')">{{ identitySession.sessionId }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:Device')">{{ identitySession.device }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:DeviceInfo')">{{ identitySession.deviceInfo }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:ClientId')">{{ identitySession.clientId }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:IpAddresses')">{{ identitySession.ipAddresses }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:SignedIn')">{{ formatToDateTime(identitySession.signedIn) }}</DescriptionItem>
<DescriptionItem v-if="identitySession.lastAccessed" :label="L('DisplayName:LastAccessed')">{{ formatToDateTime(identitySession.lastAccessed) }}</DescriptionItem>
</Descriptions>
<template #extra>
<Button
v-if="identitySession.sessionId !== abpStore.getApplication.currentUser.sessionId"
danger
@click="handleRevokeSession(identitySession)"
>{{ L('RevokeSession') }}</Button>
</template>
</Card>
</template>
</ScrollContainer>
</div>
<template #footer>
<APagination
ref="paginationRef"
:pageSizeOptions="['10', '25', '50', '100']"
:total="identitySessionTotal"
@change="fetchSessions"
@showSizeChange="fetchSessions"
/>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import type { CSSProperties } from 'vue';
import { computed, ref } from 'vue';
import { Button, Card, Descriptions, Pagination, Tag } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { ScrollContainer } from '/@/components/Container';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useContentHeight } from '/@/hooks/web/useContentHeight';
import { useAbpStoreWithOut } from '/@/store/modules/abp';
import { getSessions, revokeSession } from '/@/api/account/profiles';
import { IdentitySessionDto } from '/@/api/identity/sessions/model';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { formatToDateTime } from '/@/utils/dateUtil';
const DescriptionItem = Descriptions.Item;
const APagination = Pagination;
const props = defineProps({
autoContentHeight: {
type: Boolean,
default: true,
},
});
const contentWrapRef = ref<any>();
const contentScrollRef = ref<any>();
const paginationRef = ref<any>();
const getContentHeight = computed(() => props.autoContentHeight);
const { contentHeight } = useContentHeight(getContentHeight, contentWrapRef, [paginationRef], []);
const getContentStyle = computed((): CSSProperties => {
return {
width: '100%',
height: `${contentHeight.value}px`,
};
});
const identitySessions = ref<IdentitySessionDto[]>([]);
const identitySessionTotal = ref(0);
const abpStore = useAbpStoreWithOut();
const { createConfirm, createMessage } = useMessage();
const { L } = useLocalization(['AbpIdentity', 'AbpUi']);
const [registerModal] = useModalInner(() => {
fetchSessions();
});
function fetchSessions(page: number = 1, pageSize: number = 10) {
const request = {
skipCount: page,
maxResultCount: pageSize,
};
formatPagedRequest(request);
getSessions({
skipCount: request.skipCount,
maxResultCount: request.maxResultCount,
}).then((res) => {
identitySessions.value = res.items;
identitySessionTotal.value = res.totalCount;
});
}
function handleRevokeSession(session: IdentitySessionDto) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('SessionWillBeRevokedMessage'),
onOk: async () => {
await revokeSession(session.sessionId);
createMessage.success(L('SuccessfullyRevoked'));
fetchSessions();
},
});
}
</script>
<style lang="less" scoped>
.session {
.session__tile {
display: flex;
flex-direction: row;
}
}
</style>

150
apps/vue/src/views/identity/user/components/SessionModal.vue

@ -0,0 +1,150 @@
<template>
<BasicModal
v-bind="$attrs"
@register="registerModal"
:width="800"
:height="500"
:title="L('IdentitySessions')"
:mask-closable="false"
:can-fullscreen="false"
:show-ok-btn="false"
>
<div v-if="identitySessions.length <= 0">
<Empty />
</div>
<div v-else :style="getContentStyle" ref="contentWrapRef" class="session">
<ScrollContainer ref="contentScrollRef">
<template v-for="identitySession in identitySessions" :key="identitySession.id">
<Card style="height: 100%">
<template #title>
<div class="session__tile">
<span>{{ identitySession.device }}</span>
<div style="padding-left: 5px;">
<Tag
v-if="identitySession.sessionId === abpStore.getApplication.currentUser.sessionId"
color="#87d068"
>{{ L('CurrentSession') }}</Tag>
</div>
</div>
</template>
<Descriptions bordered size="small" :column="1">
<DescriptionItem :label="L('DisplayName:SessionId')">{{ identitySession.sessionId }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:Device')">{{ identitySession.device }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:DeviceInfo')">{{ identitySession.deviceInfo }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:ClientId')">{{ identitySession.clientId }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:IpAddresses')">{{ identitySession.ipAddresses }}</DescriptionItem>
<DescriptionItem :label="L('DisplayName:SignedIn')">{{ formatToDateTime(identitySession.signedIn) }}</DescriptionItem>
<DescriptionItem v-if="identitySession.lastAccessed" :label="L('DisplayName:LastAccessed')">{{ formatToDateTime(identitySession.lastAccessed) }}</DescriptionItem>
</Descriptions>
<template #extra>
<Button
v-auth="['AbpIdentity.IdentitySessions.Revoke']"
v-if="identitySession.sessionId !== abpStore.getApplication.currentUser.sessionId"
danger
@click="handleRevokeSession(identitySession)"
>{{ L('RevokeSession') }}</Button>
</template>
</Card>
</template>
</ScrollContainer>
</div>
<template #footer>
<APagination
v-if="identitySessions.length > 0"
ref="paginationRef"
:pageSizeOptions="['10', '25', '50', '100']"
:total="identitySessionTotal"
@change="fetchSessions"
@showSizeChange="fetchSessions"
/>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import type { CSSProperties } from 'vue';
import { computed, ref } from 'vue';
import { Button, Card, Descriptions, Empty, Pagination, Tag } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { ScrollContainer } from '/@/components/Container';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useContentHeight } from '/@/hooks/web/useContentHeight';
import { useAbpStoreWithOut } from '/@/store/modules/abp';
import { getSessions, revokeSession } from '/@/api/identity/sessions';
import { IdentitySessionDto } from '/@/api/identity/sessions/model';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { formatToDateTime } from '/@/utils/dateUtil';
const DescriptionItem = Descriptions.Item;
const APagination = Pagination;
const props = defineProps({
autoContentHeight: {
type: Boolean,
default: true,
},
});
const userId = ref('');
const contentWrapRef = ref<any>();
const contentScrollRef = ref<any>();
const paginationRef = ref<any>();
const getContentHeight = computed(() => props.autoContentHeight);
const { contentHeight } = useContentHeight(getContentHeight, contentWrapRef, [paginationRef], []);
const getContentStyle = computed((): CSSProperties => {
return {
width: '100%',
height: `${contentHeight.value}px`,
};
});
const identitySessions = ref<IdentitySessionDto[]>([]);
const identitySessionTotal = ref(0);
const abpStore = useAbpStoreWithOut();
const { createConfirm, createMessage } = useMessage();
const { L } = useLocalization(['AbpIdentity', 'AbpUi']);
const [registerModal] = useModalInner((data: { userId: string }) => {
userId.value = data.userId;
identitySessions.value = [];
fetchSessions();
});
function fetchSessions(page: number = 1, pageSize: number = 10) {
const request = {
skipCount: page,
maxResultCount: pageSize,
};
formatPagedRequest(request);
getSessions({
userId: userId.value,
skipCount: request.skipCount,
maxResultCount: request.maxResultCount,
}).then((res) => {
identitySessions.value = res.items;
identitySessionTotal.value = res.totalCount;
});
}
function handleRevokeSession(session: IdentitySessionDto) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('SessionWillBeRevokedMessage'),
onOk: async () => {
await revokeSession(session.sessionId);
createMessage.success(L('SuccessfullyRevoked'));
fetchSessions();
},
});
}
</script>
<style lang="less" scoped>
.session {
.session__tile {
display: flex;
flex-direction: row;
}
}
</style>

13
apps/vue/src/views/identity/user/components/UserTable.vue

@ -57,6 +57,11 @@
ifShow: !lockEnd(record), ifShow: !lockEnd(record),
onClick: showLockModal.bind(null, record.id), onClick: showLockModal.bind(null, record.id),
}, },
{
auth: 'AbpIdentity.IdentitySessions',
label: L('IdentitySessions'),
onClick: handleShowSessionModal.bind(null, record),
},
{ {
auth: 'AbpIdentity.Users.Update', auth: 'AbpIdentity.Users.Update',
label: L('UnLock'), label: L('UnLock'),
@ -90,6 +95,7 @@
</template> </template>
</BasicTable> </BasicTable>
<UserModal @register="registerModal" @change="reloadTable" /> <UserModal @register="registerModal" @change="reloadTable" />
<SessionModal @register="registerSessionModal" />
<PermissionModal @register="registerPermissionModal" /> <PermissionModal @register="registerPermissionModal" />
<PasswordModal @register="registerPasswordModal" /> <PasswordModal @register="registerPasswordModal" />
<ClaimModal <ClaimModal
@ -129,11 +135,13 @@
updateClaim, updateClaim,
deleteClaim, deleteClaim,
} from '/@/api/identity/users'; } from '/@/api/identity/users';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import UserModal from './UserModal.vue'; import UserModal from './UserModal.vue';
import PasswordModal from './PasswordModal.vue'; import PasswordModal from './PasswordModal.vue';
import LockModal from './LockModal.vue'; import LockModal from './LockModal.vue';
import MenuModal from '../../components/MenuModal.vue'; import MenuModal from '../../components/MenuModal.vue';
import ClaimModal from '../../components/ClaimModal.vue'; import ClaimModal from '../../components/ClaimModal.vue';
const SessionModal = createAsyncComponent(() => import('./SessionModal.vue'));
const emits = defineEmits(['change']); const emits = defineEmits(['change']);
@ -146,6 +154,7 @@
const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit: emits }); const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit: emits });
const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef); const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef);
const [registerClaimModal, { openModal: openClaimModal }] = useModal(); const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerSessionModal, { openModal: openSessionModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] = useModal(); const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] = useModal();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal(); const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
@ -188,4 +197,8 @@
function handleShowClaims(record) { function handleShowClaims(record) {
openClaimModal(true, { id: record.id }); openClaimModal(true, { id: record.id });
} }
function handleShowSessionModal(record) {
openSessionModal(true, { userId: record.id });
}
</script> </script>

1
apps/vue/types/abp.d.ts

@ -110,6 +110,7 @@ declare interface CurrentUser {
phoneNumber?: string; phoneNumber?: string;
phoneNumberVerified: boolean; phoneNumberVerified: boolean;
roles: string[]; roles: string[];
sessionId?: string;
} }
type SimpleStateCheckerResult<TState extends IHasSimpleStateCheckers<TState>> = Recordable< type SimpleStateCheckerResult<TState extends IHasSimpleStateCheckers<TState>> = Recordable<

248
aspnet-core/LINGYUN.MicroService.All.sln

@ -742,73 +742,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.OpenIdd
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Scriban", "modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj", "{15482834-9242-4D20-9736-9DA571A9A83A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Scriban", "modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj", "{15482834-9242-4D20-9736-9DA571A9A83A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{8A255A72-50FC-460E-9897-FA53F455580B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{8A255A72-50FC-460E-9897-FA53F455580B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.Common", "framework\wechat\LINGYUN.Abp.WeChat.Work.Common\LINGYUN.Abp.WeChat.Work.Common.csproj", "{46038910-8EDD-4822-8768-097B7D276FED}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Common", "framework\wechat\LINGYUN.Abp.WeChat.Work.Common\LINGYUN.Abp.WeChat.Work.Common.csproj", "{CED33625-A034-475B-A4C0-A4E7D1BADD10}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Domain.Shared", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain.Shared\LINGYUN.Abp.TaskManagement.Domain.Shared.csproj", "{332F2031-6B67-4199-8BA4-317679D2FFF8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session", "modules\identity\LINGYUN.Abp.Identity.Session\LINGYUN.Abp.Identity.Session.csproj", "{E3BA2413-5755-4F61-9A7C-5D49AE9E7016}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks", "modules\task-management\LINGYUN.Abp.BackgroundTasks\LINGYUN.Abp.BackgroundTasks.csproj", "{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session.AspNetCore", "modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj", "{BF85DB7F-70C2-4804-AA57-FACE204981DA}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Quartz", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Quartz\LINGYUN.Abp.BackgroundTasks.Quartz.csproj", "{FF53669D-560C-4791-BE9A-28231C15FA4E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Session", "modules\identityServer\LINGYUN.Abp.IdentityServer.Session\LINGYUN.Abp.IdentityServer.Session.csproj", "{893F7376-0913-43DC-AD3D-40AF5B8F9E3B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.DistributedLocking", "modules\task-management\LINGYUN.Abp.BackgroundTasks.DistributedLocking\LINGYUN.Abp.BackgroundTasks.DistributedLocking.csproj", "{2F8BB49E-92E5-4468-8656-BD4BC03FA505}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.AspNetCore.Session", "modules\identity\LINGYUN.Abp.Identity.AspNetCore.Session\LINGYUN.Abp.Identity.AspNetCore.Session.csproj", "{8826831D-8733-473A-B47B-A30C3732B13D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.ExceptionHandling", "modules\task-management\LINGYUN.Abp.BackgroundTasks.ExceptionHandling\LINGYUN.Abp.BackgroundTasks.ExceptionHandling.csproj", "{5CAC42F1-58A4-4716-B8E5-E28042D1B612}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.AspNetCore.Session", "modules\openIddict\LINGYUN.Abp.OpenIddict.AspNetCore.Session\LINGYUN.Abp.OpenIddict.AspNetCore.Session.csproj", "{D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.EntityFrameworkCore", "modules\task-management\LINGYUN.Abp.TaskManagement.EntityFrameworkCore\LINGYUN.Abp.TaskManagement.EntityFrameworkCore.csproj", "{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Notifications", "modules\identity\LINGYUN.Abp.Identity.Notifications\LINGYUN.Abp.Identity.Notifications.csproj", "{54BBA043-317B-4A4F-B583-513D08BC25A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Activities", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Activities\LINGYUN.Abp.BackgroundTasks.Activities.csproj", "{F78B0978-4ECF-4EA3-89A7-9492AE33CB30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Domain", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain\LINGYUN.Abp.TaskManagement.Domain.csproj", "{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.Application", "modules\task-management\LINGYUN.Abp.TaskManagement.Application\LINGYUN.Abp.TaskManagement.Application.csproj", "{DC4AB835-76CA-4439-9A14-473B3838F856}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.EventBus", "modules\task-management\LINGYUN.Abp.BackgroundTasks.EventBus\LINGYUN.Abp.BackgroundTasks.EventBus.csproj", "{3310571F-1B30-49A4-AD24-0CF5C91C58F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.HttpApi", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi\LINGYUN.Abp.TaskManagement.HttpApi.csproj", "{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Application.Contracts", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Application.Contracts\LINGYUN.Abp.WebhooksManagement.Application.Contracts.csproj", "{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Application", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Application\LINGYUN.Abp.WebhooksManagement.Application.csproj", "{7D83C686-7BF0-4037-B927-A502D55D01F8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Domain", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Domain\LINGYUN.Abp.WebhooksManagement.Domain.csproj", "{C7F7F9E2-F877-4658-BFEC-E47AE27B0139}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.Domain.Shared", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.Domain.Shared\LINGYUN.Abp.WebhooksManagement.Domain.Shared.csproj", "{2BC04B60-6959-47FF-8860-96AB51986584}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore.csproj", "{1752BAA2-4305-4655-99B4-6832E2CE6CAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.HttpApi", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.HttpApi\LINGYUN.Abp.WebhooksManagement.HttpApi.csproj", "{6F2A09CE-183E-4FBA-BB12-DD6105B90B00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WebhooksManagement.HttpApi.Client", "modules\webhooks\LINGYUN.Abp.WebhooksManagement.HttpApi.Client\LINGYUN.Abp.WebhooksManagement.HttpApi.Client.csproj", "{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.TaskManagement.HttpApi.Host", "services\LY.MicroService.TaskManagement.HttpApi.Host\LY.MicroService.TaskManagement.HttpApi.Host.csproj", "{7D760508-A5A8-44D9-8958-F5AD5F1B7949}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "task", "task", "{C1EFDD32-5524-4DDD-9925-88B6E3530994}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.WebhooksManagement.HttpApi.Host", "services\LY.MicroService.WebhooksManagement.HttpApi.Host\LY.MicroService.WebhooksManagement.HttpApi.Host.csproj", "{2D3B6C77-465E-4D39-A83D-47E74F14D6D0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "webhooks", "webhooks", "{0107020D-22E5-4DDF-8A62-5DE850BA6C79}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.WorkflowManagement.HttpApi.Host", "services\LY.MicroService.WorkflowManagement.HttpApi.Host\LY.MicroService.WorkflowManagement.HttpApi.Host.csproj", "{E8139252-2F6D-437D-97C7-6FB77C705E58}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflow", "workflow", "{74319001-6F4B-41D9-BE32-128EC12AB10B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Notifications", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Notifications\LINGYUN.Abp.BackgroundTasks.Notifications.csproj", "{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.TaskManagement.EntityFrameworkCore", "migrations\LY.MicroService.TaskManagement.EntityFrameworkCore\LY.MicroService.TaskManagement.EntityFrameworkCore.csproj", "{CE309DF2-FB96-4917-9DC6-14DC1DED7EED}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "task", "task", "{A922E0EE-5302-4E2B-9D84-0EC681416DA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.Identity", "modules\webhooks\LINGYUN.Abp.Webhooks.Identity\LINGYUN.Abp.Webhooks.Identity.csproj", "{27505FC3-2659-40CC-A9C7-0857FBECE099}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.Saas", "modules\webhooks\LINGYUN.Abp.Webhooks.Saas\LINGYUN.Abp.Webhooks.Saas.csproj", "{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Webhooks.EventBus", "modules\webhooks\LINGYUN.Abp.Webhooks.EventBus\LINGYUN.Abp.Webhooks.EventBus.csproj", "{65951546-93DB-4415-94C5-2B7B1E232A3E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.WebhooksManagement.EntityFrameworkCore", "migrations\LY.MicroService.WebhooksManagement.EntityFrameworkCore\LY.MicroService.WebhooksManagement.EntityFrameworkCore.csproj", "{E41F9F32-7A18-485D-BAAE-D858F7EE72E7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "webhooks", "webhooks", "{E93F5D2E-14FF-47A0-B899-0E34AFDBCCBD}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -1964,118 +1912,34 @@ Global
{8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.Build.0 = Debug|Any CPU {8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.Build.0 = Release|Any CPU {8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.Build.0 = Release|Any CPU
{46038910-8EDD-4822-8768-097B7D276FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46038910-8EDD-4822-8768-097B7D276FED}.Debug|Any CPU.Build.0 = Debug|Any CPU {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46038910-8EDD-4822-8768-097B7D276FED}.Release|Any CPU.ActiveCfg = Release|Any CPU {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46038910-8EDD-4822-8768-097B7D276FED}.Release|Any CPU.Build.0 = Release|Any CPU {CED33625-A034-475B-A4C0-A4E7D1BADD10}.Release|Any CPU.Build.0 = Release|Any CPU
{332F2031-6B67-4199-8BA4-317679D2FFF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{332F2031-6B67-4199-8BA4-317679D2FFF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Debug|Any CPU.Build.0 = Debug|Any CPU
{332F2031-6B67-4199-8BA4-317679D2FFF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Release|Any CPU.ActiveCfg = Release|Any CPU
{332F2031-6B67-4199-8BA4-317679D2FFF8}.Release|Any CPU.Build.0 = Release|Any CPU {E3BA2413-5755-4F61-9A7C-5D49AE9E7016}.Release|Any CPU.Build.0 = Release|Any CPU
{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306}.Debug|Any CPU.Build.0 = Debug|Any CPU {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306}.Release|Any CPU.ActiveCfg = Release|Any CPU {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306}.Release|Any CPU.Build.0 = Release|Any CPU {BF85DB7F-70C2-4804-AA57-FACE204981DA}.Release|Any CPU.Build.0 = Release|Any CPU
{FF53669D-560C-4791-BE9A-28231C15FA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF53669D-560C-4791-BE9A-28231C15FA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF53669D-560C-4791-BE9A-28231C15FA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF53669D-560C-4791-BE9A-28231C15FA4E}.Release|Any CPU.Build.0 = Release|Any CPU {893F7376-0913-43DC-AD3D-40AF5B8F9E3B}.Release|Any CPU.Build.0 = Release|Any CPU
{2F8BB49E-92E5-4468-8656-BD4BC03FA505}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8826831D-8733-473A-B47B-A30C3732B13D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F8BB49E-92E5-4468-8656-BD4BC03FA505}.Debug|Any CPU.Build.0 = Debug|Any CPU {8826831D-8733-473A-B47B-A30C3732B13D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F8BB49E-92E5-4468-8656-BD4BC03FA505}.Release|Any CPU.ActiveCfg = Release|Any CPU {8826831D-8733-473A-B47B-A30C3732B13D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F8BB49E-92E5-4468-8656-BD4BC03FA505}.Release|Any CPU.Build.0 = Release|Any CPU {8826831D-8733-473A-B47B-A30C3732B13D}.Release|Any CPU.Build.0 = Release|Any CPU
{5CAC42F1-58A4-4716-B8E5-E28042D1B612}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CAC42F1-58A4-4716-B8E5-E28042D1B612}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CAC42F1-58A4-4716-B8E5-E28042D1B612}.Release|Any CPU.ActiveCfg = Release|Any CPU {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CAC42F1-58A4-4716-B8E5-E28042D1B612}.Release|Any CPU.Build.0 = Release|Any CPU {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72}.Release|Any CPU.Build.0 = Release|Any CPU
{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {54BBA043-317B-4A4F-B583-513D08BC25A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU {54BBA043-317B-4A4F-B583-513D08BC25A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU {54BBA043-317B-4A4F-B583-513D08BC25A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A}.Release|Any CPU.Build.0 = Release|Any CPU {54BBA043-317B-4A4F-B583-513D08BC25A7}.Release|Any CPU.Build.0 = Release|Any CPU
{F78B0978-4ECF-4EA3-89A7-9492AE33CB30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F78B0978-4ECF-4EA3-89A7-9492AE33CB30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F78B0978-4ECF-4EA3-89A7-9492AE33CB30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F78B0978-4ECF-4EA3-89A7-9492AE33CB30}.Release|Any CPU.Build.0 = Release|Any CPU
{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02}.Release|Any CPU.Build.0 = Release|Any CPU
{DC4AB835-76CA-4439-9A14-473B3838F856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC4AB835-76CA-4439-9A14-473B3838F856}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC4AB835-76CA-4439-9A14-473B3838F856}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC4AB835-76CA-4439-9A14-473B3838F856}.Release|Any CPU.Build.0 = Release|Any CPU
{3310571F-1B30-49A4-AD24-0CF5C91C58F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3310571F-1B30-49A4-AD24-0CF5C91C58F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3310571F-1B30-49A4-AD24-0CF5C91C58F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3310571F-1B30-49A4-AD24-0CF5C91C58F7}.Release|Any CPU.Build.0 = Release|Any CPU
{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D}.Release|Any CPU.Build.0 = Release|Any CPU
{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A}.Release|Any CPU.Build.0 = Release|Any CPU
{7D83C686-7BF0-4037-B927-A502D55D01F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D83C686-7BF0-4037-B927-A502D55D01F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D83C686-7BF0-4037-B927-A502D55D01F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D83C686-7BF0-4037-B927-A502D55D01F8}.Release|Any CPU.Build.0 = Release|Any CPU
{C7F7F9E2-F877-4658-BFEC-E47AE27B0139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7F7F9E2-F877-4658-BFEC-E47AE27B0139}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7F7F9E2-F877-4658-BFEC-E47AE27B0139}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7F7F9E2-F877-4658-BFEC-E47AE27B0139}.Release|Any CPU.Build.0 = Release|Any CPU
{2BC04B60-6959-47FF-8860-96AB51986584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BC04B60-6959-47FF-8860-96AB51986584}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BC04B60-6959-47FF-8860-96AB51986584}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BC04B60-6959-47FF-8860-96AB51986584}.Release|Any CPU.Build.0 = Release|Any CPU
{1752BAA2-4305-4655-99B4-6832E2CE6CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1752BAA2-4305-4655-99B4-6832E2CE6CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1752BAA2-4305-4655-99B4-6832E2CE6CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1752BAA2-4305-4655-99B4-6832E2CE6CAF}.Release|Any CPU.Build.0 = Release|Any CPU
{6F2A09CE-183E-4FBA-BB12-DD6105B90B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F2A09CE-183E-4FBA-BB12-DD6105B90B00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F2A09CE-183E-4FBA-BB12-DD6105B90B00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F2A09CE-183E-4FBA-BB12-DD6105B90B00}.Release|Any CPU.Build.0 = Release|Any CPU
{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80}.Release|Any CPU.Build.0 = Release|Any CPU
{7D760508-A5A8-44D9-8958-F5AD5F1B7949}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D760508-A5A8-44D9-8958-F5AD5F1B7949}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D760508-A5A8-44D9-8958-F5AD5F1B7949}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D760508-A5A8-44D9-8958-F5AD5F1B7949}.Release|Any CPU.Build.0 = Release|Any CPU
{2D3B6C77-465E-4D39-A83D-47E74F14D6D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D3B6C77-465E-4D39-A83D-47E74F14D6D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D3B6C77-465E-4D39-A83D-47E74F14D6D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D3B6C77-465E-4D39-A83D-47E74F14D6D0}.Release|Any CPU.Build.0 = Release|Any CPU
{E8139252-2F6D-437D-97C7-6FB77C705E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8139252-2F6D-437D-97C7-6FB77C705E58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8139252-2F6D-437D-97C7-6FB77C705E58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8139252-2F6D-437D-97C7-6FB77C705E58}.Release|Any CPU.Build.0 = Release|Any CPU
{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007}.Release|Any CPU.Build.0 = Release|Any CPU
{CE309DF2-FB96-4917-9DC6-14DC1DED7EED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE309DF2-FB96-4917-9DC6-14DC1DED7EED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE309DF2-FB96-4917-9DC6-14DC1DED7EED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE309DF2-FB96-4917-9DC6-14DC1DED7EED}.Release|Any CPU.Build.0 = Release|Any CPU
{27505FC3-2659-40CC-A9C7-0857FBECE099}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27505FC3-2659-40CC-A9C7-0857FBECE099}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27505FC3-2659-40CC-A9C7-0857FBECE099}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27505FC3-2659-40CC-A9C7-0857FBECE099}.Release|Any CPU.Build.0 = Release|Any CPU
{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D}.Release|Any CPU.Build.0 = Release|Any CPU
{65951546-93DB-4415-94C5-2B7B1E232A3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65951546-93DB-4415-94C5-2B7B1E232A3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65951546-93DB-4415-94C5-2B7B1E232A3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65951546-93DB-4415-94C5-2B7B1E232A3E}.Release|Any CPU.Build.0 = Release|Any CPU
{E41F9F32-7A18-485D-BAAE-D858F7EE72E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E41F9F32-7A18-485D-BAAE-D858F7EE72E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E41F9F32-7A18-485D-BAAE-D858F7EE72E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E41F9F32-7A18-485D-BAAE-D858F7EE72E7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -2435,39 +2299,13 @@ Global
{ED3DF100-C5DB-4334-A847-118922B28D95} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} {ED3DF100-C5DB-4334-A847-118922B28D95} = {3C7A8246-DE82-4330-8697-24EF1B1C515D}
{15482834-9242-4D20-9736-9DA571A9A83A} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} {15482834-9242-4D20-9736-9DA571A9A83A} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F}
{8A255A72-50FC-460E-9897-FA53F455580B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37} {8A255A72-50FC-460E-9897-FA53F455580B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37}
{46038910-8EDD-4822-8768-097B7D276FED} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21} {CED33625-A034-475B-A4C0-A4E7D1BADD10} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21}
{332F2031-6B67-4199-8BA4-317679D2FFF8} = {77ED7922-BF30-4436-8A85-78F812583913} {E3BA2413-5755-4F61-9A7C-5D49AE9E7016} = {52B5D4F7-237B-4E0A-A167-68442164F70A}
{C8138D8C-BF2B-41CB-BEA2-3ACC5E70E306} = {77ED7922-BF30-4436-8A85-78F812583913} {BF85DB7F-70C2-4804-AA57-FACE204981DA} = {52B5D4F7-237B-4E0A-A167-68442164F70A}
{FF53669D-560C-4791-BE9A-28231C15FA4E} = {77ED7922-BF30-4436-8A85-78F812583913} {893F7376-0913-43DC-AD3D-40AF5B8F9E3B} = {0439B173-F41E-4CE0-A44A-CCB70328F272}
{2F8BB49E-92E5-4468-8656-BD4BC03FA505} = {77ED7922-BF30-4436-8A85-78F812583913} {8826831D-8733-473A-B47B-A30C3732B13D} = {52B5D4F7-237B-4E0A-A167-68442164F70A}
{5CAC42F1-58A4-4716-B8E5-E28042D1B612} = {77ED7922-BF30-4436-8A85-78F812583913} {D1484DD3-BB0A-45A4-BED5-FFA132DE2E72} = {83E698F6-F8CD-4604-AB80-01A203389501}
{7D235CB7-EC8E-418F-978A-D2E6EA5F9E9A} = {77ED7922-BF30-4436-8A85-78F812583913} {54BBA043-317B-4A4F-B583-513D08BC25A7} = {52B5D4F7-237B-4E0A-A167-68442164F70A}
{F78B0978-4ECF-4EA3-89A7-9492AE33CB30} = {77ED7922-BF30-4436-8A85-78F812583913}
{7C1A3331-D3D0-4CF0-A7D4-9E27F507AB02} = {77ED7922-BF30-4436-8A85-78F812583913}
{DC4AB835-76CA-4439-9A14-473B3838F856} = {77ED7922-BF30-4436-8A85-78F812583913}
{3310571F-1B30-49A4-AD24-0CF5C91C58F7} = {77ED7922-BF30-4436-8A85-78F812583913}
{00C8A2BC-361D-4999-AEC3-BA4DD7991A9D} = {77ED7922-BF30-4436-8A85-78F812583913}
{D60CF8FB-45BB-4F95-97EB-E1CE54B3105A} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{7D83C686-7BF0-4037-B927-A502D55D01F8} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{C7F7F9E2-F877-4658-BFEC-E47AE27B0139} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{2BC04B60-6959-47FF-8860-96AB51986584} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{1752BAA2-4305-4655-99B4-6832E2CE6CAF} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{6F2A09CE-183E-4FBA-BB12-DD6105B90B00} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{5E3E2B57-4BF1-45A7-9BAE-EDA000F27C80} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{C1EFDD32-5524-4DDD-9925-88B6E3530994} = {672E1170-7B18-474B-85C7-1961BF2A48AE}
{7D760508-A5A8-44D9-8958-F5AD5F1B7949} = {C1EFDD32-5524-4DDD-9925-88B6E3530994}
{0107020D-22E5-4DDF-8A62-5DE850BA6C79} = {672E1170-7B18-474B-85C7-1961BF2A48AE}
{74319001-6F4B-41D9-BE32-128EC12AB10B} = {672E1170-7B18-474B-85C7-1961BF2A48AE}
{2D3B6C77-465E-4D39-A83D-47E74F14D6D0} = {0107020D-22E5-4DDF-8A62-5DE850BA6C79}
{E8139252-2F6D-437D-97C7-6FB77C705E58} = {74319001-6F4B-41D9-BE32-128EC12AB10B}
{40FEF2F7-BB0E-4192-89EE-BDA98B3E4007} = {77ED7922-BF30-4436-8A85-78F812583913}
{A922E0EE-5302-4E2B-9D84-0EC681416DA2} = {C90A505F-000E-4AE4-8CCD-AB5FE5092B5C}
{CE309DF2-FB96-4917-9DC6-14DC1DED7EED} = {A922E0EE-5302-4E2B-9D84-0EC681416DA2}
{27505FC3-2659-40CC-A9C7-0857FBECE099} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{1E6F9CF8-577C-45A7-A2E0-2BB3C40AFB9D} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{65951546-93DB-4415-94C5-2B7B1E232A3E} = {13ACF670-F109-404E-B252-2FA34A4EA061}
{E93F5D2E-14FF-47A0-B899-0E34AFDBCCBD} = {C90A505F-000E-4AE4-8CCD-AB5FE5092B5C}
{E41F9F32-7A18-485D-BAAE-D858F7EE72E7} = {E93F5D2E-14FF-47A0-B899-0E34AFDBCCBD}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}

63
aspnet-core/LINGYUN.MicroService.SingleProject.sln

@ -515,6 +515,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Jobs", "modules\saas\LINGYUN.Abp.Saas.Jobs\LINGYUN.Abp.Saas.Jobs.csproj", "{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Saas.Jobs", "modules\saas\LINGYUN.Abp.Saas.Jobs\LINGYUN.Abp.Saas.Jobs.csproj", "{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.SmsValidator", "modules\identityServer\LINGYUN.Abp.IdentityServer.SmsValidator\LINGYUN.Abp.IdentityServer.SmsValidator.csproj", "{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Portal", "modules\identityServer\LINGYUN.Abp.IdentityServer.Portal\LINGYUN.Abp.IdentityServer.Portal.csproj", "{986B92F6-A758-4D1F-8BC7-BFD13FF38591}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.WeChat.Work", "modules\identityServer\LINGYUN.Abp.IdentityServer.WeChat.Work\LINGYUN.Abp.IdentityServer.WeChat.Work.csproj", "{62D72C3E-5C57-439D-B7F7-5C55CC384A7A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session", "modules\identity\LINGYUN.Abp.Identity.Session\LINGYUN.Abp.Identity.Session.csproj", "{74156CFF-C236-4DED-B810-FAD8948F51CA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session.AspNetCore", "modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj", "{63D08153-B43C-4884-8818-4AB42E1FEE75}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.AspNetCore.Session", "modules\identity\LINGYUN.Abp.Identity.AspNetCore.Session\LINGYUN.Abp.Identity.AspNetCore.Session.csproj", "{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Session", "modules\identityServer\LINGYUN.Abp.IdentityServer.Session\LINGYUN.Abp.IdentityServer.Session.csproj", "{F7459720-873C-4741-A991-A671CF03A6AF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.AspNetCore.Session", "modules\openIddict\LINGYUN.Abp.OpenIddict.AspNetCore.Session\LINGYUN.Abp.OpenIddict.AspNetCore.Session.csproj", "{382CAC43-EE1F-4DA3-B433-E23C3F58F44A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Notifications", "modules\identity\LINGYUN.Abp.Identity.Notifications\LINGYUN.Abp.Identity.Notifications.csproj", "{4634B421-36E6-4169-AA1A-11050902495F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1349,6 +1367,42 @@ Global
{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Release|Any CPU.ActiveCfg = Release|Any CPU {8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Release|Any CPU.Build.0 = Release|Any CPU {8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3}.Release|Any CPU.Build.0 = Release|Any CPU
{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F}.Release|Any CPU.Build.0 = Release|Any CPU
{986B92F6-A758-4D1F-8BC7-BFD13FF38591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{986B92F6-A758-4D1F-8BC7-BFD13FF38591}.Debug|Any CPU.Build.0 = Debug|Any CPU
{986B92F6-A758-4D1F-8BC7-BFD13FF38591}.Release|Any CPU.ActiveCfg = Release|Any CPU
{986B92F6-A758-4D1F-8BC7-BFD13FF38591}.Release|Any CPU.Build.0 = Release|Any CPU
{62D72C3E-5C57-439D-B7F7-5C55CC384A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62D72C3E-5C57-439D-B7F7-5C55CC384A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62D72C3E-5C57-439D-B7F7-5C55CC384A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62D72C3E-5C57-439D-B7F7-5C55CC384A7A}.Release|Any CPU.Build.0 = Release|Any CPU
{74156CFF-C236-4DED-B810-FAD8948F51CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74156CFF-C236-4DED-B810-FAD8948F51CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74156CFF-C236-4DED-B810-FAD8948F51CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74156CFF-C236-4DED-B810-FAD8948F51CA}.Release|Any CPU.Build.0 = Release|Any CPU
{63D08153-B43C-4884-8818-4AB42E1FEE75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D08153-B43C-4884-8818-4AB42E1FEE75}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63D08153-B43C-4884-8818-4AB42E1FEE75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63D08153-B43C-4884-8818-4AB42E1FEE75}.Release|Any CPU.Build.0 = Release|Any CPU
{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE}.Release|Any CPU.Build.0 = Release|Any CPU
{F7459720-873C-4741-A991-A671CF03A6AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7459720-873C-4741-A991-A671CF03A6AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7459720-873C-4741-A991-A671CF03A6AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7459720-873C-4741-A991-A671CF03A6AF}.Release|Any CPU.Build.0 = Release|Any CPU
{382CAC43-EE1F-4DA3-B433-E23C3F58F44A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{382CAC43-EE1F-4DA3-B433-E23C3F58F44A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{382CAC43-EE1F-4DA3-B433-E23C3F58F44A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{382CAC43-EE1F-4DA3-B433-E23C3F58F44A}.Release|Any CPU.Build.0 = Release|Any CPU
{4634B421-36E6-4169-AA1A-11050902495F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4634B421-36E6-4169-AA1A-11050902495F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4634B421-36E6-4169-AA1A-11050902495F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4634B421-36E6-4169-AA1A-11050902495F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1600,6 +1654,15 @@ Global
{66A6E78D-E547-4DD7-9844-087FAB3D03C2} = {C22741F9-FC56-4AE3-B543-9F15C779D345} {66A6E78D-E547-4DD7-9844-087FAB3D03C2} = {C22741F9-FC56-4AE3-B543-9F15C779D345}
{A99F5406-37DC-4677-9166-9BDE90C26CA6} = {D9C65C9D-8591-46DA-A3EE-419393E607AB} {A99F5406-37DC-4677-9166-9BDE90C26CA6} = {D9C65C9D-8591-46DA-A3EE-419393E607AB}
{8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3} = {0DF5AD76-AEEA-4052-A6CA-A44C24879F11} {8FA3ED81-19AB-4E0C-B36A-DF49131A2AB3} = {0DF5AD76-AEEA-4052-A6CA-A44C24879F11}
{7C1A8FF7-9FD1-41FC-856D-7A2DC6F7CE6F} = {A3B6DFC3-5D27-496E-9AD6-C1035213F1DC}
{986B92F6-A758-4D1F-8BC7-BFD13FF38591} = {A3B6DFC3-5D27-496E-9AD6-C1035213F1DC}
{62D72C3E-5C57-439D-B7F7-5C55CC384A7A} = {A3B6DFC3-5D27-496E-9AD6-C1035213F1DC}
{74156CFF-C236-4DED-B810-FAD8948F51CA} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{63D08153-B43C-4884-8818-4AB42E1FEE75} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{AF02868C-283E-4CB2-8866-3B0CAD1BB2DE} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{F7459720-873C-4741-A991-A671CF03A6AF} = {A3B6DFC3-5D27-496E-9AD6-C1035213F1DC}
{382CAC43-EE1F-4DA3-B433-E23C3F58F44A} = {7C714185-D3D9-4D94-B5CB-D857A0091F04}
{4634B421-36E6-4169-AA1A-11050902495F} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1} SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1}

17
aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln

@ -147,6 +147,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Security", "fra
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{047F892F-F8D2-4952-A1E9-93AA2B030F76}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{047F892F-F8D2-4952-A1E9-93AA2B030F76}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{23E99204-F7C1-47BA-84CD-3C9D05210F4F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session", "modules\identity\LINGYUN.Abp.Identity.Session\LINGYUN.Abp.Identity.Session.csproj", "{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session.AspNetCore", "modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj", "{BE58649C-EA57-4DFC-8D25-54FDCB1943A1}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -381,6 +387,14 @@ Global
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Debug|Any CPU.Build.0 = Debug|Any CPU {047F892F-F8D2-4952-A1E9-93AA2B030F76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.ActiveCfg = Release|Any CPU {047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.Build.0 = Release|Any CPU {047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.Build.0 = Release|Any CPU
{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1}.Release|Any CPU.Build.0 = Release|Any CPU
{BE58649C-EA57-4DFC-8D25-54FDCB1943A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE58649C-EA57-4DFC-8D25-54FDCB1943A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE58649C-EA57-4DFC-8D25-54FDCB1943A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE58649C-EA57-4DFC-8D25-54FDCB1943A1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -454,6 +468,9 @@ Global
{0DFDAC71-BCB9-44CF-A44A-E8288E75246F} = {FB7A9794-06D2-42CF-939E-4626497B97BD} {0DFDAC71-BCB9-44CF-A44A-E8288E75246F} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{8F11DADB-557A-4ECF-BEBB-19AFA71998A1} = {FB7A9794-06D2-42CF-939E-4626497B97BD} {8F11DADB-557A-4ECF-BEBB-19AFA71998A1} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{047F892F-F8D2-4952-A1E9-93AA2B030F76} = {FB7A9794-06D2-42CF-939E-4626497B97BD} {047F892F-F8D2-4952-A1E9-93AA2B030F76} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{23E99204-F7C1-47BA-84CD-3C9D05210F4F} = {03B4B0AA-83CE-4E4B-9CE2-47369BF88B97}
{BF298DF5-BC1D-4DDD-A51E-8E9020D2C5F1} = {23E99204-F7C1-47BA-84CD-3C9D05210F4F}
{BE58649C-EA57-4DFC-8D25-54FDCB1943A1} = {23E99204-F7C1-47BA-84CD-3C9D05210F4F}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {80ED12A5-C899-459F-A181-ADCC9D680DE5} SolutionGuid = {80ED12A5-C899-459F-A181-ADCC9D680DE5}

16
aspnet-core/LINGYUN.MicroService.Workflow.sln

@ -165,6 +165,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Security", "fra
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{1859E205-88DC-4E08-A0BD-55A045DCC495}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{1859E205-88DC-4E08-A0BD-55A045DCC495}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{9C73D4E6-4408-4717-B51C-63C20321D4DA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session", "modules\identity\LINGYUN.Abp.Identity.Session\LINGYUN.Abp.Identity.Session.csproj", "{6ECF678D-6F3A-4084-8538-A86C1D67C703}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Session.AspNetCore", "modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj", "{9FB5E943-7F6F-4281-9C00-E76284B4F1F3}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -443,6 +449,14 @@ Global
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Debug|Any CPU.Build.0 = Debug|Any CPU {1859E205-88DC-4E08-A0BD-55A045DCC495}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.ActiveCfg = Release|Any CPU {1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.Build.0 = Release|Any CPU {1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.Build.0 = Release|Any CPU
{6ECF678D-6F3A-4084-8538-A86C1D67C703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6ECF678D-6F3A-4084-8538-A86C1D67C703}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6ECF678D-6F3A-4084-8538-A86C1D67C703}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6ECF678D-6F3A-4084-8538-A86C1D67C703}.Release|Any CPU.Build.0 = Release|Any CPU
{9FB5E943-7F6F-4281-9C00-E76284B4F1F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FB5E943-7F6F-4281-9C00-E76284B4F1F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FB5E943-7F6F-4281-9C00-E76284B4F1F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FB5E943-7F6F-4281-9C00-E76284B4F1F3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -518,6 +532,8 @@ Global
{4D055853-DE80-4145-BB2F-33EB6B379F5E} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {4D055853-DE80-4145-BB2F-33EB6B379F5E} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
{E4783690-052A-4AB0-837E-BDBC77CC7EEC} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {E4783690-052A-4AB0-837E-BDBC77CC7EEC} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
{1859E205-88DC-4E08-A0BD-55A045DCC495} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A} {1859E205-88DC-4E08-A0BD-55A045DCC495} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
{6ECF678D-6F3A-4084-8538-A86C1D67C703} = {9C73D4E6-4408-4717-B51C-63C20321D4DA}
{9FB5E943-7F6F-4281-9C00-E76284B4F1F3} = {9C73D4E6-4408-4717-B51C-63C20321D4DA}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F} SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F}

7
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj

@ -4,7 +4,12 @@
<Import Project="..\..\..\..\common.props" /> <Import Project="..\..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AuditLogging.Elasticsearch</AssemblyName>
<PackageId>LINGYUN.Abp.AuditLogging.Elasticsearch</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

23
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs

@ -3,20 +3,19 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
[DependsOn(
typeof(AbpAuditLoggingModule),
typeof(AbpElasticsearchModule),
typeof(AbpJsonModule))]
public class AbpAuditLoggingElasticsearchModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpAuditLoggingModule),
typeof(AbpElasticsearchModule),
typeof(AbpJsonModule))]
public class AbpAuditLoggingElasticsearchModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) var configuration = context.Services.GetConfiguration();
{ Configure<AbpAuditLoggingElasticsearchOptions>(configuration.GetSection("AuditLogging:Elasticsearch"));
var configuration = context.Services.GetConfiguration();
Configure<AbpAuditLoggingElasticsearchOptions>(configuration.GetSection("AuditLogging:Elasticsearch"));
context.Services.AddHostedService<IndexInitializerService>(); context.Services.AddHostedService<IndexInitializerService>();
}
} }
} }

21
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs

@ -1,17 +1,16 @@
using Nest; using Nest;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class AbpAuditLoggingElasticsearchOptions
{ {
public class AbpAuditLoggingElasticsearchOptions public const string DefaultIndexPrefix = "auditlogging";
{ public string IndexPrefix { get; set; }
public const string DefaultIndexPrefix = "auditlogging"; public IIndexSettings IndexSettings { get; set; }
public string IndexPrefix { get; set; }
public IIndexSettings IndexSettings { get; set; }
public AbpAuditLoggingElasticsearchOptions() public AbpAuditLoggingElasticsearchOptions()
{ {
IndexPrefix = DefaultIndexPrefix; IndexPrefix = DefaultIndexPrefix;
IndexSettings = new IndexSettings(); IndexSettings = new IndexSettings();
}
} }
} }

171
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs

@ -11,105 +11,104 @@ using Volo.Abp.Guids;
using Volo.Abp.Http; using Volo.Abp.Http;
using Volo.Abp.Json; using Volo.Abp.Json;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, ITransientDependency
{ {
public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, ITransientDependency protected IGuidGenerator GuidGenerator { get; }
protected AbpExceptionHandlingOptions ExceptionHandlingOptions { get; }
protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; }
protected IJsonSerializer JsonSerializer { get; }
public AuditLogInfoToAuditLogConverter(
IGuidGenerator guidGenerator,
IOptions<AbpExceptionHandlingOptions> exceptionHandlingOptions,
IExceptionToErrorInfoConverter exceptionToErrorInfoConverter,
IJsonSerializer jsonSerializer)
{ {
protected IGuidGenerator GuidGenerator { get; } GuidGenerator = guidGenerator;
protected AbpExceptionHandlingOptions ExceptionHandlingOptions { get; } ExceptionHandlingOptions = exceptionHandlingOptions.Value;
protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter;
protected IJsonSerializer JsonSerializer { get; } JsonSerializer = jsonSerializer;
}
public AuditLogInfoToAuditLogConverter( public virtual Task<AuditLog> ConvertAsync(AuditLogInfo auditLogInfo)
IGuidGenerator guidGenerator, {
IOptions<AbpExceptionHandlingOptions> exceptionHandlingOptions, var auditLogId = GuidGenerator.Create();
IExceptionToErrorInfoConverter exceptionToErrorInfoConverter,
IJsonSerializer jsonSerializer)
{
GuidGenerator = guidGenerator;
ExceptionHandlingOptions = exceptionHandlingOptions.Value;
ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter;
JsonSerializer = jsonSerializer;
}
public virtual Task<AuditLog> ConvertAsync(AuditLogInfo auditLogInfo) var extraProperties = new ExtraPropertyDictionary();
if (auditLogInfo.ExtraProperties != null)
{ {
var auditLogId = GuidGenerator.Create(); foreach (var pair in auditLogInfo.ExtraProperties)
var extraProperties = new ExtraPropertyDictionary();
if (auditLogInfo.ExtraProperties != null)
{ {
foreach (var pair in auditLogInfo.ExtraProperties) extraProperties.Add(pair.Key, pair.Value);
{
extraProperties.Add(pair.Key, pair.Value);
}
} }
}
var entityChanges = auditLogInfo var entityChanges = auditLogInfo
.EntityChanges? .EntityChanges?
.Select(entityChangeInfo => new EntityChange( .Select(entityChangeInfo => new EntityChange(
GuidGenerator, GuidGenerator,
auditLogId, auditLogId,
entityChangeInfo, entityChangeInfo,
tenantId: auditLogInfo.TenantId, tenantId: auditLogInfo.TenantId,
entityTenantId: entityChangeInfo.EntityTenantId)) entityTenantId: entityChangeInfo.EntityTenantId))
.ToList() .ToList()
?? new List<EntityChange>(); ?? new List<EntityChange>();
var actions = auditLogInfo var actions = auditLogInfo
.Actions? .Actions?
.Select(auditLogActionInfo => new AuditLogAction( .Select(auditLogActionInfo => new AuditLogAction(
GuidGenerator.Create(), GuidGenerator.Create(),
auditLogId, auditLogId,
auditLogActionInfo, auditLogActionInfo,
tenantId: auditLogInfo.TenantId)) tenantId: auditLogInfo.TenantId))
.ToList() .ToList()
?? new List<AuditLogAction>(); ?? new List<AuditLogAction>();
var remoteServiceErrorInfos = auditLogInfo.Exceptions?.Select(exception => var remoteServiceErrorInfos = auditLogInfo.Exceptions?.Select(exception =>
ExceptionToErrorInfoConverter.Convert(exception, options => ExceptionToErrorInfoConverter.Convert(exception, options =>
{ {
options.SendExceptionsDetailsToClients = ExceptionHandlingOptions.SendExceptionsDetailsToClients; options.SendExceptionsDetailsToClients = ExceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = ExceptionHandlingOptions.SendStackTraceToClients; options.SendStackTraceToClients = ExceptionHandlingOptions.SendStackTraceToClients;
})) ?? new List<RemoteServiceErrorInfo>(); })) ?? new List<RemoteServiceErrorInfo>();
var exceptions = remoteServiceErrorInfos.Any() var exceptions = remoteServiceErrorInfos.Any()
? JsonSerializer.Serialize(remoteServiceErrorInfos, indented: true) ? JsonSerializer.Serialize(remoteServiceErrorInfos, indented: true)
: null; : null;
var comments = auditLogInfo var comments = auditLogInfo
.Comments? .Comments?
.JoinAsString(Environment.NewLine); .JoinAsString(Environment.NewLine);
var auditLog = new AuditLog( var auditLog = new AuditLog(
auditLogId, auditLogId,
auditLogInfo.ApplicationName, auditLogInfo.ApplicationName,
auditLogInfo.TenantId, auditLogInfo.TenantId,
auditLogInfo.TenantName, auditLogInfo.TenantName,
auditLogInfo.UserId, auditLogInfo.UserId,
auditLogInfo.UserName, auditLogInfo.UserName,
auditLogInfo.ExecutionTime, auditLogInfo.ExecutionTime,
auditLogInfo.ExecutionDuration, auditLogInfo.ExecutionDuration,
auditLogInfo.ClientIpAddress, auditLogInfo.ClientIpAddress,
auditLogInfo.ClientName, auditLogInfo.ClientName,
auditLogInfo.ClientId, auditLogInfo.ClientId,
auditLogInfo.CorrelationId, auditLogInfo.CorrelationId,
auditLogInfo.BrowserInfo, auditLogInfo.BrowserInfo,
auditLogInfo.HttpMethod, auditLogInfo.HttpMethod,
auditLogInfo.Url, auditLogInfo.Url,
auditLogInfo.HttpStatusCode, auditLogInfo.HttpStatusCode,
auditLogInfo.ImpersonatorUserId, auditLogInfo.ImpersonatorUserId,
auditLogInfo.ImpersonatorUserName, auditLogInfo.ImpersonatorUserName,
auditLogInfo.ImpersonatorTenantId, auditLogInfo.ImpersonatorTenantId,
auditLogInfo.ImpersonatorTenantName, auditLogInfo.ImpersonatorTenantName,
extraProperties, extraProperties,
entityChanges, entityChanges,
actions, actions,
exceptions, exceptions,
comments comments
); );
return Task.FromResult(auditLog); return Task.FromResult(auditLog);
}
} }
} }

633
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs

@ -13,361 +13,360 @@ using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing; using Volo.Abp.Timing;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
[Dependency(ReplaceServices = true)]
public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] private readonly AbpAuditingOptions _auditingOptions;
public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependency private readonly AbpElasticsearchOptions _elasticsearchOptions;
private readonly IIndexNameNormalizer _indexNameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory;
private readonly IAuditLogInfoToAuditLogConverter _converter;
private readonly IClock _clock;
public ILogger<ElasticsearchAuditLogManager> Logger { protected get; set; }
public ElasticsearchAuditLogManager(
IClock clock,
IIndexNameNormalizer indexNameNormalizer,
IOptions<AbpElasticsearchOptions> elasticsearchOptions,
IElasticsearchClientFactory clientFactory,
IOptions<AbpAuditingOptions> auditingOptions,
IAuditLogInfoToAuditLogConverter converter)
{ {
private readonly AbpAuditingOptions _auditingOptions; _clock = clock;
private readonly AbpElasticsearchOptions _elasticsearchOptions; _converter = converter;
private readonly IIndexNameNormalizer _indexNameNormalizer; _clientFactory = clientFactory;
private readonly IElasticsearchClientFactory _clientFactory; _auditingOptions = auditingOptions.Value;
private readonly IAuditLogInfoToAuditLogConverter _converter; _elasticsearchOptions = elasticsearchOptions.Value;
private readonly IClock _clock; _indexNameNormalizer = indexNameNormalizer;
public ILogger<ElasticsearchAuditLogManager> Logger { protected get; set; } Logger = NullLogger<ElasticsearchAuditLogManager>.Instance;
}
public ElasticsearchAuditLogManager(
IClock clock,
IIndexNameNormalizer indexNameNormalizer,
IOptions<AbpElasticsearchOptions> elasticsearchOptions,
IElasticsearchClientFactory clientFactory,
IOptions<AbpAuditingOptions> auditingOptions,
IAuditLogInfoToAuditLogConverter converter)
{
_clock = clock;
_converter = converter;
_clientFactory = clientFactory;
_auditingOptions = auditingOptions.Value;
_elasticsearchOptions = elasticsearchOptions.Value;
_indexNameNormalizer = indexNameNormalizer;
Logger = NullLogger<ElasticsearchAuditLogManager>.Instance;
}
public async virtual Task<long> GetCountAsync( public async virtual Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string httpMethod = null,
string url = null, string url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string applicationName = null, string applicationName = null,
string correlationId = null, string correlationId = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
var client = _clientFactory.Create(); var client = _clientFactory.Create();
var querys = BuildQueryDescriptor( var querys = BuildQueryDescriptor(
startTime, startTime,
endTime, endTime,
httpMethod, httpMethod,
url, url,
userId, userId,
userName, userName,
applicationName, applicationName,
correlationId, correlationId,
clientId, clientId,
clientIpAddress, clientIpAddress,
maxExecutionDuration, maxExecutionDuration,
minExecutionDuration, minExecutionDuration,
hasException, hasException,
httpStatusCode); httpStatusCode);
var response = await client.CountAsync<AuditLog>(dsl => var response = await client.CountAsync<AuditLog>(dsl =>
dsl.Index(CreateIndex()) dsl.Index(CreateIndex())
.Query(log => log.Bool(b => b.Must(querys.ToArray()))), .Query(log => log.Bool(b => b.Must(querys.ToArray()))),
cancellationToken); cancellationToken);
return response.Count; return response.Count;
} }
public async virtual Task<List<AuditLog>> GetListAsync( public async virtual Task<List<AuditLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string httpMethod = null,
string url = null, string url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string applicationName = null, string applicationName = null,
string correlationId = null, string correlationId = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("asc", StringComparison.InvariantCultureIgnoreCase)
? SortOrder.Ascending : SortOrder.Descending;
sorting = !sorting.IsNullOrWhiteSpace()
? sorting.Split()[0]
: nameof(AuditLog.ExecutionTime);
var querys = BuildQueryDescriptor(
startTime,
endTime,
httpMethod,
url,
userId,
userName,
applicationName,
correlationId,
clientId,
clientIpAddress,
maxExecutionDuration,
minExecutionDuration,
hasException,
httpStatusCode);
SourceFilterDescriptor<AuditLog> SourceFilter(SourceFilterDescriptor<AuditLog> selector)
{ {
var client = _clientFactory.Create(); selector.IncludeAll();
if (!includeDetails)
var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("asc", StringComparison.InvariantCultureIgnoreCase)
? SortOrder.Ascending : SortOrder.Descending;
sorting = !sorting.IsNullOrWhiteSpace()
? sorting.Split()[0]
: nameof(AuditLog.ExecutionTime);
var querys = BuildQueryDescriptor(
startTime,
endTime,
httpMethod,
url,
userId,
userName,
applicationName,
correlationId,
clientId,
clientIpAddress,
maxExecutionDuration,
minExecutionDuration,
hasException,
httpStatusCode);
SourceFilterDescriptor<AuditLog> SourceFilter(SourceFilterDescriptor<AuditLog> selector)
{ {
selector.IncludeAll(); selector.Excludes(field =>
if (!includeDetails) field.Field(f => f.Actions)
{ .Field(f => f.Comments)
selector.Excludes(field => .Field(f => f.Exceptions)
field.Field(f => f.Actions) .Field(f => f.EntityChanges));
.Field(f => f.Comments)
.Field(f => f.Exceptions)
.Field(f => f.EntityChanges));
}
return selector;
} }
var response = await client.SearchAsync<AuditLog>(dsl => return selector;
dsl.Index(CreateIndex())
.Query(log => log.Bool(b => b.Must(querys.ToArray())))
.Source(SourceFilter)
.Sort(log => log.Field(GetField(sorting), sortOrder))
.From(skipCount)
.Size(maxResultCount),
cancellationToken);
return response.Documents.ToList();
} }
public async virtual Task<AuditLog> GetAsync( var response = await client.SearchAsync<AuditLog>(dsl =>
Guid id, dsl.Index(CreateIndex())
bool includeDetails = false, .Query(log => log.Bool(b => b.Must(querys.ToArray())))
CancellationToken cancellationToken = default) .Source(SourceFilter)
{ .Sort(log => log.Field(GetField(sorting), sortOrder))
var client = _clientFactory.Create(); .From(skipCount)
.Size(maxResultCount),
cancellationToken);
var response = await client.GetAsync<AuditLog>( return response.Documents.ToList();
id, }
dsl =>
dsl.Index(CreateIndex()),
cancellationToken);
return response.Source; public async virtual Task<AuditLog> GetAsync(
} Guid id,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) var response = await client.GetAsync<AuditLog>(
{ id,
var client = _clientFactory.Create(); dsl =>
dsl.Index(CreateIndex()),
cancellationToken);
await client.DeleteAsync<AuditLog>( return response.Source;
id, }
dsl =>
dsl.Index(CreateIndex()),
cancellationToken);
}
public async virtual Task<string> SaveAsync( public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
AuditLogInfo auditInfo, {
CancellationToken cancellationToken = default(CancellationToken)) var client = _clientFactory.Create();
{
if (!_auditingOptions.HideErrors)
{
return await SaveLogAsync(auditInfo, cancellationToken);
}
try await client.DeleteAsync<AuditLog>(
{ id,
return await SaveLogAsync(auditInfo, cancellationToken); dsl =>
} dsl.Index(CreateIndex()),
catch (Exception ex) cancellationToken);
{ }
Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString());
Logger.LogException(ex, Microsoft.Extensions.Logging.LogLevel.Error); public async virtual Task<string> SaveAsync(
} AuditLogInfo auditInfo,
return ""; CancellationToken cancellationToken = default)
{
if (!_auditingOptions.HideErrors)
{
return await SaveLogAsync(auditInfo, cancellationToken);
} }
protected async virtual Task<string> SaveLogAsync( try
AuditLogInfo auditLogInfo,
CancellationToken cancellationToken = default(CancellationToken))
{ {
var client = _clientFactory.Create(); return await SaveLogAsync(auditInfo, cancellationToken);
}
catch (Exception ex)
{
Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString());
Logger.LogException(ex, Microsoft.Extensions.Logging.LogLevel.Error);
}
return "";
}
var auditLog = await _converter.ConvertAsync(auditLogInfo); protected async virtual Task<string> SaveLogAsync(
AuditLogInfo auditLogInfo,
CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
//var response = await client.IndexAsync( var auditLog = await _converter.ConvertAsync(auditLogInfo);
// auditLog,
// (x) => x.Index(CreateIndex())
// .Id(auditLog.Id),
// cancellationToken);
// 使用 Bulk 命令传输可能存在参数庞大的日志结构 //var response = await client.IndexAsync(
var response = await client.BulkAsync( // auditLog,
dsl => dsl.Index(CreateIndex()) // (x) => x.Index(CreateIndex())
.Create<AuditLog>(ct => // .Id(auditLog.Id),
ct.Id(auditLog.Id) // cancellationToken);
.Document(auditLog)));
return response.Items?.FirstOrDefault()?.Id; // 使用 Bulk 命令传输可能存在参数庞大的日志结构
} var response = await client.BulkAsync(
dsl => dsl.Index(CreateIndex())
.Create<AuditLog>(ct =>
ct.Id(auditLog.Id)
.Document(auditLog)));
protected virtual List<Func<QueryContainerDescriptor<AuditLog>, QueryContainer>> BuildQueryDescriptor( return response.Items?.FirstOrDefault()?.Id;
DateTime? startTime = null, }
DateTime? endTime = null,
string httpMethod = null,
string url = null,
Guid? userId = null,
string userName = null,
string applicationName = null,
string correlationId = null,
string clientId = null,
string clientIpAddress = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null)
{
var querys = new List<Func<QueryContainerDescriptor<AuditLog>, QueryContainer>>();
if (startTime.HasValue) protected virtual List<Func<QueryContainerDescriptor<AuditLog>, QueryContainer>> BuildQueryDescriptor(
{ DateTime? startTime = null,
querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(AuditLog.ExecutionTime))).GreaterThanOrEquals(_clock.Normalize(startTime.Value)))); DateTime? endTime = null,
} string httpMethod = null,
if (endTime.HasValue) string url = null,
{ Guid? userId = null,
querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(AuditLog.ExecutionTime))).LessThanOrEquals(_clock.Normalize(endTime.Value)))); string userName = null,
} string applicationName = null,
if (!httpMethod.IsNullOrWhiteSpace()) string correlationId = null,
{ string clientId = null,
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.HttpMethod))).Value(httpMethod))); string clientIpAddress = null,
} int? maxExecutionDuration = null,
if (!url.IsNullOrWhiteSpace()) int? minExecutionDuration = null,
{ bool? hasException = null,
querys.Add((log) => log.Wildcard((q) => q.Field(GetField(nameof(AuditLog.Url))).Value($"*{url}*"))); HttpStatusCode? httpStatusCode = null)
} {
if (userId.HasValue) var querys = new List<Func<QueryContainerDescriptor<AuditLog>, QueryContainer>>();
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.UserId))).Value(userId))); if (startTime.HasValue)
} {
if (!userName.IsNullOrWhiteSpace()) querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(AuditLog.ExecutionTime))).GreaterThanOrEquals(_clock.Normalize(startTime.Value))));
{ }
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.UserName))).Value(userName))); if (endTime.HasValue)
} {
if (!applicationName.IsNullOrWhiteSpace()) querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(AuditLog.ExecutionTime))).LessThanOrEquals(_clock.Normalize(endTime.Value))));
{ }
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ApplicationName))).Value(applicationName))); if (!httpMethod.IsNullOrWhiteSpace())
} {
if (!correlationId.IsNullOrWhiteSpace()) querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.HttpMethod))).Value(httpMethod)));
{ }
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.CorrelationId))).Value(correlationId))); if (!url.IsNullOrWhiteSpace())
} {
if (!clientId.IsNullOrWhiteSpace()) querys.Add((log) => log.Wildcard((q) => q.Field(GetField(nameof(AuditLog.Url))).Value($"*{url}*")));
{ }
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ClientId))).Value(clientId))); if (userId.HasValue)
} {
if (!clientIpAddress.IsNullOrWhiteSpace()) querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.UserId))).Value(userId)));
{ }
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ClientIpAddress))).Value(clientIpAddress))); if (!userName.IsNullOrWhiteSpace())
} {
if (maxExecutionDuration.HasValue) querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.UserName))).Value(userName)));
{ }
querys.Add((log) => log.Range((q) => q.Field(GetField(nameof(AuditLog.ExecutionDuration))).LessThanOrEquals(maxExecutionDuration))); if (!applicationName.IsNullOrWhiteSpace())
} {
if (minExecutionDuration.HasValue) querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ApplicationName))).Value(applicationName)));
{ }
querys.Add((log) => log.Range((q) => q.Field(GetField(nameof(AuditLog.ExecutionDuration))).GreaterThanOrEquals(minExecutionDuration))); if (!correlationId.IsNullOrWhiteSpace())
} {
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.CorrelationId))).Value(correlationId)));
}
if (!clientId.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ClientId))).Value(clientId)));
}
if (!clientIpAddress.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.ClientIpAddress))).Value(clientIpAddress)));
}
if (maxExecutionDuration.HasValue)
{
querys.Add((log) => log.Range((q) => q.Field(GetField(nameof(AuditLog.ExecutionDuration))).LessThanOrEquals(maxExecutionDuration)));
}
if (minExecutionDuration.HasValue)
{
querys.Add((log) => log.Range((q) => q.Field(GetField(nameof(AuditLog.ExecutionDuration))).GreaterThanOrEquals(minExecutionDuration)));
}
if (hasException.HasValue) if (hasException.HasValue)
{
if (hasException.Value)
{ {
if (hasException.Value) querys.Add(
{ (q) => q.Bool(
querys.Add( (b) => b.Must(
(q) => q.Bool( (m) => m.Exists(
(b) => b.Must( (e) => e.Field((f) => f.Exceptions)))
(m) => m.Exists( )
(e) => e.Field((f) => f.Exceptions))) );
)
);
}
else
{
querys.Add(
(q) => q.Bool(
(b) => b.MustNot(
(mn) => mn.Exists(
(e) => e.Field(
(f) => f.Exceptions)))
)
);
}
} }
else
if (httpStatusCode.HasValue)
{ {
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.HttpStatusCode))).Value(httpStatusCode))); querys.Add(
(q) => q.Bool(
(b) => b.MustNot(
(mn) => mn.Exists(
(e) => e.Field(
(f) => f.Exceptions)))
)
);
} }
return querys;
} }
protected virtual string CreateIndex() if (httpStatusCode.HasValue)
{ {
return _indexNameNormalizer.NormalizeIndex("audit-log"); querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(AuditLog.HttpStatusCode))).Value(httpStatusCode)));
} }
private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) return querys;
{ }
{ "Id", "Id.keyword" },
{ "ApplicationName", "ApplicationName.keyword" }, protected virtual string CreateIndex()
{ "UserId", "UserId.keyword" }, {
{ "UserName", "UserName.keyword" }, return _indexNameNormalizer.NormalizeIndex("audit-log");
{ "TenantId", "TenantId.keyword" }, }
{ "TenantName", "TenantName.keyword" },
{ "ImpersonatorUserId", "ImpersonatorUserId.keyword" },
{ "ImpersonatorTenantId", "ImpersonatorTenantId.keyword" },
{ "ClientName", "ClientName.keyword" },
{ "ClientIpAddress", "ClientIpAddress.keyword" },
{ "ClientId", "ClientId.keyword" },
{ "CorrelationId", "CorrelationId.keyword" },
{ "BrowserInfo", "BrowserInfo.keyword" },
{ "HttpMethod", "HttpMethod.keyword" },
{ "Url", "Url.keyword" },
{ "ExecutionDuration", "ExecutionDuration" },
{ "ExecutionTime", "ExecutionTime" },
{ "HttpStatusCode", "HttpStatusCode" },
};
protected virtual string GetField(string field)
{
if (_fieldMaps.TryGetValue(field, out string mapField))
{
return _elasticsearchOptions.FieldCamelCase ? mapField.ToCamelCase() : mapField.ToPascalCase();
}
return _elasticsearchOptions.FieldCamelCase ? field.ToCamelCase() : field.ToPascalCase(); private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{ "Id", "Id.keyword" },
{ "ApplicationName", "ApplicationName.keyword" },
{ "UserId", "UserId.keyword" },
{ "UserName", "UserName.keyword" },
{ "TenantId", "TenantId.keyword" },
{ "TenantName", "TenantName.keyword" },
{ "ImpersonatorUserId", "ImpersonatorUserId.keyword" },
{ "ImpersonatorTenantId", "ImpersonatorTenantId.keyword" },
{ "ClientName", "ClientName.keyword" },
{ "ClientIpAddress", "ClientIpAddress.keyword" },
{ "ClientId", "ClientId.keyword" },
{ "CorrelationId", "CorrelationId.keyword" },
{ "BrowserInfo", "BrowserInfo.keyword" },
{ "HttpMethod", "HttpMethod.keyword" },
{ "Url", "Url.keyword" },
{ "ExecutionDuration", "ExecutionDuration" },
{ "ExecutionTime", "ExecutionTime" },
{ "HttpStatusCode", "HttpStatusCode" },
};
protected virtual string GetField(string field)
{
if (_fieldMaps.TryGetValue(field, out string mapField))
{
return _elasticsearchOptions.FieldCamelCase ? mapField.ToCamelCase() : mapField.ToPascalCase();
} }
return _elasticsearchOptions.FieldCamelCase ? field.ToCamelCase() : field.ToPascalCase();
} }
} }

441
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs

@ -13,260 +13,259 @@ using Volo.Abp.Guids;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
using Volo.Abp.Timing; using Volo.Abp.Timing;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
[Dependency(ReplaceServices = true)]
public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] private readonly AbpSecurityLogOptions _securityLogOptions;
public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDependency private readonly AbpElasticsearchOptions _elasticsearchOptions;
private readonly IIndexNameNormalizer _indexNameNormalizer;
private readonly IGuidGenerator _guidGenerator;
private readonly IElasticsearchClientFactory _clientFactory;
private readonly IClock _clock;
public ILogger<ElasticsearchSecurityLogManager> Logger { protected get; set; }
public ElasticsearchSecurityLogManager(
IClock clock,
IGuidGenerator guidGenerator,
IIndexNameNormalizer indexNameNormalizer,
IOptions<AbpSecurityLogOptions> securityLogOptions,
IOptions<AbpElasticsearchOptions> elasticsearchOptions,
IElasticsearchClientFactory clientFactory)
{ {
private readonly AbpSecurityLogOptions _securityLogOptions; _clock = clock;
private readonly AbpElasticsearchOptions _elasticsearchOptions; _guidGenerator = guidGenerator;
private readonly IIndexNameNormalizer _indexNameNormalizer; _clientFactory = clientFactory;
private readonly IGuidGenerator _guidGenerator; _indexNameNormalizer = indexNameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory; _securityLogOptions = securityLogOptions.Value;
private readonly IClock _clock; _elasticsearchOptions = elasticsearchOptions.Value;
public ILogger<ElasticsearchSecurityLogManager> Logger { protected get; set; } Logger = NullLogger<ElasticsearchSecurityLogManager>.Instance;
}
public ElasticsearchSecurityLogManager( public async virtual Task SaveAsync(
IClock clock, SecurityLogInfo securityLogInfo,
IGuidGenerator guidGenerator, CancellationToken cancellationToken = default)
IIndexNameNormalizer indexNameNormalizer, {
IOptions<AbpSecurityLogOptions> securityLogOptions, // TODO: 框架不把这玩意儿放在 ISecurityLogManager?
IOptions<AbpElasticsearchOptions> elasticsearchOptions, if (!_securityLogOptions.IsEnabled)
IElasticsearchClientFactory clientFactory)
{ {
_clock = clock; return;
_guidGenerator = guidGenerator;
_clientFactory = clientFactory;
_indexNameNormalizer = indexNameNormalizer;
_securityLogOptions = securityLogOptions.Value;
_elasticsearchOptions = elasticsearchOptions.Value;
Logger = NullLogger<ElasticsearchSecurityLogManager>.Instance;
} }
public async virtual Task SaveAsync( var client = _clientFactory.Create();
SecurityLogInfo securityLogInfo,
CancellationToken cancellationToken = default(CancellationToken))
{
// TODO: 框架不把这玩意儿放在 ISecurityLogManager?
if (!_securityLogOptions.IsEnabled)
{
return;
}
var client = _clientFactory.Create(); var securityLog = new SecurityLog(
_guidGenerator.Create(),
securityLogInfo);
var securityLog = new SecurityLog( await client.IndexAsync(
_guidGenerator.Create(), securityLog,
securityLogInfo); (x) => x.Index(CreateIndex())
.Id(securityLog.Id),
cancellationToken);
}
await client.IndexAsync( public async virtual Task<SecurityLog> GetAsync(
securityLog, Guid id,
(x) => x.Index(CreateIndex()) bool includeDetails = false,
.Id(securityLog.Id), CancellationToken cancellationToken = default)
cancellationToken); {
} var client = _clientFactory.Create();
public async virtual Task<SecurityLog> GetAsync( var response = await client.GetAsync<SecurityLog>(
Guid id, id,
bool includeDetails = false, dsl =>
CancellationToken cancellationToken = default) dsl.Index(CreateIndex()),
{ cancellationToken);
var client = _clientFactory.Create();
var response = await client.GetAsync<SecurityLog>( return response.Source;
id, }
dsl =>
dsl.Index(CreateIndex()),
cancellationToken);
return response.Source; public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
} {
var client = _clientFactory.Create();
public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) await client.DeleteAsync<SecurityLog>(
{ id,
var client = _clientFactory.Create(); dsl =>
dsl.Index(CreateIndex()),
cancellationToken);
}
await client.DeleteAsync<SecurityLog>( public async virtual Task<List<SecurityLog>> GetListAsync(
id, string sorting = null,
dsl => int maxResultCount = 50,
dsl.Index(CreateIndex()), int skipCount = 0,
cancellationToken); DateTime? startTime = null,
} DateTime? endTime = null,
string applicationName = null,
string identity = null,
string action = null,
Guid? userId = null,
string userName = null,
string clientId = null,
string clientIpAddress = null,
string correlationId = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
public async virtual Task<List<SecurityLog>> GetListAsync( var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("asc", StringComparison.InvariantCultureIgnoreCase)
string sorting = null, ? SortOrder.Ascending : SortOrder.Descending;
int maxResultCount = 50, sorting = !sorting.IsNullOrWhiteSpace()
int skipCount = 0, ? sorting.Split()[0]
DateTime? startTime = null, : nameof(SecurityLog.CreationTime);
DateTime? endTime = null,
string applicationName = null,
string identity = null,
string action = null,
Guid? userId = null,
string userName = null,
string clientId = null,
string clientIpAddress = null,
string correlationId = null,
bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken))
{
var client = _clientFactory.Create();
var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("asc", StringComparison.InvariantCultureIgnoreCase) var querys = BuildQueryDescriptor(
? SortOrder.Ascending : SortOrder.Descending; startTime,
sorting = !sorting.IsNullOrWhiteSpace() endTime,
? sorting.Split()[0] applicationName,
: nameof(SecurityLog.CreationTime); identity,
action,
userId,
userName,
clientId,
clientIpAddress,
correlationId);
var querys = BuildQueryDescriptor( var response = await client.SearchAsync<SecurityLog>(dsl =>
startTime, dsl.Index(CreateIndex())
endTime, .Query(log => log.Bool(b => b.Must(querys.ToArray())))
applicationName, .Source(log => log.IncludeAll())
identity, .Sort(log => log.Field(GetField(sorting), sortOrder))
action, .From(skipCount)
userId, .Size(maxResultCount),
userName, cancellationToken);
clientId,
clientIpAddress,
correlationId);
var response = await client.SearchAsync<SecurityLog>(dsl => return response.Documents.ToList();
dsl.Index(CreateIndex()) }
.Query(log => log.Bool(b => b.Must(querys.ToArray())))
.Source(log => log.IncludeAll())
.Sort(log => log.Field(GetField(sorting), sortOrder))
.From(skipCount)
.Size(maxResultCount),
cancellationToken);
return response.Documents.ToList();
}
public async virtual Task<long> GetCountAsync(
DateTime? startTime = null,
DateTime? endTime = null,
string applicationName = null,
string identity = null,
string action = null,
Guid? userId = null,
string userName = null,
string clientId = null,
string clientIpAddress = null,
string correlationId = null,
CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
public async virtual Task<long> GetCountAsync( var querys = BuildQueryDescriptor(
DateTime? startTime = null, startTime,
DateTime? endTime = null, endTime,
string applicationName = null, applicationName,
string identity = null, identity,
string action = null, action,
Guid? userId = null, userId,
string userName = null, userName,
string clientId = null, clientId,
string clientIpAddress = null, clientIpAddress,
string correlationId = null, correlationId);
CancellationToken cancellationToken = default(CancellationToken))
{
var client = _clientFactory.Create();
var querys = BuildQueryDescriptor( var response = await client.CountAsync<SecurityLog>(dsl =>
startTime, dsl.Index(CreateIndex())
endTime, .Query(log => log.Bool(b => b.Must(querys.ToArray()))),
applicationName, cancellationToken);
identity,
action,
userId,
userName,
clientId,
clientIpAddress,
correlationId);
var response = await client.CountAsync<SecurityLog>(dsl => return response.Count;
dsl.Index(CreateIndex()) }
.Query(log => log.Bool(b => b.Must(querys.ToArray()))),
cancellationToken);
return response.Count; protected virtual List<Func<QueryContainerDescriptor<SecurityLog>, QueryContainer>> BuildQueryDescriptor(
} DateTime? startTime = null,
DateTime? endTime = null,
string applicationName = null,
string identity = null,
string action = null,
Guid? userId = null,
string userName = null,
string clientId = null,
string clientIpAddress = null,
string correlationId = null)
{
var querys = new List<Func<QueryContainerDescriptor<SecurityLog>, QueryContainer>>();
protected virtual List<Func<QueryContainerDescriptor<SecurityLog>, QueryContainer>> BuildQueryDescriptor( if (startTime.HasValue)
DateTime? startTime = null,
DateTime? endTime = null,
string applicationName = null,
string identity = null,
string action = null,
Guid? userId = null,
string userName = null,
string clientId = null,
string clientIpAddress = null,
string correlationId = null)
{ {
var querys = new List<Func<QueryContainerDescriptor<SecurityLog>, QueryContainer>>(); querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(SecurityLog.CreationTime))).GreaterThanOrEquals(_clock.Normalize(startTime.Value))));
if (startTime.HasValue)
{
querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(SecurityLog.CreationTime))).GreaterThanOrEquals(_clock.Normalize(startTime.Value))));
}
if (endTime.HasValue)
{
querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(SecurityLog.CreationTime))).LessThanOrEquals(_clock.Normalize(endTime.Value))));
}
if (!applicationName.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ApplicationName))).Value(applicationName)));
}
if (!identity.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.Identity))).Value(identity)));
}
if (!action.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.Action))).Value(action)));
}
if (userId.HasValue)
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.UserId))).Value(userId)));
}
if (!userName.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.UserName))).Value(userName)));
}
if (!clientId.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ClientId))).Value(clientId)));
}
if (!clientIpAddress.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ClientIpAddress))).Value(clientIpAddress)));
}
if (!correlationId.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.CorrelationId))).Value(correlationId)));
}
return querys;
} }
if (endTime.HasValue)
protected virtual string CreateIndex()
{ {
return _indexNameNormalizer.NormalizeIndex("security-log"); querys.Add((log) => log.DateRange((q) => q.Field(GetField(nameof(SecurityLog.CreationTime))).LessThanOrEquals(_clock.Normalize(endTime.Value))));
} }
if (!applicationName.IsNullOrWhiteSpace())
private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) {
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ApplicationName))).Value(applicationName)));
}
if (!identity.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.Identity))).Value(identity)));
}
if (!action.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.Action))).Value(action)));
}
if (userId.HasValue)
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.UserId))).Value(userId)));
}
if (!userName.IsNullOrWhiteSpace())
{
querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.UserName))).Value(userName)));
}
if (!clientId.IsNullOrWhiteSpace())
{ {
{ "Id", "Id.keyword" }, querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ClientId))).Value(clientId)));
{ "ApplicationName", "ApplicationName.keyword" }, }
{ "UserId", "UserId.keyword" }, if (!clientIpAddress.IsNullOrWhiteSpace())
{ "UserName", "UserName.keyword" }, {
{ "TenantId", "TenantId.keyword" }, querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.ClientIpAddress))).Value(clientIpAddress)));
{ "TenantName", "TenantName.keyword" }, }
{ "Identity", "Identity.keyword" }, if (!correlationId.IsNullOrWhiteSpace())
{ "Action", "Action.keyword" },
{ "BrowserInfo", "BrowserInfo.keyword" },
{ "ClientIpAddress", "ClientIpAddress.keyword" },
{ "ClientId", "ClientId.keyword" },
{ "CorrelationId", "CorrelationId.keyword" },
{ "CreationTime", "CreationTime" },
};
protected virtual string GetField(string field)
{ {
if (_fieldMaps.TryGetValue(field, out string mapField)) querys.Add((log) => log.Term((q) => q.Field(GetField(nameof(SecurityLog.CorrelationId))).Value(correlationId)));
{ }
return _elasticsearchOptions.FieldCamelCase ? mapField.ToCamelCase() : mapField.ToPascalCase();
}
return _elasticsearchOptions.FieldCamelCase ? field.ToCamelCase() : field.ToPascalCase(); return querys;
}
protected virtual string CreateIndex()
{
return _indexNameNormalizer.NormalizeIndex("security-log");
}
private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{ "Id", "Id.keyword" },
{ "ApplicationName", "ApplicationName.keyword" },
{ "UserId", "UserId.keyword" },
{ "UserName", "UserName.keyword" },
{ "TenantId", "TenantId.keyword" },
{ "TenantName", "TenantName.keyword" },
{ "Identity", "Identity.keyword" },
{ "Action", "Action.keyword" },
{ "BrowserInfo", "BrowserInfo.keyword" },
{ "ClientIpAddress", "ClientIpAddress.keyword" },
{ "ClientId", "ClientId.keyword" },
{ "CorrelationId", "CorrelationId.keyword" },
{ "CreationTime", "CreationTime" },
};
protected virtual string GetField(string field)
{
if (_fieldMaps.TryGetValue(field, out string mapField))
{
return _elasticsearchOptions.FieldCamelCase ? mapField.ToCamelCase() : mapField.ToPascalCase();
} }
return _elasticsearchOptions.FieldCamelCase ? field.ToCamelCase() : field.ToPascalCase();
} }
} }

9
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs

@ -1,10 +1,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public interface IAuditLogInfoToAuditLogConverter
{ {
public interface IAuditLogInfoToAuditLogConverter Task<AuditLog> ConvertAsync(AuditLogInfo auditLogInfo);
{
Task<AuditLog> ConvertAsync(AuditLogInfo auditLogInfo);
}
} }

9
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs

@ -1,9 +1,8 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public interface IIndexInitializer
{ {
public interface IIndexInitializer Task InitializeAsync();
{
Task InitializeAsync();
}
} }

9
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexNameNormalizer.cs

@ -1,7 +1,6 @@
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public interface IIndexNameNormalizer
{ {
public interface IIndexNameNormalizer string NormalizeIndex(string index);
{
string NormalizeIndex(string index);
}
} }

155
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs

@ -9,98 +9,97 @@ using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexInitializer : IIndexInitializer, ISingletonDependency
{ {
public class IndexInitializer : IIndexInitializer, ISingletonDependency private readonly AbpJsonOptions _jsonOptions;
{ private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions;
private readonly AbpJsonOptions _jsonOptions; private readonly IIndexNameNormalizer _nameNormalizer;
private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions; private readonly IElasticsearchClientFactory _clientFactory;
private readonly IIndexNameNormalizer _nameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory;
public ILogger<IndexInitializer> Logger { protected get; set; } public ILogger<IndexInitializer> Logger { protected get; set; }
public IndexInitializer( public IndexInitializer(
IOptions<AbpJsonOptions> jsonOptions, IOptions<AbpJsonOptions> jsonOptions,
IOptions<AbpAuditLoggingElasticsearchOptions> elasticsearchOptions, IOptions<AbpAuditLoggingElasticsearchOptions> elasticsearchOptions,
IIndexNameNormalizer nameNormalizer, IIndexNameNormalizer nameNormalizer,
IElasticsearchClientFactory clientFactory) IElasticsearchClientFactory clientFactory)
{ {
_jsonOptions = jsonOptions.Value; _jsonOptions = jsonOptions.Value;
_elasticsearchOptions = elasticsearchOptions.Value; _elasticsearchOptions = elasticsearchOptions.Value;
_nameNormalizer = nameNormalizer; _nameNormalizer = nameNormalizer;
_clientFactory = clientFactory; _clientFactory = clientFactory;
Logger = NullLogger<IndexInitializer>.Instance; Logger = NullLogger<IndexInitializer>.Instance;
} }
public async virtual Task InitializeAsync() public async virtual Task InitializeAsync()
{
var client = _clientFactory.Create();
var dateTimeFormat = !_jsonOptions.OutputDateTimeFormat.IsNullOrWhiteSpace()
? $"{_jsonOptions.OutputDateTimeFormat}||strict_date_optional_time||epoch_millis"
: "strict_date_optional_time||epoch_millis";
var indexState = new IndexState
{ {
var client = _clientFactory.Create(); Settings = _elasticsearchOptions.IndexSettings,
var dateTimeFormat = !_jsonOptions.OutputDateTimeFormat.IsNullOrWhiteSpace() };
? $"{_jsonOptions.OutputDateTimeFormat}||strict_date_optional_time||epoch_millis" await InitlizeAuditLogIndex(client, indexState, dateTimeFormat);
: "strict_date_optional_time||epoch_millis"; await InitlizeSecurityLogIndex(client, indexState, dateTimeFormat);
var indexState = new IndexState }
{
Settings = _elasticsearchOptions.IndexSettings,
};
await InitlizeAuditLogIndex(client, indexState, dateTimeFormat);
await InitlizeSecurityLogIndex(client, indexState, dateTimeFormat);
}
protected async virtual Task InitlizeAuditLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat) protected async virtual Task InitlizeAuditLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat)
{
var indexName = _nameNormalizer.NormalizeIndex("audit-log");
var indexExists = await client.Indices.ExistsAsync(indexName);
if (!indexExists.Exists)
{ {
var indexName = _nameNormalizer.NormalizeIndex("audit-log"); var indexCreateResponse = await client.Indices.CreateAsync(
var indexExists = await client.Indices.ExistsAsync(indexName); indexName,
if (!indexExists.Exists) dsl => dsl.InitializeUsing(indexState)
.Map<AuditLog>(map =>
map.AutoMap()
.Properties(mp =>
mp.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat))
.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Nested<EntityChange>(n =>
n.AutoMap()
.Name(nameof(AuditLog.EntityChanges))
.Properties(np =>
np.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.ChangeTime).Format(dateTimeFormat))
.Nested<EntityPropertyChange>(npn => npn.Name(nameof(EntityChange.PropertyChanges)))))
.Nested<AuditLogAction>(n => n.Name(nameof(AuditLog.Actions))
.AutoMap()
.Properties((np =>
np.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat))))))));
if (!indexCreateResponse.IsValid)
{ {
var indexCreateResponse = await client.Indices.CreateAsync( Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
indexName, Logger.LogWarning(indexCreateResponse.OriginalException.ToString());
dsl => dsl.InitializeUsing(indexState)
.Map<AuditLog>(map =>
map.AutoMap()
.Properties(mp =>
mp.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat))
.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Nested<EntityChange>(n =>
n.AutoMap()
.Name(nameof(AuditLog.EntityChanges))
.Properties(np =>
np.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.ChangeTime).Format(dateTimeFormat))
.Nested<EntityPropertyChange>(npn => npn.Name(nameof(EntityChange.PropertyChanges)))))
.Nested<AuditLogAction>(n => n.Name(nameof(AuditLog.Actions))
.AutoMap()
.Properties((np =>
np.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat))))))));
if (!indexCreateResponse.IsValid)
{
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.OriginalException.ToString());
}
} }
} }
}
protected async virtual Task InitlizeSecurityLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat) protected async virtual Task InitlizeSecurityLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat)
{
var indexName = _nameNormalizer.NormalizeIndex("security-log");
var indexExists = await client.Indices.ExistsAsync(indexName);
if (!indexExists.Exists)
{ {
var indexName = _nameNormalizer.NormalizeIndex("security-log"); var indexCreateResponse = await client.Indices.CreateAsync(
var indexExists = await client.Indices.ExistsAsync(indexName); indexName,
if (!indexExists.Exists) dsl => dsl.InitializeUsing(indexState)
.Map<SecurityLog>(map =>
map.AutoMap()
.Properties(mp =>
mp.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.CreationTime).Format(dateTimeFormat)))));
if (!indexCreateResponse.IsValid)
{ {
var indexCreateResponse = await client.Indices.CreateAsync( Logger.LogWarning("Failed to initialize index and security log may not be retrieved.");
indexName, Logger.LogWarning(indexCreateResponse.OriginalException.ToString());
dsl => dsl.InitializeUsing(indexState)
.Map<SecurityLog>(map =>
map.AutoMap()
.Properties(mp =>
mp.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.CreationTime).Format(dateTimeFormat)))));
if (!indexCreateResponse.IsValid)
{
Logger.LogWarning("Failed to initialize index and security log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.OriginalException.ToString());
}
} }
} }
} }

23
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs

@ -2,20 +2,19 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexInitializerService : BackgroundService
{ {
public class IndexInitializerService : BackgroundService private readonly IIndexInitializer _indexInitializer;
{
private readonly IIndexInitializer _indexInitializer;
public IndexInitializerService(IIndexInitializer indexInitializer) public IndexInitializerService(IIndexInitializer indexInitializer)
{ {
_indexInitializer = indexInitializer; _indexInitializer = indexInitializer;
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await _indexInitializer.InitializeAsync(); await _indexInitializer.InitializeAsync();
}
} }
} }

39
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexNameNormalizer.cs

@ -3,30 +3,29 @@ using System;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexNameNormalizer : IIndexNameNormalizer, ISingletonDependency
{ {
public class IndexNameNormalizer : IIndexNameNormalizer, ISingletonDependency private readonly ICurrentTenant _currentTenant;
{ private readonly AbpAuditLoggingElasticsearchOptions _options;
private readonly ICurrentTenant _currentTenant;
private readonly AbpAuditLoggingElasticsearchOptions _options;
public IndexNameNormalizer( public IndexNameNormalizer(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IOptions<AbpAuditLoggingElasticsearchOptions> options) IOptions<AbpAuditLoggingElasticsearchOptions> options)
{ {
_currentTenant = currentTenant; _currentTenant = currentTenant;
_options = options.Value; _options = options.Value;
} }
public string NormalizeIndex(string index) public string NormalizeIndex(string index)
{
if (_currentTenant.IsAvailable)
{ {
if (_currentTenant.IsAvailable) return $"{_options.IndexPrefix}-{index}-{_currentTenant.Id:N}";
{
return $"{_options.IndexPrefix}-{index}-{_currentTenant.Id:N}";
}
return _options.IndexPrefix.IsNullOrWhiteSpace()
? index
: $"{_options.IndexPrefix}-{index}";
} }
return _options.IndexPrefix.IsNullOrWhiteSpace()
? index
: $"{_options.IndexPrefix}-{index}";
} }
} }

5
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj

@ -5,6 +5,11 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.AuditLogging.EntityFrameworkCore</AssemblyName>
<PackageId>LINGYUN.Abp.AuditLogging.EntityFrameworkCore</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

31
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs

@ -2,24 +2,23 @@
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore;
[DependsOn(
typeof(Volo.Abp.Identity.EntityFrameworkCore.AbpIdentityEntityFrameworkCoreModule),
typeof(Volo.Abp.AuditLogging.EntityFrameworkCore.AbpAuditLoggingEntityFrameworkCoreModule))]
[DependsOn(
typeof(AbpAuditLoggingModule),
typeof(AbpAutoMapperModule))]
public class AbpAuditLoggingEntityFrameworkCoreModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(Volo.Abp.Identity.EntityFrameworkCore.AbpIdentityEntityFrameworkCoreModule),
typeof(Volo.Abp.AuditLogging.EntityFrameworkCore.AbpAuditLoggingEntityFrameworkCoreModule))]
[DependsOn(
typeof(AbpAuditLoggingModule),
typeof(AbpAutoMapperModule))]
public class AbpAuditLoggingEntityFrameworkCoreModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddAutoMapperObjectMapper<AbpAuditLoggingEntityFrameworkCoreModule>();
{
context.Services.AddAutoMapperObjectMapper<AbpAuditLoggingEntityFrameworkCoreModule>();
Configure<AbpAutoMapperOptions>(options => Configure<AbpAutoMapperOptions>(options =>
{ {
options.AddProfile<AbpAuditingMapperProfile>(validate: true); options.AddProfile<AbpAuditingMapperProfile>(validate: true);
}); });
}
} }
} }

27
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs

@ -1,21 +1,20 @@
using AutoMapper; using AutoMapper;
namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore;
public class AbpAuditingMapperProfile : Profile
{ {
public class AbpAuditingMapperProfile : Profile public AbpAuditingMapperProfile()
{ {
public AbpAuditingMapperProfile() CreateMap<Volo.Abp.AuditLogging.AuditLogAction, LINGYUN.Abp.AuditLogging.AuditLogAction>()
{ .MapExtraProperties();
CreateMap<Volo.Abp.AuditLogging.AuditLogAction, LINGYUN.Abp.AuditLogging.AuditLogAction>() CreateMap<Volo.Abp.AuditLogging.EntityPropertyChange, LINGYUN.Abp.AuditLogging.EntityPropertyChange>();
.MapExtraProperties(); CreateMap<Volo.Abp.AuditLogging.EntityChange, LINGYUN.Abp.AuditLogging.EntityChange>()
CreateMap<Volo.Abp.AuditLogging.EntityPropertyChange, LINGYUN.Abp.AuditLogging.EntityPropertyChange>(); .MapExtraProperties();
CreateMap<Volo.Abp.AuditLogging.EntityChange, LINGYUN.Abp.AuditLogging.EntityChange>() CreateMap<Volo.Abp.AuditLogging.AuditLog, LINGYUN.Abp.AuditLogging.AuditLog>()
.MapExtraProperties(); .MapExtraProperties();
CreateMap<Volo.Abp.AuditLogging.AuditLog, LINGYUN.Abp.AuditLogging.AuditLog>()
.MapExtraProperties();
CreateMap<Volo.Abp.Identity.IdentitySecurityLog, LINGYUN.Abp.AuditLogging.SecurityLog>() CreateMap<Volo.Abp.Identity.IdentitySecurityLog, LINGYUN.Abp.AuditLogging.SecurityLog>()
.MapExtraProperties(); .MapExtraProperties();
}
} }
} }

289
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs

@ -12,168 +12,169 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore;
[Dependency(ReplaceServices = true)]
public class AuditLogManager : IAuditLogManager, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] protected IObjectMapper ObjectMapper { get; }
public class AuditLogManager : IAuditLogManager, ITransientDependency protected IAuditLogRepository AuditLogRepository { get; }
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected AbpAuditingOptions Options { get; }
protected IAuditLogInfoToAuditLogConverter Converter { get; }
public ILogger<AuditLogManager> Logger { protected get; set; }
public AuditLogManager(
IObjectMapper objectMapper,
IAuditLogRepository auditLogRepository,
IUnitOfWorkManager unitOfWorkManager,
IOptions<AbpAuditingOptions> options,
IAuditLogInfoToAuditLogConverter converter)
{ {
protected IObjectMapper ObjectMapper { get; } ObjectMapper = objectMapper;
protected IAuditLogRepository AuditLogRepository { get; } AuditLogRepository = auditLogRepository;
protected IUnitOfWorkManager UnitOfWorkManager { get; } UnitOfWorkManager = unitOfWorkManager;
protected AbpAuditingOptions Options { get; } Converter = converter;
protected IAuditLogInfoToAuditLogConverter Converter { get; } Options = options.Value;
public ILogger<AuditLogManager> Logger { protected get; set; }
public AuditLogManager(
IObjectMapper objectMapper,
IAuditLogRepository auditLogRepository,
IUnitOfWorkManager unitOfWorkManager,
IOptions<AbpAuditingOptions> options,
IAuditLogInfoToAuditLogConverter converter)
{
ObjectMapper = objectMapper;
AuditLogRepository = auditLogRepository;
UnitOfWorkManager = unitOfWorkManager;
Converter = converter;
Options = options.Value;
Logger = NullLogger<AuditLogManager>.Instance; Logger = NullLogger<AuditLogManager>.Instance;
} }
public async virtual Task<long> GetCountAsync( public async virtual Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string httpMethod = null,
string url = null, string url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string applicationName = null, string applicationName = null,
string correlationId = null, string correlationId = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
return await AuditLogRepository.GetCountAsync( return await AuditLogRepository.GetCountAsync(
startTime, startTime,
endTime, endTime,
httpMethod, httpMethod,
url, url,
userId, clientId,
userName, userId,
applicationName, userName,
clientIpAddress, applicationName,
correlationId, clientIpAddress,
maxExecutionDuration, correlationId,
minExecutionDuration, maxExecutionDuration,
hasException, minExecutionDuration,
httpStatusCode, hasException,
cancellationToken); httpStatusCode,
} cancellationToken);
}
public async virtual Task<List<AuditLog>> GetListAsync( public async virtual Task<List<AuditLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string httpMethod = null,
string url = null, string url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string applicationName = null, string applicationName = null,
string correlationId = null, string correlationId = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
var auditLogs = await AuditLogRepository.GetListAsync( var auditLogs = await AuditLogRepository.GetListAsync(
sorting, sorting,
maxResultCount, maxResultCount,
skipCount, skipCount,
startTime, startTime,
endTime, endTime,
httpMethod, httpMethod,
url, url,
userId, clientId,
userName, userId,
applicationName, userName,
clientIpAddress, applicationName,
correlationId, clientIpAddress,
maxExecutionDuration, correlationId,
minExecutionDuration, maxExecutionDuration,
hasException, minExecutionDuration,
httpStatusCode, hasException,
includeDetails, httpStatusCode,
cancellationToken); includeDetails,
cancellationToken);
return ObjectMapper.Map<List<Volo.Abp.AuditLogging.AuditLog>, List<AuditLog>>(auditLogs); return ObjectMapper.Map<List<Volo.Abp.AuditLogging.AuditLog>, List<AuditLog>>(auditLogs);
} }
public async virtual Task<AuditLog> GetAsync( public async virtual Task<AuditLog> GetAsync(
Guid id, Guid id,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var auditLog = await AuditLogRepository.GetAsync(id, includeDetails, cancellationToken); var auditLog = await AuditLogRepository.GetAsync(id, includeDetails, cancellationToken);
return ObjectMapper.Map<Volo.Abp.AuditLogging.AuditLog, AuditLog>(auditLog);
}
return ObjectMapper.Map<Volo.Abp.AuditLogging.AuditLog, AuditLog>(auditLog); public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
using (var uow = UnitOfWorkManager.Begin(true))
{
await AuditLogRepository.DeleteAsync(id);
await uow.CompleteAsync();
} }
}
public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) public async virtual Task<string> SaveAsync(
AuditLogInfo auditInfo,
CancellationToken cancellationToken = default)
{
if (!Options.HideErrors)
{ {
using (var uow = UnitOfWorkManager.Begin(true)) return await SaveLogAsync(auditInfo, cancellationToken);
{
await AuditLogRepository.DeleteAsync(id);
await uow.CompleteAsync();
}
} }
public async virtual Task<string> SaveAsync( try
AuditLogInfo auditInfo, {
CancellationToken cancellationToken = default(CancellationToken)) return await SaveLogAsync(auditInfo, cancellationToken);
}
catch (Exception ex)
{ {
if (!Options.HideErrors) Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString());
{ Logger.LogException(ex, LogLevel.Error);
return await SaveLogAsync(auditInfo, cancellationToken);
}
try
{
return await SaveLogAsync(auditInfo, cancellationToken);
}
catch (Exception ex)
{
Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString());
Logger.LogException(ex, LogLevel.Error);
}
return "";
} }
return "";
}
protected async virtual Task<string> SaveLogAsync( protected async virtual Task<string> SaveLogAsync(
AuditLogInfo auditInfo, AuditLogInfo auditInfo,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{
using (var uow = UnitOfWorkManager.Begin(true))
{ {
using (var uow = UnitOfWorkManager.Begin(true)) var auditLog = await AuditLogRepository.InsertAsync(
{ await Converter.ConvertAsync(auditInfo),
var auditLog = await AuditLogRepository.InsertAsync( false,
await Converter.ConvertAsync(auditInfo), cancellationToken);
false, await uow.CompleteAsync();
cancellationToken);
await uow.CompleteAsync(); return auditLog.Id.ToString();
return auditLog.Id.ToString();
}
} }
} }
} }

223
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs

@ -11,134 +11,133 @@ using Volo.Abp.ObjectMapping;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore;
[Dependency(ReplaceServices = true)]
public class SecurityLogManager : ISecurityLogManager, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] public ILogger<SecurityLogManager> Logger { get; set; }
public class SecurityLogManager : ISecurityLogManager, ITransientDependency
{ protected IObjectMapper ObjectMapper { get; }
public ILogger<SecurityLogManager> Logger { get; set; } protected AbpSecurityLogOptions SecurityLogOptions { get; }
protected IIdentitySecurityLogRepository IdentitySecurityLogRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected IObjectMapper ObjectMapper { get; } public SecurityLogManager(
protected AbpSecurityLogOptions SecurityLogOptions { get; } IObjectMapper objectMapper,
protected IIdentitySecurityLogRepository IdentitySecurityLogRepository { get; } ILogger<SecurityLogManager> logger,
protected IGuidGenerator GuidGenerator { get; } IOptions<AbpSecurityLogOptions> securityLogOptions,
protected IUnitOfWorkManager UnitOfWorkManager { get; } IIdentitySecurityLogRepository identitySecurityLogRepository,
IGuidGenerator guidGenerator,
IUnitOfWorkManager unitOfWorkManager)
{
Logger = logger;
ObjectMapper = objectMapper;
SecurityLogOptions = securityLogOptions.Value;
IdentitySecurityLogRepository = identitySecurityLogRepository;
GuidGenerator = guidGenerator;
UnitOfWorkManager = unitOfWorkManager;
}
public SecurityLogManager( public async virtual Task SaveAsync(
IObjectMapper objectMapper, SecurityLogInfo securityLogInfo,
ILogger<SecurityLogManager> logger, CancellationToken cancellationToken = default)
IOptions<AbpSecurityLogOptions> securityLogOptions, {
IIdentitySecurityLogRepository identitySecurityLogRepository, if (!SecurityLogOptions.IsEnabled)
IGuidGenerator guidGenerator,
IUnitOfWorkManager unitOfWorkManager)
{ {
Logger = logger; return;
ObjectMapper = objectMapper;
SecurityLogOptions = securityLogOptions.Value;
IdentitySecurityLogRepository = identitySecurityLogRepository;
GuidGenerator = guidGenerator;
UnitOfWorkManager = unitOfWorkManager;
} }
public async virtual Task SaveAsync( using (var uow = UnitOfWorkManager.Begin(requiresNew: true))
SecurityLogInfo securityLogInfo,
CancellationToken cancellationToken = default(CancellationToken))
{ {
if (!SecurityLogOptions.IsEnabled) await IdentitySecurityLogRepository.InsertAsync(
{ new IdentitySecurityLog(GuidGenerator, securityLogInfo),
return; false,
} cancellationToken);
await uow.CompleteAsync();
using (var uow = UnitOfWorkManager.Begin(requiresNew: true))
{
await IdentitySecurityLogRepository.InsertAsync(
new IdentitySecurityLog(GuidGenerator, securityLogInfo),
false,
cancellationToken);
await uow.CompleteAsync();
}
} }
}
public async virtual Task<SecurityLog> GetAsync( public async virtual Task<SecurityLog> GetAsync(
Guid id, Guid id,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var securityLog = await IdentitySecurityLogRepository.GetAsync(id, includeDetails, cancellationToken); var securityLog = await IdentitySecurityLogRepository.GetAsync(id, includeDetails, cancellationToken);
return ObjectMapper.Map<IdentitySecurityLog, SecurityLog>(securityLog); return ObjectMapper.Map<IdentitySecurityLog, SecurityLog>(securityLog);
} }
public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) public async virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
using (var uow = UnitOfWorkManager.Begin(true))
{ {
using (var uow = UnitOfWorkManager.Begin(true)) await IdentitySecurityLogRepository.DeleteAsync(id);
{ await uow.CompleteAsync();
await IdentitySecurityLogRepository.DeleteAsync(id);
await uow.CompleteAsync();
}
} }
}
public async virtual Task<List<SecurityLog>> GetListAsync( public async virtual Task<List<SecurityLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string applicationName = null, string applicationName = null,
string identity = null, string identity = null,
string action = null, string action = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
string correlationId = null, string correlationId = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
var securityLogs = await IdentitySecurityLogRepository.GetListAsync( var securityLogs = await IdentitySecurityLogRepository.GetListAsync(
sorting, sorting,
maxResultCount, maxResultCount,
skipCount, skipCount,
startTime, startTime,
endTime, endTime,
applicationName, applicationName,
identity, identity,
action, action,
userId, userId,
userName, userName,
clientId, clientId,
correlationId, correlationId,
includeDetails, includeDetails,
cancellationToken); cancellationToken);
return ObjectMapper.Map<List<IdentitySecurityLog>, List<SecurityLog>>(securityLogs); return ObjectMapper.Map<List<IdentitySecurityLog>, List<SecurityLog>>(securityLogs);
} }
public async virtual Task<long> GetCountAsync( public async virtual Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string applicationName = null, string applicationName = null,
string identity = null, string identity = null,
string action = null, string action = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string userName = null,
string clientId = null, string clientId = null,
string clientIpAddress = null, string clientIpAddress = null,
string correlationId = null, string correlationId = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
return await IdentitySecurityLogRepository.GetCountAsync( return await IdentitySecurityLogRepository.GetCountAsync(
startTime, startTime,
endTime, endTime,
applicationName, applicationName,
identity, identity,
action, action,
userId, userId,
userName, userName,
clientId, clientId,
correlationId, correlationId,
cancellationToken); cancellationToken);
}
} }
} }

9
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj

@ -4,7 +4,14 @@
<Import Project="..\..\..\..\common.props" /> <Import Project="..\..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>LINGYUN.Abp.AuditLogging</AssemblyName>
<PackageId>LINGYUN.Abp.AuditLogging</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

25
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs

@ -5,21 +5,20 @@ using Volo.Abp.ExceptionHandling;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[DependsOn(
typeof(AbpAuditingModule),
typeof(AbpGuidsModule),
typeof(AbpExceptionHandlingModule))]
public class AbpAuditLoggingModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpAuditingModule),
typeof(AbpGuidsModule),
typeof(AbpExceptionHandlingModule))]
public class AbpAuditLoggingModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpAuditingOptions>(options =>
{ {
Configure<AbpAuditingOptions>(options => options.IgnoredTypes.AddIfNotContains(typeof(CancellationToken));
{ options.IgnoredTypes.AddIfNotContains(typeof(CancellationTokenSource));
options.IgnoredTypes.AddIfNotContains(typeof(CancellationToken)); });
options.IgnoredTypes.AddIfNotContains(typeof(CancellationTokenSource));
});
}
} }
} }

176
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs

@ -1,122 +1,120 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Auditing;
using Volo.Abp.Data; using Volo.Abp.Data;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public class AuditLog : IHasExtraProperties
{ {
public class AuditLog : IHasExtraProperties public Guid Id { get; set; }
{
public Guid Id { get; set; }
public string ApplicationName { get; set; } public string? ApplicationName { get; set; }
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public string UserName { get; set; } public string? UserName { get; set; }
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public string TenantName { get; set; } public string? TenantName { get; set; }
public Guid? ImpersonatorUserId { get; set; } public Guid? ImpersonatorUserId { get; set; }
public string ImpersonatorUserName { get; set; } public string? ImpersonatorUserName { get; set; }
public Guid? ImpersonatorTenantId { get; set; } public Guid? ImpersonatorTenantId { get; set; }
public string ImpersonatorTenantName { get; set; } public string? ImpersonatorTenantName { get; set; }
public DateTime ExecutionTime { get; set; } public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; set; } public int ExecutionDuration { get; set; }
public string ClientIpAddress { get; set; } public string? ClientIpAddress { get; set; }
public string ClientName { get; set; } public string? ClientName { get; set; }
public string ClientId { get; set; } public string? ClientId { get; set; }
public string CorrelationId { get; set; } public string? CorrelationId { get; set; }
public string BrowserInfo { get; set; } public string? BrowserInfo { get; set; }
public string HttpMethod { get; set; } public string? HttpMethod { get; set; }
public string Url { get; set; } public string? Url { get; set; }
public string Exceptions { get; set; } public string? Exceptions { get; set; }
public string Comments { get; set; } public string? Comments { get; set; }
public int? HttpStatusCode { get; set; } public int? HttpStatusCode { get; set; }
public List<EntityChange> EntityChanges { get; set; } public List<EntityChange> EntityChanges { get; set; }
public List<AuditLogAction> Actions { get; set; } public List<AuditLogAction> Actions { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; set; } public ExtraPropertyDictionary ExtraProperties { get; set; }
public AuditLog() public AuditLog()
{ {
Actions = new List<AuditLogAction>(); Actions = new List<AuditLogAction>();
EntityChanges = new List<EntityChange>(); EntityChanges = new List<EntityChange>();
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
} }
public AuditLog( public AuditLog(
Guid id, Guid id,
string applicationName, string? applicationName,
Guid? tenantId, Guid? tenantId,
string tenantName, string? tenantName,
Guid? userId, Guid? userId,
string userName, string? userName,
DateTime executionTime, DateTime executionTime,
int executionDuration, int executionDuration,
string clientIpAddress, string? clientIpAddress,
string clientName, string? clientName,
string clientId, string? clientId,
string correlationId, string? correlationId,
string browserInfo, string? browserInfo,
string httpMethod, string? httpMethod,
string url, string? url,
int? httpStatusCode, int? httpStatusCode,
Guid? impersonatorUserId, Guid? impersonatorUserId,
string impersonatorUserName, string? impersonatorUserName,
Guid? impersonatorTenantId, Guid? impersonatorTenantId,
string impersonatorTenantName, string? impersonatorTenantName,
ExtraPropertyDictionary extraPropertyDictionary, ExtraPropertyDictionary extraPropertyDictionary,
List<EntityChange> entityChanges, List<EntityChange> entityChanges,
List<AuditLogAction> actions, List<AuditLogAction> actions,
string exceptions, string? exceptions,
string comments) string? comments)
{ {
Id = id; Id = id;
ApplicationName = applicationName; ApplicationName = applicationName;
TenantId = tenantId; TenantId = tenantId;
TenantName = tenantName; TenantName = tenantName;
UserId = userId; UserId = userId;
UserName = userName; UserName = userName;
ExecutionTime = executionTime; ExecutionTime = executionTime;
ExecutionDuration = executionDuration; ExecutionDuration = executionDuration;
ClientIpAddress = clientIpAddress; ClientIpAddress = clientIpAddress;
ClientName = clientName; ClientName = clientName;
ClientId = clientId; ClientId = clientId;
CorrelationId = correlationId; CorrelationId = correlationId;
BrowserInfo = browserInfo; BrowserInfo = browserInfo;
HttpMethod = httpMethod; HttpMethod = httpMethod;
Url = url; Url = url;
HttpStatusCode = httpStatusCode; HttpStatusCode = httpStatusCode;
ImpersonatorUserId = impersonatorUserId; ImpersonatorUserId = impersonatorUserId;
ImpersonatorUserName = impersonatorUserName; ImpersonatorUserName = impersonatorUserName;
ImpersonatorTenantId = impersonatorTenantId; ImpersonatorTenantId = impersonatorTenantId;
ImpersonatorTenantName = impersonatorTenantName; ImpersonatorTenantName = impersonatorTenantName;
ExtraProperties = extraPropertyDictionary; ExtraProperties = extraPropertyDictionary;
EntityChanges = entityChanges; EntityChanges = entityChanges;
Actions = actions; Actions = actions;
Exceptions = exceptions; Exceptions = exceptions;
Comments = comments; Comments = comments;
}
} }
} }

59
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs

@ -2,47 +2,46 @@
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Data; using Volo.Abp.Data;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[DisableAuditing]
public class AuditLogAction : IHasExtraProperties
{ {
[DisableAuditing] public Guid Id { get; set; }
public class AuditLogAction : IHasExtraProperties
{
public Guid Id { get; set; }
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public Guid AuditLogId { get; set; } public Guid AuditLogId { get; set; }
public string ServiceName { get; set; } public string ServiceName { get; set; }
public string MethodName { get; set; } public string MethodName { get; set; }
public string Parameters { get; set; } public string Parameters { get; set; }
public DateTime ExecutionTime { get; set; } public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; set; } public int ExecutionDuration { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; set; } public ExtraPropertyDictionary ExtraProperties { get; set; }
public AuditLogAction() public AuditLogAction()
{ {
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
} }
public AuditLogAction(Guid id, Guid auditLogId, AuditLogActionInfo actionInfo, Guid? tenantId = null) public AuditLogAction(Guid id, Guid auditLogId, AuditLogActionInfo actionInfo, Guid? tenantId = null)
{ {
Id = id; Id = id;
TenantId = tenantId; TenantId = tenantId;
AuditLogId = auditLogId; AuditLogId = auditLogId;
ExecutionTime = actionInfo.ExecutionTime; ExecutionTime = actionInfo.ExecutionTime;
ExecutionDuration = actionInfo.ExecutionDuration; ExecutionDuration = actionInfo.ExecutionDuration;
ExtraProperties = new ExtraPropertyDictionary(actionInfo.ExtraProperties); ExtraProperties = new ExtraPropertyDictionary(actionInfo.ExtraProperties);
ServiceName = actionInfo.ServiceName; ServiceName = actionInfo.ServiceName;
MethodName = actionInfo.MethodName; MethodName = actionInfo.MethodName;
Parameters = actionInfo.Parameters; Parameters = actionInfo.Parameters;
// Parameters = actionInfo.Parameters.Length > 2000 ? "" : actionInfo.Parameters; // Parameters = actionInfo.Parameters.Length > 2000 ? "" : actionInfo.Parameters;
}
} }
} }

27
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs

@ -2,22 +2,21 @@
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[Dependency(ReplaceServices = true)]
public class AuditingStore : IAuditingStore, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] private readonly IAuditLogManager _manager;
public class AuditingStore : IAuditingStore, ITransientDependency
{
private readonly IAuditLogManager _manager;
public AuditingStore( public AuditingStore(
IAuditLogManager manager) IAuditLogManager manager)
{ {
_manager = manager; _manager = manager;
} }
public async virtual Task SaveAsync(AuditLogInfo auditInfo) public async virtual Task SaveAsync(AuditLogInfo auditInfo)
{ {
await _manager.SaveAsync(auditInfo); await _manager.SaveAsync(auditInfo);
}
} }
} }

149
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs

@ -8,89 +8,88 @@ using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[Dependency(TryRegister = true)]
public class DefaultAuditLogManager : IAuditLogManager, ISingletonDependency
{ {
[Dependency(TryRegister = true)] public ILogger<DefaultAuditLogManager> Logger { protected get; set; }
public class DefaultAuditLogManager : IAuditLogManager, ISingletonDependency
{
public ILogger<DefaultAuditLogManager> Logger { protected get; set; }
public DefaultAuditLogManager() public DefaultAuditLogManager()
{ {
Logger = NullLogger<DefaultAuditLogManager>.Instance; Logger = NullLogger<DefaultAuditLogManager>.Instance;
} }
public virtual Task<long> GetCountAsync( public virtual Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string? httpMethod = null,
string url = null, string? url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string applicationName = null, string? applicationName = null,
string correlationId = null, string? correlationId = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No audit log manager is available!"); Logger.LogDebug("No audit log manager is available!");
return Task.FromResult(0L); return Task.FromResult(0L);
} }
public virtual Task<List<AuditLog>> GetListAsync( public virtual Task<List<AuditLog>> GetListAsync(
string sorting = null, string? sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string? httpMethod = null,
string url = null, string? url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string applicationName = null, string? applicationName = null,
string correlationId = null, string? correlationId = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No audit log manager is available!"); Logger.LogDebug("No audit log manager is available!");
return Task.FromResult(new List<AuditLog>()); return Task.FromResult(new List<AuditLog>());
} }
public virtual Task<string> SaveAsync( public virtual Task<string> SaveAsync(
AuditLogInfo auditInfo, AuditLogInfo auditInfo,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No audit log manager is available and is written to the local log by default"); Logger.LogDebug("No audit log manager is available and is written to the local log by default");
Logger.LogInformation(auditInfo.ToString()); Logger.LogInformation(auditInfo.ToString());
return Task.FromResult(""); return Task.FromResult("");
} }
public virtual Task<AuditLog> GetAsync( public virtual Task<AuditLog> GetAsync(
Guid id, Guid id,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No audit log manager is available!"); Logger.LogDebug("No audit log manager is available!");
AuditLog auditLog = null; AuditLog? auditLog = null;
return Task.FromResult(auditLog); return Task.FromResult(auditLog!);
} }
public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No audit log manager is available!"); Logger.LogDebug("No audit log manager is available!");
return Task.CompletedTask; return Task.CompletedTask;
}
} }
} }

67
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultEntityChangeStore.cs

@ -5,36 +5,53 @@ using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[Dependency(TryRegister = true)]
public class DefaultEntityChangeStore : IEntityChangeStore, ISingletonDependency
{ {
[Dependency(TryRegister = true)] public Task<EntityChange?> GetAsync(Guid entityChangeId, CancellationToken cancellationToken = default)
public class DefaultEntityChangeStore : IEntityChangeStore, ISingletonDependency
{ {
public Task<EntityChange> GetAsync(Guid entityChangeId, CancellationToken cancellationToken = default) EntityChange? entityChange = null;
{ return Task.FromResult(entityChange);
EntityChange entityChange = null; }
return Task.FromResult(entityChange);
}
public Task<long> GetCountAsync(Guid? auditLogId = null, DateTime? startTime = null, DateTime? endTime = null, EntityChangeType? changeType = null, string entityId = null, string entityTypeFullName = null, CancellationToken cancellationToken = default) public Task<long> GetCountAsync(
{ Guid? auditLogId = null,
return Task.FromResult(0L); DateTime? startTime = null,
} DateTime? endTime = null,
EntityChangeType? changeType = null,
string? entityId = null,
string? entityTypeFullName = null,
CancellationToken cancellationToken = default)
{
return Task.FromResult(0L);
}
public Task<List<EntityChange>> GetListAsync(string sorting = null, int maxResultCount = 50, int skipCount = 0, Guid? auditLogId = null, DateTime? startTime = null, DateTime? endTime = null, EntityChangeType? changeType = null, string entityId = null, string entityTypeFullName = null, bool includeDetails = false, CancellationToken cancellationToken = default) public Task<List<EntityChange>> GetListAsync(
{ string? sorting = null,
return Task.FromResult(new List<EntityChange>()); int maxResultCount = 50,
} int skipCount = 0,
Guid? auditLogId = null,
DateTime? startTime = null,
DateTime? endTime = null,
EntityChangeType? changeType = null,
string? entityId = null,
string? entityTypeFullName = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return Task.FromResult(new List<EntityChange>());
}
public Task<EntityChangeWithUsername> GetWithUsernameAsync(Guid entityChangeId, CancellationToken cancellationToken = default) public Task<EntityChangeWithUsername> GetWithUsernameAsync(Guid entityChangeId, CancellationToken cancellationToken = default)
{ {
EntityChangeWithUsername entityChange = null; EntityChangeWithUsername? entityChange = null;
return Task.FromResult(entityChange); return Task.FromResult(entityChange!);
} }
public Task<List<EntityChangeWithUsername>> GetWithUsernameAsync(string entityId, string entityTypeFullName, CancellationToken cancellationToken = default) public Task<List<EntityChangeWithUsername>> GetWithUsernameAsync(string entityId, string entityTypeFullName, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(new List<EntityChangeWithUsername>()); return Task.FromResult(new List<EntityChangeWithUsername>());
}
} }
} }

133
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs

@ -7,81 +7,80 @@ using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[Dependency(TryRegister = true)]
public class DefaultSecurityLogManager : ISecurityLogManager, ISingletonDependency
{ {
[Dependency(TryRegister = true)] public ILogger<DefaultSecurityLogManager> Logger { protected get; set; }
public class DefaultSecurityLogManager : ISecurityLogManager, ISingletonDependency
{
public ILogger<DefaultSecurityLogManager> Logger { protected get; set; }
public DefaultSecurityLogManager() public DefaultSecurityLogManager()
{ {
Logger = NullLogger<DefaultSecurityLogManager>.Instance; Logger = NullLogger<DefaultSecurityLogManager>.Instance;
} }
public Task<long> GetCountAsync( public Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string applicationName = null, string? applicationName = null,
string identity = null, string? identity = null,
string action = null, string? action = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
string correlationId = null, string? correlationId = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No security log manager is available!"); Logger.LogDebug("No security log manager is available!");
return Task.FromResult(0L); return Task.FromResult(0L);
} }
public Task<List<SecurityLog>> GetListAsync( public Task<List<SecurityLog>> GetListAsync(
string sorting = null, string? sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string applicationName = null, string? applicationName = null,
string identity = null, string? identity = null,
string action = null, string? action = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
string correlationId = null, string? correlationId = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No security log manager is available!"); Logger.LogDebug("No security log manager is available!");
return Task.FromResult(new List<SecurityLog>()); return Task.FromResult(new List<SecurityLog>());
} }
public Task SaveAsync( public Task SaveAsync(
SecurityLogInfo securityLogInfo, SecurityLogInfo securityLogInfo,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No security log manager is available and is written to the local log by default"); Logger.LogDebug("No security log manager is available and is written to the local log by default");
Logger.LogInformation(securityLogInfo.ToString()); Logger.LogInformation(securityLogInfo.ToString());
return Task.CompletedTask; return Task.CompletedTask;
} }
public virtual Task<SecurityLog> GetAsync( public virtual Task<SecurityLog> GetAsync(
Guid id, Guid id,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No security log manager is available!"); Logger.LogDebug("No security log manager is available!");
SecurityLog securityLog = null; SecurityLog? securityLog = null;
return Task.FromResult(securityLog); return Task.FromResult(securityLog!);
} }
public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{ {
Logger.LogDebug("No security log manager is available!"); Logger.LogDebug("No security log manager is available!");
return Task.CompletedTask; return Task.CompletedTask;
}
} }
} }

89
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs

@ -5,66 +5,65 @@ using Volo.Abp.Auditing;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Guids; using Volo.Abp.Guids;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[DisableAuditing]
public class EntityChange : IHasExtraProperties
{ {
[DisableAuditing] public Guid Id { get; set; }
public class EntityChange : IHasExtraProperties
{
public Guid Id { get; set; }
public Guid AuditLogId { get; set; } public Guid AuditLogId { get; set; }
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public DateTime ChangeTime { get; set; } public DateTime ChangeTime { get; set; }
public EntityChangeType ChangeType { get; set; } public EntityChangeType ChangeType { get; set; }
public Guid? EntityTenantId { get; set; } public Guid? EntityTenantId { get; set; }
public string EntityId { get; set; } public string? EntityId { get; set; }
public string EntityTypeFullName { get; set; } public string? EntityTypeFullName { get; set; }
public List<EntityPropertyChange> PropertyChanges { get; set; } public List<EntityPropertyChange> PropertyChanges { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; set; } public ExtraPropertyDictionary ExtraProperties { get; set; }
public EntityChange() public EntityChange()
{ {
PropertyChanges = new List<EntityPropertyChange>(); PropertyChanges = new List<EntityPropertyChange>();
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
} }
public EntityChange( public EntityChange(
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
Guid auditLogId, Guid auditLogId,
EntityChangeInfo entityChangeInfo, EntityChangeInfo entityChangeInfo,
Guid? tenantId = null, Guid? tenantId = null,
Guid? entityTenantId = null) Guid? entityTenantId = null)
{ {
Id = guidGenerator.Create(); Id = guidGenerator.Create();
AuditLogId = auditLogId; AuditLogId = auditLogId;
TenantId = tenantId; TenantId = tenantId;
EntityTenantId = entityTenantId; EntityTenantId = entityTenantId;
ChangeTime = entityChangeInfo.ChangeTime; ChangeTime = entityChangeInfo.ChangeTime;
ChangeType = entityChangeInfo.ChangeType; ChangeType = entityChangeInfo.ChangeType;
EntityId = entityChangeInfo.EntityId; EntityId = entityChangeInfo.EntityId;
EntityTypeFullName = entityChangeInfo.EntityTypeFullName; EntityTypeFullName = entityChangeInfo.EntityTypeFullName;
PropertyChanges = entityChangeInfo PropertyChanges = entityChangeInfo
.PropertyChanges? .PropertyChanges?
.Select(p => new EntityPropertyChange(guidGenerator, Id, p, tenantId)) .Select(p => new EntityPropertyChange(guidGenerator, Id, p, tenantId))
.ToList() .ToList()
?? new List<EntityPropertyChange>(); ?? new List<EntityPropertyChange>();
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
if (entityChangeInfo.ExtraProperties != null) if (entityChangeInfo.ExtraProperties != null)
{
foreach (var pair in entityChangeInfo.ExtraProperties)
{ {
foreach (var pair in entityChangeInfo.ExtraProperties) ExtraProperties.Add(pair.Key, pair.Value);
{
ExtraProperties.Add(pair.Key, pair.Value);
}
} }
} }
} }

11
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeWithUsername.cs

@ -1,9 +1,8 @@
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public class EntityChangeWithUsername
{ {
public class EntityChangeWithUsername public EntityChange EntityChange { get; set; }
{
public EntityChange EntityChange { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
}
} }

55
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs

@ -2,42 +2,41 @@
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Guids; using Volo.Abp.Guids;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[DisableAuditing]
public class EntityPropertyChange
{ {
[DisableAuditing] public Guid Id { get; set; }
public class EntityPropertyChange
{
public Guid Id { get; set; }
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public Guid EntityChangeId { get; set; } public Guid EntityChangeId { get; set; }
public string NewValue { get; set; } public string? NewValue { get; set; }
public string OriginalValue { get; set; } public string? OriginalValue { get; set; }
public string PropertyName { get; set; } public string PropertyName { get; set; }
public string PropertyTypeFullName { get; set; } public string PropertyTypeFullName { get; set; }
public EntityPropertyChange() public EntityPropertyChange()
{ {
} }
public EntityPropertyChange( public EntityPropertyChange(
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
Guid entityChangeId, Guid entityChangeId,
EntityPropertyChangeInfo entityChangeInfo, EntityPropertyChangeInfo entityChangeInfo,
Guid? tenantId = null) Guid? tenantId = null)
{ {
Id = guidGenerator.Create(); Id = guidGenerator.Create();
TenantId = tenantId; TenantId = tenantId;
EntityChangeId = entityChangeId; EntityChangeId = entityChangeId;
NewValue = entityChangeInfo.NewValue; NewValue = entityChangeInfo.NewValue;
OriginalValue = entityChangeInfo.OriginalValue; OriginalValue = entityChangeInfo.OriginalValue;
PropertyName = entityChangeInfo.PropertyName; PropertyName = entityChangeInfo.PropertyName;
PropertyTypeFullName = entityChangeInfo.PropertyTypeFullName; PropertyTypeFullName = entityChangeInfo.PropertyTypeFullName;
}
} }
} }

99
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs

@ -5,60 +5,59 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public interface IAuditLogManager
{ {
public interface IAuditLogManager Task<AuditLog> GetAsync(
{ Guid id,
Task<AuditLog> GetAsync( bool includeDetails = false,
Guid id, CancellationToken cancellationToken = default);
bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken));
Task DeleteAsync( Task DeleteAsync(
Guid id, Guid id,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default);
Task<string> SaveAsync( Task<string> SaveAsync(
AuditLogInfo auditInfo, AuditLogInfo auditInfo,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default);
Task<long> GetCountAsync( Task<long> GetCountAsync(
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string? httpMethod = null,
string url = null, string? url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string applicationName = null, string? applicationName = null,
string correlationId = null, string? correlationId = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default);
Task<List<AuditLog>> GetListAsync( Task<List<AuditLog>> GetListAsync(
string sorting = null, string? sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
string httpMethod = null, string? httpMethod = null,
string url = null, string? url = null,
Guid? userId = null, Guid? userId = null,
string userName = null, string? userName = null,
string applicationName = null, string? applicationName = null,
string correlationId = null, string? correlationId = null,
string clientId = null, string? clientId = null,
string clientIpAddress = null, string? clientIpAddress = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null, bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default);
}
} }

67
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IEntityChangeStore.cs

@ -4,43 +4,42 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public interface IEntityChangeStore
{ {
public interface IEntityChangeStore Task<EntityChange?> GetAsync(
{ Guid entityChangeId,
Task<EntityChange> GetAsync( CancellationToken cancellationToken = default);
Guid entityChangeId,
CancellationToken cancellationToken = default);
Task<long> GetCountAsync( Task<long> GetCountAsync(
Guid? auditLogId = null, Guid? auditLogId = null,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
EntityChangeType? changeType = null, EntityChangeType? changeType = null,
string entityId = null, string? entityId = null,
string entityTypeFullName = null, string? entityTypeFullName = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<List<EntityChange>> GetListAsync( Task<List<EntityChange>> GetListAsync(
string sorting = null, string? sorting = null,
int maxResultCount = 50, int maxResultCount = 50,
int skipCount = 0, int skipCount = 0,
Guid? auditLogId = null, Guid? auditLogId = null,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,
EntityChangeType? changeType = null, EntityChangeType? changeType = null,
string entityId = null, string? entityId = null,
string entityTypeFullName = null, string? entityTypeFullName = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<EntityChangeWithUsername> GetWithUsernameAsync( Task<EntityChangeWithUsername> GetWithUsernameAsync(
Guid entityChangeId, Guid entityChangeId,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<List<EntityChangeWithUsername>> GetWithUsernameAsync( Task<List<EntityChangeWithUsername>> GetWithUsernameAsync(
string entityId, string entityId,
string entityTypeFullName, string entityTypeFullName,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
}
} }

95
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs

@ -4,53 +4,52 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public interface ISecurityLogManager
{ {
public interface ISecurityLogManager Task<SecurityLog> GetAsync(
{ Guid id,
Task<SecurityLog> GetAsync( bool includeDetails = false,
Guid id, CancellationToken cancellationToken = default);
bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken)); Task DeleteAsync(
Guid id,
Task DeleteAsync( CancellationToken cancellationToken = default);
Guid id,
CancellationToken cancellationToken = default(CancellationToken)); Task SaveAsync(
SecurityLogInfo securityLogInfo,
Task SaveAsync( CancellationToken cancellationToken = default);
SecurityLogInfo securityLogInfo,
CancellationToken cancellationToken = default(CancellationToken)); Task<List<SecurityLog>> GetListAsync(
string? sorting = null,
Task<List<SecurityLog>> GetListAsync( int maxResultCount = 50,
string sorting = null, int skipCount = 0,
int maxResultCount = 50, DateTime? startTime = null,
int skipCount = 0, DateTime? endTime = null,
DateTime? startTime = null, string? applicationName = null,
DateTime? endTime = null, string? identity = null,
string applicationName = null, string? action = null,
string identity = null, Guid? userId = null,
string action = null, string? userName = null,
Guid? userId = null, string? clientId = null,
string userName = null, string? clientIpAddress = null,
string clientId = null, string? correlationId = null,
string clientIpAddress = null, bool includeDetails = false,
string correlationId = null, CancellationToken cancellationToken = default);
bool includeDetails = false,
CancellationToken cancellationToken = default(CancellationToken));
Task<long> GetCountAsync(
DateTime? startTime = null,
Task<long> GetCountAsync( DateTime? endTime = null,
DateTime? startTime = null, string? applicationName = null,
DateTime? endTime = null, string? identity = null,
string applicationName = null, string? action = null,
string identity = null, Guid? userId = null,
string action = null, string? userName = null,
Guid? userId = null, string? clientId = null,
string userName = null, string? clientIpAddress = null,
string clientId = null, string? correlationId = null,
string clientIpAddress = null, CancellationToken cancellationToken = default);
string correlationId = null,
CancellationToken cancellationToken = default(CancellationToken));
}
} }

83
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs

@ -2,70 +2,69 @@
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
public class SecurityLog : IHasExtraProperties
{ {
public class SecurityLog : IHasExtraProperties public Guid Id { get; set; }
{
public Guid Id { get; set; }
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public string ApplicationName { get; set; } public string? ApplicationName { get; set; }
public string Identity { get; set; } public string? Identity { get; set; }
public string Action { get; set; } public string? Action { get; set; }
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public string UserName { get; set; } public string? UserName { get; set; }
public string TenantName { get; set; } public string? TenantName { get; set; }
public string ClientId { get; set; } public string? ClientId { get; set; }
public string CorrelationId { get; set; } public string? CorrelationId { get; set; }
public string ClientIpAddress { get; set; } public string? ClientIpAddress { get; set; }
public string BrowserInfo { get; set; } public string? BrowserInfo { get; set; }
public DateTime CreationTime { get; set; } public DateTime CreationTime { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; set; } public ExtraPropertyDictionary ExtraProperties { get; set; }
public SecurityLog() public SecurityLog()
{ {
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
} }
public SecurityLog(Guid id, SecurityLogInfo securityLogInfo) public SecurityLog(Guid id, SecurityLogInfo securityLogInfo)
{ {
Id = id; Id = id;
TenantId = securityLogInfo.TenantId; TenantId = securityLogInfo.TenantId;
TenantName = securityLogInfo.TenantName; TenantName = securityLogInfo.TenantName;
ApplicationName = securityLogInfo.ApplicationName; ApplicationName = securityLogInfo.ApplicationName;
Identity = securityLogInfo.Identity; Identity = securityLogInfo.Identity;
Action = securityLogInfo.Action; Action = securityLogInfo.Action;
UserId = securityLogInfo.UserId; UserId = securityLogInfo.UserId;
UserName = securityLogInfo.UserName; UserName = securityLogInfo.UserName;
CreationTime = securityLogInfo.CreationTime; CreationTime = securityLogInfo.CreationTime;
ClientIpAddress = securityLogInfo.ClientIpAddress; ClientIpAddress = securityLogInfo.ClientIpAddress;
ClientId = securityLogInfo.ClientId; ClientId = securityLogInfo.ClientId;
CorrelationId = securityLogInfo.CorrelationId; CorrelationId = securityLogInfo.CorrelationId;
BrowserInfo = securityLogInfo.BrowserInfo; BrowserInfo = securityLogInfo.BrowserInfo;
ExtraProperties = new ExtraPropertyDictionary(); ExtraProperties = new ExtraPropertyDictionary();
if (securityLogInfo.ExtraProperties != null) if (securityLogInfo.ExtraProperties != null)
{
foreach (var pair in securityLogInfo.ExtraProperties)
{ {
foreach (var pair in securityLogInfo.ExtraProperties) ExtraProperties.Add(pair.Key, pair.Value);
{
ExtraProperties.Add(pair.Key, pair.Value);
}
} }
} }
} }

27
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs

@ -2,22 +2,21 @@
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
namespace LINGYUN.Abp.AuditLogging namespace LINGYUN.Abp.AuditLogging;
[Dependency(ReplaceServices = true)]
public class SecurityLogStore : ISecurityLogStore, ITransientDependency
{ {
[Dependency(ReplaceServices = true)] private readonly ISecurityLogManager _manager;
public class SecurityLogStore : ISecurityLogStore, ITransientDependency
{
private readonly ISecurityLogManager _manager;
public SecurityLogStore( public SecurityLogStore(
ISecurityLogManager manager) ISecurityLogManager manager)
{ {
_manager = manager; _manager = manager;
} }
public async virtual Task SaveAsync(SecurityLogInfo securityLogInfo) public async virtual Task SaveAsync(SecurityLogInfo securityLogInfo)
{ {
await _manager.SaveAsync(securityLogInfo); await _manager.SaveAsync(securityLogInfo);
}
} }
} }

5
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/LINGYUN.Abp.Authentication.QQ.csproj

@ -5,6 +5,11 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Authentication.QQ</AssemblyName>
<PackageId>LINGYUN.Abp.Authentication.QQ</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

53
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/LINGYUN/Abp/Authentication/QQ/AbpQQClaimTypes.cs

@ -1,31 +1,30 @@
namespace LINGYUN.Abp.Authentication.QQ namespace LINGYUN.Abp.Authentication.QQ;
/// <summary>
/// QQ互联身份类型,可以像 <see cref="Volo.Abp.Security.Claims.AbpClaimTypes"/> 自行配置
/// <br />
/// See: <see cref="https://wiki.connect.qq.com/get_user_info"/>
/// </summary>
public class AbpQQClaimTypes
{ {
/// <summary> /// <summary>
/// QQ互联身份类型,可以像 <see cref="Volo.Abp.Security.Claims.AbpClaimTypes"/> 自行配置 /// 用户的唯一标识
/// <br />
/// See: <see cref="https://wiki.connect.qq.com/get_user_info"/>
/// </summary> /// </summary>
public class AbpQQClaimTypes public static string OpenId { get; set; } = "qq-openid"; // 可变更
{ /// <summary>
/// <summary> /// 用户昵称
/// 用户的唯一标识 /// </summary>
/// </summary> public static string NickName { get; set; } = "nickname";
public static string OpenId { get; set; } = "qq-openid"; // 可变更 /// <summary>
/// <summary> /// 性别。 如果获取不到则默认返回"男"
/// 用户昵称 /// </summary>
/// </summary> public static string Gender { get; set; } = "gender";
public static string NickName { get; set; } = "nickname"; /// <summary>
/// <summary> /// 用户头像, 取自字段: figureurl_qq_1
/// 性别。 如果获取不到则默认返回"男" /// </summary>
/// </summary> /// <remarks>
public static string Gender { get; set; } = "gender"; /// 根据QQ互联文档, 40x40的头像是一定会存在的, 只取40x40的头像
/// <summary> /// see: https://wiki.connect.qq.com/get_user_info
/// 用户头像, 取自字段: figureurl_qq_1 /// </remarks>
/// </summary> public static string AvatarUrl { get; set; } = "avatar";
/// <remarks>
/// 根据QQ互联文档, 40x40的头像是一定会存在的, 只取40x40的头像
/// see: https://wiki.connect.qq.com/get_user_info
/// </remarks>
public static string AvatarUrl { get; set; } = "avatar";
}
} }

279
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthHandler.cs

@ -12,165 +12,164 @@ using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authentication.QQ namespace Microsoft.AspNetCore.Authentication.QQ;
/// <summary>
/// QQ互联实现
/// </summary>
public class QQConnectOAuthHandler : OAuthHandler<QQConnectOAuthOptions>
{ {
protected AbpTencentQQOptionsFactory TencentQQOptionsFactory { get; }
public QQConnectOAuthHandler(
IOptionsMonitor<QQConnectOAuthOptions> options,
AbpTencentQQOptionsFactory tencentQQOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder)
: base(options, logger, encoder)
{
TencentQQOptionsFactory = tencentQQOptionsFactory;
}
protected override async Task InitializeHandlerAsync()
{
var options = await TencentQQOptionsFactory.CreateAsync();
// 用配置项重写
Options.ClientId = options.AppId;
Options.ClientSecret = options.AppKey;
Options.IsMobile = options.IsMobile;
Options.TimeProvider ??= TimeProvider.System;
await base.InitializeHandlerAsync();
}
/// <summary> /// <summary>
/// QQ互联实现 /// 构建用户授权地址
/// </summary> /// </summary>
public class QQConnectOAuthHandler : OAuthHandler<QQConnectOAuthOptions> protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{ {
protected AbpTencentQQOptionsFactory TencentQQOptionsFactory { get; } var challengeUrl = base.BuildChallengeUrl(properties, redirectUri);
public QQConnectOAuthHandler( if (Options.IsMobile)
IOptionsMonitor<QQConnectOAuthOptions> options,
AbpTencentQQOptionsFactory tencentQQOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder)
: base(options, logger, encoder)
{ {
TencentQQOptionsFactory = tencentQQOptionsFactory; challengeUrl += "&display=mobile";
} }
return challengeUrl;
protected override async Task InitializeHandlerAsync() }
/// <summary>
/// code换取access_token
/// </summary>
protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary<string, string>()
{ {
var options = await TencentQQOptionsFactory.CreateAsync(); { "client_id", Options.ClientId },
{ "redirect_uri", context.RedirectUri },
{ "client_secret", Options.ClientSecret},
{ "code", context.Code},
{ "grant_type","authorization_code"}
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
// 用配置项重写 var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
Options.ClientId = options.AppId; if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
Options.ClientSecret = options.AppKey; {
Options.IsMobile = options.IsMobile; Logger.LogError("An error occurred while retrieving an access token: the remote server " +
Options.TimeProvider ??= TimeProvider.System; "returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
await base.InitializeHandlerAsync(); return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
} }
return OAuthTokenResponse.Success(payload);
}
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var openIdEndpoint = Options.OpenIdEndpoint + "?access_token=" + tokens.AccessToken + "&fmt=json";
var openIdResponse = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);
openIdResponse.EnsureSuccessStatusCode();
var openIdPayload = JsonDocument.Parse(await openIdResponse.Content.ReadAsStringAsync());
var openId = openIdPayload.GetRootString("openid");
/// <summary> identity.AddClaim(new Claim(AbpQQClaimTypes.OpenId, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
/// 构建用户授权地址
/// </summary> var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri) {
{"oauth_consumer_key", Options.ClientId},
{"access_token", tokens.AccessToken},
{"openid", openId}
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{ {
var challengeUrl = base.BuildChallengeUrl(properties, redirectUri); Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
if (Options.IsMobile) "returned a {Status} response with the following payload: {Headers} {Body}.",
{ /* Status: */ response.StatusCode,
challengeUrl += "&display=mobile"; /* Headers: */ response.Headers.ToString(),
} /* Body: */ await response.Content.ReadAsStringAsync());
return challengeUrl;
throw new HttpRequestException("An error occurred while retrieving user information.");
} }
/// <summary> var userInfoPayload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
/// code换取access_token var errorCode = userInfoPayload.GetRootString("ret");
/// </summary> if (!"0".Equals(errorCode))
protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{ {
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary<string, string>() // See: https://wiki.connect.qq.com/%e5%85%ac%e5%85%b1%e8%bf%94%e5%9b%9e%e7%a0%81%e8%af%b4%e6%98%8e
{ Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
{ "client_id", Options.ClientId }, "returned code {Code} response with message: {Message}.",
{ "redirect_uri", context.RedirectUri }, errorCode,
{ "client_secret", Options.ClientSecret}, userInfoPayload.GetRootString("msg"));
{ "code", context.Code},
{ "grant_type","authorization_code"} throw new HttpRequestException("An error occurred while retrieving user information.");
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
return OAuthTokenResponse.Success(payload);
} }
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens) var nickName = userInfoPayload.GetRootString("nickname");
if (!nickName.IsNullOrWhiteSpace())
{ {
var openIdEndpoint = Options.OpenIdEndpoint + "?access_token=" + tokens.AccessToken + "&fmt=json"; identity.AddClaim(new Claim(AbpQQClaimTypes.NickName, nickName, ClaimValueTypes.String, Options.ClaimsIssuer));
var openIdResponse = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);
openIdResponse.EnsureSuccessStatusCode();
var openIdPayload = JsonDocument.Parse(await openIdResponse.Content.ReadAsStringAsync());
var openId = openIdPayload.GetRootString("openid");
identity.AddClaim(new Claim(AbpQQClaimTypes.OpenId, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
{
{"oauth_consumer_key", Options.ClientId},
{"access_token", tokens.AccessToken},
{"openid", openId}
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
throw new HttpRequestException("An error occurred while retrieving user information.");
}
var userInfoPayload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var errorCode = userInfoPayload.GetRootString("ret");
if (!"0".Equals(errorCode))
{
// See: https://wiki.connect.qq.com/%e5%85%ac%e5%85%b1%e8%bf%94%e5%9b%9e%e7%a0%81%e8%af%b4%e6%98%8e
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned code {Code} response with message: {Message}.",
errorCode,
userInfoPayload.GetRootString("msg"));
throw new HttpRequestException("An error occurred while retrieving user information.");
}
var nickName = userInfoPayload.GetRootString("nickname");
if (!nickName.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.NickName, nickName, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var gender = userInfoPayload.GetRootString("gender");
if (!gender.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.Gender, gender, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var avatarUrl = userInfoPayload.GetRootString("figureurl_qq_1");
if (!avatarUrl.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.AvatarUrl, avatarUrl, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var context = new OAuthCreatingTicketContext(
new ClaimsPrincipal(identity),
properties,
Context,
Scheme,
Options,
Backchannel,
tokens,
userInfoPayload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
} }
var gender = userInfoPayload.GetRootString("gender");
if (!gender.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.Gender, gender, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var avatarUrl = userInfoPayload.GetRootString("figureurl_qq_1");
if (!avatarUrl.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.AvatarUrl, avatarUrl, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var context = new OAuthCreatingTicketContext(
new ClaimsPrincipal(identity),
properties,
Context,
Scheme,
Options,
Backchannel,
tokens,
userInfoPayload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
} }
} }

73
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthOptions.cs

@ -3,44 +3,43 @@ using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Security.Claims; using System.Security.Claims;
namespace Microsoft.AspNetCore.Authentication.QQ namespace Microsoft.AspNetCore.Authentication.QQ;
public class QQConnectOAuthOptions : OAuthOptions
{ {
public class QQConnectOAuthOptions : OAuthOptions /// <summary>
/// 是否移动端样式
/// </summary>
public bool IsMobile { get; set; }
/// <summary>
/// 获取用户OpenID_OAuth2.0
/// </summary>
public string OpenIdEndpoint { get; set; }
public QQConnectOAuthOptions()
{ {
/// <summary> // 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
/// 是否移动端样式 ClientId = "QQConnect";
/// </summary> ClientSecret = "QQConnect";
public bool IsMobile { get; set; }
/// <summary> ClaimsIssuer = "connect.qq.com";
/// 获取用户OpenID_OAuth2.0 CallbackPath = new PathString(AbpAuthenticationQQConsts.CallbackPath);
/// </summary>
public string OpenIdEndpoint { get; set; } AuthorizationEndpoint = "https://graph.qq.com/oauth2.0/authorize";
TokenEndpoint = "https://graph.qq.com/oauth2.0/token";
public QQConnectOAuthOptions() OpenIdEndpoint = "https://graph.qq.com/oauth2.0/me";
{ UserInformationEndpoint = "https://graph.qq.com/user/get_user_info";
// 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
ClientId = "QQConnect"; Scope.Add("get_user_info");
ClientSecret = "QQConnect";
// 这个原始的属性一定要写进去,框架关联判断是否绑定QQ
ClaimsIssuer = "connect.qq.com"; ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
CallbackPath = new PathString(AbpAuthenticationQQConsts.CallbackPath); ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
AuthorizationEndpoint = "https://graph.qq.com/oauth2.0/authorize"; // 把自定义的身份标识写进令牌
TokenEndpoint = "https://graph.qq.com/oauth2.0/token"; ClaimActions.MapJsonKey(AbpQQClaimTypes.OpenId, "openid");
OpenIdEndpoint = "https://graph.qq.com/oauth2.0/me"; ClaimActions.MapJsonKey(AbpQQClaimTypes.NickName, "nickname");
UserInformationEndpoint = "https://graph.qq.com/user/get_user_info"; ClaimActions.MapJsonKey(AbpQQClaimTypes.Gender, "gender");
ClaimActions.MapJsonKey(AbpQQClaimTypes.AvatarUrl, "figureurl_qq_1");
Scope.Add("get_user_info");
// 这个原始的属性一定要写进去,框架关联判断是否绑定QQ
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
// 把自定义的身份标识写进令牌
ClaimActions.MapJsonKey(AbpQQClaimTypes.OpenId, "openid");
ClaimActions.MapJsonKey(AbpQQClaimTypes.NickName, "nickname");
ClaimActions.MapJsonKey(AbpQQClaimTypes.Gender, "gender");
ClaimActions.MapJsonKey(AbpQQClaimTypes.AvatarUrl, "figureurl_qq_1");
}
} }
} }

101
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/Microsoft/AspNetCore/Authentication/QQAuthenticationExtensions.cs

@ -3,61 +3,60 @@ using Microsoft.AspNetCore.Authentication.QQ;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication;
public static class QQAuthenticationExtensions
{ {
public static class QQAuthenticationExtensions /// <summary>
/// </summary>
public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder)
{ {
/// <summary> return builder
/// </summary> .AddQQConnect(
public static AuthenticationBuilder AddQQConnect( AbpAuthenticationQQConsts.AuthenticationScheme,
this AuthenticationBuilder builder) AbpAuthenticationQQConsts.DisplayName,
{ options => { });
return builder }
.AddQQConnect(
AbpAuthenticationQQConsts.AuthenticationScheme,
AbpAuthenticationQQConsts.DisplayName,
options => { });
}
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddQQConnect( public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
Action<QQConnectOAuthOptions> configureOptions) Action<QQConnectOAuthOptions> configureOptions)
{ {
return builder return builder
.AddQQConnect( .AddQQConnect(
AbpAuthenticationQQConsts.AuthenticationScheme, AbpAuthenticationQQConsts.AuthenticationScheme,
configureOptions); configureOptions);
} }
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddQQConnect( public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
string authenticationScheme, string authenticationScheme,
Action<QQConnectOAuthOptions> configureOptions) Action<QQConnectOAuthOptions> configureOptions)
{ {
return builder return builder
.AddQQConnect( .AddQQConnect(
authenticationScheme, authenticationScheme,
AbpAuthenticationQQConsts.DisplayName, AbpAuthenticationQQConsts.DisplayName,
configureOptions); configureOptions);
} }
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddQQConnect( public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
string authenticationScheme, string authenticationScheme,
string displayName, string displayName,
Action<QQConnectOAuthOptions> configureOptions) Action<QQConnectOAuthOptions> configureOptions)
{ {
return builder return builder
.AddOAuth<QQConnectOAuthOptions, QQConnectOAuthHandler>( .AddOAuth<QQConnectOAuthOptions, QQConnectOAuthHandler>(
authenticationScheme, authenticationScheme,
displayName, displayName,
configureOptions); configureOptions);
}
} }
} }

15
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/BytesExtensions.cs

@ -1,16 +1,15 @@
using System.Security.Cryptography; using System.Security.Cryptography;
namespace System namespace System;
internal static class BytesExtensions
{ {
internal static class BytesExtensions public static byte[] Sha1(this byte[] data)
{ {
public static byte[] Sha1(this byte[] data) using (var sha = SHA1.Create())
{ {
using (var sha = SHA1.Create()) var hashBytes = sha.ComputeHash(data);
{ return hashBytes;
var hashBytes = sha.ComputeHash(data);
return hashBytes;
}
} }
} }
} }

15
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/StringExtensions.cs

@ -1,17 +1,16 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace System namespace System;
internal static class StringExtensions
{ {
internal static class StringExtensions public static byte[] Sha1(this string str)
{ {
public static byte[] Sha1(this string str) using (var sha = SHA1.Create())
{ {
using (var sha = SHA1.Create()) var hashBytes = sha.ComputeHash(Encoding.ASCII.GetBytes(str));
{ return hashBytes;
var hashBytes = sha.ComputeHash(Encoding.ASCII.GetBytes(str));
return hashBytes;
}
} }
} }
} }

79
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.QQ/System/Text/Json/JsonElementExtensions.cs

@ -1,63 +1,62 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace System.Text.Json namespace System.Text.Json;
internal static class JsonElementExtensions
{ {
internal static class JsonElementExtensions public static IEnumerable<string> GetRootStrings(this JsonDocument json, string key)
{ {
public static IEnumerable<string> GetRootStrings(this JsonDocument json, string key) return json.RootElement.GetStrings(key);
{ }
return json.RootElement.GetStrings(key);
}
public static IEnumerable<string> GetStrings(this JsonElement json, string key) public static IEnumerable<string> GetStrings(this JsonElement json, string key)
{ {
var result = new List<string>(); var result = new List<string>();
if (json.TryGetProperty(key, out JsonElement property) && property.ValueKind == JsonValueKind.Array) if (json.TryGetProperty(key, out JsonElement property) && property.ValueKind == JsonValueKind.Array)
{
foreach (var jsonProp in property.EnumerateArray())
{ {
foreach (var jsonProp in property.EnumerateArray()) result.Add(jsonProp.GetString());
{
result.Add(jsonProp.GetString());
}
} }
return result;
} }
public static string GetRootString(this JsonDocument json, string key, string defaultValue = "") return result;
}
public static string GetRootString(this JsonDocument json, string key, string defaultValue = "")
{
if (json.RootElement.TryGetProperty(key, out JsonElement property))
{ {
if (json.RootElement.TryGetProperty(key, out JsonElement property)) return property.GetString();
{
return property.GetString();
}
return defaultValue;
} }
return defaultValue;
}
public static string GetString(this JsonElement json, string key, string defaultValue = "") public static string GetString(this JsonElement json, string key, string defaultValue = "")
{
if (json.TryGetProperty(key, out JsonElement property))
{ {
if (json.TryGetProperty(key, out JsonElement property)) return property.GetString();
{
return property.GetString();
}
return defaultValue;
} }
return defaultValue;
}
public static int GetRootInt32(this JsonDocument json, string key, int defaultValue = 0) public static int GetRootInt32(this JsonDocument json, string key, int defaultValue = 0)
{
if (json.RootElement.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
{ {
if (json.RootElement.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value)) return value;
{
return value;
}
return defaultValue;
} }
return defaultValue;
}
public static int GetInt32(this JsonElement json, string key, int defaultValue = 0) public static int GetInt32(this JsonElement json, string key, int defaultValue = 0)
{
if (json.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
{ {
if (json.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value)) return value;
{
return value;
}
return defaultValue;
} }
return defaultValue;
} }
} }

5
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/LINGYUN.Abp.Authentication.WeChat.csproj

@ -5,6 +5,11 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Authentication.WeChat</AssemblyName>
<PackageId>LINGYUN.Abp.Authentication.WeChat</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

455
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs

@ -16,299 +16,298 @@ using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authentication.WeChat.Official namespace Microsoft.AspNetCore.Authentication.WeChat.Official;
/// <summary>
/// 网页授权只有公众平台的实现
/// </summary>
public class WeChatOfficialOAuthHandler : OAuthHandler<WeChatOfficialOAuthOptions>
{ {
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; }
public WeChatOfficialOAuthHandler(
IOptionsMonitor<WeChatOfficialOAuthOptions> options,
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder)
: base(options, logger, encoder)
{
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
}
protected override async Task InitializeHandlerAsync()
{
var weChatOfficialOptions = await WeChatOfficialOptionsFactory.CreateAsync();
// 用配置项重写
Options.ClientId = weChatOfficialOptions.AppId;
Options.ClientSecret = weChatOfficialOptions.AppSecret;
Options.TimeProvider ??= TimeProvider.System;
await base.InitializeHandlerAsync();
}
/// <summary> /// <summary>
/// 网页授权只有公众平台的实现 /// 第一步:构建用户授权地址
/// </summary> /// </summary>
public class WeChatOfficialOAuthHandler : OAuthHandler<WeChatOfficialOAuthOptions> protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{ {
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; } var isWeChatBrewserRequest = IsWeChatBrowser();
public WeChatOfficialOAuthHandler(
IOptionsMonitor<WeChatOfficialOAuthOptions> options,
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder)
: base(options, logger, encoder)
{
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
}
protected override async Task InitializeHandlerAsync() var scope = isWeChatBrewserRequest
{ ? AbpAuthenticationWeChatConsts.UserInfoScope
var weChatOfficialOptions = await WeChatOfficialOptionsFactory.CreateAsync(); : AbpAuthenticationWeChatConsts.LoginScope;
// 用配置项重写 var endPoint = isWeChatBrewserRequest
Options.ClientId = weChatOfficialOptions.AppId; ? Options.AuthorizationEndpoint
Options.ClientSecret = weChatOfficialOptions.AppSecret; : AbpAuthenticationWeChatConsts.QrConnectEndpoint;
Options.TimeProvider ??= TimeProvider.System;
await base.InitializeHandlerAsync(); redirectUri += $"?protected={Options.StateDataFormat.Protect(properties)}";
}
/// <summary> var parameters = new Dictionary<string, string>
/// 第一步:构建用户授权地址
/// </summary>
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{ {
var isWeChatBrewserRequest = IsWeChatBrowser(); { "appid", Options.ClientId },
{ "redirect_uri", redirectUri },
{ "response_type", "code" },
{ "scope", scope },
{ "state", Guid.NewGuid().ToString("N") },
};
return $"{QueryHelpers.AddQueryString(endPoint, parameters)}#wechat_redirect";
}
var scope = isWeChatBrewserRequest /// <summary>
? AbpAuthenticationWeChatConsts.UserInfoScope /// 第二步:code换取access_token
: AbpAuthenticationWeChatConsts.LoginScope; /// </summary>
protected async override Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{
var parameters = new Dictionary<string, string>()
{
{ "appid", Options.ClientId },
{ "secret", Options.ClientSecret },
{ "code", context.Code },
{ "grant_type", "authorization_code" },
};
var endPoint = isWeChatBrewserRequest var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, parameters);
? Options.AuthorizationEndpoint
: AbpAuthenticationWeChatConsts.QrConnectEndpoint;
redirectUri += $"?protected={Options.StateDataFormat.Protect(properties)}"; var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
var parameters = new Dictionary<string, string> return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
{
{ "appid", Options.ClientId },
{ "redirect_uri", redirectUri },
{ "response_type", "code" },
{ "scope", scope },
{ "state", Guid.NewGuid().ToString("N") },
};
return $"{QueryHelpers.AddQueryString(endPoint, parameters)}#wechat_redirect";
} }
/// <summary> var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
/// 第二步:code换取access_token if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
/// </summary>
protected async override Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{ {
var parameters = new Dictionary<string, string>() Logger.LogError("An error occurred while retrieving an access token: the remote server " +
{ "returned a {Status} response with the following payload: {Headers} {Body}.",
{ "appid", Options.ClientId }, /* Status: */ response.StatusCode,
{ "secret", Options.ClientSecret }, /* Headers: */ response.Headers.ToString(),
{ "code", context.Code }, /* Body: */ await response.Content.ReadAsStringAsync());
{ "grant_type", "authorization_code" },
};
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, parameters); return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
var response = await Backchannel.GetAsync(address); return OAuthTokenResponse.Success(payload);
if (!response.IsSuccessStatusCode) }
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")); /// <summary>
} /// 第三步:构建用户票据
/// </summary>
/// <param name="identity"></param>
/// <param name="properties"></param>
/// <param name="tokens"></param>
/// <returns></returns>
/// <exception cref="HttpRequestException"></exception>
protected async override Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
{
["access_token"] = tokens.AccessToken,
["openid"] = tokens.Response.GetRootString("openid")
});
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); var response = await Backchannel.GetAsync(address);
if (!string.IsNullOrEmpty(payload.GetRootString("errcode"))) if (!response.IsSuccessStatusCode)
{ {
Logger.LogError("An error occurred while retrieving an access token: the remote server " + Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.", "returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode, /* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(), /* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync()); /* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")); throw new HttpRequestException("An error occurred while retrieving user information.");
}
return OAuthTokenResponse.Success(payload);
} }
/// <summary> var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
/// 第三步:构建用户票据 if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
/// </summary>
/// <param name="identity"></param>
/// <param name="properties"></param>
/// <param name="tokens"></param>
/// <returns></returns>
/// <exception cref="HttpRequestException"></exception>
protected async override Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{ {
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string> Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
{ "returned a {Status} response with the following payload: {Headers} {Body}.",
["access_token"] = tokens.AccessToken, /* Status: */ response.StatusCode,
["openid"] = tokens.Response.GetRootString("openid") /* Headers: */ response.Headers.ToString(),
}); /* Body: */ await response.Content.ReadAsStringAsync());
var response = await Backchannel.GetAsync(address); throw new HttpRequestException("An error occurred while retrieving user information.");
if (!response.IsSuccessStatusCode) }
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
throw new HttpRequestException("An error occurred while retrieving user information."); var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
} context.RunClaimActions();
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); await Events.CreatingTicket(context);
if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
throw new HttpRequestException("An error occurred while retrieving user information."); return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
} }
public override Task<bool> HandleRequestAsync()
{
return base.HandleRequestAsync();
}
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement); protected async override Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
context.RunClaimActions(); {
var query = Request.Query;
await Events.CreatingTicket(context); // TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密
var state = query["protected"];
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name); var properties = Options.StateDataFormat.Unprotect(state);
}
public override Task<bool> HandleRequestAsync() if (properties == null)
{ {
return base.HandleRequestAsync(); return HandleRequestResult.Fail("The oauth state was missing or invalid.");
} }
protected async override Task<HandleRequestResult> HandleRemoteAuthenticateAsync() // OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties))
{ {
var query = Request.Query; return HandleRequestResult.Fail("Correlation failed.", properties);
}
// TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密 var error = query["error"];
var state = query["protected"]; if (!StringValues.IsNullOrEmpty(error))
{
// Note: access_denied errors are special protocol errors indicating the user didn't
// approve the authorization demand requested by the remote authorization server.
// Since it's a frequent scenario (that is not caused by incorrect configuration),
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
// Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
var errorDescription = query["error_description"];
var errorUri = query["error_uri"];
if (StringValues.Equals(error, "access_denied"))
{
var result = await HandleAccessDeniedErrorAsync(properties);
if (!result.None)
{
return result;
}
var deniedEx = new Exception("Access was denied by the resource owner or by the remote server.");
deniedEx.Data["error"] = error.ToString();
deniedEx.Data["error_description"] = errorDescription.ToString();
deniedEx.Data["error_uri"] = errorUri.ToString();
var properties = Options.StateDataFormat.Unprotect(state); return HandleRequestResult.Fail(deniedEx, properties);
}
if (properties == null) var failureMessage = new StringBuilder();
failureMessage.Append(error);
if (!StringValues.IsNullOrEmpty(errorDescription))
{ {
return HandleRequestResult.Fail("The oauth state was missing or invalid."); failureMessage.Append(";Description=").Append(errorDescription);
} }
if (!StringValues.IsNullOrEmpty(errorUri))
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties))
{ {
return HandleRequestResult.Fail("Correlation failed.", properties); failureMessage.Append(";Uri=").Append(errorUri);
} }
var error = query["error"]; var ex = new Exception(failureMessage.ToString());
if (!StringValues.IsNullOrEmpty(error)) ex.Data["error"] = error.ToString();
{ ex.Data["error_description"] = errorDescription.ToString();
// Note: access_denied errors are special protocol errors indicating the user didn't ex.Data["error_uri"] = errorUri.ToString();
// approve the authorization demand requested by the remote authorization server.
// Since it's a frequent scenario (that is not caused by incorrect configuration),
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
// Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
var errorDescription = query["error_description"];
var errorUri = query["error_uri"];
if (StringValues.Equals(error, "access_denied"))
{
var result = await HandleAccessDeniedErrorAsync(properties);
if (!result.None)
{
return result;
}
var deniedEx = new Exception("Access was denied by the resource owner or by the remote server.");
deniedEx.Data["error"] = error.ToString();
deniedEx.Data["error_description"] = errorDescription.ToString();
deniedEx.Data["error_uri"] = errorUri.ToString();
return HandleRequestResult.Fail(deniedEx, properties);
}
var failureMessage = new StringBuilder(); return HandleRequestResult.Fail(ex, properties);
failureMessage.Append(error); }
if (!StringValues.IsNullOrEmpty(errorDescription))
{
failureMessage.Append(";Description=").Append(errorDescription);
}
if (!StringValues.IsNullOrEmpty(errorUri))
{
failureMessage.Append(";Uri=").Append(errorUri);
}
var ex = new Exception(failureMessage.ToString()); var code = query["code"];
ex.Data["error"] = error.ToString();
ex.Data["error_description"] = errorDescription.ToString();
ex.Data["error_uri"] = errorUri.ToString();
return HandleRequestResult.Fail(ex, properties); if (StringValues.IsNullOrEmpty(code))
} {
return HandleRequestResult.Fail("Code was not found.", properties);
}
var code = query["code"]; var codeExchangeContext = new OAuthCodeExchangeContext(properties, code, BuildRedirectUri(Options.CallbackPath));
using var tokens = await ExchangeCodeAsync(codeExchangeContext);
if (StringValues.IsNullOrEmpty(code)) if (tokens.Error != null)
{ {
return HandleRequestResult.Fail("Code was not found.", properties); return HandleRequestResult.Fail(tokens.Error, properties);
} }
if (string.IsNullOrEmpty(tokens.AccessToken))
{
return HandleRequestResult.Fail("Failed to retrieve access token.", properties);
}
var codeExchangeContext = new OAuthCodeExchangeContext(properties, code, BuildRedirectUri(Options.CallbackPath)); var identity = new ClaimsIdentity(ClaimsIssuer);
using var tokens = await ExchangeCodeAsync(codeExchangeContext);
if (tokens.Error != null) if (Options.SaveTokens)
{
var authTokens = new List<AuthenticationToken>();
authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
if (!string.IsNullOrEmpty(tokens.RefreshToken))
{ {
return HandleRequestResult.Fail(tokens.Error, properties); authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
} }
if (string.IsNullOrEmpty(tokens.AccessToken)) if (!string.IsNullOrEmpty(tokens.TokenType))
{ {
return HandleRequestResult.Fail("Failed to retrieve access token.", properties); authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType });
} }
var identity = new ClaimsIdentity(ClaimsIssuer); if (!string.IsNullOrEmpty(tokens.ExpiresIn))
if (Options.SaveTokens)
{ {
var authTokens = new List<AuthenticationToken>(); int value;
if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
if (!string.IsNullOrEmpty(tokens.RefreshToken))
{
authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
}
if (!string.IsNullOrEmpty(tokens.TokenType))
{ {
authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType }); // https://www.w3.org/TR/xmlschema-2/#dateTime
} // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
var expiresAt = Options.TimeProvider.GetUtcNow() + TimeSpan.FromSeconds(value);
if (!string.IsNullOrEmpty(tokens.ExpiresIn)) authTokens.Add(new AuthenticationToken
{
int value;
if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{ {
// https://www.w3.org/TR/xmlschema-2/#dateTime Name = "expires_at",
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
var expiresAt = Options.TimeProvider.GetUtcNow() + TimeSpan.FromSeconds(value); });
authTokens.Add(new AuthenticationToken
{
Name = "expires_at",
Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
});
}
} }
properties.StoreTokens(authTokens);
} }
var ticket = await CreateTicketAsync(identity, properties, tokens); properties.StoreTokens(authTokens);
if (ticket != null)
{
return HandleRequestResult.Success(ticket);
}
else
{
return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
}
} }
protected override string FormatScope() var ticket = await CreateTicketAsync(identity, properties, tokens);
if (ticket != null)
{ {
return string.Join(",", Options.Scope); return HandleRequestResult.Success(ticket);
} }
else
protected virtual bool IsWeChatBrowser()
{ {
var userAgent = Request.Headers[HeaderNames.UserAgent].ToString(); return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
return userAgent.Contains("micromessenger", StringComparison.InvariantCultureIgnoreCase);
} }
} }
protected override string FormatScope()
{
return string.Join(",", Options.Scope);
}
protected virtual bool IsWeChatBrowser()
{
var userAgent = Request.Headers[HeaderNames.UserAgent].ToString();
return userAgent.Contains("micromessenger", StringComparison.InvariantCultureIgnoreCase);
}
} }

61
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs

@ -5,43 +5,42 @@ using Microsoft.AspNetCore.Http;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Json; using System.Text.Json;
namespace Microsoft.AspNetCore.Authentication.WeChat.Official namespace Microsoft.AspNetCore.Authentication.WeChat.Official;
public class WeChatOfficialOAuthOptions : OAuthOptions
{ {
public class WeChatOfficialOAuthOptions : OAuthOptions public WeChatOfficialOAuthOptions()
{ {
public WeChatOfficialOAuthOptions() // 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
{ ClientId = "WeChatOfficial";
// 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写 ClientSecret = "WeChatOfficial";
ClientId = "WeChatOfficial";
ClientSecret = "WeChatOfficial";
ClaimsIssuer = AbpAuthenticationWeChatConsts.ProviderKey; ClaimsIssuer = AbpAuthenticationWeChatConsts.ProviderKey;
CallbackPath = new PathString(AbpAuthenticationWeChatConsts.CallbackPath); CallbackPath = new PathString(AbpAuthenticationWeChatConsts.CallbackPath);
AuthorizationEndpoint = AbpAuthenticationWeChatConsts.AuthorizationEndpoint; AuthorizationEndpoint = AbpAuthenticationWeChatConsts.AuthorizationEndpoint;
TokenEndpoint = AbpAuthenticationWeChatConsts.TokenEndpoint; TokenEndpoint = AbpAuthenticationWeChatConsts.TokenEndpoint;
UserInformationEndpoint = AbpAuthenticationWeChatConsts.UserInformationEndpoint; UserInformationEndpoint = AbpAuthenticationWeChatConsts.UserInformationEndpoint;
Scope.Add(AbpAuthenticationWeChatConsts.LoginScope); Scope.Add(AbpAuthenticationWeChatConsts.LoginScope);
Scope.Add(AbpAuthenticationWeChatConsts.UserInfoScope); Scope.Add(AbpAuthenticationWeChatConsts.UserInfoScope);
// 这个原始的属性一定要写进去,框架与UserLogin.ProviderKey进行关联判断是否绑定微信 // 这个原始的属性一定要写进去,框架与UserLogin.ProviderKey进行关联判断是否绑定微信
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid"); ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname"); ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
// 把自定义的身份标识写进令牌 // 把自定义的身份标识写进令牌
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.OpenId, "openid"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.OpenId, "openid");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.UnionId, "unionid");// 公众号如果与小程序关联,这个可以用上 ClaimActions.MapJsonKey(AbpWeChatClaimTypes.UnionId, "unionid");// 公众号如果与小程序关联,这个可以用上
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.NickName, "nickname"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.NickName, "nickname");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Sex, "sex", ClaimValueTypes.Integer); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Sex, "sex", ClaimValueTypes.Integer);
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Country, "country"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Country, "country");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Province, "province"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Province, "province");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.City, "city"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.City, "city");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.AvatarUrl, "headimgurl"); ClaimActions.MapJsonKey(AbpWeChatClaimTypes.AvatarUrl, "headimgurl");
ClaimActions.MapCustomJson(AbpWeChatClaimTypes.Privilege, user => ClaimActions.MapCustomJson(AbpWeChatClaimTypes.Privilege, user =>
{ {
return string.Join(",", user.GetStrings("privilege")); return string.Join(",", user.GetStrings("privilege"));
}); });
}
} }
} }

25
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs

@ -1,18 +1,17 @@
namespace Microsoft.AspNetCore.Authentication.WeChat.Official namespace Microsoft.AspNetCore.Authentication.WeChat.Official;
public class WeChatOfficialStateCacheItem
{ {
public class WeChatOfficialStateCacheItem public string State { get; set; }
{
public string State { get; set; }
public WeChatOfficialStateCacheItem() { } public WeChatOfficialStateCacheItem() { }
public WeChatOfficialStateCacheItem(string state) public WeChatOfficialStateCacheItem(string state)
{ {
State = state; State = state;
} }
public static string CalculateCacheKey(string correlationId, string purpose) public static string CalculateCacheKey(string correlationId, string purpose)
{ {
return $"ci:{correlationId};p:{purpose ?? "null"}"; return $"ci:{correlationId};p:{purpose ?? "null"}";
}
} }
} }

103
aspnet-core/framework/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs

@ -4,62 +4,61 @@ using Microsoft.AspNetCore.Authentication.WeChat.Official;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication;
public static class WeChatAuthenticationExtensions
{ {
public static class WeChatAuthenticationExtensions /// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder)
{ {
/// <summary> return builder
/// </summary> .AddWeChat(
public static AuthenticationBuilder AddWeChat( AbpWeChatGlobalConsts.AuthenticationScheme,
this AuthenticationBuilder builder) AbpWeChatGlobalConsts.DisplayName,
{ options => { });
return builder }
.AddWeChat(
AbpWeChatGlobalConsts.AuthenticationScheme,
AbpWeChatGlobalConsts.DisplayName,
options => { });
}
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddWeChat( public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
Action<WeChatOfficialOAuthOptions> configureOptions) Action<WeChatOfficialOAuthOptions> configureOptions)
{ {
return builder return builder
.AddWeChat( .AddWeChat(
AbpWeChatGlobalConsts.AuthenticationScheme, AbpWeChatGlobalConsts.AuthenticationScheme,
AbpWeChatGlobalConsts.DisplayName, AbpWeChatGlobalConsts.DisplayName,
configureOptions); configureOptions);
} }
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddWeChat( public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
string authenticationScheme, string authenticationScheme,
Action<WeChatOfficialOAuthOptions> configureOptions) Action<WeChatOfficialOAuthOptions> configureOptions)
{ {
return builder return builder
.AddWeChat( .AddWeChat(
authenticationScheme, authenticationScheme,
AbpAuthenticationWeChatConsts.DisplayName, AbpAuthenticationWeChatConsts.DisplayName,
configureOptions); configureOptions);
} }
/// <summary> /// <summary>
/// </summary> /// </summary>
public static AuthenticationBuilder AddWeChat( public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder, this AuthenticationBuilder builder,
string authenticationScheme, string authenticationScheme,
string displayName, string displayName,
Action<WeChatOfficialOAuthOptions> configureOptions) Action<WeChatOfficialOAuthOptions> configureOptions)
{ {
return builder return builder
.AddOAuth<WeChatOfficialOAuthOptions, WeChatOfficialOAuthHandler>( .AddOAuth<WeChatOfficialOAuthOptions, WeChatOfficialOAuthHandler>(
authenticationScheme, authenticationScheme,
displayName, displayName,
configureOptions); configureOptions);
}
} }
} }

9
aspnet-core/framework/authorization/LINGYUN.Abp.Authorization.OrganizationUnits/LINGYUN.Abp.Authorization.OrganizationUnits.csproj

@ -4,7 +4,14 @@
<Import Project="..\..\..\..\common.props" /> <Import Project="..\..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>LINGYUN.Abp.Authorization.OrganizationUnits</AssemblyName>
<PackageId>LINGYUN.Abp.Authorization.OrganizationUnits</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

2
aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj

@ -5,7 +5,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Version>8.1.1</Version> <Version>8.2.0</Version>
<Copyright>colin</Copyright> <Copyright>colin</Copyright>
<Description>Use LINGYUN.MicroService.Templates command line</Description> <Description>Use LINGYUN.MicroService.Templates command line</Description>
<PackAsTool>true</PackAsTool> <PackAsTool>true</PackAsTool>

5
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN.Abp.Aliyun.SettingManagement.csproj

@ -5,6 +5,11 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Aliyun.SettingManagement</AssemblyName>
<PackageId>LINGYUN.Abp.Aliyun.SettingManagement</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

49
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AbpAliyunSettingManagementModule.cs

@ -7,36 +7,35 @@ using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
[DependsOn(
typeof(AbpAliyunModule),
typeof(AbpAliyunSmsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpAliyunSettingManagementModule : AbpModule
{ {
[DependsOn( public override void PreConfigureServices(ServiceConfigurationContext context)
typeof(AbpAliyunModule),
typeof(AbpAliyunSmsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpAliyunSettingManagementModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) PreConfigure<IMvcBuilder>(mvcBuilder =>
{ {
PreConfigure<IMvcBuilder>(mvcBuilder => mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAliyunSettingManagementModule).Assembly);
{ });
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAliyunSettingManagementModule).Assembly); }
});
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<AbpAliyunSettingManagementModule>();
{ });
options.FileSets.AddEmbedded<AbpAliyunSettingManagementModule>();
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options.Resources
.Get<AliyunResource>() .Get<AliyunResource>()
.AddBaseTypes(typeof(AbpUiResource)) .AddBaseTypes(typeof(AbpUiResource))
.AddVirtualJson("/LINGYUN/Abp/Aliyun/SettingManagement/Localization/Resources"); .AddVirtualJson("/LINGYUN/Abp/Aliyun/SettingManagement/Localization/Resources");
}); });
}
} }
} }

333
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingAppService.cs

@ -11,192 +11,191 @@ using Volo.Abp.SettingManagement;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using ValueType = LINGYUN.Abp.SettingManagement.ValueType; using ValueType = LINGYUN.Abp.SettingManagement.ValueType;
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
public class AliyunSettingAppService : ApplicationService, IAliyunSettingAppService
{ {
public class AliyunSettingAppService : ApplicationService, IAliyunSettingAppService protected ISettingManager SettingManager { get; }
protected IPermissionChecker PermissionChecker { get; }
protected ISettingDefinitionManager SettingDefinitionManager { get; }
public AliyunSettingAppService(
ISettingManager settingManager,
IPermissionChecker permissionChecker,
ISettingDefinitionManager settingDefinitionManager)
{ {
protected ISettingManager SettingManager { get; } SettingManager = settingManager;
protected IPermissionChecker PermissionChecker { get; } PermissionChecker = permissionChecker;
protected ISettingDefinitionManager SettingDefinitionManager { get; } SettingDefinitionManager = settingDefinitionManager;
LocalizationResource = typeof(AliyunResource);
public AliyunSettingAppService( }
ISettingManager settingManager,
IPermissionChecker permissionChecker,
ISettingDefinitionManager settingDefinitionManager)
{
SettingManager = settingManager;
PermissionChecker = permissionChecker;
SettingDefinitionManager = settingDefinitionManager;
LocalizationResource = typeof(AliyunResource);
}
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync()
{ {
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString());
} }
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() public async virtual Task<SettingGroupResult> GetAllForGlobalAsync()
{ {
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null);
} }
protected async virtual Task<SettingGroupResult> GetAllForProviderAsync(string providerName, string providerKey) protected async virtual Task<SettingGroupResult> GetAllForProviderAsync(string providerName, string providerKey)
{
var settingGroups = new SettingGroupResult();
// 无权限返回空结果,直接报错的话,网关聚合会抛出异常
if (await FeatureChecker.IsEnabledAsync(AliyunFeatureNames.Enable) &&
await PermissionChecker.IsGrantedAsync(AliyunSettingPermissionNames.Settings))
{ {
var settingGroups = new SettingGroupResult(); var aliyunSettingGroup = new SettingGroupDto(L["DisplayName:Aliyun"], L["Description:Aliyun"]);
#region 访问控制
var ramSetting = aliyunSettingGroup.AddSetting(L["DisplayName:Aliyun.RAM"], L["Description:Aliyun.RAM"]);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RegionId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId, providerName, providerKey),
ValueType.Option,
providerName)
.AddOptions(GetAvailableRegionOptions());
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.AccessKeyId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId, providerName, providerKey),
ValueType.String,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.AccessKeySecret),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret, providerName, providerKey),
ValueType.String,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RamRoleArn),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn, providerName, providerKey),
ValueType.String,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RoleSessionName),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName, providerName, providerKey),
ValueType.String,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.Policy),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.Policy, providerName, providerKey),
ValueType.String,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.UseSecurityTokenService),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.UseSecurityTokenService, providerName, providerKey),
ValueType.Boolean,
providerName);
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.DurationSeconds),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.DurationSeconds, providerName, providerKey),
ValueType.Number,
providerName);
// 无权限返回空结果,直接报错的话,网关聚合会抛出异常 #endregion
if (await FeatureChecker.IsEnabledAsync(AliyunFeatureNames.Enable) &&
await PermissionChecker.IsGrantedAsync(AliyunSettingPermissionNames.Settings)) #region 短信
if (await FeatureChecker.IsEnabledAsync(AliyunFeatureNames.Sms.Enable))
{ {
var aliyunSettingGroup = new SettingGroupDto(L["DisplayName:Aliyun"], L["Description:Aliyun"]); var smsSetting = aliyunSettingGroup.AddSetting(L["DisplayName:Aliyun.Sms"], L["Description:Aliyun.Sms"]);
#region 访问控制 smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.Domain),
var ramSetting = aliyunSettingGroup.AddSetting(L["DisplayName:Aliyun.RAM"], L["Description:Aliyun.RAM"]); StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.Domain, providerName, providerKey),
ramSetting.AddDetail( ValueType.String,
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RegionId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId, providerName, providerKey),
ValueType.Option,
providerName)
.AddOptions(GetAvailableRegionOptions());
ramSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.AccessKeyId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId, providerName, providerKey),
ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.AccessKeySecret), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.Version),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.Version, providerName, providerKey),
ValueType.String, ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RamRoleArn), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.ActionName),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.ActionName, providerName, providerKey),
ValueType.String, ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.RoleSessionName), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultPhoneNumber),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultPhoneNumber, providerName, providerKey),
ValueType.String, ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.Policy), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultSignName),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.Policy, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultSignName, providerName, providerKey),
ValueType.String, ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.UseSecurityTokenService), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultTemplateCode),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.UseSecurityTokenService, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultTemplateCode, providerName, providerKey),
ValueType.Boolean, ValueType.String,
providerName); providerName);
ramSetting.AddDetail( smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Authorization.DurationSeconds), await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.VisableErrorToClient),
StringLocalizerFactory, StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Authorization.DurationSeconds, providerName, providerKey), await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.VisableErrorToClient, providerName, providerKey),
ValueType.Number, ValueType.Boolean,
providerName); providerName);
#endregion
#region 短信
if (await FeatureChecker.IsEnabledAsync(AliyunFeatureNames.Sms.Enable))
{
var smsSetting = aliyunSettingGroup.AddSetting(L["DisplayName:Aliyun.Sms"], L["Description:Aliyun.Sms"]);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.Domain),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.Domain, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.Version),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.Version, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.ActionName),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.ActionName, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultPhoneNumber),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultPhoneNumber, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultSignName),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultSignName, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.DefaultTemplateCode),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.DefaultTemplateCode, providerName, providerKey),
ValueType.String,
providerName);
smsSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AliyunSettingNames.Sms.VisableErrorToClient),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AliyunSettingNames.Sms.VisableErrorToClient, providerName, providerKey),
ValueType.Boolean,
providerName);
}
#endregion
settingGroups.AddGroup(aliyunSettingGroup);
} }
return settingGroups; #endregion
settingGroups.AddGroup(aliyunSettingGroup);
} }
protected virtual IEnumerable<OptionDto> GetAvailableRegionOptions() return settingGroups;
}
protected virtual IEnumerable<OptionDto> GetAvailableRegionOptions()
{
return new OptionDto[]
{ {
return new OptionDto[] new OptionDto(L["Region:HangZhou"], "oss-cn-hangzhou"),
{ new OptionDto(L["Region:ShangHai"], "oss-cn-shanghai"),
new OptionDto(L["Region:HangZhou"], "oss-cn-hangzhou"), new OptionDto(L["Region:NanJing"], "oss-cn-nanjing"),
new OptionDto(L["Region:ShangHai"], "oss-cn-shanghai"), new OptionDto(L["Region:FuZhou"], "oss-cn-fuzhou"),
new OptionDto(L["Region:NanJing"], "oss-cn-nanjing"), new OptionDto(L["Region:WuHan"], "oss-cn-wuhan"),
new OptionDto(L["Region:FuZhou"], "oss-cn-fuzhou"), new OptionDto(L["Region:QingDao"], "oss-cn-qingdao"),
new OptionDto(L["Region:WuHan"], "oss-cn-wuhan"), new OptionDto(L["Region:BeiJing"], "oss-cn-beijing"),
new OptionDto(L["Region:QingDao"], "oss-cn-qingdao"), new OptionDto(L["Region:ZhangJiaKou"], "oss-cn-zhangjiakou"),
new OptionDto(L["Region:BeiJing"], "oss-cn-beijing"), new OptionDto(L["Region:HuHeHaoTe"], "oss-cn-huhehaote"),
new OptionDto(L["Region:ZhangJiaKou"], "oss-cn-zhangjiakou"), new OptionDto(L["Region:WuLanChaBu"], "oss-cn-wulanchabu"),
new OptionDto(L["Region:HuHeHaoTe"], "oss-cn-huhehaote"), new OptionDto(L["Region:ShenZhen"], "oss-cn-shenzhen"),
new OptionDto(L["Region:WuLanChaBu"], "oss-cn-wulanchabu"), new OptionDto(L["Region:HeYuan"], "oss-cn-heyuan"),
new OptionDto(L["Region:ShenZhen"], "oss-cn-shenzhen"), new OptionDto(L["Region:GuangZhou"], "oss-cn-guangzhou"),
new OptionDto(L["Region:HeYuan"], "oss-cn-heyuan"), new OptionDto(L["Region:ChengDu"], "oss-cn-chengdu"),
new OptionDto(L["Region:GuangZhou"], "oss-cn-guangzhou"), new OptionDto(L["Region:HongKong"], "oss-cn-hongkong"),
new OptionDto(L["Region:ChengDu"], "oss-cn-chengdu"), new OptionDto(L["Region:SiliconValley"], "oss-us-west-1"),
new OptionDto(L["Region:HongKong"], "oss-cn-hongkong"), new OptionDto(L["Region:Virginia"], "oss-us-east-1"),
new OptionDto(L["Region:SiliconValley"], "oss-us-west-1"), new OptionDto(L["Region:Tokoyo"], "oss-ap-northeast-1"),
new OptionDto(L["Region:Virginia"], "oss-us-east-1"), new OptionDto(L["Region:Seoul"], "oss-ap-northeast-2"),
new OptionDto(L["Region:Tokoyo"], "oss-ap-northeast-1"), new OptionDto(L["Region:Singapore"], "oss-ap-southeast-1"),
new OptionDto(L["Region:Seoul"], "oss-ap-northeast-2"), new OptionDto(L["Region:Sydney"], "oss-ap-southeast-2"),
new OptionDto(L["Region:Singapore"], "oss-ap-southeast-1"), new OptionDto(L["Region:KualaLumpur"], "oss-ap-southeast-3"),
new OptionDto(L["Region:Sydney"], "oss-ap-southeast-2"), new OptionDto(L["Region:Jakarta"], "oss-ap-southeast-5"),
new OptionDto(L["Region:KualaLumpur"], "oss-ap-southeast-3"), new OptionDto(L["Region:Manila"], "oss-ap-southeast-6"),
new OptionDto(L["Region:Jakarta"], "oss-ap-southeast-5"), new OptionDto(L["Region:Bangkok"], "oss-ap-southeast-7"),
new OptionDto(L["Region:Manila"], "oss-ap-southeast-6"), new OptionDto(L["Region:Bombay"], "oss-ap-south-1"),
new OptionDto(L["Region:Bangkok"], "oss-ap-southeast-7"), new OptionDto(L["Region:Frankfurt"], "oss-eu-central-1"),
new OptionDto(L["Region:Bombay"], "oss-ap-south-1"), new OptionDto(L["Region:London"], "oss-eu-west-1"),
new OptionDto(L["Region:Frankfurt"], "oss-eu-central-1"), new OptionDto(L["Region:Dubai"], "oss-me-east-1"),
new OptionDto(L["Region:London"], "oss-eu-west-1"), new OptionDto(L["Region:MainLand"], "oss-rg-china-mainland"),
new OptionDto(L["Region:Dubai"], "oss-me-east-1"), };
new OptionDto(L["Region:MainLand"], "oss-rg-china-mainland"),
};
}
} }
} }

47
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingController.cs

@ -4,33 +4,32 @@ using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)]
[Area("settingManagement")]
[Route("api/setting-management/aliyun")]
public class AliyunSettingController : AbpControllerBase, IAliyunSettingAppService
{ {
[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] protected IAliyunSettingAppService AppService { get; }
[Area("settingManagement")]
[Route("api/setting-management/aliyun")]
public class AliyunSettingController : AbpControllerBase, IAliyunSettingAppService
{
protected IAliyunSettingAppService AppService { get; }
public AliyunSettingController( public AliyunSettingController(
IAliyunSettingAppService appService) IAliyunSettingAppService appService)
{ {
AppService = appService; AppService = appService;
} }
[HttpGet] [HttpGet]
[Route("by-current-tenant")] [Route("by-current-tenant")]
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync()
{ {
return await AppService.GetAllForCurrentTenantAsync(); return await AppService.GetAllForCurrentTenantAsync();
} }
[HttpGet] [HttpGet]
[Route("by-global")] [Route("by-global")]
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() public async virtual Task<SettingGroupResult> GetAllForGlobalAsync()
{ {
return await AppService.GetAllForGlobalAsync(); return await AppService.GetAllForGlobalAsync();
}
} }
} }

27
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingPermissionDefinitionProvider.cs

@ -2,23 +2,22 @@
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization; using Volo.Abp.Localization;
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
public class AliyunSettingPermissionDefinitionProvider : PermissionDefinitionProvider
{ {
public class AliyunSettingPermissionDefinitionProvider : PermissionDefinitionProvider public override void Define(IPermissionDefinitionContext context)
{ {
public override void Define(IPermissionDefinitionContext context) var wechatGroup = context.AddGroup(
{ AliyunSettingPermissionNames.GroupName,
var wechatGroup = context.AddGroup( L("Permission:Aliyun"));
AliyunSettingPermissionNames.GroupName,
L("Permission:Aliyun"));
wechatGroup.AddPermission( wechatGroup.AddPermission(
AliyunSettingPermissionNames.Settings, L("Permission:Aliyun.Settings")); AliyunSettingPermissionNames.Settings, L("Permission:Aliyun.Settings"));
} }
protected LocalizableString L(string name) protected LocalizableString L(string name)
{ {
return LocalizableString.Create<AliyunResource>(name); return LocalizableString.Create<AliyunResource>(name);
}
} }
} }

11
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/AliyunSettingPermissionNames.cs

@ -1,9 +1,8 @@
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
public class AliyunSettingPermissionNames
{ {
public class AliyunSettingPermissionNames public const string GroupName = "Abp.Aliyun";
{
public const string GroupName = "Abp.Aliyun";
public const string Settings = GroupName + ".Settings"; public const string Settings = GroupName + ".Settings";
}
} }

7
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN/Abp/Aliyun/SettingManagement/IAliyunSettingAppService.cs

@ -1,8 +1,7 @@
using LINGYUN.Abp.SettingManagement; using LINGYUN.Abp.SettingManagement;
namespace LINGYUN.Abp.Aliyun.SettingManagement namespace LINGYUN.Abp.Aliyun.SettingManagement;
public interface IAliyunSettingAppService : IReadonlySettingAppService
{ {
public interface IAliyunSettingAppService : IReadonlySettingAppService
{
}
} }

7
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj

@ -4,7 +4,12 @@
<Import Project="..\..\..\..\common.props" /> <Import Project="..\..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Aliyun</AssemblyName>
<PackageId>LINGYUN.Abp.Aliyun</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
<Description>阿里云SDK基础框架</Description> <Description>阿里云SDK基础框架</Description>
</PropertyGroup> </PropertyGroup>

21
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AbpAliyunException.cs

@ -3,19 +3,18 @@ using Volo.Abp;
using Volo.Abp.ExceptionHandling; using Volo.Abp.ExceptionHandling;
using Volo.Abp.Logging; using Volo.Abp.Logging;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
public class AbpAliyunException : AbpException, IHasErrorCode, IHasLogLevel
{ {
public class AbpAliyunException : AbpException, IHasErrorCode, IHasLogLevel public LogLevel LogLevel { get; set; }
{
public LogLevel LogLevel { get; set; }
public string Code { get; } public string Code { get; }
public AbpAliyunException(string code, string message) public AbpAliyunException(string code, string message)
: base(message) : base(message)
{ {
Code = code; Code = code;
LogLevel = LogLevel.Warning; LogLevel = LogLevel.Warning;
}
} }
} }

39
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AbpAliyunModule.cs

@ -7,29 +7,28 @@ using Volo.Abp.Modularity;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
[DependsOn(
typeof(AbpCachingModule),
typeof(AbpSettingsModule),
typeof(AbpJsonModule),
typeof(AbpLocalizationModule),
typeof(AbpFeaturesLimitValidationModule))]
public class AbpAliyunModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpCachingModule),
typeof(AbpSettingsModule),
typeof(AbpJsonModule),
typeof(AbpLocalizationModule),
typeof(AbpFeaturesLimitValidationModule))]
public class AbpAliyunModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<AbpAliyunModule>();
{ });
options.FileSets.AddEmbedded<AbpAliyunModule>();
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options.Resources
.Add<AliyunResource>("zh-Hans") // 中国区云服务,默认使用简体中文 .Add<AliyunResource>("zh-Hans") // 中国区云服务,默认使用简体中文
.AddVirtualJson("/LINGYUN/Abp/Aliyun/Localization/Resources"); .AddVirtualJson("/LINGYUN/Abp/Aliyun/Localization/Resources");
}); });
}
} }
} }

39
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AcsClientFactory.cs

@ -7,29 +7,28 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.Features; using Volo.Abp.Features;
using Volo.Abp.Settings; using Volo.Abp.Settings;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
[RequiresFeature(AliyunFeatureNames.Enable)]
public class AcsClientFactory : AliyunClientFactory<IAcsClient>, IAcsClientFactory, ITransientDependency
{ {
[RequiresFeature(AliyunFeatureNames.Enable)] public AcsClientFactory(
public class AcsClientFactory : AliyunClientFactory<IAcsClient>, IAcsClientFactory, ITransientDependency ISettingProvider settingProvider,
IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
: base(settingProvider, cache)
{ {
public AcsClientFactory( }
ISettingProvider settingProvider,
IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
: base(settingProvider, cache)
{
}
protected override IAcsClient GetClient(string regionId, string accessKeyId, string accessKeySecret) protected override IAcsClient GetClient(string regionId, string accessKeyId, string accessKeySecret)
{ {
return new DefaultAcsClient( return new DefaultAcsClient(
DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret)); DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret));
} }
protected override IAcsClient GetSecurityTokenClient(string regionId, string accessKeyId, string accessKeySecret, string securityToken) protected override IAcsClient GetSecurityTokenClient(string regionId, string accessKeyId, string accessKeySecret, string securityToken)
{ {
var profile = DefaultProfile.GetProfile(regionId); var profile = DefaultProfile.GetProfile(regionId);
var credentials = new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken); var credentials = new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken);
return new DefaultAcsClient(profile, credentials); return new DefaultAcsClient(profile, credentials);
}
} }
} }

43
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AliyunBasicSessionCredentialsCacheItem.cs

@ -1,31 +1,30 @@
using System; using System;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
[Serializable]
public class AliyunBasicSessionCredentialsCacheItem
{ {
[Serializable] private readonly static string _cacheKey;
public class AliyunBasicSessionCredentialsCacheItem public static string CacheKey => _cacheKey;
{ public string AccessKeyId { get; set; }
private readonly static string _cacheKey; public string AccessKeySecret { get; set; }
public static string CacheKey => _cacheKey; public string SecurityToken { get; set; }
public string AccessKeyId { get; set; }
public string AccessKeySecret { get; set; }
public string SecurityToken { get; set; }
static AliyunBasicSessionCredentialsCacheItem() static AliyunBasicSessionCredentialsCacheItem()
{ {
_cacheKey = Guid.NewGuid().ToString("N"); _cacheKey = Guid.NewGuid().ToString("N");
} }
public AliyunBasicSessionCredentialsCacheItem() public AliyunBasicSessionCredentialsCacheItem()
{ {
} }
public AliyunBasicSessionCredentialsCacheItem(string accessKeyId, string accessKeySecret, string securityToken) public AliyunBasicSessionCredentialsCacheItem(string accessKeyId, string accessKeySecret, string securityToken)
{ {
AccessKeyId = accessKeyId; AccessKeyId = accessKeyId;
AccessKeySecret = accessKeySecret; AccessKeySecret = accessKeySecret;
SecurityToken = securityToken; SecurityToken = securityToken;
}
} }
} }

271
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/AliyunClientFactory.cs

@ -10,171 +10,170 @@ using Volo.Abp;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Settings; using Volo.Abp.Settings;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
/// <summary>
/// 阿里云通用客户端构建工厂
/// </summary>
/// <typeparam name="TClient"></typeparam>
public abstract class AliyunClientFactory<TClient>
{ {
/// <summary> protected ISettingProvider SettingProvider { get; }
/// 阿里云通用客户端构建工厂 protected IDistributedCache<AliyunBasicSessionCredentialsCacheItem> Cache { get; }
/// </summary> public AliyunClientFactory(
/// <typeparam name="TClient"></typeparam> ISettingProvider settingProvider,
public abstract class AliyunClientFactory<TClient> IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
{ {
protected ISettingProvider SettingProvider { get; } Cache = cache;
protected IDistributedCache<AliyunBasicSessionCredentialsCacheItem> Cache { get; } SettingProvider = settingProvider;
public AliyunClientFactory( }
ISettingProvider settingProvider,
IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
{
Cache = cache;
SettingProvider = settingProvider;
}
public async virtual Task<TClient> 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); public async virtual Task<TClient> CreateAsync()
Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId); {
Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret); var regionId = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId);
var accessKey = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId);
var accessKeySecret = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret);
if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService)) Check.NotNullOrWhiteSpace(regionId, AliyunSettingNames.Authorization.RegionId);
{ Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId);
var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId); Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret);
return GetSecurityTokenClient(regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken); if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService))
} {
var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId);
return GetClient(regionId, accessKey, accessKeySecret); return GetSecurityTokenClient(regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken);
} }
protected abstract TClient GetClient(string regionId, string accessKeyId, string accessKeySecret); 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 abstract TClient GetSecurityTokenClient(string regionId, string accessKeyId, string accessKeySecret, string securityToken);
protected async virtual Task<AliyunBasicSessionCredentialsCacheItem> GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId) protected async virtual Task<AliyunBasicSessionCredentialsCacheItem> GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId)
{
var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey);
if (cacheItem == null)
{ {
var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey); var roleArn = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn);
if (cacheItem == null) var roleSession = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName);
{ Check.NotNullOrWhiteSpace(roleArn, AliyunSettingNames.Authorization.RamRoleArn);
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 policy = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.Policy);
var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000); var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000);
var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret);
var request = new AssumeRoleRequest 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
{ {
AcceptFormat = FormatType.JSON, AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(durationSeconds - 10)
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;
} }
return cacheItem;
} }
/// <summary> }
/// 阿里云通用客户端构建工厂 /// <summary>
/// </summary> /// 阿里云通用客户端构建工厂
/// <typeparam name="TClient">客户端类型</typeparam> /// </summary>
/// <typeparam name="TConfiguration">客户端参数类型</typeparam> /// <typeparam name="TClient">客户端类型</typeparam>
public abstract class AliyunClientFactory<TClient, TConfiguration> /// <typeparam name="TConfiguration">客户端参数类型</typeparam>
public abstract class AliyunClientFactory<TClient, TConfiguration>
{
protected ISettingProvider SettingProvider { get; }
protected IDistributedCache<AliyunBasicSessionCredentialsCacheItem> Cache { get; }
public AliyunClientFactory(
ISettingProvider settingProvider,
IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
{ {
protected ISettingProvider SettingProvider { get; } Cache = cache;
protected IDistributedCache<AliyunBasicSessionCredentialsCacheItem> Cache { get; } SettingProvider = settingProvider;
public AliyunClientFactory( }
ISettingProvider settingProvider,
IDistributedCache<AliyunBasicSessionCredentialsCacheItem> cache)
{
Cache = cache;
SettingProvider = settingProvider;
}
public async virtual Task<TClient> 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); public async virtual Task<TClient> CreateAsync(TConfiguration configuration)
Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId); {
Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret); var regionId = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RegionId);
var accessKey = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeyId);
var accessKeySecret = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.AccessKeySecret);
if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService)) Check.NotNullOrWhiteSpace(regionId, AliyunSettingNames.Authorization.RegionId);
{ Check.NotNullOrWhiteSpace(accessKey, AliyunSettingNames.Authorization.AccessKeyId);
var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId); Check.NotNullOrWhiteSpace(accessKeySecret, AliyunSettingNames.Authorization.AccessKeySecret);
return GetSecurityTokenClient(configuration, regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken); if (await SettingProvider.IsTrueAsync(AliyunSettingNames.Authorization.UseSecurityTokenService))
} {
var cacheItem = await GetCacheItemAsync(accessKey, accessKeySecret, regionId);
return GetClient(configuration, regionId, accessKey, accessKeySecret); return GetSecurityTokenClient(configuration, regionId, cacheItem.AccessKeyId, cacheItem.AccessKeySecret, cacheItem.SecurityToken);
} }
protected abstract TClient GetClient(TConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret); 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 abstract TClient GetSecurityTokenClient(TConfiguration configuration, string regionId, string accessKeyId, string accessKeySecret, string securityToken);
protected async virtual Task<AliyunBasicSessionCredentialsCacheItem> GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId) protected async virtual Task<AliyunBasicSessionCredentialsCacheItem> GetCacheItemAsync(string accessKeyId, string accessKeySecret, string regionId)
{
var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey);
if (cacheItem == null)
{ {
var cacheItem = await Cache.GetAsync(AliyunBasicSessionCredentialsCacheItem.CacheKey); var roleArn = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RamRoleArn);
if (cacheItem == null) var roleSession = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.RoleSessionName);
{ Check.NotNullOrWhiteSpace(roleArn, AliyunSettingNames.Authorization.RamRoleArn);
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 policy = await SettingProvider.GetOrNullAsync(AliyunSettingNames.Authorization.Policy);
var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000); var durationSeconds = await SettingProvider.GetAsync(AliyunSettingNames.Authorization.DurationSeconds, 3000);
var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret);
var request = new AssumeRoleRequest 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
{ {
AcceptFormat = FormatType.JSON, AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(durationSeconds - 10)
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;
} }
return cacheItem;
} }
} }

19
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/IAcsClientFactory.cs

@ -1,15 +1,14 @@
using Aliyun.Acs.Core; using Aliyun.Acs.Core;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.Aliyun namespace LINGYUN.Abp.Aliyun;
public interface IAcsClientFactory
{ {
public interface IAcsClientFactory /// <summary>
{ /// 构造一个通用的Acs客户端调用
/// <summary> /// 通过CommonRequest调用可以不需要集成其他SDK包
/// 构造一个通用的Acs客户端调用 /// </summary>
/// 通过CommonRequest调用可以不需要集成其他SDK包 /// <returns></returns>
/// </summary> Task<IAcsClient> CreateAsync();
/// <returns></returns>
Task<IAcsClient> CreateAsync();
}
} }

9
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Localization/AliyunResource.cs

@ -1,9 +1,8 @@
using Volo.Abp.Localization; using Volo.Abp.Localization;
namespace LINGYUN.Abp.Aliyun.Localization namespace LINGYUN.Abp.Aliyun.Localization;
[LocalizationResourceName("Aliyun")]
public class AliyunResource
{ {
[LocalizationResourceName("Aliyun")]
public class AliyunResource
{
}
} }

147
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Settings/AliyunSettingNames.cs

@ -1,83 +1,82 @@
namespace LINGYUN.Abp.Aliyun.Settings namespace LINGYUN.Abp.Aliyun.Settings;
public static class AliyunSettingNames
{ {
public static class AliyunSettingNames public const string Prefix = "Abp.Aliyun";
{
public const string Prefix = "Abp.Aliyun";
/// <summary>
/// 认证方式
/// </summary>
public class Authorization
{
public const string Prefix = AliyunSettingNames.Prefix + ".Authorization";
/// <summary>
/// 地域ID
/// </summary>
public const string RegionId = Prefix + ".RegionId";
/// <summary>
/// RAM账号的AccessKey ID
/// </summary>
public const string AccessKeyId = Prefix + ".AccessKeyId";
/// <summary>
/// RAM账号的AccessKey Secret
/// </summary>
public const string AccessKeySecret = Prefix + ".AccessKeySecret";
/// <summary>
/// 使用STS Token访问
/// </summary>
public const string UseSecurityTokenService = Prefix + ".UseSecurityTokenService";
/// <summary>
/// 使用RAM子账号的AssumeRole方式访问
/// </summary>
public const string RamRoleArn = Prefix + ".RamRoleArn";
/// <summary>
/// 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计
/// </summary>
public const string RoleSessionName = Prefix + ".RoleSessionName";
/// <summary> /// <summary>
/// 认证方式 /// 过期时间,单位为秒。
/// </summary> /// </summary>
public class Authorization public const string DurationSeconds = Prefix + ".DurationSeconds";
{ /// <summary>
public const string Prefix = AliyunSettingNames.Prefix + ".Authorization"; /// 权限策略。
/// <summary> /// </summary>
/// 地域ID public const string Policy = Prefix + ".Policy";
/// </summary> }
public const string RegionId = Prefix + ".RegionId";
/// <summary>
/// RAM账号的AccessKey ID
/// </summary>
public const string AccessKeyId = Prefix + ".AccessKeyId";
/// <summary>
/// RAM账号的AccessKey Secret
/// </summary>
public const string AccessKeySecret = Prefix + ".AccessKeySecret";
/// <summary>
/// 使用STS Token访问
/// </summary>
public const string UseSecurityTokenService = Prefix + ".UseSecurityTokenService";
/// <summary>
/// 使用RAM子账号的AssumeRole方式访问
/// </summary>
public const string RamRoleArn = Prefix + ".RamRoleArn";
/// <summary>
/// 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计
/// </summary>
public const string RoleSessionName = Prefix + ".RoleSessionName";
/// <summary>
/// 过期时间,单位为秒。
/// </summary>
public const string DurationSeconds = Prefix + ".DurationSeconds";
/// <summary>
/// 权限策略。
/// </summary>
public const string Policy = Prefix + ".Policy";
}
/// <summary>
/// 短信服务
/// </summary>
public class Sms
{
public const string Prefix = AliyunSettingNames.Prefix + ".Sms";
/// <summary>
/// 阿里云sms服务域名
/// </summary>
public const string Domain = Prefix + ".Domain";
/// <summary>
/// 调用方法名称
/// </summary>
public const string ActionName = Prefix + ".ActionName";
/// <summary>
/// 默认版本号
/// </summary>
public const string Version = Prefix + ".Version";
/// <summary>
/// 默认签名
/// </summary>
public const string DefaultSignName = Prefix + ".DefaultSignName";
/// <summary>
/// 默认短信模板号
/// </summary>
public const string DefaultTemplateCode = Prefix + ".DefaultTemplateCode";
/// <summary>
/// 默认号码
/// </summary>
public const string DefaultPhoneNumber = Prefix + ".DefaultPhoneNumber";
/// <summary> /// <summary>
/// 短信服务 /// 展示错误给客户端
/// </summary> /// </summary>
public class Sms public const string VisableErrorToClient = Prefix + ".VisableErrorToClient";
{
public const string Prefix = AliyunSettingNames.Prefix + ".Sms";
/// <summary>
/// 阿里云sms服务域名
/// </summary>
public const string Domain = Prefix + ".Domain";
/// <summary>
/// 调用方法名称
/// </summary>
public const string ActionName = Prefix + ".ActionName";
/// <summary>
/// 默认版本号
/// </summary>
public const string Version = Prefix + ".Version";
/// <summary>
/// 默认签名
/// </summary>
public const string DefaultSignName = Prefix + ".DefaultSignName";
/// <summary>
/// 默认短信模板号
/// </summary>
public const string DefaultTemplateCode = Prefix + ".DefaultTemplateCode";
/// <summary>
/// 默认号码
/// </summary>
public const string DefaultPhoneNumber = Prefix + ".DefaultPhoneNumber";
/// <summary>
/// 展示错误给客户端
/// </summary>
public const string VisableErrorToClient = Prefix + ".VisableErrorToClient";
}
} }
} }

399
aspnet-core/framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN/Abp/Aliyun/Settings/AliyunSettingProvider.cs

@ -2,211 +2,210 @@
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Settings; using Volo.Abp.Settings;
namespace LINGYUN.Abp.Aliyun.Settings namespace LINGYUN.Abp.Aliyun.Settings;
public class AliyunSettingProvider : SettingDefinitionProvider
{ {
public class AliyunSettingProvider : SettingDefinitionProvider public override void Define(ISettingDefinitionContext context)
{ {
public override void Define(ISettingDefinitionContext context) context.Add(GetAuthorizationSettings());
{ context.Add(GetSmsSettings());
context.Add(GetAuthorizationSettings()); }
context.Add(GetSmsSettings());
}
private SettingDefinition[] GetAuthorizationSettings() private SettingDefinition[] GetAuthorizationSettings()
{
return new SettingDefinition[]
{ {
return new SettingDefinition[] new SettingDefinition(
{ AliyunSettingNames.Authorization.AccessKeyId,
new SettingDefinition( displayName: L("DisplayName:AccessKeyId"),
AliyunSettingNames.Authorization.AccessKeyId, description: L("Description:AccessKeyId"),
displayName: L("DisplayName:AccessKeyId"), isVisibleToClients: false,
description: L("Description:AccessKeyId"), isEncrypted: true
isVisibleToClients: false, )
isEncrypted: true .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.AccessKeySecret,
new SettingDefinition( displayName: L("DisplayName:AccessKeySecret"),
AliyunSettingNames.Authorization.AccessKeySecret, description: L("Description:AccessKeySecret"),
displayName: L("DisplayName:AccessKeySecret"), isVisibleToClients: false,
description: L("Description:AccessKeySecret"), isEncrypted: true
isVisibleToClients: false, )
isEncrypted: true .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.DurationSeconds,
new SettingDefinition( defaultValue: "3600",
AliyunSettingNames.Authorization.DurationSeconds, displayName: L("DisplayName:DurationSeconds"),
defaultValue: "3600", description: L("Description:DurationSeconds"),
displayName: L("DisplayName:DurationSeconds"), isVisibleToClients: false
description: L("Description:DurationSeconds"), )
isVisibleToClients: false .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.Policy,
new SettingDefinition( displayName: L("DisplayName:Policy"),
AliyunSettingNames.Authorization.Policy, description: L("Description:Policy"),
displayName: L("DisplayName:Policy"), isVisibleToClients: false,
description: L("Description:Policy"), isEncrypted: true
isVisibleToClients: false, )
isEncrypted: true .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.RamRoleArn,
new SettingDefinition( displayName: L("DisplayName:RamRoleArn"),
AliyunSettingNames.Authorization.RamRoleArn, description: L("Description:RamRoleArn"),
displayName: L("DisplayName:RamRoleArn"), isVisibleToClients: false,
description: L("Description:RamRoleArn"), isEncrypted: true
isVisibleToClients: false, )
isEncrypted: true .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.RegionId,
new SettingDefinition( defaultValue: "oss-cn-hangzhou",
AliyunSettingNames.Authorization.RegionId, displayName: L("DisplayName:RegionId"),
defaultValue: "oss-cn-hangzhou", description: L("Description:RegionId"),
displayName: L("DisplayName:RegionId"), isVisibleToClients: false
description: L("Description:RegionId"), )
isVisibleToClients: false .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.RoleSessionName,
new SettingDefinition( displayName: L("DisplayName:RoleSessionName"),
AliyunSettingNames.Authorization.RoleSessionName, description: L("Description:RoleSessionName"),
displayName: L("DisplayName:RoleSessionName"), isVisibleToClients: false,
description: L("Description:RoleSessionName"), isEncrypted: true
isVisibleToClients: false, )
isEncrypted: true .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, new SettingDefinition(
TenantSettingValueProvider.ProviderName), AliyunSettingNames.Authorization.UseSecurityTokenService,
new SettingDefinition( defaultValue: true.ToString(),
AliyunSettingNames.Authorization.UseSecurityTokenService, displayName: L("DisplayName:UseSecurityTokenService"),
defaultValue: true.ToString(), description: L("Description:UseSecurityTokenService"),
displayName: L("DisplayName:UseSecurityTokenService"), isVisibleToClients: false
description: L("Description:UseSecurityTokenService"), )
isVisibleToClients: false .WithProviders(
) DefaultValueSettingValueProvider.ProviderName,
.WithProviders( ConfigurationSettingValueProvider.ProviderName,
DefaultValueSettingValueProvider.ProviderName, GlobalSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName, TenantSettingValueProvider.ProviderName),
GlobalSettingValueProvider.ProviderName, };
TenantSettingValueProvider.ProviderName), }
};
}
private SettingDefinition[] GetSmsSettings() private SettingDefinition[] GetSmsSettings()
{ {
return new SettingDefinition[] return new SettingDefinition[]
{
new SettingDefinition(
AliyunSettingNames.Sms.ActionName,
defaultValue: "SendSms",
displayName: L("DisplayName:ActionName"),
description: L("Description:ActionName"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultSignName,
displayName: L("DisplayName:DefaultSignName"),
description: L("Description:DefaultSignName"),
isVisibleToClients: false,
isEncrypted: true
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultTemplateCode,
displayName: L("DisplayName:DefaultTemplateCode"),
description: L("Description:DefaultTemplateCode"),
isVisibleToClients: false,
isEncrypted: true
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultPhoneNumber,
displayName: L("DisplayName:DefaultPhoneNumber"),
description: L("Description:DefaultPhoneNumber"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.Domain,
defaultValue: "dysmsapi.aliyuncs.com",
displayName: L("DisplayName:Domain"),
description: L("Description:Domain"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.Version,
defaultValue: "2017-05-25",
displayName: L("DisplayName:Version"),
description: L("Description:Version"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.VisableErrorToClient,
defaultValue: false.ToString(),
displayName: L("DisplayName:VisableErrorToClient"),
description: L("Description:VisableErrorToClient"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName)
};
}
private ILocalizableString L(string name)
{ {
return LocalizableString.Create<AliyunResource>(name); new SettingDefinition(
} AliyunSettingNames.Sms.ActionName,
defaultValue: "SendSms",
displayName: L("DisplayName:ActionName"),
description: L("Description:ActionName"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultSignName,
displayName: L("DisplayName:DefaultSignName"),
description: L("Description:DefaultSignName"),
isVisibleToClients: false,
isEncrypted: true
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultTemplateCode,
displayName: L("DisplayName:DefaultTemplateCode"),
description: L("Description:DefaultTemplateCode"),
isVisibleToClients: false,
isEncrypted: true
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.DefaultPhoneNumber,
displayName: L("DisplayName:DefaultPhoneNumber"),
description: L("Description:DefaultPhoneNumber"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.Domain,
defaultValue: "dysmsapi.aliyuncs.com",
displayName: L("DisplayName:Domain"),
description: L("Description:Domain"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.Version,
defaultValue: "2017-05-25",
displayName: L("DisplayName:Version"),
description: L("Description:Version"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AliyunSettingNames.Sms.VisableErrorToClient,
defaultValue: false.ToString(),
displayName: L("DisplayName:VisableErrorToClient"),
description: L("Description:VisableErrorToClient"),
isVisibleToClients: false
)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName)
};
}
private ILocalizableString L(string name)
{
return LocalizableString.Create<AliyunResource>(name);
} }
} }

7
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN.Abp.BlobStoring.Tencent.csproj

@ -4,7 +4,12 @@
<Import Project="..\..\..\..\common.props" /> <Import Project="..\..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.BlobStoring.Tencent</AssemblyName>
<PackageId>LINGYUN.Abp.BlobStoring.Tencent</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace /> <RootNamespace />
<Description>腾讯云Oss对象存储Abp集成</Description> <Description>腾讯云Oss对象存储Abp集成</Description>
</PropertyGroup> </PropertyGroup>

29
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/DefaultTencentBlobNameCalculator.cs

@ -2,23 +2,22 @@
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public class DefaultTencentBlobNameCalculator : ITencentBlobNameCalculator, ITransientDependency
{ {
public class DefaultTencentBlobNameCalculator : ITencentBlobNameCalculator, ITransientDependency protected ICurrentTenant CurrentTenant { get; }
{
protected ICurrentTenant CurrentTenant { get; }
public DefaultTencentBlobNameCalculator( public DefaultTencentBlobNameCalculator(
ICurrentTenant currentTenant) ICurrentTenant currentTenant)
{ {
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
} }
public string Calculate(BlobProviderArgs args) public string Calculate(BlobProviderArgs args)
{ {
return CurrentTenant.Id == null return CurrentTenant.Id == null
? $"host/{args.BlobName}" ? $"host/{args.BlobName}"
: $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}"; : $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}";
}
} }
} }

9
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/ITencentBlobNameCalculator.cs

@ -1,9 +1,8 @@
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public interface ITencentBlobNameCalculator
{ {
public interface ITencentBlobNameCalculator string Calculate(BlobProviderArgs args);
{
string Calculate(BlobProviderArgs args);
}
} }

29
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobContainerConfigurationExtensions.cs

@ -1,25 +1,24 @@
using System; using System;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public static class TencentBlobContainerConfigurationExtensions
{ {
public static class TencentBlobContainerConfigurationExtensions public static TencentBlobProviderConfiguration GetTencentConfiguration(
this BlobContainerConfiguration containerConfiguration)
{ {
public static TencentBlobProviderConfiguration GetTencentConfiguration( return new TencentBlobProviderConfiguration(containerConfiguration);
this BlobContainerConfiguration containerConfiguration) }
{
return new TencentBlobProviderConfiguration(containerConfiguration);
}
public static BlobContainerConfiguration UseTencentCloud( public static BlobContainerConfiguration UseTencentCloud(
this BlobContainerConfiguration containerConfiguration, this BlobContainerConfiguration containerConfiguration,
Action<TencentBlobProviderConfiguration> aliyunConfigureAction) Action<TencentBlobProviderConfiguration> aliyunConfigureAction)
{ {
containerConfiguration.ProviderType = typeof(TencentCloudBlobProvider); containerConfiguration.ProviderType = typeof(TencentCloudBlobProvider);
aliyunConfigureAction(new TencentBlobProviderConfiguration(containerConfiguration)); aliyunConfigureAction(new TencentBlobProviderConfiguration(containerConfiguration));
return containerConfiguration; return containerConfiguration;
}
} }
} }

99
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobNamingNormalizer.cs

@ -2,60 +2,59 @@
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public class TencentBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency
{ {
public class TencentBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency /// <summary>
/// 腾讯云对象命名规范
/// https://cloud.tencent.com/document/product/436/13324
/// </summary>
/// <param name="blobName"></param>
/// <returns></returns>
public virtual string NormalizeBlobName(string blobName)
{ {
/// <summary> // 不允许以正斜线/或者反斜线\开头。
/// 腾讯云对象命名规范 blobName = Regex.Replace(blobName, "^/", string.Empty);
/// https://cloud.tencent.com/document/product/436/13324 blobName = blobName.StartsWith("\\") ? blobName.Substring(1) : blobName;
/// </summary>
/// <param name="blobName"></param> // 对象键中不支持 ASCII 控制字符中的
/// <returns></returns> // 字符上(↑),字符下(↓),字符右(→),字符左(←),
public virtual string NormalizeBlobName(string blobName) // 分别对应 CAN(24),EM(25),SUB(26),ESC(27)。
{ blobName = blobName.Replace("↑", "");
// 不允许以正斜线/或者反斜线\开头。 blobName = blobName.Replace("↓", "");
blobName = Regex.Replace(blobName, "^/", string.Empty); blobName = blobName.Replace("←", "");
blobName = blobName.StartsWith("\\") ? blobName.Substring(1) : blobName; blobName = blobName.Replace("→", "");
// 对象键中不支持 ASCII 控制字符中的 // TODO: 要求还真多...其他暂时不写了
// 字符上(↑),字符下(↓),字符右(→),字符左(←),
// 分别对应 CAN(24),EM(25),SUB(26),ESC(27)。 return blobName;
blobName = blobName.Replace("↑", ""); }
blobName = blobName.Replace("↓", "");
blobName = blobName.Replace("←", ""); /// <summary>
blobName = blobName.Replace("→", ""); /// 腾讯云BucketName命名规范
/// https://cloud.tencent.com/document/product/436/13312
// TODO: 要求还真多...其他暂时不写了 /// </summary>
/// <param name="containerName"></param>
return blobName; /// <returns></returns>
} public virtual string NormalizeContainerName(string containerName)
{
// 仅支持小写英文字母和数字,即[a-z,0-9]、中划线“-”及其组合。
containerName = containerName.ToLower();
containerName = Regex.Replace(containerName, "[^a-z0-9-]", string.Empty);
/// <summary> // 不能以短划线(-)开头
/// 腾讯云BucketName命名规范 containerName = Regex.Replace(containerName, "^-", string.Empty);
/// https://cloud.tencent.com/document/product/436/13312 // 不能以短划线(-)结尾
/// </summary> containerName = Regex.Replace(containerName, "-$", string.Empty);
/// <param name="containerName"></param>
/// <returns></returns> // 存储桶名称的最大允许字符受到 地域简称 和 APPID 的字符数影响,组成的完整请求域名字符数总计最多60个字符。
public virtual string NormalizeContainerName(string containerName) // 例如请求域名123456789012345678901-1250000000.cos.ap-beijing.myqcloud.com总和为60个字符。
if (containerName.Length > 60)
{ {
// 仅支持小写英文字母和数字,即[a-z,0-9]、中划线“-”及其组合。 containerName = containerName.Substring(0, 60);
containerName = containerName.ToLower();
containerName = Regex.Replace(containerName, "[^a-z0-9-]", string.Empty);
// 不能以短划线(-)开头
containerName = Regex.Replace(containerName, "^-", string.Empty);
// 不能以短划线(-)结尾
containerName = Regex.Replace(containerName, "-$", string.Empty);
// 存储桶名称的最大允许字符受到 地域简称 和 APPID 的字符数影响,组成的完整请求域名字符数总计最多60个字符。
// 例如请求域名123456789012345678901-1250000000.cos.ap-beijing.myqcloud.com总和为60个字符。
if (containerName.Length > 60)
{
containerName = containerName.Substring(0, 60);
}
return containerName;
} }
return containerName;
} }
} }

101
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfiguration.cs

@ -2,62 +2,61 @@
using Volo.Abp; using Volo.Abp;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public class TencentBlobProviderConfiguration
{ {
public class TencentBlobProviderConfiguration /// <summary>
/// AppId
/// </summary>
public string AppId {
get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.AppId);
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.AppId, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
/// <summary>
/// 区域
/// </summary>
public string Region {
get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.Region);
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.Region, value);
}
/// <summary>
/// 命名空间
/// </summary>
public string BucketName
{ {
/// <summary> get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.BucketName);
/// AppId set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value)));
/// </summary> }
public string AppId { /// <summary>
get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.AppId); /// 命名空间不存在是否创建
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.AppId, Check.NotNullOrWhiteSpace(value, nameof(value))); /// </summary>
} public bool CreateBucketIfNotExists
/// <summary> {
/// 区域 get => _containerConfiguration.GetConfigurationOrDefault(TencentBlobProviderConfigurationNames.CreateBucketIfNotExists, false);
/// </summary> set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketIfNotExists, value);
public string Region { }
get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.Region); /// <summary>
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.Region, value); /// 创建命名空间时防盗链列表
} /// </summary>
/// <summary> public List<string> CreateBucketReferer {
/// 命名空间 get => _containerConfiguration.GetConfiguration<List<string>>(TencentBlobProviderConfigurationNames.CreateBucketReferer);
/// </summary> set {
public string BucketName if (value == null)
{ {
get => _containerConfiguration.GetConfiguration<string>(TencentBlobProviderConfigurationNames.BucketName); _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketReferer, new List<string>());
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value))); }
} else
/// <summary> {
/// 命名空间不存在是否创建 _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketReferer, value);
/// </summary>
public bool CreateBucketIfNotExists
{
get => _containerConfiguration.GetConfigurationOrDefault(TencentBlobProviderConfigurationNames.CreateBucketIfNotExists, false);
set => _containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketIfNotExists, value);
}
/// <summary>
/// 创建命名空间时防盗链列表
/// </summary>
public List<string> CreateBucketReferer {
get => _containerConfiguration.GetConfiguration<List<string>>(TencentBlobProviderConfigurationNames.CreateBucketReferer);
set {
if (value == null)
{
_containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketReferer, new List<string>());
}
else
{
_containerConfiguration.SetConfiguration(TencentBlobProviderConfigurationNames.CreateBucketReferer, value);
}
} }
} }
}
private readonly BlobContainerConfiguration _containerConfiguration; private readonly BlobContainerConfiguration _containerConfiguration;
public TencentBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) public TencentBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
{ {
_containerConfiguration = containerConfiguration; _containerConfiguration = containerConfiguration;
}
} }
} }

47
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfigurationNames.cs

@ -1,26 +1,25 @@
namespace LINGYUN.Abp.BlobStoring.Tencent namespace LINGYUN.Abp.BlobStoring.Tencent;
public static class TencentBlobProviderConfigurationNames
{ {
public static class TencentBlobProviderConfigurationNames /// <summary>
{ /// AppId
/// <summary> /// </summary>
/// AppId public const string AppId = "Tencent:OSS:AppId";
/// </summary> /// <summary>
public const string AppId = "Tencent:OSS:AppId"; /// 区域
/// <summary> /// </summary>
/// 区域 public const string Region = "Tencent:OSS:Region";
/// </summary> /// <summary>
public const string Region = "Tencent:OSS:Region"; /// 命名空间
/// <summary> /// </summary>
/// 命名空间 public const string BucketName = "Tencent:OSS:BucketName";
/// </summary> /// <summary>
public const string BucketName = "Tencent:OSS:BucketName"; /// 命名空间不存在是否创建
/// <summary> /// </summary>
/// 命名空间不存在是否创建 public const string CreateBucketIfNotExists = "Tencent:OSS:CreateBucketIfNotExists";
/// </summary> /// <summary>
public const string CreateBucketIfNotExists = "Tencent:OSS:CreateBucketIfNotExists"; /// 创建命名空间时防盗链列表
/// <summary> /// </summary>
/// 创建命名空间时防盗链列表 public const string CreateBucketReferer = "Tencent:OSS:CreateBucketReferer";
/// </summary>
public const string CreateBucketReferer = "Tencent:OSS:CreateBucketReferer";
}
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save