From e151d16804a5b7c53e3ad9d7a442004dedb1b6cb Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Nov 2020 09:28:57 +0800 Subject: [PATCH 1/2] Use AbpDynamicOptionsManager to replace AbpOptionsFactory. --- .../AbpRequestLocalizationMiddleware.cs | 8 ++- .../AbpRequestLocalizationOptionsFactory.cs | 28 ----------- .../AbpRequestLocalizationOptionsManager.cs | 32 ++++++++++++ ...ltAbpRequestLocalizationOptionsProvider.cs | 11 ---- .../IAbpRequestLocalizationOptionsProvider.cs | 4 +- .../Abp/AspNetCore/AbpAspNetCoreModule.cs | 2 +- .../Abp/Options/AbpDynamicOptionsManager.cs | 4 +- .../Volo/Abp/Options/AbpOptionsFactory.cs | 50 +++++++++++++++++-- ...Factory.cs => AbpAbpLdapOptionsManager.cs} | 22 ++------ .../Volo/Abp/Ldap/AbpLdapModule.cs | 3 +- .../Volo/Abp/Ldap/LdapOptions_Tests.cs | 2 +- .../BloggingTestAppModule.cs | 2 +- .../Abp/Identity/AbpIdentityOptionsManager.cs | 2 +- 13 files changed, 94 insertions(+), 76 deletions(-) delete mode 100644 framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs create mode 100644 framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsManager.cs rename framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/{AbpAbpLdapOptionsFactory.cs => AbpAbpLdapOptionsManager.cs} (61%) diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs index 2a8c48b1c5..e83e240c85 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs @@ -23,15 +23,13 @@ namespace Microsoft.AspNetCore.RequestLocalization public async Task InvokeAsync(HttpContext context, RequestDelegate next) { + var middleware = new RequestLocalizationMiddleware( next, - new OptionsWrapper( - await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync() -), - _loggerFactory + new OptionsWrapper(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()), _loggerFactory ); await middleware.Invoke(context); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs deleted file mode 100644 index 10cce6a776..0000000000 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Options; -using Volo.Abp.Options; - -namespace Microsoft.AspNetCore.RequestLocalization -{ - public class AbpRequestLocalizationOptionsFactory : AbpOptionsFactory - { - private readonly IAbpRequestLocalizationOptionsProvider _abpRequestLocalizationOptionsProvider; - - public AbpRequestLocalizationOptionsFactory( - IAbpRequestLocalizationOptionsProvider abpRequestLocalizationOptionsProvider, - IEnumerable> setups, - IEnumerable> postConfigures) - : base( - setups, - postConfigures) - { - _abpRequestLocalizationOptionsProvider = abpRequestLocalizationOptionsProvider; - } - - public override RequestLocalizationOptions Create(string name) - { - return _abpRequestLocalizationOptionsProvider.GetLocalizationOptions(); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsManager.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsManager.cs new file mode 100644 index 0000000000..3748e6ff6c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsManager.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Options; +using Volo.Abp.Options; + +namespace Microsoft.AspNetCore.RequestLocalization +{ + public class AbpRequestLocalizationOptionsManager : AbpDynamicOptionsManager + { + private RequestLocalizationOptions _options; + + private readonly IAbpRequestLocalizationOptionsProvider _abpRequestLocalizationOptionsProvider; + + public AbpRequestLocalizationOptionsManager( + IOptionsFactory factory, + IAbpRequestLocalizationOptionsProvider abpRequestLocalizationOptionsProvider) + : base(factory) + { + _abpRequestLocalizationOptionsProvider = abpRequestLocalizationOptionsProvider; + } + + public override RequestLocalizationOptions Get(string name) + { + return _options ?? base.Get(name); + } + + protected override async Task OverrideOptionsAsync(string name, RequestLocalizationOptions options) + { + _options = await _abpRequestLocalizationOptionsProvider.GetLocalizationOptionsAsync(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs index eca6990649..24713651f5 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs @@ -11,7 +11,6 @@ using Nito.AsyncEx; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace Microsoft.AspNetCore.RequestLocalization { @@ -33,16 +32,6 @@ namespace Microsoft.AspNetCore.RequestLocalization _optionsAction = optionsAction; } - public RequestLocalizationOptions GetLocalizationOptions() - { - if (_requestLocalizationOptions != null) - { - return _requestLocalizationOptions; - } - - return AsyncHelper.RunSync(GetLocalizationOptionsAsync); - } - public async Task GetLocalizationOptionsAsync() { if (_requestLocalizationOptions == null) diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs index cb4daec7f2..aea718b7cb 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs @@ -8,8 +8,6 @@ namespace Microsoft.AspNetCore.RequestLocalization { void InitLocalizationOptions(Action optionsAction = null); - RequestLocalizationOptions GetLocalizationOptions(); - Task GetLocalizationOptionsAsync(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs index fad534949d..c97c3787e7 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.AspNetCore AddAspNetServices(context.Services); context.Services.AddObjectAccessor(); - context.Services.Replace(ServiceDescriptor.Transient, AbpRequestLocalizationOptionsFactory>()); + context.Services.AddAbpDynamicOptions(); } private static void AddAspNetServices(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs index af40ff1825..43d98aead4 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs @@ -16,9 +16,9 @@ namespace Volo.Abp.Options public virtual Task SetAsync(string name) { - return OverrideOptionsAsync(base.Get(name)); + return OverrideOptionsAsync(name, base.Get(name)); } - protected abstract Task OverrideOptionsAsync(T options); + protected abstract Task OverrideOptionsAsync(string name, T options); } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpOptionsFactory.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpOptionsFactory.cs index ecbe0d8271..e2a7a7bf53 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpOptionsFactory.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpOptionsFactory.cs @@ -4,21 +4,44 @@ using Microsoft.Extensions.Options; namespace Volo.Abp.Options { //TODO: Derive from OptionsFactory when this is released: https://github.com/aspnet/Options/pull/258 (or completely remove this!) + // https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs public class AbpOptionsFactory : IOptionsFactory where TOptions : class, new() { private readonly IEnumerable> _setups; private readonly IEnumerable> _postConfigures; + private readonly IEnumerable> _validations; - public AbpOptionsFactory(IEnumerable> setups, IEnumerable> postConfigures) + public AbpOptionsFactory( + IEnumerable> setups, + IEnumerable> postConfigures) + : this(setups, postConfigures, validations: null) + { + + } + + public AbpOptionsFactory( + IEnumerable> setups, + IEnumerable> postConfigures, + IEnumerable> validations) { _setups = setups; _postConfigures = postConfigures; + _validations = validations; } public virtual TOptions Create(string name) { var options = new TOptions(); + ConfigureOptions(name, options); + PostConfigureOptions(name, options); + ValidateOptions(name, options); + + return options; + } + + protected virtual void ConfigureOptions(string name, TOptions options) + { foreach (var setup in _setups) { if (setup is IConfigureNamedOptions namedSetup) @@ -30,13 +53,34 @@ namespace Volo.Abp.Options setup.Configure(options); } } + } + protected virtual void PostConfigureOptions(string name, TOptions options) + { foreach (var post in _postConfigures) { post.PostConfigure(name, options); } + } - return options; + protected virtual void ValidateOptions(string name, TOptions options) + { + if (_validations != null) + { + var failures = new List(); + foreach (var validate in _validations) + { + var result = validate.Validate(name, options); + if (result.Failed) + { + failures.AddRange(result.Failures); + } + } + if (failures.Count > 0) + { + throw new OptionsValidationException(name, typeof(TOptions), failures); + } + } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsFactory.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsManager.cs similarity index 61% rename from framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsFactory.cs rename to framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsManager.cs index 9579e169be..57d13693b4 100644 --- a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsFactory.cs +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsManager.cs @@ -1,36 +1,22 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Options; using Volo.Abp.Options; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace Volo.Abp.Ldap { - public class AbpAbpLdapOptionsFactory : AbpOptionsFactory + public class AbpAbpLdapOptionsManager : AbpDynamicOptionsManager { protected ISettingProvider SettingProvider { get; } - public AbpAbpLdapOptionsFactory( - IEnumerable> setups, - IEnumerable> postConfigures, - ISettingProvider settingProvider) - : base(setups, postConfigures) + public AbpAbpLdapOptionsManager(IOptionsFactory factory, ISettingProvider settingProvider) + : base(factory) { SettingProvider = settingProvider; } - public override AbpLdapOptions Create(string name) - { - var options = base.Create(name); - - AsyncHelper.RunSync(() => OverrideOptionsAsync(options)); - - return options; - } - - protected virtual async Task OverrideOptionsAsync(AbpLdapOptions options) + protected override async Task OverrideOptionsAsync(string name, AbpLdapOptions options) { options.ServerHost = await GetSettingOrDefaultValue(LdapSettingNames.ServerHost, options.ServerHost); options.ServerPort = await SettingProvider.GetAsync(LdapSettingNames.ServerPort, options.ServerPort); diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs index c842d4d76b..3366f3d70f 100644 --- a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs @@ -18,8 +18,7 @@ namespace Volo.Abp.Ldap { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.Replace(ServiceDescriptor.Transient, AbpAbpLdapOptionsFactory>()); - context.Services.Replace(ServiceDescriptor.Scoped, OptionsManager>()); + context.Services.AddAbpDynamicOptions(); var configuration = context.Services.GetConfiguration(); var ldapConfiguration = configuration["Ldap"]; diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapOptions_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapOptions_Tests.cs index 8ec7ef94c6..d6e6e1fc29 100644 --- a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapOptions_Tests.cs +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapOptions_Tests.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.Ldap [Fact] public void Should_Resolve_AbpAbpLdapOptionsFactory() { - GetRequiredService>().ShouldBeOfType(typeof(AbpAbpLdapOptionsFactory)); + GetRequiredService>().ShouldBeOfType(typeof(AbpAbpLdapOptionsManager)); } } } diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 600cc05f84..c41beef251 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -166,7 +166,7 @@ namespace Volo.BloggingTestApp app.UseAuthentication(); - app.UseRequestLocalization(app.ApplicationServices.GetRequiredService>().Value); + app.UseAbpRequestLocalization(); app.UseConfiguredEndpoints(); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs index 5735f36051..8ff4c141eb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Identity SettingProvider = settingProvider; } - protected override async Task OverrideOptionsAsync(IdentityOptions options) + protected override async Task OverrideOptionsAsync(string name, 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); From e91dd06f3e86c307fe32dc61ad05e878d4c11dae Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Nov 2020 21:32:42 +0800 Subject: [PATCH 2/2] Use LdapForNet instead of Novell. Make Ldap async! --- .../src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj | 2 +- .../Volo/Abp/Ldap/ILdapManager.cs | 6 ++-- .../Volo/Abp/Ldap/LdapManager.cs | 34 +++++++++++++------ .../Volo/Abp/Ldap/LdapManager_Tests.cs | 10 +++--- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj index 277ac1c24b..584c3e74c0 100644 --- a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj +++ b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs index 6ad66b0cb3..2d41724c88 100644 --- a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs @@ -1,7 +1,9 @@ -namespace Volo.Abp.Ldap +using System.Threading.Tasks; + +namespace Volo.Abp.Ldap { public interface ILdapManager { - bool Authenticate(string username, string password); + Task AuthenticateAsync(string username, string password); } } diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs index 2d890c10f7..7a8d06746a 100644 --- a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs @@ -1,6 +1,8 @@ using System; +using System.Threading.Tasks; +using LdapForNet; +using LdapForNet.Native; using Microsoft.Extensions.Options; -using Novell.Directory.Ldap; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; @@ -15,17 +17,16 @@ namespace Volo.Abp.Ldap public LdapManager(IOptions ldapSettingsOptions) { LdapOptions = ldapSettingsOptions.Value; - Logger = NullLogger.Instance; } - public bool Authenticate(string username, string password) + public virtual async Task AuthenticateAsync(string username, string password) { try { - using (var conn = CreateLdapConnection()) + using (var conn = await CreateLdapConnectionAsync()) { - AuthenticateLdapConnection(conn, username, password); + await AuthenticateLdapConnectionAsync(conn, username, password); return true; } } @@ -36,22 +37,33 @@ namespace Volo.Abp.Ldap } } - protected virtual ILdapConnection CreateLdapConnection() + protected virtual async Task CreateLdapConnectionAsync() { var ldapConnection = new LdapConnection(); - ConfigureLdapConnection(ldapConnection); - ldapConnection.Connect(LdapOptions.ServerHost, LdapOptions.ServerPort); + await ConfigureLdapConnectionAsync(ldapConnection); + await ConnectAsync(ldapConnection); return ldapConnection; } - protected virtual void ConfigureLdapConnection(ILdapConnection connection) + protected virtual Task ConfigureLdapConnectionAsync(ILdapConnection ldapConnection) { + return Task.CompletedTask; + } + protected virtual Task ConnectAsync(ILdapConnection ldapConnection) + { + ldapConnection.Connect(LdapOptions.ServerHost, LdapOptions.ServerPort); + + return Task.CompletedTask; } - protected virtual void AuthenticateLdapConnection(ILdapConnection connection, string username, string password) + protected virtual async Task AuthenticateLdapConnectionAsync(ILdapConnection connection, string username, string password) { - connection.Bind(username, password); + await connection.BindAsync(Native.LdapAuthType.Simple, new LdapCredential() + { + UserName = username, + Password = password + }); } } } diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs index 8da9a9303d..6cc3a0acc7 100644 --- a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System.Threading.Tasks; +using Shouldly; using Volo.Abp.Testing; using Xunit; @@ -19,10 +20,11 @@ namespace Volo.Abp.Ldap } [Fact(Skip = "Required Ldap environment")] - public void Authenticate() + public async Task AuthenticateAsync() { - _ldapManager.Authenticate("cn=abp,dc=abp,dc=io", "123qwe").ShouldBe(true); - _ldapManager.Authenticate("NoExists", "123qwe").ShouldBe(false); + (await _ldapManager.AuthenticateAsync("cn=abp,dc=abp,dc=io", "123qwe")).ShouldBe(true); + (await _ldapManager.AuthenticateAsync("cn=abp,dc=abp,dc=io", "123123")).ShouldBe(false); + (await _ldapManager.AuthenticateAsync("NoExists", "123qwe")).ShouldBe(false); } } }