Browse Source

Merge branch 'rel-4.0' into dev

pull/6402/head
Halil İbrahim Kalkan 6 years ago
parent
commit
1f0e3127cc
  1. 2
      docs/en/AspNet-Boilerplate-Migration-Guide.md
  2. 2
      docs/en/Authorization.md
  3. 2
      docs/en/CSRF-Anti-Forgery.md
  4. 2
      docs/en/Contribution/Index.md
  5. 4
      docs/en/Getting-Started-React-Native.md
  6. 19
      docs/en/Migration-Guides/Abp-4_0.md
  7. 4
      docs/en/Modules/Docs.md
  8. 2
      docs/en/Startup-Templates/Application.md
  9. 2
      docs/en/UI/AspNetCore/Data-Tables.md
  10. 2
      docs/en/UI/AspNetCore/Navigation-Menu.md
  11. 2
      docs/en/UI/AspNetCore/Tag-Helpers/Index.md
  12. 8
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
  13. 28
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs
  14. 32
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsManager.cs
  15. 11
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
  16. 4
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
  17. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
  18. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpDynamicOptionsManager.cs
  19. 50
      framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpOptionsFactory.cs
  20. 2
      framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj
  21. 22
      framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsManager.cs
  22. 3
      framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs
  23. 6
      framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs
  24. 34
      framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs
  25. 10
      framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs
  26. 2
      framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapOptions_Tests.cs
  27. 2
      modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
  28. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsManager.cs

2
docs/en/AspNet-Boilerplate-Migration-Guide.md

@ -438,7 +438,7 @@ ABP Framework uses and extends ASP.NET Core's [distributed caching abstraction](
### Logging
ASP.NET Boilerplate uses Castle Windsor's [logging facility](http://docs.castleproject.org/Windsor.Logging-Facility.ashx) as an abstraction and supports multiple logging providers including Log4Net (the default one comes with the startup projects) and Serilog. You typically property-inject the logger:
ASP.NET Boilerplate uses Castle Windsor's [logging facility](https://github.com/castleproject/Windsor/blob/master/docs/logging-facility.md) as an abstraction and supports multiple logging providers including Log4Net (the default one comes with the startup projects) and Serilog. You typically property-inject the logger:
````csharp
using Castle.Core.Logging; //1: Import Logging namespace

2
docs/en/Authorization.md

@ -406,5 +406,5 @@ This is already done for the startup template integration tests.
## See Also
* [Permission Management Module](Modules/Permission-Management.md)
* [ASP.NET Core MVC / Razor Pages JavaScript Auth API](API/JavaScript-API/Auth.md)
* [ASP.NET Core MVC / Razor Pages JavaScript Auth API](UI/AspNetCore/JavaScript-API/Auth.md)
* [Permission Management in Angular UI](UI/Angular/Permission-Management.md)

2
docs/en/CSRF-Anti-Forgery.md

@ -25,7 +25,7 @@ ABP Framework provides `[AbpValidateAntiForgeryToken]` and `[AbpAutoValidateAnti
ABP Framework also automates the following infrastructure;
* Server side sets a **special cookie**, named `XSRF-TOKEN` by default, that is used make the antiforgery token value available to the browser. This is **done automatically** (by the [application configuration](Application-Configuration.md) endpoint). Nothing to do in the client side.
* Server side sets a **special cookie**, named `XSRF-TOKEN` by default, that is used make the antiforgery token value available to the browser. This is **done automatically** (by the [application configuration](API/Application-Configuration.md) endpoint). Nothing to do in the client side.
* In the client side, it reads the token from the cookie and sends it in the **HTTP header** (named `RequestVerificationToken` by default). This is implemented for all the supported UI types.
* Server side validates the antiforgery token **only for same and cross site requests** made by the browser. It bypasses the validation for non-browser clients.

2
docs/en/Contribution/Index.md

@ -26,7 +26,7 @@ If you have a feature idea for the framework or modules, [create an issue](https
## Document Translation
You may want to translate the complete [documentation](https://abp.io/documents/) (including this one) to your mother language. If so, follow these steps:
You may want to translate the complete [documentation](https://docs.abp.io) (including this one) to your mother language. If so, follow these steps:
* Clone the [ABP repository](https://github.com/abpframework/abp/) from Github.
* To add a new language, create a new folder inside the [docs](https://github.com/abpframework/abp/tree/master/docs) folder. Folder names can be "en", "es", "fr", "tr" and so on based on the language (see [all culture codes](https://msdn.microsoft.com/en-us/library/hh441729.aspx)).

4
docs/en/Getting-Started-React-Native.md

@ -27,13 +27,13 @@ You have multiple options to initiate a new React Native project that works with
### 1. Using ABP CLI
ABP CLI is probably the most convenient and flexible way to initiate an ABP solution with a React Native application. Simply [install the ABP CLI](../../CLI.md) and run the following command in your terminal:
ABP CLI is probably the most convenient and flexible way to initiate an ABP solution with a React Native application. Simply [install the ABP CLI](CLI.md) and run the following command in your terminal:
```shell
abp new MyCompanyName.MyProjectName -csf -u <angular or mvc> -m react-native
```
> To see further options in the CLI, please visit the [CLI manual](../../CLI.md).
> To see further options in the CLI, please visit the [CLI manual](CLI.md).
This command will prepare a solution with an **Angular** or an **MVC** (depends on your choice), a **.NET Core**, and a **React Native** project in it.

19
docs/en/Migration-Guides/Abp-4_0.md

@ -244,13 +244,28 @@ public class MyService : ITransientDependency
public async Task DoItAsync()
{
await _options.SetAsync();
var requiredLength = _options.Value.Password.RequiredLength;
}
}
````
Pre-built modules already handles this. However, if you have used `IdentityOptions` directly in your code, you also need to follow this new pattern.
Please make sure that the injected `IOptions<IdentityOptions>` service and the service consuming it are in the same scope of dependency injection container.
### LDAP module full async
In order to solve the problem of async over sync, `ILdapManager` uses async method instead of sync. And use [`ldap4net`](https://github.com/flamencist/ldap4net) to replace [`Novell.Directory.Ldap.NETStandard`](https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard) package.
### Dynamic external login provider system
You need to change the `WithDynamicOptions` method and pass the `Handler` class of the external login provider.
Use the `goto definition` function in Visual Studio or Rider to check `Handler` in the extension method like `AddGoogle`.
```csharp
- WithDynamicOptions<GoogleOptions>()
+ WithDynamicOptions<GoogleOptions, GoogleHandler>()
````
## ASP.NET Core MVC / Razor Pages UI
@ -262,4 +277,4 @@ See the [Angular UI Migration Guide](Abp-4_0-Angular.md).
## Blazor UI
See the [Blazor UI Migration Guide](Abp-4_0-Blazor.md).
See the [Blazor UI Migration Guide](Abp-4_0-Blazor.md).

4
docs/en/Modules/Docs.md

@ -446,7 +446,7 @@ As an example you can see ABP Framework documentation:
#### Conditional sections feature (Using Scriban)
Docs module uses [Scriban](<https://github.com/lunet-io/scriban/tree/master/doc> ) for conditionally show or hide some parts of a document. In order to use that feature, you have to create a JSON file as **Parameter document** per every language. It will contain all the key-values, as well as their display names.
Docs module uses [Scriban](https://github.com/lunet-io/scriban/tree/master/doc) for conditionally show or hide some parts of a document. In order to use that feature, you have to create a JSON file as **Parameter document** per every language. It will contain all the key-values, as well as their display names.
For example, [en/docs-params.json](https://github.com/abpio/abp-commercial-docs/blob/master/en/docs-params.json):
@ -537,7 +537,7 @@ Also, **Document_Language_Code** and **Document_Version** keys are pre-defined i
------
**IMPORTANT NOTICE**: Scriban uses "{{" and "}}" for syntax. Therefore, you must use escape blocks if you are going to use those in your document (an Angular document, for example). See [Scriban docs](<https://github.com/lunet-io/scriban/blob/master/doc/language.md#13-escape-block> ) for more information.
**IMPORTANT NOTICE**: Scriban uses "{{" and "}}" for syntax. Therefore, you must use escape blocks if you are going to use those in your document (an Angular document, for example). See [Scriban docs](https://github.com/lunet-io/scriban/blob/master/doc/language.md#13-escape-block) for more information.
### 8- Creating the Navigation Document

2
docs/en/Startup-Templates/Application.md

@ -97,7 +97,7 @@ A `BookType` enum and a `BookConsts` class (which may have some constant fields
#### .Domain Project
This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects.
This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value objects](../Value-Objects.md), [repository interfaces](../Repositories.md) and other domain objects.
A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project.

2
docs/en/UI/AspNetCore/Data-Tables.md

@ -101,7 +101,7 @@ Here, the all configuration options;
DataTables.Net has its own expected data format while getting results of an AJAX call to the server to get the table data. They are especially related how paging and sorting parameters are sent and received. ABP Framework also offers its own conventions for the client-server [AJAX](JavaScript-API/Ajax.md) communication.
The `abp.libs.datatables.createAjax` method (used in the example above) adapts request and response data format and perfectly works with the [Dynamic JavaScript Client Proxy](Dynamic-JavaScript-Client-Proxies.md) system.
The `abp.libs.datatables.createAjax` method (used in the example above) adapts request and response data format and perfectly works with the [Dynamic JavaScript Client Proxy](Dynamic-JavaScript-Proxies.md) system.
This works automatically, so most of the times you don't need to know how it works. See the [DTO document](../../Data-Transfer-Objects.md) if you want to learn more about `IPagedAndSortedResultRequest`, `IPagedResult` and other standard interfaces and base DTO classes those are used in client to server communication.

2
docs/en/UI/AspNetCore/Navigation-Menu.md

@ -109,7 +109,7 @@ There are more options of a menu item (the constructor of the `ApplicationMenuIt
As seen above, a menu contributor contributes to the menu dynamically. So, you can perform any custom logic or get menu items from any source.
One use case is the [authorization](Authorization.md). You typically want to add menu items by checking a permission.
One use case is the [authorization](../../Authorization.md). You typically want to add menu items by checking a permission.
**Example: Check if the current user has a permission**

2
docs/en/UI/AspNetCore/Tag-Helpers/Index.md

@ -16,7 +16,7 @@ Here, the list of components those are wrapped by the ABP Framework:
* [Badges](Badges.md)
* [Blockquote](Blockquote.md)
* [Borders](Borders.md)
* [Breadcrumb](Breadcrumb.md)
* [Breadcrumb](Breadcrumbs.md)
* [Buttons](Buttons.md)
* [Cards](Cards.md)
* [Carousel](Carousel.md)

8
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<RequestLocalizationOptions>(
await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()
),
_loggerFactory
new OptionsWrapper<RequestLocalizationOptions>(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()), _loggerFactory
);
await middleware.Invoke(context);
}
}
}
}

28
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptionsFactory.cs

@ -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<RequestLocalizationOptions>
{
private readonly IAbpRequestLocalizationOptionsProvider _abpRequestLocalizationOptionsProvider;
public AbpRequestLocalizationOptionsFactory(
IAbpRequestLocalizationOptionsProvider abpRequestLocalizationOptionsProvider,
IEnumerable<IConfigureOptions<RequestLocalizationOptions>> setups,
IEnumerable<IPostConfigureOptions<RequestLocalizationOptions>> postConfigures)
: base(
setups,
postConfigures)
{
_abpRequestLocalizationOptionsProvider = abpRequestLocalizationOptionsProvider;
}
public override RequestLocalizationOptions Create(string name)
{
return _abpRequestLocalizationOptionsProvider.GetLocalizationOptions();
}
}
}

32
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<RequestLocalizationOptions>
{
private RequestLocalizationOptions _options;
private readonly IAbpRequestLocalizationOptionsProvider _abpRequestLocalizationOptionsProvider;
public AbpRequestLocalizationOptionsManager(
IOptionsFactory<RequestLocalizationOptions> 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();
}
}
}

11
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs

@ -10,7 +10,6 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
namespace Microsoft.AspNetCore.RequestLocalization
{
@ -32,16 +31,6 @@ namespace Microsoft.AspNetCore.RequestLocalization
_optionsAction = optionsAction;
}
public RequestLocalizationOptions GetLocalizationOptions()
{
if (_requestLocalizationOptions != null)
{
return _requestLocalizationOptions;
}
return AsyncHelper.RunSync(GetLocalizationOptionsAsync);
}
public async Task<RequestLocalizationOptions> GetLocalizationOptionsAsync()
{
if (_requestLocalizationOptions == null)

4
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs

@ -8,8 +8,6 @@ namespace Microsoft.AspNetCore.RequestLocalization
{
void InitLocalizationOptions(Action<RequestLocalizationOptions> optionsAction = null);
RequestLocalizationOptions GetLocalizationOptions();
Task<RequestLocalizationOptions> GetLocalizationOptionsAsync();
}
}
}

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs

@ -38,7 +38,7 @@ namespace Volo.Abp.AspNetCore
AddAspNetServices(context.Services);
context.Services.AddObjectAccessor<IApplicationBuilder>();
context.Services.Replace(ServiceDescriptor.Transient<IOptionsFactory<RequestLocalizationOptions>, AbpRequestLocalizationOptionsFactory>());
context.Services.AddAbpDynamicOptions<RequestLocalizationOptions, AbpRequestLocalizationOptionsManager>();
}
private static void AddAspNetServices(IServiceCollection services)

4
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);
}
}

50
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<TOptions> : IOptionsFactory<TOptions> where TOptions : class, new()
{
private readonly IEnumerable<IConfigureOptions<TOptions>> _setups;
private readonly IEnumerable<IPostConfigureOptions<TOptions>> _postConfigures;
private readonly IEnumerable<IValidateOptions<TOptions>> _validations;
public AbpOptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures)
public AbpOptionsFactory(
IEnumerable<IConfigureOptions<TOptions>> setups,
IEnumerable<IPostConfigureOptions<TOptions>> postConfigures)
: this(setups, postConfigures, validations: null)
{
}
public AbpOptionsFactory(
IEnumerable<IConfigureOptions<TOptions>> setups,
IEnumerable<IPostConfigureOptions<TOptions>> postConfigures,
IEnumerable<IValidateOptions<TOptions>> 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<TOptions> 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<string>();
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);
}
}
}
}
}
}

2
framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.2.0" />
<PackageReference Include="LdapForNet" Version="2.7.11" />
</ItemGroup>
<ItemGroup>

22
framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpAbpLdapOptionsFactory.cs → 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<AbpLdapOptions>
public class AbpAbpLdapOptionsManager : AbpDynamicOptionsManager<AbpLdapOptions>
{
protected ISettingProvider SettingProvider { get; }
public AbpAbpLdapOptionsFactory(
IEnumerable<IConfigureOptions<AbpLdapOptions>> setups,
IEnumerable<IPostConfigureOptions<AbpLdapOptions>> postConfigures,
ISettingProvider settingProvider)
: base(setups, postConfigures)
public AbpAbpLdapOptionsManager(IOptionsFactory<AbpLdapOptions> 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);

3
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<IOptionsFactory<AbpLdapOptions>, AbpAbpLdapOptionsFactory>());
context.Services.Replace(ServiceDescriptor.Scoped<IOptions<AbpLdapOptions>, OptionsManager<AbpLdapOptions>>());
context.Services.AddAbpDynamicOptions<AbpLdapOptions, AbpAbpLdapOptionsManager>();
var configuration = context.Services.GetConfiguration();
var ldapConfiguration = configuration["Ldap"];

6
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<bool> AuthenticateAsync(string username, string password);
}
}

34
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<AbpLdapOptions> ldapSettingsOptions)
{
LdapOptions = ldapSettingsOptions.Value;
Logger = NullLogger<LdapManager>.Instance;
}
public bool Authenticate(string username, string password)
public virtual async Task<bool> 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<ILdapConnection> 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
});
}
}
}

10
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);
}
}
}

2
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<IOptionsFactory<AbpLdapOptions>>().ShouldBeOfType(typeof(AbpAbpLdapOptionsFactory));
GetRequiredService<IOptions<AbpLdapOptions>>().ShouldBeOfType(typeof(AbpAbpLdapOptionsManager));
}
}
}

2
modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs

@ -166,7 +166,7 @@ namespace Volo.BloggingTestApp
app.UseAuthentication();
app.UseRequestLocalization(app.ApplicationServices.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
app.UseAbpRequestLocalization();
app.UseConfiguredEndpoints();

2
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);

Loading…
Cancel
Save