diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicOptionsManagerExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicOptionsManagerExtensions.cs new file mode 100644 index 0000000000..5562555c89 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicOptionsManagerExtensions.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Volo.Abp.Options; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionDynamicOptionsManagerExtensions + { + public static IServiceCollection AddAbpDynamicOptions(this IServiceCollection services) + where TOptions : class + where TManager : AbpDynamicOptionsManager + { + services.Replace(ServiceDescriptor.Scoped(typeof(IOptions), typeof(TManager))); + services.Replace(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot), typeof(TManager))); + + return services; + } + } +} diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Options/OptionsAbpDynamicOptionsManagerExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Options/OptionsAbpDynamicOptionsManagerExtensions.cs new file mode 100644 index 0000000000..d7c686b24a --- /dev/null +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Options/OptionsAbpDynamicOptionsManagerExtensions.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Options; + +namespace Microsoft.Extensions.Options +{ + public static class OptionsAbpDynamicOptionsManagerExtensions + { + public static Task SetAsync(this IOptions options) + where T : class + { + return options.ToDynamicOptions().SetAsync(); + } + + public static Task SetAsync(this IOptions options, string name) + where T : class + { + return options.ToDynamicOptions().SetAsync(name); + } + + private static AbpDynamicOptionsManager ToDynamicOptions(this IOptions options) + where T : class + { + if (options is AbpDynamicOptionsManager dynamicOptionsManager) + { + return dynamicOptionsManager; + } + + throw new AbpException($"Options must be derived from the {typeof(AbpDynamicOptionsManager<>).FullName}!"); + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs new file mode 100644 index 0000000000..af40ff1825 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.Options +{ + public abstract class AbpDynamicOptionsManager : OptionsManager + where T : class + { + protected AbpDynamicOptionsManager(IOptionsFactory factory) + : base(factory) + { + + } + + public Task SetAsync() => SetAsync(Microsoft.Extensions.Options.Options.DefaultName); + + public virtual Task SetAsync(string name) + { + return OverrideOptionsAsync(base.Get(name)); + } + + protected abstract Task OverrideOptionsAsync(T options); + } +} diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs index ac3c6c2735..731c64fc52 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.Account.Emailing; using Volo.Abp.Account.Localization; using Volo.Abp.Account.Settings; @@ -15,17 +16,21 @@ namespace Volo.Abp.Account protected IdentityUserManager UserManager { get; } protected IAccountEmailer AccountEmailer { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } + protected IOptions IdentityOptions { get; } public AccountAppService( IdentityUserManager userManager, IIdentityRoleRepository roleRepository, IAccountEmailer accountEmailer, - IdentitySecurityLogManager identitySecurityLogManager) + IdentitySecurityLogManager identitySecurityLogManager, + IOptions identityOptions) { RoleRepository = roleRepository; AccountEmailer = accountEmailer; IdentitySecurityLogManager = identitySecurityLogManager; UserManager = userManager; + IdentityOptions = identityOptions; + LocalizationResource = typeof(AccountResource); } @@ -33,6 +38,8 @@ namespace Volo.Abp.Account { await CheckSelfRegistrationAsync(); + await IdentityOptions.SetAsync(); + var user = new IdentityUser(GuidGenerator.Create(), input.UserName, input.EmailAddress, CurrentTenant.Id); (await UserManager.CreateAsync(user, input.Password)).CheckErrors(); @@ -52,6 +59,8 @@ namespace Volo.Abp.Account public virtual async Task ResetPasswordAsync(ResetPasswordDto input) { + await IdentityOptions.SetAsync(); + var user = await UserManager.GetByIdAsync(input.UserId); (await UserManager.ResetPasswordAsync(user, input.ResetToken, input.Password)).CheckErrors(); diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs index e52f6731dc..3d7381d2c3 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs @@ -12,6 +12,7 @@ using System.Linq; using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Volo.Abp.Account.Settings; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; @@ -33,17 +34,19 @@ namespace Volo.Abp.Account.Web.Pages.Account IOptions accountOptions, IIdentityServerInteractionService interaction, IClientStore clientStore, - IEventService identityServerEvents) + IEventService identityServerEvents, + IOptions identityOptions) :base( schemeProvider, - accountOptions) + accountOptions, + identityOptions) { Interaction = interaction; ClientStore = clientStore; IdentityServerEvents = identityServerEvents; } - public async override Task OnGetAsync() + public override async Task OnGetAsync() { LoginInput = new LoginInputModel(); @@ -98,7 +101,7 @@ namespace Volo.Abp.Account.Web.Pages.Account return Page(); } - public async override Task OnPostAsync(string action) + public override async Task OnPostAsync(string action) { if (action == "Cancel") { @@ -120,6 +123,8 @@ namespace Volo.Abp.Account.Web.Pages.Account ValidateModel(); + await IdentityOptions.SetAsync(); + ExternalProviders = await GetExternalProviders(); EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin); @@ -173,7 +178,7 @@ namespace Volo.Abp.Account.Web.Pages.Account return RedirectSafely(ReturnUrl, ReturnUrlHash); } - public async override Task OnPostExternalLogin(string provider) + public override async Task OnPostExternalLogin(string provider) { if (AccountOptions.WindowsAuthenticationSchemeName == provider) { diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs index 5e3ffad3fc..ec9f26179d 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs @@ -2,6 +2,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Volo.Abp.Account.Localization; using Volo.Abp.Account.Settings; using Volo.Abp.Account.Web.Areas.Account.Controllers.Models; @@ -27,12 +28,14 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers protected IdentityUserManager UserManager { get; } protected ISettingProvider SettingProvider { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } + protected IOptions IdentityOptions { get; } public AccountController( SignInManager signInManager, IdentityUserManager userManager, ISettingProvider settingProvider, - IdentitySecurityLogManager identitySecurityLogManager) + IdentitySecurityLogManager identitySecurityLogManager, + IOptions identityOptions) { LocalizationResource = typeof(AccountResource); @@ -40,6 +43,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers UserManager = userManager; SettingProvider = settingProvider; IdentitySecurityLogManager = identitySecurityLogManager; + IdentityOptions = identityOptions; } [HttpPost] @@ -104,6 +108,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers return new AbpLoginResult(LoginResultType.InvalidUserNameOrPassword); } + await IdentityOptions.SetAsync(); return GetAbpLoginResult(await SignInManager.CheckPasswordSignInAsync(identityUser, login.Password, true)); } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs index 5fd2124f49..36564f9af8 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.Identity; @@ -16,6 +17,7 @@ namespace Volo.Abp.Account.Web.Pages.Account public SignInManager SignInManager { get; set; } public IdentityUserManager UserManager { get; set; } public IdentitySecurityLogManager IdentitySecurityLogManager { get; set; } + public IOptions IdentityOptions { get; set; } protected AccountPageModel() { diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs index b1dc1375cd..a69b186adc 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs @@ -51,14 +51,17 @@ namespace Volo.Abp.Account.Web.Pages.Account protected IAuthenticationSchemeProvider SchemeProvider { get; } protected AbpAccountOptions AccountOptions { get; } + protected IOptions IdentityOptions { get; } public bool ShowCancelButton { get; set; } public LoginModel( IAuthenticationSchemeProvider schemeProvider, - IOptions accountOptions) + IOptions accountOptions, + IOptions identityOptions) { SchemeProvider = schemeProvider; + IdentityOptions = identityOptions; AccountOptions = accountOptions.Value; } @@ -91,6 +94,8 @@ namespace Volo.Abp.Account.Web.Pages.Account await ReplaceEmailToUsernameOfInputIfNeeds(); + await IdentityOptions.SetAsync(); + var result = await SignInManager.PasswordSignInAsync( LoginInput.UserNameOrEmailAddress, LoginInput.Password, @@ -181,6 +186,8 @@ namespace Volo.Abp.Account.Web.Pages.Account return RedirectToPage("./Login"); } + await IdentityOptions.SetAsync(); + var loginInfo = await SignInManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { @@ -254,6 +261,8 @@ namespace Volo.Abp.Account.Web.Pages.Account protected virtual async Task CreateExternalUserAsync(ExternalLoginInfo info) { + await IdentityOptions.SetAsync(); + var emailAddress = info.Principal.FindFirstValue(AbpClaimTypes.Email); var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id); diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 0560197cd3..065573c137 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Volo.Abp.Account.Settings; using Volo.Abp.Auditing; using Volo.Abp.Identity; @@ -124,6 +125,8 @@ namespace Volo.Abp.Account.Web.Pages.Account protected virtual async Task RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress) { + await IdentityOptions.SetAsync(); + var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id); (await UserManager.CreateAsync(user)).CheckErrors(); diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs index b11d19b7a6..1bd5b54f1f 100644 --- a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs +++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.Identity; using Xunit; @@ -12,18 +13,22 @@ namespace Volo.Abp.Account private readonly IIdentityUserRepository _identityUserRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityUserManager _userManager; - + private readonly IOptions _identityOptions; + public AccountAppService_Tests() { _accountAppService = GetRequiredService(); _identityUserRepository = GetRequiredService(); _lookupNormalizer = GetRequiredService(); _userManager = GetRequiredService(); + _identityOptions = GetRequiredService>(); } [Fact] public async Task RegisterAsync() { + await _identityOptions.SetAsync(); + var registerDto = new RegisterDto { UserName = "bob.lee", diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index acd573f916..31c9de0e18 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.Application.Dtos; using Volo.Abp.ObjectExtending; @@ -12,16 +13,19 @@ namespace Volo.Abp.Identity { protected IdentityUserManager UserManager { get; } protected IIdentityUserRepository UserRepository { get; } - public IIdentityRoleRepository RoleRepository { get; } + protected IIdentityRoleRepository RoleRepository { get; } + protected IOptions IdentityOptions { get; } public IdentityUserAppService( IdentityUserManager userManager, IIdentityUserRepository userRepository, - IIdentityRoleRepository roleRepository) + IIdentityRoleRepository roleRepository, + IOptions identityOptions) { UserManager = userManager; UserRepository = userRepository; RoleRepository = roleRepository; + IdentityOptions = identityOptions; } //TODO: [Authorize(IdentityPermissions.Users.Default)] should go the IdentityUserAppService class. @@ -68,6 +72,8 @@ namespace Volo.Abp.Identity [Authorize(IdentityPermissions.Users.Create)] public virtual async Task CreateAsync(IdentityUserCreateDto input) { + await IdentityOptions.SetAsync(); + var user = new IdentityUser( GuidGenerator.Create(), input.UserName, @@ -88,6 +94,8 @@ namespace Volo.Abp.Identity [Authorize(IdentityPermissions.Users.Update)] public virtual async Task UpdateAsync(Guid id, IdentityUserUpdateDto input) { + await IdentityOptions.SetAsync(); + var user = await UserManager.GetByIdAsync(id); user.ConcurrencyStamp = input.ConcurrencyStamp; diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs index c08eb7ce32..9097bbc144 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.Identity.Settings; using Volo.Abp.ObjectExtending; using Volo.Abp.Settings; @@ -13,10 +14,14 @@ namespace Volo.Abp.Identity public class ProfileAppService : IdentityAppServiceBase, IProfileAppService { protected IdentityUserManager UserManager { get; } + protected IOptions IdentityOptions { get; } - public ProfileAppService(IdentityUserManager userManager) + public ProfileAppService( + IdentityUserManager userManager, + IOptions identityOptions) { UserManager = userManager; + IdentityOptions = identityOptions; } public virtual async Task GetAsync() @@ -28,6 +33,8 @@ namespace Volo.Abp.Identity public virtual async Task UpdateAsync(UpdateProfileDto input) { + await IdentityOptions.SetAsync(); + var user = await UserManager.GetByIdAsync(CurrentUser.GetId()); if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled)) @@ -56,6 +63,8 @@ namespace Volo.Abp.Identity public virtual async Task ChangePasswordAsync(ChangePasswordInput input) { + await IdentityOptions.SetAsync(); + var currentUser = await UserManager.GetByIdAsync(CurrentUser.GetId()); if (currentUser.IsExternal) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs index e43cc36ba7..4269ae2e01 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs @@ -56,7 +56,7 @@ namespace Volo.Abp.Identity options.ClaimsIdentity.RoleClaimType = AbpClaimTypes.Role; }); - AddAbpIdentityOptionsFactory(context.Services); + context.Services.AddAbpDynamicOptions(); } public override void PostConfigureServices(ServiceConfigurationContext context) @@ -88,11 +88,5 @@ namespace Volo.Abp.Identity ); }); } - - private static void AddAbpIdentityOptionsFactory(IServiceCollection services) - { - services.Replace(ServiceDescriptor.Transient, AbpIdentityOptionsFactory>()); - services.Replace(ServiceDescriptor.Scoped, OptionsManager>()); - } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsFactory.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs similarity index 74% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsFactory.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs index ef383ac0ad..5735f36051 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsFactory.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs @@ -1,43 +1,25 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Volo.Abp.Identity.Settings; using Volo.Abp.Options; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace Volo.Abp.Identity { - public class AbpIdentityOptionsFactory : AbpOptionsFactory + public class AbpIdentityOptionsManager : AbpDynamicOptionsManager { protected ISettingProvider SettingProvider { get; } - public AbpIdentityOptionsFactory( - IEnumerable> setups, - IEnumerable> postConfigures, + public AbpIdentityOptionsManager(IOptionsFactory factory, ISettingProvider settingProvider) - : base(setups, postConfigures) + : base(factory) { SettingProvider = settingProvider; } - public override IdentityOptions Create(string name) - { - var options = base.Create(name); - - OverrideOptions(options); - - return options; - } - - protected virtual void OverrideOptions(IdentityOptions options) - { - AsyncHelper.RunSync(()=>OverrideOptionsAsync(options)); - } - - protected virtual async Task OverrideOptionsAsync(IdentityOptions options) + protected override async Task OverrideOptionsAsync(IdentityOptions options) { options.Password.RequiredLength = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength); options.Password.RequiredUniqueChars = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars); @@ -52,7 +34,6 @@ namespace Volo.Abp.Identity options.SignIn.RequireConfirmedEmail = await SettingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail); options.SignIn.RequireConfirmedPhoneNumber = await SettingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber); - } } -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs index 0898577e3d..c7efc3510b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.Domain.Repositories; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; @@ -14,23 +15,28 @@ namespace Volo.Abp.Identity protected ICurrentTenant CurrentTenant { get; } protected IdentityUserManager UserManager { get; } protected IIdentityUserRepository IdentityUserRepository { get; } + protected IOptions IdentityOptions { get; } protected ExternalLoginProviderBase( IGuidGenerator guidGenerator, ICurrentTenant currentTenant, IdentityUserManager userManager, - IIdentityUserRepository identityUserRepository) + IIdentityUserRepository identityUserRepository, + IOptions identityOptions) { GuidGenerator = guidGenerator; CurrentTenant = currentTenant; UserManager = userManager; IdentityUserRepository = identityUserRepository; + IdentityOptions = identityOptions; } public abstract Task TryAuthenticateAsync(string userName, string plainPassword); public virtual async Task CreateUserAsync(string userName, string providerName) { + await IdentityOptions.SetAsync(); + var externalUser = await GetUserInfoAsync(userName); NormalizeExternalLoginUserInfo(externalUser, userName); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs index 72c8a6ad74..f6bed1b914 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; @@ -17,6 +18,7 @@ namespace Volo.Abp.Identity protected IdentityUserManager UserManager { get; } protected IdentityRoleManager RoleManager { get; } protected ICurrentTenant CurrentTenant { get; } + protected IOptions IdentityOptions { get; } public IdentityDataSeeder( IGuidGenerator guidGenerator, @@ -25,7 +27,8 @@ namespace Volo.Abp.Identity ILookupNormalizer lookupNormalizer, IdentityUserManager userManager, IdentityRoleManager roleManager, - ICurrentTenant currentTenant) + ICurrentTenant currentTenant, + IOptions identityOptions) { GuidGenerator = guidGenerator; RoleRepository = roleRepository; @@ -34,6 +37,7 @@ namespace Volo.Abp.Identity UserManager = userManager; RoleManager = roleManager; CurrentTenant = currentTenant; + IdentityOptions = identityOptions; } [UnitOfWork] @@ -45,6 +49,8 @@ namespace Volo.Abp.Identity Check.NotNullOrWhiteSpace(adminEmail, nameof(adminEmail)); Check.NotNullOrWhiteSpace(adminPassword, nameof(adminPassword)); + await IdentityOptions.SetAsync(); + var result = new IdentityDataSeedResult(); using (CurrentTenant.Change(tenantId)) diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs index 6a54ccf7e3..66acc057a3 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; @@ -14,12 +16,14 @@ namespace Volo.Abp.Identity.AspNetCore IGuidGenerator guidGenerator, ICurrentTenant currentTenant, IdentityUserManager userManager, - IIdentityUserRepository identityUserRepository) + IIdentityUserRepository identityUserRepository, + IOptions identityOptions) : base( guidGenerator, currentTenant, userManager, - identityUserRepository) + identityUserRepository, + identityOptions) { } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs index e48e2171b9..0c9a682f67 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs @@ -23,28 +23,52 @@ namespace Volo.Abp.Identity } [Fact] - public void Should_Resolve_AbpIdentityOptionsFactory() + public void Should_Resolve_AbpIdentityOptionsManager() { - GetRequiredService>().ShouldBeOfType(typeof(AbpIdentityOptionsFactory)); + GetRequiredService>().ShouldBeOfType(typeof(AbpIdentityOptionsManager)); } [Fact] - public void Should_Get_Options_From_Custom_Settings_If_Available() + public async Task Should_Get_Options_From_Custom_Settings_If_Available() { using (var scope1 = ServiceProvider.CreateScope()) { - var options = scope1.ServiceProvider.GetRequiredService>().Value; - options.Password.RequiredLength.ShouldBe(6); //Default value - options.Password.RequiredUniqueChars.ShouldBe(1); //Default value + var options = scope1.ServiceProvider.GetRequiredService>(); + + //Can not get the values from the SettingProvider without options.SetAsync(); + + options.Value.Password.RequiredLength.ShouldBe(6); //Default value + options.Value.Password.RequiredUniqueChars.ShouldBe(1); //Default value + } + + using (var scope2 = ServiceProvider.CreateScope()) + { + var options = scope2.ServiceProvider.GetRequiredService>(); + var optionsValue = options.Value; + + await options.SetAsync(); + + //Still the default values because SettingProvider has not been configured yet + + optionsValue.Password.RequiredLength.ShouldBe(6); //Default value + optionsValue.Password.RequiredUniqueChars.ShouldBe(1); //Default value } - _settingProvider.GetOrNullAsync(IdentitySettingNames.Password.RequiredLength).Returns(Task.FromResult("42")); + _settingProvider + .GetOrNullAsync(IdentitySettingNames.Password.RequiredLength) + .Returns(Task.FromResult("42")); using (var scope2 = ServiceProvider.CreateScope()) { - var options = scope2.ServiceProvider.GetRequiredService>().Value; - options.Password.RequiredLength.ShouldBe(42); //Setting value - options.Password.RequiredUniqueChars.ShouldBe(1); //Default value + var options = scope2.ServiceProvider.GetRequiredService>(); + var optionsValue = options.Value; + + await options.SetAsync(); + + //Get the value from SettingProvider + + optionsValue.Password.RequiredLength.ShouldBe(42); //Setting value + optionsValue.Password.RequiredUniqueChars.ShouldBe(1); //Default value } } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index 04f08ed266..e60227cafe 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.Uow; using Xunit; @@ -18,6 +19,7 @@ namespace Volo.Abp.Identity private readonly ILookupNormalizer _lookupNormalizer; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IdentityTestData _testData; + protected IOptions _identityOptions { get; } public IdentityUserManager_Tests() { @@ -28,6 +30,7 @@ namespace Volo.Abp.Identity _lookupNormalizer = GetRequiredService(); _testData = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); + _identityOptions = GetRequiredService>(); } [Fact] @@ -120,6 +123,8 @@ namespace Volo.Abp.Identity [Fact] public async Task AddDefaultRolesAsync_In_Same_Uow() { + await _identityOptions.SetAsync(); + await CreateRandomDefaultRoleAsync(); using (var uow = _unitOfWorkManager.Begin()) @@ -176,6 +181,8 @@ namespace Volo.Abp.Identity [Fact] public async Task AddDefaultRolesAsync_In_Different_Uow() { + await _identityOptions.SetAsync(); + await CreateRandomDefaultRoleAsync(); Guid userId; diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index f892b034c8..eee4c001ed 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs @@ -33,6 +33,7 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity protected IStringLocalizer Localizer { get; } protected IHybridServiceScopeFactory ServiceScopeFactory { get; } protected AbpIdentityOptions AbpIdentityOptions { get; } + protected IOptions IdentityOptions { get; } public AbpResourceOwnerPasswordValidator( UserManager userManager, @@ -41,7 +42,8 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity ILogger> logger, IStringLocalizer localizer, IOptions abpIdentityOptions, - IHybridServiceScopeFactory serviceScopeFactory) + IHybridServiceScopeFactory serviceScopeFactory, + IOptions identityOptions) { UserManager = userManager; SignInManager = signInManager; @@ -50,6 +52,7 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity Localizer = localizer; ServiceScopeFactory = serviceScopeFactory; AbpIdentityOptions = abpIdentityOptions.Value; + IdentityOptions = identityOptions; } /// @@ -123,6 +126,7 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity string errorDescription; if (user != null) { + await IdentityOptions.SetAsync(); var result = await SignInManager.CheckPasswordSignInAsync(user, context.Password, true); if (result.Succeeded) {