Browse Source

Merge remote-tracking branch 'origin/dev' into feat/mudblazor

# Conflicts:
#	docs/en/package-version-changes.md
#	templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj
#	templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj
#	templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj
pull/25235/head
maliming 6 months ago
parent
commit
3cd90a09c6
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 126
      Directory.Packages.props
  2. 24
      docs/en/modules/account/shared-user-accounts.md
  3. 28
      docs/en/modules/elsa-pro.md
  4. 68
      docs/en/package-version-changes.md
  5. 4
      framework/Volo.Abp.abpmdl
  6. 1
      framework/Volo.Abp.slnx
  7. 42
      framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs
  8. 3
      framework/test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.abppkg
  9. 16
      framework/test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.csproj
  10. 359
      framework/test/Volo.Abp.RabbitMQ.Tests/Volo/Abp/RabbitMQ/ChannelPool_Tests.cs
  11. 78
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs
  12. 27
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs
  13. 86
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs
  14. 135
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/GetTwoFactorAuthenticationUser_Tests.cs
  15. 50
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/Isolated_TwoFactor_Tests.cs
  16. 7
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestBase.cs
  17. 17
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestModule.cs
  18. 18
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestStartup.cs
  19. 113
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/Shared_SignIn_Tests.cs
  20. 41
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SignInTestController.cs
  21. 88
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs
  22. 2
      npm/packs/lodash/package.json
  23. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj
  24. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  25. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj
  26. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj
  27. 6
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj
  28. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj
  29. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj
  30. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj
  31. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj
  32. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj
  33. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj
  34. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj
  35. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
  36. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  37. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj
  38. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj
  39. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj
  40. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj
  41. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
  42. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj
  43. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj
  44. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj
  45. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
  46. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj
  47. 4
      templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj
  48. 2
      templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj
  49. 2
      templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj
  50. 4
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj
  51. 4
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj
  52. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj
  53. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj
  54. 6
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
  55. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj
  56. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj
  57. 2
      templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj
  58. 2
      templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj
  59. 2
      templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj
  60. 2
      templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj
  61. 2
      templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj

126
Directory.Packages.props

@ -58,63 +58,63 @@
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="14.9.1" />
<PackageVersion Include="MailKit" Version="4.13.0" />
<PackageVersion Include="Markdig.Signed" Version="0.42.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="10.0.20" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.20" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="10.0.51" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.51" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="10.0.2" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="10.0.7" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.2" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Abstractions" Version="1.71.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.9.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.7" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
@ -123,7 +123,7 @@
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.16.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.16.0" />
<PackageVersion Include="Minio" Version="6.0.5" />
<PackageVersion Include="MongoDB.Driver" Version="3.7.1" />
<PackageVersion Include="MongoDB.Driver" Version="3.8.0" />
<PackageVersion Include="NEST" Version="7.17.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" />
@ -133,11 +133,11 @@
<PackageVersion Include="NUglify" Version="1.21.17" />
<PackageVersion Include="Nullable" Version="1.3.1" />
<PackageVersion Include="Octokit" Version="14.0.0" />
<PackageVersion Include="OpenIddict.Abstractions" Version="7.3.0" />
<PackageVersion Include="OpenIddict.Core" Version="7.3.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="7.3.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="7.3.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="7.3.0" />
<PackageVersion Include="OpenIddict.Abstractions" Version="7.5.0" />
<PackageVersion Include="OpenIddict.Core" Version="7.5.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="7.5.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="7.5.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="7.5.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="10.23.26000" />
<PackageVersion Include="Polly" Version="8.6.3" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
@ -170,17 +170,17 @@
<PackageVersion Include="Spectre.Console" Version="0.51.1" />
<PackageVersion Include="StackExchange.Redis" Version="2.9.17" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.0.1" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.2" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.7" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.7" />
<PackageVersion Include="System.Linq.Queryable" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="10.0.6" />
<PackageVersion Include="System.Security.Permissions" Version="10.0.2" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="10.0.7" />
<PackageVersion Include="System.Security.Permissions" Version="10.0.7" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.2" />
<PackageVersion Include="System.Text.Encodings.Web" Version="10.0.2" />
<PackageVersion Include="System.Text.Json" Version="10.0.2" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.7" />
<PackageVersion Include="System.Text.Encodings.Web" Version="10.0.7" />
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1273" />
<PackageVersion Include="TimeZoneConverter" Version="7.2.0" />
@ -195,6 +195,6 @@
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.9.3" />
<PackageVersion Include="System.Management" Version="10.0.2"/>
<PackageVersion Include="System.Management" Version="10.0.7" />
</ItemGroup>
</Project>

24
docs/en/modules/account/shared-user-accounts.md

@ -142,6 +142,30 @@ Configure<AbpIdentityPendingTenantUserOptions>(options =>
![new-user--join-strategy-inform](../../images/new-user-join-strategy-inform.png)
## Tenant Admin vs Host Admin Operations
When the Shared strategy is enabled, a user is a **global resource** across host and all tenants. Their identity, activation state, lockout, password policy and two-factor settings live at the host level. Therefore some user management operations are restricted to host administrators and are not available to tenant administrators.
### Host-only operations
The following operations can only be performed by a host administrator when Shared is enabled. Both the Identity Pro UI (MVC + Blazor) and the `IdentityUserAppService` enforce this — a direct API call from a tenant context will be rejected with a `UserFriendlyException`:
- Delete a user
- Activate / deactivate a user (`IsActive`)
- Lock / unlock a user
- Enable or disable two-factor authentication
- Change `LockoutEnabled` or `ShouldChangePasswordOnNextLogin`
### What tenant admins can do
- Invite users to the tenant (see the Invitation flow above)
- Manage role and organization-unit assignments within the tenant
- View audit / security logs scoped to the tenant
### What a user can do for themselves
Users can leave a tenant from their own account menu (`Switch Tenant` → `Leave`). Leaving marks the tenant membership as `Leaved = true` and preserves the user's host identity, so they can be re-invited later with the same `UserId`.
## Migration Guide
If you plan to migrate an existing multi-tenant application from an isolated strategy to Shared User Accounts, keep the following in mind:

28
docs/en/modules/elsa-pro.md

@ -46,7 +46,7 @@ After adding the package references, open the module class of the project (e.g.:
### `AbpElsaAspNetCoreModule` and `AbpElsaIdentityModule`
These two modules generally will be added to your authentication project. Please add `Volo.Elsa.Abp.AspNetCore` and `Volo.Elsa.Abp.Identity` packages to your project and add the `AbpElsaAspNetCoreModule` and `AbpElsaIdentityModule` to the `DependsOn` attribute of your module class based on your project structure:
These two modules generally will be added to your authentication project. Please add `Volo.Abp.Elsa.AspNetCore` and `Volo.Abp.Elsa.Identity` packages to your project and add the `AbpElsaAspNetCoreModule` and `AbpElsaIdentityModule` to the `DependsOn` attribute of your module class based on your project structure:
```xml
<PackageReference Include="Volo.Abp.Elsa.AspNetCore" Version="x.x.x" />
@ -65,20 +65,20 @@ These two modules generally will be added to your authentication project. Please
The Elsa Workflows has its own database provider, and also has a Tenant/Role/User system. They are under active development, so the ABP Elsa module is not yet fully integrated. Below is the current status of each module in the ABP's Elsa Module:
- `AbpElsaAspNetCoreModule(Volo.Elsa.Abp.AspNetCore)` module is used to integrate Elsa authentication.
- `AbpElsaIdentityModule(Volo.Elsa.Abp.Identity)` module is used to integrate ABP Identity authentication.
- `AbpElsaApplicationModule(Volo.Elsa.Abp.Application)` and `AbpElsaApplicationContractsModule(Volo.Elsa.Abp.Application.Contracts)` modules are used to define the Elsa permissions.
- `AbpElsaAspNetCoreModule(Volo.Abp.Elsa.AspNetCore)` module is used to integrate Elsa authentication.
- `AbpElsaIdentityModule(Volo.Abp.Elsa.Identity)` module is used to integrate ABP Identity authentication.
- `AbpElsaApplicationModule(Volo.Abp.Elsa.Application)` and `AbpElsaApplicationContractsModule(Volo.Abp.Elsa.Application.Contracts)` modules are used to define the Elsa permissions.
The rest of the projects/modules are basically empty and will be implemented in the future based on the Elsa features:
- `AbpElsaDomainModule(Volo.Elsa.Abp.Domain)`
- `AbpElsaEntityFrameworkCoreModule(Volo.Elsa.Abp.EntityFrameworkCore)`
- `AbpElsaHttpApiModule(Volo.Elsa.Abp.HttpApi)`
- `AbpElsaHttpApiClientModule(Volo.Elsa.Abp.HttpApi.Client)`
- `AbpElsaBlazorModule(Volo.Elsa.Abp.Blazor)`
- `AbpElsaBlazorServerModule(Volo.Elsa.Abp.Blazor.Server)`
- `AbpElsaBlazorWebAssemblyModule(Volo.Elsa.Abp.Blazor.WebAssembly)`
- `AbpElsaWebModule(Volo.Elsa.Abp.Web)`
- `AbpElsaDomainModule(Volo.Abp.Elsa.Domain)`
- `AbpElsaEntityFrameworkCoreModule(Volo.Abp.Elsa.EntityFrameworkCore)`
- `AbpElsaHttpApiModule(Volo.Abp.Elsa.HttpApi)`
- `AbpElsaHttpApiClientModule(Volo.Abp.Elsa.HttpApi.Client)`
- `AbpElsaBlazorModule(Volo.Abp.Elsa.Blazor)`
- `AbpElsaBlazorServerModule(Volo.Abp.Elsa.Blazor.Server)`
- `AbpElsaBlazorWebAssemblyModule(Volo.Abp.Elsa.Blazor.WebAssembly)`
- `AbpElsaWebModule(Volo.Abp.Elsa.Web)`
## Configure the Elsa Server
@ -129,7 +129,7 @@ The Elsa Workflow API endpoints check permissions. Also, it has a `*` wildcard p
The ABP Elsa module defines all permissions that are used in the Elsa workflow. You can use ABP Permission Management module to manage the permissions.
`AbpElsaAspNetCoreModule(Volo.Elsa.Abp.AspNetCore)` module will check and add these permissions to the current user's claims:
`AbpElsaAspNetCoreModule(Volo.Abp.Elsa.AspNetCore)` module will check and add these permissions to the current user's claims:
![Elsa Permissions](../images/elsa-permissions.png)
@ -158,7 +158,7 @@ Elsa Studio requires authentication and there are two ways to authenticate Elsa
##### Elsa Studio - Password Flow Authentication
The `AbpElsaIdentityModule(Volo.Elsa.Abp.Identity)` module is used to integrate with [ABP Identity module](./identity-pro.md) to check Elsa Studio *username* and *password* against ABP Identity.
The `AbpElsaIdentityModule(Volo.Abp.Elsa.Identity)` module is used to integrate with [ABP Identity module](./identity-pro.md) to check Elsa Studio *username* and *password* against ABP Identity.
You need to replace `UseIdentity` with `UseAbpIdentity` when configuring Elsa in your Elsa server project as follows:

68
docs/en/package-version-changes.md

@ -15,10 +15,78 @@
|---------|---------|-----|
| MudBlazor | 8.0.0 | #25235 |
**Updated:**
| Package | Old Version | New Version | PR |
|---------|-------------|-------------|-----|
| Microsoft.AspNetCore.Authentication.JwtBearer | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Authentication.OpenIdConnect | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Authorization | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.Authorization | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.Web | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.WebAssembly | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.WebAssembly.Authentication | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.WebAssembly.DevServer | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.WebAssembly.Server | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Components.WebView.Maui | 10.0.20 | 10.0.51 | #25313 |
| Microsoft.AspNetCore.DataProtection.StackExchangeRedis | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Mvc.NewtonsoftJson | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.Mvc.Testing | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.TestHost | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.AspNetCore.WebUtilities | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Bcl.AsyncInterfaces | 10.0.4 | 10.0.7 | #25313 |
| Microsoft.Data.Sqlite | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.Design | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.InMemory | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.Proxies | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.Relational | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.SqlServer | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.Sqlite | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.EntityFrameworkCore.Tools | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Caching.Memory | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Caching.StackExchangeRedis | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Configuration.Binder | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Configuration.CommandLine | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Configuration.EnvironmentVariables | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Configuration.UserSecrets | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.DependencyInjection | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.DependencyInjection.Abstractions | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.FileProviders.Composite | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.FileProviders.Embedded | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.FileProviders.Physical | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.FileSystemGlobbing | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Hosting | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Hosting.Abstractions | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Http | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Identity.Core | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Localization | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Logging | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Logging.Abstractions | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Logging.Console | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Options | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Extensions.Options.ConfigurationExtensions | 10.0.2 | 10.0.7 | #25313 |
| Microsoft.Maui.Controls | 10.0.20 | 10.0.51 | #25313 |
| OpenIddict.Abstractions | 7.3.0 | 7.5.0 | #25306 |
| OpenIddict.Core | 7.3.0 | 7.5.0 | #25306 |
| OpenIddict.Server.AspNetCore | 7.3.0 | 7.5.0 | #25306 |
| OpenIddict.Validation.AspNetCore | 7.3.0 | 7.5.0 | #25306 |
| OpenIddict.Validation.ServerIntegration | 7.3.0 | 7.5.0 | #25306 |
| System.Collections.Immutable | 10.0.2 | 10.0.7 | #25313 |
| System.Management | 10.0.2 | 10.0.7 | #25313 |
| System.Security.Cryptography.Xml | 10.0.6 | 10.0.7 | #25313 |
| System.Security.Permissions | 10.0.2 | 10.0.7 | #25313 |
| System.Text.Encoding.CodePages | 10.0.2 | 10.0.7 | #25313 |
| System.Text.Encodings.Web | 10.0.2 | 10.0.7 | #25313 |
| System.Text.Json | 10.0.2 | 10.0.7 | #25313 |
## 10.3.1
| Package | Old Version | New Version | PR |
|---------|-------------|-------------|-----|
| MongoDB.Driver | 3.7.1 | 3.8.0 | #25302 |
| System.Security.Cryptography.Xml | 10.0.2 | 10.0.6 | #25279 |
## 10.3.0-rc.1

4
framework/Volo.Abp.abpmdl

@ -478,6 +478,10 @@
"path": "test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.abppkg",
"folder": "test"
},
"Volo.Abp.RabbitMQ.Tests": {
"path": "test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.abppkg",
"folder": "test"
},
"Volo.Abp.Ddd.Application.Contracts": {
"path": "src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.abppkg",
"folder": "src"

1
framework/Volo.Abp.slnx

@ -247,6 +247,7 @@
<Project Path="test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj" />
<Project Path="test/Volo.Abp.ObjectExtending.Tests/Volo.Abp.ObjectExtending.Tests.csproj" />
<Project Path="test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj" />
<Project Path="test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.csproj" />
<Project Path="test/Volo.Abp.RemoteServices.Tests/Volo.Abp.RemoteServices.Tests.csproj" />
<Project Path="test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj" />
<Project Path="test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj" />

42
framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs

@ -61,29 +61,45 @@ public class ChannelPool : IChannelPool, ISingletonDependency
}
}
poolItem.Acquire();
if (poolItem.Channel.IsClosed)
{
await poolItem.DisposeAsync();
Channels.TryRemove(channelName, out _);
using (await Semaphore.LockAsync())
ChannelPoolItem? staleItem = null;
try
{
if (Channels.TryGetValue(channelName, out var existingChannelPoolItem3))
using (await Semaphore.LockAsync())
{
poolItem = existingChannelPoolItem3;
if (Channels.TryGetValue(channelName, out var currentChannelPoolItem) &&
ReferenceEquals(currentChannelPoolItem, poolItem))
{
staleItem = poolItem;
Channels.TryRemove(channelName, out _);
poolItem = new ChannelPoolItem(await CreateChannelAsync(channelName, connectionName));
Channels.TryAdd(channelName, poolItem);
}
else if (currentChannelPoolItem != null)
{
poolItem = currentChannelPoolItem;
}
else
{
poolItem = new ChannelPoolItem(await CreateChannelAsync(channelName, connectionName));
Channels.TryAdd(channelName, poolItem);
}
}
else
}
finally
{
if (staleItem != null)
{
poolItem = new ChannelPoolItem(await CreateChannelAsync(channelName, connectionName));
Channels.TryAdd(channelName, poolItem);
staleItem.WaitIfInUse(TotalDisposeWaitDuration);
await staleItem.DisposeAsync();
}
}
poolItem.Acquire();
}
poolItem.Acquire();
return new ChannelAccessor(
poolItem.Channel,
channelName,

3
framework/test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.abppkg

@ -0,0 +1,3 @@
{
"role": "lib.test"
}

16
framework/test/Volo.Abp.RabbitMQ.Tests/Volo.Abp.RabbitMQ.Tests.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.RabbitMQ\Volo.Abp.RabbitMQ.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
</ItemGroup>
</Project>

359
framework/test/Volo.Abp.RabbitMQ.Tests/Volo/Abp/RabbitMQ/ChannelPool_Tests.cs

@ -0,0 +1,359 @@
#nullable enable
using System;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using RabbitMQ.Client;
using Shouldly;
using Xunit;
namespace Volo.Abp.RabbitMQ;
public class ChannelPool_Tests
{
private static readonly TimeSpan RaceTimeout = TimeSpan.FromSeconds(5);
// ---- Regression tests for issue #25310 / PR #25311 --------------------
/// <summary>
/// After a RabbitMQ restart the cached channel becomes closed. Two callers
/// that both observe the stale poolItem must not deadlock while the pool
/// replaces it with a fresh channel.
/// </summary>
[Fact]
public async Task AcquireAsync_Should_Not_Hang_When_Channel_Closed_With_Concurrent_Callers()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using (await channelPool.AcquireAsync("q"))
{
}
fixture.Channel1.IsClosed.Returns(true);
fixture.Channel1
.DisposeAsync()
.Returns(_ => new ValueTask(Task.Delay(300)));
using var barrier = new Barrier(2);
var firstCaller = Task.Run(async () =>
{
barrier.SignalAndWait(RaceTimeout);
using var accessor = await channelPool.AcquireAsync("q");
});
var secondCaller = Task.Run(async () =>
{
barrier.SignalAndWait(RaceTimeout);
await Task.Delay(50);
using var accessor = await channelPool.AcquireAsync("q");
});
var completed = Task.WhenAll(firstCaller, secondCaller);
var winner = await Task.WhenAny(completed, Task.Delay(RaceTimeout));
winner.ShouldBe(
completed,
$"AcquireAsync is hanging on a stale poolItem. firstCaller={firstCaller.Status}, secondCaller={secondCaller.Status}");
await completed;
}
/// <summary>
/// When several callers race through the closed-channel recovery path, only one new
/// channel must be created and the dictionary must keep exactly the channel that callers
/// receive — otherwise the replacement leaks on the broker side.
/// </summary>
[Fact]
public async Task AcquireAsync_Should_Create_Only_One_Replacement_Channel_When_Many_Callers_Race()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using (await channelPool.AcquireAsync("q"))
{
}
fixture.Channel1.IsClosed.Returns(true);
const int callerCount = 8;
using var barrier = new Barrier(callerCount);
var tasks = new Task<IChannel>[callerCount];
for (var i = 0; i < callerCount; i++)
{
tasks[i] = Task.Run(async () =>
{
barrier.SignalAndWait(RaceTimeout);
using var accessor = await channelPool.AcquireAsync("q");
return accessor.Channel;
});
}
var channels = await Task.WhenAll(tasks);
foreach (var channel in channels)
{
channel.ShouldBe(fixture.Channel2, "every caller must receive the single replacement channel");
}
fixture.CreateChannelCalls.ShouldBe(
2,
$"exactly one initial + one replacement channel should be created, but got {fixture.CreateChannelCalls}");
}
// ---- Behavior guard-rails: make sure the refactor preserves core semantics ----
[Fact]
public async Task AcquireAsync_Should_Return_Channel_From_ConnectionPool()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using var accessor = await channelPool.AcquireAsync("q");
accessor.Channel.ShouldBe(fixture.Channel1);
accessor.Name.ShouldBe("q");
fixture.CreateChannelCalls.ShouldBe(1);
}
[Fact]
public async Task AcquireAsync_Should_Reuse_Cached_Channel_On_Subsequent_Calls()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using (var first = await channelPool.AcquireAsync("q"))
{
first.Channel.ShouldBe(fixture.Channel1);
}
using (var second = await channelPool.AcquireAsync("q"))
{
second.Channel.ShouldBe(fixture.Channel1);
}
using (var third = await channelPool.AcquireAsync("q"))
{
third.Channel.ShouldBe(fixture.Channel1);
}
fixture.CreateChannelCalls.ShouldBe(1, "a healthy cached channel must be reused");
}
[Fact]
public async Task AcquireAsync_Should_Keep_Separate_PoolItems_For_Different_ChannelNames()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using var a = await channelPool.AcquireAsync("queue-a");
using var b = await channelPool.AcquireAsync("queue-b");
a.Channel.ShouldBe(fixture.Channel1);
b.Channel.ShouldBe(fixture.Channel2);
a.Name.ShouldBe("queue-a");
b.Name.ShouldBe("queue-b");
fixture.CreateChannelCalls.ShouldBe(2);
}
[Fact]
public async Task AcquireAsync_Should_Serialize_Concurrent_Callers_On_Same_Channel()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
var first = await channelPool.AcquireAsync("q");
var secondTask = Task.Run(() => channelPool.AcquireAsync("q"));
await Task.Delay(100);
secondTask.IsCompleted.ShouldBeFalse("second caller must block while the channel is held");
first.Dispose();
var completed = await Task.WhenAny(secondTask, Task.Delay(RaceTimeout));
completed.ShouldBe(secondTask, "second caller must be unblocked after release");
var secondAccessor = await secondTask;
secondAccessor.Channel.ShouldBe(fixture.Channel1, "the cached channel is reused");
secondAccessor.Dispose();
fixture.CreateChannelCalls.ShouldBe(1, "channel is reused, never recreated");
}
[Fact]
public async Task AcquireAsync_Should_Not_Rebuild_When_Cached_Channel_Is_Healthy()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
using (await channelPool.AcquireAsync("q"))
{
}
// Channel stays open, so subsequent calls must not go through the rebuild branch.
using (await channelPool.AcquireAsync("q"))
{
}
await fixture.Channel1.DidNotReceive().DisposeAsync();
fixture.CreateChannelCalls.ShouldBe(1);
}
[Fact]
public async Task AcquireAsync_Should_Propagate_Exception_When_CreateChannel_Fails()
{
var channel = Substitute.For<IChannel>();
channel.IsClosed.Returns(false);
var connection = Substitute.For<IConnection>();
var attempts = 0;
connection
.CreateChannelAsync(Arg.Any<CreateChannelOptions?>(), Arg.Any<CancellationToken>())
.Returns(_ =>
{
var n = Interlocked.Increment(ref attempts);
if (n == 1)
{
throw new InvalidOperationException("broker down");
}
return Task.FromResult(channel);
});
var connectionPool = Substitute.For<IConnectionPool>();
connectionPool.GetAsync(Arg.Any<string?>()).Returns(Task.FromResult(connection));
var channelPool = new TestChannelPool(connectionPool);
await Should.ThrowAsync<InvalidOperationException>(() => channelPool.AcquireAsync("q"));
// Subsequent call should be able to succeed (broker came back).
using var accessor = await channelPool.AcquireAsync("q");
accessor.Channel.ShouldBe(channel);
attempts.ShouldBe(2);
}
[Fact]
public async Task AcquireAsync_Should_Dispose_Stale_Channel_Even_When_Recreate_Fails()
{
var staleChannel = Substitute.For<IChannel>();
staleChannel.IsClosed.Returns(false);
var connection = Substitute.For<IConnection>();
var attempts = 0;
connection
.CreateChannelAsync(Arg.Any<CreateChannelOptions?>(), Arg.Any<CancellationToken>())
.Returns(_ =>
{
var n = Interlocked.Increment(ref attempts);
if (n == 1)
{
return Task.FromResult(staleChannel);
}
throw new InvalidOperationException("broker still down");
});
var connectionPool = Substitute.For<IConnectionPool>();
connectionPool.GetAsync(Arg.Any<string?>()).Returns(Task.FromResult(connection));
var channelPool = new TestChannelPool(connectionPool);
using (await channelPool.AcquireAsync("q"))
{
}
staleChannel.IsClosed.Returns(true);
await Should.ThrowAsync<InvalidOperationException>(() => channelPool.AcquireAsync("q"));
await staleChannel.Received(1).DisposeAsync();
}
[Fact]
public async Task AcquireAsync_Should_Throw_After_Pool_Disposed()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
await channelPool.DisposeAsync();
await Should.ThrowAsync<ObjectDisposedException>(() => channelPool.AcquireAsync("q"));
}
[Fact]
public async Task AcquireAsync_Should_Only_Create_One_Channel_Even_When_First_Callers_Race()
{
var fixture = BuildConnectionPool();
var channelPool = new TestChannelPool(fixture.Pool);
const int callerCount = 8;
using var barrier = new Barrier(callerCount);
var tasks = new Task<IChannel>[callerCount];
for (var i = 0; i < callerCount; i++)
{
tasks[i] = Task.Run(async () =>
{
barrier.SignalAndWait(RaceTimeout);
using var accessor = await channelPool.AcquireAsync("q");
return accessor.Channel;
});
}
var channels = await Task.WhenAll(tasks);
foreach (var channel in channels)
{
channel.ShouldBe(fixture.Channel1, "the first-creation semaphore must serialize initial creation");
}
fixture.CreateChannelCalls.ShouldBe(1);
}
// ---- Fixture ---------------------------------------------------------
private static ConnectionPoolFixture BuildConnectionPool()
{
var channel1 = Substitute.For<IChannel>();
channel1.IsClosed.Returns(false);
var channel2 = Substitute.For<IChannel>();
channel2.IsClosed.Returns(false);
var fixture = new ConnectionPoolFixture(channel1, channel2);
var connection = Substitute.For<IConnection>();
connection
.CreateChannelAsync(Arg.Any<CreateChannelOptions?>(), Arg.Any<CancellationToken>())
.Returns(_ =>
{
var n = Interlocked.Increment(ref fixture.CreateChannelCallsField);
return n == 1 ? Task.FromResult(channel1) : Task.FromResult(channel2);
});
var connectionPool = Substitute.For<IConnectionPool>();
connectionPool.GetAsync(Arg.Any<string?>()).Returns(Task.FromResult(connection));
fixture.Pool = connectionPool;
return fixture;
}
private sealed class ConnectionPoolFixture
{
public IConnectionPool Pool { get; set; } = default!;
public IChannel Channel1 { get; }
public IChannel Channel2 { get; }
public int CreateChannelCallsField;
public int CreateChannelCalls => CreateChannelCallsField;
public ConnectionPoolFixture(IChannel channel1, IChannel channel2)
{
Channel1 = channel1;
Channel2 = channel2;
}
}
private sealed class TestChannelPool : ChannelPool
{
public TestChannelPool(IConnectionPool connectionPool) : base(connectionPool)
{
}
}
}

78
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
@ -16,6 +17,7 @@ public class AbpSignInManager : SignInManager<IdentityUser>
protected ISettingProvider SettingProvider { get; }
protected IdentityUserManager IdentityUserManager { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IOptions<IdentityOptions> IdentityOptionsAccessor { get; }
public AbpSignInManager(
IdentityUserManager userManager,
@ -40,6 +42,7 @@ public class AbpSignInManager : SignInManager<IdentityUser>
SettingProvider = settingProvider;
IdentityUserManager = userManager;
CurrentTenant = currentTenant;
IdentityOptionsAccessor = optionsAccessor;
}
public override async Task<SignInResult> PasswordSignInAsync(
@ -85,6 +88,7 @@ public class AbpSignInManager : SignInManager<IdentityUser>
using (CurrentTenant.Change(user.TenantId))
{
await IdentityOptionsAccessor.SetAsync();
return await SignInOrTwoFactorAsync(user, isPersistent);
}
}
@ -98,6 +102,7 @@ public class AbpSignInManager : SignInManager<IdentityUser>
using (CurrentTenant.Change(user.TenantId))
{
await IdentityOptionsAccessor.SetAsync();
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
}
}
@ -110,12 +115,17 @@ public class AbpSignInManager : SignInManager<IdentityUser>
return SignInResult.Failed;
}
var error = await PreSignInCheck(user);
if (error != null)
using (CurrentTenant.Change(user.TenantId))
{
return error;
await IdentityOptionsAccessor.SetAsync();
var error = await PreSignInCheck(user);
if (error != null)
{
return error;
}
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor);
}
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor);
}
public virtual async Task<IdentityUser> FindByEmailAsync(string email)
@ -133,6 +143,64 @@ public class AbpSignInManager : SignInManager<IdentityUser>
return await IdentityUserManager.FindSharedUserByLoginAsync(loginProvider, providerKey);
}
public override async Task<IdentityUser> GetTwoFactorAuthenticationUserAsync()
{
var result = await Context.AuthenticateAsync(IdentityConstants.TwoFactorUserIdScheme);
if (result?.Principal == null)
{
return null;
}
var userId = result.Principal.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(userId))
{
return null;
}
return await IdentityUserManager.FindSharedUserByIdAsync(userId);
}
public override async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient)
{
var user = await GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return SignInResult.Failed;
}
using (CurrentTenant.Change(user.TenantId))
{
await IdentityOptionsAccessor.SetAsync();
return await base.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient);
}
}
public override async Task<SignInResult> TwoFactorRecoveryCodeSignInAsync(string recoveryCode)
{
var user = await GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return SignInResult.Failed;
}
using (CurrentTenant.Change(user.TenantId))
{
await IdentityOptionsAccessor.SetAsync();
// Base TwoFactorRecoveryCodeSignInAsync does not invoke PreSignInCheck, which means
// AbpSignInManager's IsActive / ShouldChangePassword checks would be bypassed. Run the
// same pre-sign-in checks here so recovery-code sign-in has the same gating as the
// regular two-factor sign-in path.
var preSignInCheckResult = await PreSignInCheck(user);
if (preSignInCheckResult != null)
{
return preSignInCheckResult;
}
return await base.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
}
}
/// <summary>
/// This is to call the protection method PreSignInCheck
/// </summary>

27
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs

@ -718,4 +718,31 @@ public class IdentityUserManager : UserManager<IdentityUser>, IDomainService
}
}
public virtual async Task<IdentityUser> FindSharedUserByIdAsync(string userId)
{
if (MultiTenancyOptions.Value.UserSharingStrategy == TenantUserSharingStrategy.Isolated)
{
return await base.FindByIdAsync(userId);
}
using (CurrentTenant.Change(null))
{
using (DataFilter.Disable<IMultiTenant>())
{
var user = await base.FindByIdAsync(userId);
if (user == null)
{
return null;
}
using (DataFilter.Enable<IMultiTenant>())
{
using (CurrentTenant.Change(user.TenantId))
{
return await base.FindByIdAsync(userId);
}
}
}
}
}
}

86
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs

@ -190,4 +190,90 @@ public class AbpIdentityUserValidator_SharedUser_Tests : AbpIdentityAspNetCoreTe
result.Errors.First().Code.ShouldBe("InvalidEmail");
}
}
[Fact]
public async Task Should_Allow_Update_Without_UserName_Or_Email_Changes()
{
var tenantId = Guid.NewGuid();
using (_currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), "unchanged-user", "unchanged@volosoft.com") { Name = "Original" };
(await _identityUserManager.CreateAsync(user)).Succeeded.ShouldBeTrue();
user.Name = "Changed";
(await _identityUserManager.UpdateAsync(user)).Succeeded.ShouldBeTrue();
}
}
[Fact]
public async Task Should_Allow_Update_Changing_UserName_To_A_Globally_Unique_Value()
{
var tenantId = Guid.NewGuid();
using (_currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), "rename-start", "rename@volosoft.com");
(await _identityUserManager.CreateAsync(user)).Succeeded.ShouldBeTrue();
var result = await _identityUserManager.SetUserNameAsync(user, "rename-end");
result.Succeeded.ShouldBeTrue();
}
}
[Fact]
public async Task Should_Allow_Update_Changing_Email_To_A_Globally_Unique_Value()
{
var tenantId = Guid.NewGuid();
using (_currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), "email-change", "email-before@volosoft.com");
(await _identityUserManager.CreateAsync(user)).Succeeded.ShouldBeTrue();
var result = await _identityUserManager.SetEmailAsync(user, "email-after@volosoft.com");
result.Succeeded.ShouldBeTrue();
}
}
// Host-user scenarios (TenantId == null): still must enforce global uniqueness on Create.
[Fact]
public async Task Should_Reject_Duplicate_UserName_Between_Host_User_And_Tenant_User()
{
var tenantId = Guid.NewGuid();
const string sharedName = "host-vs-tenant-name";
// Host user first.
var hostUser = new IdentityUser(Guid.NewGuid(), sharedName, "host-side@volosoft.com");
(await _identityUserManager.CreateAsync(hostUser)).Succeeded.ShouldBeTrue();
using (_currentTenant.Change(tenantId))
{
var tenantUser = new IdentityUser(Guid.NewGuid(), sharedName, "tenant-side@volosoft.com");
var result = await _identityUserManager.CreateAsync(tenantUser);
result.Succeeded.ShouldBeFalse();
result.Errors.Any(e => e.Code == "DuplicateUserName").ShouldBeTrue();
}
}
[Fact]
public async Task Should_Reject_Duplicate_Email_Between_Host_User_And_Tenant_User()
{
var tenantId = Guid.NewGuid();
const string sharedEmail = "host-vs-tenant-email@volosoft.com";
var hostUser = new IdentityUser(Guid.NewGuid(), "host-email-user", sharedEmail);
(await _identityUserManager.CreateAsync(hostUser)).Succeeded.ShouldBeTrue();
using (_currentTenant.Change(tenantId))
{
var tenantUser = new IdentityUser(Guid.NewGuid(), "tenant-email-user", sharedEmail);
var result = await _identityUserManager.CreateAsync(tenantUser);
result.Succeeded.ShouldBeFalse();
result.Errors.Any(e => e.Code == "DuplicateEmail").ShouldBeTrue();
}
}
}

135
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/GetTwoFactorAuthenticationUser_Tests.cs

@ -0,0 +1,135 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.Identity.AspNetCore;
public class GetTwoFactorAuthenticationUser_Tests : SharedAbpIdentityAspNetCoreTestBase
{
[Fact]
public async Task Should_Resolve_Tenant_User_By_Id_When_Current_Tenant_Is_Host()
{
var userRepository = GetRequiredService<IIdentityUserRepository>();
var currentTenant = GetRequiredService<ICurrentTenant>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
var tenantId = Guid.NewGuid();
Guid tenantUserId;
using (var uow = unitOfWorkManager.Begin())
{
using (currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), "shared-2fa-tenant-user", "shared-2fa-tenant-user@abp.io", tenantId);
await userRepository.InsertAsync(user);
tenantUserId = user.Id;
}
await uow.CompleteAsync();
}
await WriteTwoFactorCookieAsync(tenantUserId);
var getResponse = await Client.GetAsync("/api/signin-test/get-two-factor-user");
getResponse.EnsureSuccessStatusCode();
var content = await getResponse.Content.ReadAsStringAsync();
content.ShouldBe(tenantUserId.ToString());
}
[Fact]
public async Task Should_Return_Null_When_No_Two_Factor_Cookie()
{
var getResponse = await Client.GetAsync("/api/signin-test/get-two-factor-user");
getResponse.EnsureSuccessStatusCode();
var content = await getResponse.Content.ReadAsStringAsync();
content.ShouldBe("null");
}
[Fact]
public async Task TwoFactorSignInAsync_Should_Resolve_Tenant_User_In_Shared_Mode()
{
// If the tenant switch inside AbpSignInManager.TwoFactorSignInAsync regresses,
// the base implementation would not find the user and return SignInResult.Failed.
// An inactive tenant user lets PreSignInCheck return NotAllowed, proving the user
// was actually located and inspected under its own tenant context.
var tenantUserId = await CreateInactiveTenantUserAsync("shared-2fa-signin", "shared-2fa-signin@abp.io");
await WriteTwoFactorCookieAsync(tenantUserId);
var response = await Client.GetAsync("/api/signin-test/two-factor-signin?provider=Email&code=invalid");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("NotAllowed");
}
[Fact]
public async Task TwoFactorRecoveryCodeSignInAsync_Should_Resolve_Tenant_User_In_Shared_Mode()
{
// AbpSignInManager.TwoFactorRecoveryCodeSignInAsync runs PreSignInCheck after locating
// the user under its own tenant context. An inactive tenant user therefore produces
// NotAllowed only when the override actually resolves the user; a regression would
// return Failed instead.
var tenantUserId = await CreateInactiveTenantUserAsync("shared-2fa-recovery", "shared-2fa-recovery@abp.io");
await WriteTwoFactorCookieAsync(tenantUserId);
var response = await Client.GetAsync("/api/signin-test/two-factor-recovery-signin?recoveryCode=invalid");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("NotAllowed");
}
private async Task<Guid> CreateInactiveTenantUserAsync(string userName, string email)
{
return await CreateTenantUserAsync(userName, email, isActive: false);
}
private async Task<Guid> CreateTenantUserAsync(string userName, string email, bool isActive)
{
var userRepository = GetRequiredService<IIdentityUserRepository>();
var currentTenant = GetRequiredService<ICurrentTenant>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
var tenantId = Guid.NewGuid();
Guid userId;
using (var uow = unitOfWorkManager.Begin())
{
using (currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), userName, email, tenantId);
if (!isActive)
{
user.SetIsActive(false);
}
await userRepository.InsertAsync(user);
userId = user.Id;
}
await uow.CompleteAsync();
}
return userId;
}
private async Task WriteTwoFactorCookieAsync(Guid userId)
{
var writeResponse = await Client.GetAsync($"/api/signin-test/write-two-factor-cookie?userId={userId}");
writeResponse.EnsureSuccessStatusCode();
if (writeResponse.Headers.TryGetValues("Set-Cookie", out var setCookies))
{
Client.DefaultRequestHeaders.Remove("Cookie");
foreach (var cookie in setCookies)
{
Client.DefaultRequestHeaders.Add("Cookie", cookie.Split(';').First());
}
}
}
}

50
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/Isolated_TwoFactor_Tests.cs

@ -0,0 +1,50 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.Identity.AspNetCore;
public class Isolated_TwoFactor_Tests : AbpIdentityAspNetCoreTestBase
{
[Fact]
public async Task TwoFactorRecoveryCodeSignInAsync_Should_Return_NotAllowed_For_Inactive_User()
{
// The AbpSignInManager override adds PreSignInCheck to the recovery-code path (the base
// AspNetCore Identity implementation does not). This test asserts that behavior also works
// in the default (isolated) configuration so the new invariant is protected across modes.
var userManager = GetRequiredService<IdentityUserManager>();
var userRepository = GetRequiredService<IIdentityUserRepository>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
Guid userId;
using (var uow = unitOfWorkManager.Begin())
{
var user = new IdentityUser(Guid.NewGuid(), "iso-recovery-inactive", "iso-recovery-inactive@abp.io");
(await userManager.CreateAsync(user, "Iso!9Aa")).Succeeded.ShouldBeTrue();
user.SetIsActive(false);
await userRepository.UpdateAsync(user);
userId = user.Id;
await uow.CompleteAsync();
}
var writeResponse = await Client.GetAsync($"/api/signin-test/write-two-factor-cookie?userId={userId}");
writeResponse.EnsureSuccessStatusCode();
if (writeResponse.Headers.TryGetValues("Set-Cookie", out var setCookies))
{
Client.DefaultRequestHeaders.Remove("Cookie");
foreach (var cookie in setCookies)
{
Client.DefaultRequestHeaders.Add("Cookie", cookie.Split(';').First());
}
}
var response = await Client.GetAsync("/api/signin-test/two-factor-recovery-signin?recoveryCode=invalid");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("NotAllowed");
}
}

7
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestBase.cs

@ -0,0 +1,7 @@
using Volo.Abp.AspNetCore.TestBase;
namespace Volo.Abp.Identity.AspNetCore;
public abstract class SharedAbpIdentityAspNetCoreTestBase : AbpAspNetCoreIntegratedTestBase<SharedAbpIdentityAspNetCoreTestStartup>
{
}

17
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestModule.cs

@ -0,0 +1,17 @@
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity.AspNetCore;
[DependsOn(typeof(AbpIdentityAspNetCoreTestModule))]
public class SharedAbpIdentityAspNetCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = true;
options.UserSharingStrategy = TenantUserSharingStrategy.Shared;
});
}
}

18
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SharedAbpIdentityAspNetCoreTestStartup.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Volo.Abp.Identity.AspNetCore;
public class SharedAbpIdentityAspNetCoreTestStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<SharedAbpIdentityAspNetCoreTestModule>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
}

113
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/Shared_SignIn_Tests.cs

@ -0,0 +1,113 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.Identity.AspNetCore;
public class Shared_SignIn_Tests : SharedAbpIdentityAspNetCoreTestBase
{
[Fact]
public async Task PasswordSignInAsync_Should_Sign_In_Tenant_User_From_Host_Context()
{
// In shared mode, calling PasswordSignInAsync with a username while CurrentTenant is host
// must resolve the tenant user via FindSharedUserByNameAsync, apply the user's tenant
// IdentityOptions (the fix added in AbpSignInManager), and complete the sign-in.
var userManager = GetRequiredService<IdentityUserManager>();
var currentTenant = GetRequiredService<ICurrentTenant>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
var tenantId = Guid.NewGuid();
const string userName = "shared-password-signin";
const string password = "Shared!9Aa";
using (var uow = unitOfWorkManager.Begin())
{
using (currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), userName, userName + "@abp.io", tenantId);
(await userManager.CreateAsync(user, password)).Succeeded.ShouldBeTrue();
}
await uow.CompleteAsync();
}
var response = await Client.GetAsync($"/api/signin-test/password?userName={userName}&password={password}");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("Succeeded");
}
[Fact]
public async Task PasswordSignInAsync_Should_Fail_For_Wrong_Password_In_Shared_Mode()
{
var userManager = GetRequiredService<IdentityUserManager>();
var currentTenant = GetRequiredService<ICurrentTenant>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
var tenantId = Guid.NewGuid();
const string userName = "shared-password-wrong";
using (var uow = unitOfWorkManager.Begin())
{
using (currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), userName, userName + "@abp.io", tenantId);
(await userManager.CreateAsync(user, "Shared!9Aa")).Succeeded.ShouldBeTrue();
}
await uow.CompleteAsync();
}
var response = await Client.GetAsync($"/api/signin-test/password?userName={userName}&password=wrong");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("Failed");
}
[Fact]
public async Task ExternalLoginSignInAsync_Should_Sign_In_Tenant_User_From_Host_Context()
{
// Covers the AbpSignInManager.ExternalLoginSignInAsync override: finds the user via
// FindSharedUserByLoginAsync, switches CurrentTenant to user.TenantId, applies tenant
// IdentityOptions, then calls PreSignInCheck + SignInOrTwoFactorAsync.
const string loginProvider = "test-provider";
var providerKey = "ext-" + Guid.NewGuid().ToString("N").Substring(0, 8);
var userManager = GetRequiredService<IdentityUserManager>();
var currentTenant = GetRequiredService<ICurrentTenant>();
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
var tenantId = Guid.NewGuid();
using (var uow = unitOfWorkManager.Begin())
{
using (currentTenant.Change(tenantId))
{
var user = new IdentityUser(Guid.NewGuid(), "shared-external-signin", "shared-external-signin@abp.io", tenantId);
(await userManager.CreateAsync(user, "Shared!9Aa")).Succeeded.ShouldBeTrue();
(await userManager.AddLoginAsync(user, new UserLoginInfo(loginProvider, providerKey, "Test Provider"))).Succeeded.ShouldBeTrue();
}
await uow.CompleteAsync();
}
var response = await Client.GetAsync($"/api/signin-test/external-login-signin?loginProvider={loginProvider}&providerKey={providerKey}");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("Succeeded");
}
[Fact]
public async Task ExternalLoginSignInAsync_Should_Fail_For_Unknown_Provider_Key_In_Shared_Mode()
{
var response = await Client.GetAsync($"/api/signin-test/external-login-signin?loginProvider=unknown&providerKey=none");
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
result.ShouldBe("Failed");
}
}

41
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/SignInTestController.cs

@ -1,4 +1,6 @@
using System.Threading.Tasks;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
@ -27,4 +29,41 @@ public class SignInTestController : AbpController
return Content(result.ToString());
}
[Route("write-two-factor-cookie")]
public async Task<ActionResult> WriteTwoFactorCookie(string userId)
{
var identity = new ClaimsIdentity(IdentityConstants.TwoFactorUserIdScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, userId));
await HttpContext.SignInAsync(IdentityConstants.TwoFactorUserIdScheme, new ClaimsPrincipal(identity));
return Content("OK");
}
[Route("get-two-factor-user")]
public async Task<ActionResult> GetTwoFactorUser()
{
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
return Content(user?.Id.ToString() ?? "null");
}
[Route("two-factor-signin")]
public async Task<ActionResult> TwoFactorSignIn(string provider, string code)
{
var result = await _signInManager.TwoFactorSignInAsync(provider, code, false, false);
return Content(result.ToString());
}
[Route("two-factor-recovery-signin")]
public async Task<ActionResult> TwoFactorRecoverySignIn(string recoveryCode)
{
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
return Content(result.ToString());
}
[Route("external-login-signin")]
public async Task<ActionResult> ExternalLoginSignIn(string loginProvider, string providerKey)
{
var result = await _signInManager.ExternalLoginSignInAsync(loginProvider, providerKey, false, false);
return Content(result.ToString());
}
}

88
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs

@ -618,6 +618,94 @@ public class SharedTenantUserSharingStrategy_IdentityUserManager_Tests : AbpIden
}
}
[Fact]
public async Task FindSharedUserByIdAsync_Should_Find_Tenant_User_From_Host_Context()
{
var tenantId = Guid.NewGuid();
IdentityUser tenantUser;
using (var uow = _unitOfWorkManager.Begin())
{
tenantUser = await CreateUserAsync(tenantId, "shared-id-tenant-only", "shared-id-tenant-only@abp.io");
await uow.CompleteAsync();
}
// Simulates the 2FA mid-flow on a Shared deployment: CurrentTenant is null
// but the user row only exists under a tenant. FindByIdAsync alone would be
// filtered out by the IMultiTenant filter, so FindSharedUserByIdAsync must
// disable the filter and still return the tenant user.
using (_currentTenant.Change(null))
{
var user = await _identityUserManager.FindSharedUserByIdAsync(tenantUser.Id.ToString());
user.ShouldNotBeNull();
user.Id.ShouldBe(tenantUser.Id);
user.TenantId.ShouldBe(tenantId);
user.UserName.ShouldBe("shared-id-tenant-only");
}
}
[Fact]
public async Task FindSharedUserByIdAsync_Should_Find_Host_User_From_Tenant_Context()
{
var tenantId = Guid.NewGuid();
IdentityUser hostUser;
using (var uow = _unitOfWorkManager.Begin())
{
hostUser = await CreateUserAsync(null, "shared-id-host-only", "shared-id-host-only@abp.io");
await uow.CompleteAsync();
}
using (_currentTenant.Change(tenantId))
{
var user = await _identityUserManager.FindSharedUserByIdAsync(hostUser.Id.ToString());
user.ShouldNotBeNull();
user.Id.ShouldBe(hostUser.Id);
user.TenantId.ShouldBeNull();
user.UserName.ShouldBe("shared-id-host-only");
}
}
[Fact]
public async Task FindSharedUserByIdAsync_Should_Return_Null_For_Unknown_Id()
{
using (_currentTenant.Change(null))
{
var user = await _identityUserManager.FindSharedUserByIdAsync(Guid.NewGuid().ToString());
user.ShouldBeNull();
}
}
[Fact]
public async Task Login_Then_TwoFactor_MidFlow_Should_Resolve_Same_Tenant_User_In_Shared_Mode()
{
// Covers the data-access contract behind the 2FA redirect bug:
// 1. login lookup (by user name) must find a tenant user from a host context,
// 2. the 2FA mid-flow lookup (by id) must then return the same tenant user
// from the same host context. Regressing either side re-opens the bug.
var tenantId = Guid.NewGuid();
using (var uow = _unitOfWorkManager.Begin())
{
await CreateUserAsync(tenantId, "shared-2fa-linked", "shared-2fa-linked@abp.io");
await uow.CompleteAsync();
}
using (_currentTenant.Change(null))
{
var loginUser = await _identityUserManager.FindSharedUserByNameAsync("shared-2fa-linked");
loginUser.ShouldNotBeNull();
loginUser.TenantId.ShouldBe(tenantId);
var twoFactorUser = await _identityUserManager.FindSharedUserByIdAsync(loginUser.Id.ToString());
twoFactorUser.ShouldNotBeNull();
twoFactorUser.Id.ShouldBe(loginUser.Id);
twoFactorUser.TenantId.ShouldBe(tenantId);
}
}
private async Task<IdentityUser> CreateUserAsync(
Guid? tenantId,
string userName,

2
npm/packs/lodash/package.json

@ -11,7 +11,7 @@
},
"dependencies": {
"@abp/core": "~10.3.0",
"lodash": "^4.17.21"
"lodash": "^4.18.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431",
"homepage": "https://abp.io",

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj

@ -79,7 +79,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -80,11 +80,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets>
</PackageReference>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj

@ -9,8 +9,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
@ -78,7 +78,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

6
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
@ -79,11 +79,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets>
</PackageReference>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj

@ -29,7 +29,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj

@ -73,7 +73,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj

@ -74,11 +74,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets>
</PackageReference>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj

@ -76,7 +76,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj

@ -77,11 +77,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets>
</PackageReference>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj

@ -41,7 +41,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
</ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj

@ -12,8 +12,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj

@ -16,7 +16,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
</ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -14,7 +14,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
</ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj

@ -15,10 +15,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
</ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
</ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj

@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme.Bundling\Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme.Bundling.csproj" />

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj

@ -22,7 +22,7 @@
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj

@ -26,7 +26,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
</Project>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj

@ -22,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj

@ -13,8 +13,8 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj" />

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj

@ -19,7 +19,7 @@
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj

@ -22,8 +22,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.7" />
</ItemGroup>
</Project>

2
templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj

@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.2" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />

2
templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj

@ -35,7 +35,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

4
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj

@ -13,8 +13,8 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

4
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj

@ -10,8 +10,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj

@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme.Bundling\Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme.Bundling.csproj" />

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

6
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj

@ -14,9 +14,9 @@
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Duende.IdentityModel" Version="7.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Caching.StackExchangeRedis\Volo.Abp.Caching.StackExchangeRedis.csproj" />

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj

@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.7" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Caching.StackExchangeRedis\Volo.Abp.Caching.StackExchangeRedis.csproj" />

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj

@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

2
templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj

@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj

@ -22,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>
<ItemGroup>

2
templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj

@ -10,7 +10,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.7" />
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.EntityFrameworkCore\MyCompanyName.MyProjectName.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Tests\MyCompanyName.MyProjectName.Application.Tests.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.EntityFrameworkCore.Sqlite\Volo.Abp.EntityFrameworkCore.Sqlite.csproj" />

2
templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj

@ -23,7 +23,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
</ItemGroup>
</Project>

2
templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj

@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.2" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />

Loading…
Cancel
Save