Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/en/framework/infrastructure/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,31 @@ There are three pre-defined value providers, executed by the given order:

* `TenantFeatureValueProvider` tries to get if the feature value is explicitly set for the **current tenant**.
* `EditionFeatureValueProvider` tries to get the feature value for the current edition. Edition Id is obtained from the current principal identity (`ICurrentPrincipalAccessor`) with the claim name `editionid` (a constant defined as`AbpClaimTypes.EditionId`). Editions are not implemented for the [tenant management](../../modules/tenant-management.md) module. You can implement it yourself or consider to use the [SaaS module](https://abp.io/modules/Volo.Saas) of the ABP Commercial.
* `ConfigurationFeatureValueProvider`: Gets the value from the [IConfiguration service](../fundamentals/configuration.md).
* `DefaultValueFeatureValueProvider` gets the default value of the feature.

#### Feature Values in the Application Configuration

The `ConfigurationFeatureValueProvider` reads the feature values from the `IConfiguration` service, which can read values from the `appsettings.json` by default. So, the easiest way to configure feature values is to define them in the `appsettings.json` file.

For example, you can configure feature values as shown below:

````json
{
"Features": {
"MyApp.Reporting": "true",
"MyApp.PdfReporting": "true",
"MyApp.MaxProductCount": "50"
}
}
````

Feature values should be configured under the `Features` section as like in this example.

> `IConfiguration` is an .NET Core service and it can read values not only from the `appsettings.json`, but also from the environment, user secrets... etc. See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) for more.

#### Custom Feature Value Providers

You can write your own provider by inheriting the `FeatureValueProvider`.

**Example: Enable all features for a user with "SystemAdmin" as a "User_Type" claim value**
Expand Down
3 changes: 2 additions & 1 deletion docs/en/modules/feature-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ namespace Demo

## Feature Management Providers

Features Management Module is extensible, just like the [features system](../framework/infrastructure/features.md). You can extend it by defining feature management providers. There are 3 pre-built feature management providers registered it the following order:
Features Management Module is extensible, just like the [features system](../framework/infrastructure/features.md). You can extend it by defining feature management providers. There are 4 pre-built feature management providers registered in the following order:

* `DefaultValueFeatureManagementProvider`: Gets the value from the default value of the feature definition. It can not set the default value since default values are hard-coded on the feature definition.
* `ConfigurationFeatureManagementProvider`: Gets the value from the [IConfiguration service](../framework/fundamentals/configuration.md).
* `EditionFeatureManagementProvider`: Gets or sets the feature values for an edition. Edition is a group of features assigned to tenants. Edition system has not implemented by the Tenant Management module. You can implement it yourself or purchase the ABP [SaaS Module](https://abp.io/modules/Volo.Saas) which implements it and also provides more SaaS features, like subscription and payment.
* `TenantFeatureManagementProvider`: Gets or sets the features values for tenants.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public override void ConfigureServices(ServiceConfigurationContext context)
context.Services.Configure<AbpFeatureOptions>(options =>
{
options.ValueProviders.Add<DefaultValueFeatureValueProvider>();
options.ValueProviders.Add<ConfigurationFeatureValueProvider>();
options.ValueProviders.Add<EditionFeatureValueProvider>();
options.ValueProviders.Add<TenantFeatureValueProvider>();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

namespace Volo.Abp.Features;

public class ConfigurationFeatureValueProvider : FeatureValueProvider
{
public const string ConfigurationNamePrefix = "Features:";

public const string ProviderName = "C";

public override string Name => ProviderName;

protected IConfiguration Configuration { get; }

public ConfigurationFeatureValueProvider(IFeatureStore featureStore, IConfiguration configuration)
: base(featureStore)
{
Configuration = configuration;
}

public override Task<string?> GetOrNullAsync(FeatureDefinition feature)
{
return Task.FromResult(Configuration[ConfigurationNamePrefix + feature.Name]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public override void ConfigureServices(ServiceConfigurationContext context)
Configure<FeatureManagementOptions>(options =>
{
options.Providers.Add<DefaultValueFeatureManagementProvider>();
options.Providers.Add<ConfigurationFeatureManagementProvider>();
options.Providers.Add<EditionFeatureManagementProvider>();

//TODO: Should be moved to the Tenant Management module
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;

namespace Volo.Abp.FeatureManagement;

public class ConfigurationFeatureManagementProvider : IFeatureManagementProvider, ISingletonDependency
{
public string Name => ConfigurationFeatureValueProvider.ProviderName;

protected IConfiguration Configuration { get; }

public ConfigurationFeatureManagementProvider(IConfiguration configuration)
{
Configuration = configuration;
}

public virtual bool Compatible(string providerName)
{
return providerName == Name;
}

public virtual Task<IAsyncDisposable> HandleContextAsync(string providerName, string providerKey)
{
return Task.FromResult<IAsyncDisposable>(NullAsyncDisposable.Instance);
}

public virtual Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{
return Task.FromResult(Configuration[ConfigurationFeatureValueProvider.ConfigurationNamePrefix + feature.Name]);
}

public virtual Task SetAsync(FeatureDefinition feature, string value, string providerKey)
{
throw new AbpException($"Can not set a feature value to the application configuration.");
}

public virtual Task ClearAsync(FeatureDefinition feature, string providerKey)
{
throw new AbpException($"Can not set a feature value to the application configuration.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Features;

namespace Volo.Abp.FeatureManagement;

public static class ConfigurationValueFeatureManagerExtensions
{
public static Task<string> GetOrNullConfigurationAsync(this IFeatureManager featureManager, [NotNull] string name, bool fallback = true)
{
return featureManager.GetOrNullAsync(name, ConfigurationFeatureValueProvider.ProviderName, null, fallback);
}

public static Task<List<FeatureNameValue>> GetAllConfigurationAsync(this IFeatureManager featureManager, bool fallback = true)
{
return featureManager.GetAllAsync(ConfigurationFeatureValueProvider.ProviderName, null, fallback);
}
}
Loading