Resolved #6318: Remove AsyncHelper usage for the IdentityOptions.

pull/6332/head
Halil İbrahim Kalkan 5 years ago
parent 869bc26a02
commit 79415470e2

@ -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<TOptions, TManager>(this IServiceCollection services)
where TOptions : class
where TManager : AbpDynamicOptionsManager<TOptions>
{
services.Replace(ServiceDescriptor.Scoped(typeof(IOptions<TOptions>), typeof(TManager)));
services.Replace(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<TOptions>), typeof(TManager)));
return services;
}
}
}

@ -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<T>(this IOptions<T> options)
where T : class
{
return options.ToDynamicOptions().SetAsync();
}
public static Task SetAsync<T>(this IOptions<T> options, string name)
where T : class
{
return options.ToDynamicOptions().SetAsync(name);
}
private static AbpDynamicOptionsManager<T> ToDynamicOptions<T>(this IOptions<T> options)
where T : class
{
if (options is AbpDynamicOptionsManager<T> dynamicOptionsManager)
{
return dynamicOptionsManager;
}
throw new AbpException($"Options must be derived from the {typeof(AbpDynamicOptionsManager<>).FullName}!");
}
}
}

@ -0,0 +1,24 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
namespace Volo.Abp.Options
{
public abstract class AbpDynamicOptionsManager<T> : OptionsManager<T>
where T : class
{
protected AbpDynamicOptionsManager(IOptionsFactory<T> 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);
}
}

@ -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;
@ -16,16 +17,21 @@ namespace Volo.Abp.Account
protected IAccountEmailer AccountEmailer { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected IOptions<IdentityOptions> IdentityOptions { get; }
public AccountAppService(
IdentityUserManager userManager,
IIdentityRoleRepository roleRepository,
IAccountEmailer accountEmailer,
IdentitySecurityLogManager identitySecurityLogManager)
IdentitySecurityLogManager identitySecurityLogManager,
IOptions<IdentityOptions> identityOptions)
{
RoleRepository = roleRepository;
AccountEmailer = accountEmailer;
IdentitySecurityLogManager = identitySecurityLogManager;
UserManager = userManager;
IdentityOptions = identityOptions;
LocalizationResource = typeof(AccountResource);
}
@ -33,6 +39,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 +60,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();

@ -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<AbpAccountOptions> accountOptions,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IEventService identityServerEvents)
IEventService identityServerEvents,
IOptions<IdentityOptions> identityOptions)
:base(
schemeProvider,
accountOptions)
accountOptions,
identityOptions)
{
Interaction = interaction;
ClientStore = clientStore;
IdentityServerEvents = identityServerEvents;
}
public async override Task<IActionResult> OnGetAsync()
public override async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
@ -98,7 +101,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
return Page();
}
public async override Task<IActionResult> OnPostAsync(string action)
public override async Task<IActionResult> 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<IActionResult> OnPostExternalLogin(string provider)
public override async Task<IActionResult> OnPostExternalLogin(string provider)
{
if (AccountOptions.WindowsAuthenticationSchemeName == provider)
{

@ -51,14 +51,17 @@ namespace Volo.Abp.Account.Web.Pages.Account
protected IAuthenticationSchemeProvider SchemeProvider { get; }
protected AbpAccountOptions AccountOptions { get; }
protected IOptions<IdentityOptions> IdentityOptions { get; }
public bool ShowCancelButton { get; set; }
public LoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions)
IOptions<AbpAccountOptions> accountOptions,
IOptions<IdentityOptions> 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,

@ -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> IdentityOptions { get; }
public IdentityUserAppService(
IdentityUserManager userManager,
IIdentityUserRepository userRepository,
IIdentityRoleRepository roleRepository)
IIdentityRoleRepository roleRepository,
IOptions<IdentityOptions> 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<IdentityUserDto> 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<IdentityUserDto> UpdateAsync(Guid id, IdentityUserUpdateDto input)
{
await IdentityOptions.SetAsync();
var user = await UserManager.GetByIdAsync(id);
user.ConcurrencyStamp = input.ConcurrencyStamp;

@ -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> IdentityOptions { get; }
public ProfileAppService(IdentityUserManager userManager)
public ProfileAppService(
IdentityUserManager userManager,
IOptions<IdentityOptions> identityOptions)
{
UserManager = userManager;
IdentityOptions = identityOptions;
}
public virtual async Task<ProfileDto> GetAsync()
@ -28,6 +33,8 @@ namespace Volo.Abp.Identity
public virtual async Task<ProfileDto> 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)

@ -85,8 +85,7 @@ namespace Volo.Abp.Identity
private static void AddAbpIdentityOptionsFactory(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient<IOptionsFactory<IdentityOptions>, AbpIdentityOptionsFactory>());
services.Replace(ServiceDescriptor.Scoped<IOptions<IdentityOptions>, OptionsManager<IdentityOptions>>());
services.AddAbpDynamicOptions<IdentityOptions, AbpIdentityOptionsManager>();
}
}
}

@ -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<IdentityOptions>
public class AbpIdentityOptionsManager : AbpDynamicOptionsManager<IdentityOptions>
{
protected ISettingProvider SettingProvider { get; }
public AbpIdentityOptionsFactory(
IEnumerable<IConfigureOptions<IdentityOptions>> setups,
IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures,
public AbpIdentityOptionsManager(IOptionsFactory<IdentityOptions> 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);
}
}
}
}

@ -23,28 +23,52 @@ namespace Volo.Abp.Identity
}
[Fact]
public void Should_Resolve_AbpIdentityOptionsFactory()
public void Should_Resolve_AbpIdentityOptionsManager()
{
GetRequiredService<IOptionsFactory<IdentityOptions>>().ShouldBeOfType(typeof(AbpIdentityOptionsFactory));
GetRequiredService<IOptions<IdentityOptions>>().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<IOptions<IdentityOptions>>().Value;
options.Password.RequiredLength.ShouldBe(6); //Default value
options.Password.RequiredUniqueChars.ShouldBe(1); //Default value
var options = scope1.ServiceProvider.GetRequiredService<IOptions<IdentityOptions>>();
//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<IOptions<IdentityOptions>>();
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<IOptions<IdentityOptions>>().Value;
options.Password.RequiredLength.ShouldBe(42); //Setting value
options.Password.RequiredUniqueChars.ShouldBe(1); //Default value
var options = scope2.ServiceProvider.GetRequiredService<IOptions<IdentityOptions>>();
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
}
}
}

Loading…
Cancel
Save