mirror of https://github.com/abpframework/abp.git
98 changed files with 2315 additions and 2405 deletions
@ -1,23 +1,22 @@ |
|||
using Volo.Abp.Validation.StringValues; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureDto |
|||
{ |
|||
public class FeatureDto |
|||
{ |
|||
public string Name { get; set; } |
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
public string Value { get; set; } |
|||
|
|||
public FeatureProviderDto Provider { get; set; } |
|||
public FeatureProviderDto Provider { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
public string Description { get; set; } |
|||
|
|||
public IStringValueType ValueType { get; set; } |
|||
public IStringValueType ValueType { get; set; } |
|||
|
|||
public int Depth { get; set; } |
|||
public int Depth { get; set; } |
|||
|
|||
public string ParentName { get; set; } |
|||
} |
|||
public string ParentName { get; set; } |
|||
} |
|||
|
|||
@ -1,18 +1,17 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureGroupDto |
|||
{ |
|||
public class FeatureGroupDto |
|||
{ |
|||
public string Name { get; set; } |
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
public string DisplayName { get; set; } |
|||
|
|||
public List<FeatureDto> Features { get; set; } |
|||
public List<FeatureDto> Features { get; set; } |
|||
|
|||
public string GetNormalizedGroupName() |
|||
{ |
|||
return Name.Replace(".", "_"); |
|||
} |
|||
public string GetNormalizedGroupName() |
|||
{ |
|||
return Name.Replace(".", "_"); |
|||
} |
|||
} |
|||
|
|||
@ -1,16 +1,15 @@ |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementPermissions |
|||
{ |
|||
public class FeatureManagementPermissions |
|||
{ |
|||
public const string GroupName = "FeatureManagement"; |
|||
public const string GroupName = "FeatureManagement"; |
|||
|
|||
public const string ManageHostFeatures = GroupName + ".ManageHostFeatures"; |
|||
public const string ManageHostFeatures = GroupName + ".ManageHostFeatures"; |
|||
|
|||
public static string[] GetAll() |
|||
{ |
|||
return ReflectionHelper.GetPublicConstantsRecursively(typeof(FeatureManagementPermissions)); |
|||
} |
|||
public static string[] GetAll() |
|||
{ |
|||
return ReflectionHelper.GetPublicConstantsRecursively(typeof(FeatureManagementPermissions)); |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementRemoteServiceConsts |
|||
{ |
|||
public class FeatureManagementRemoteServiceConsts |
|||
{ |
|||
public const string RemoteServiceName = "AbpFeatureManagement"; |
|||
public const string RemoteServiceName = "AbpFeatureManagement"; |
|||
|
|||
public const string ModuleName = "featureManagement"; |
|||
} |
|||
public const string ModuleName = "featureManagement"; |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureProviderDto |
|||
{ |
|||
public class FeatureProviderDto |
|||
{ |
|||
public string Name { get; set; } |
|||
public string Name { get; set; } |
|||
|
|||
public string Key { get; set; } |
|||
} |
|||
public string Key { get; set; } |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class GetFeatureListResultDto |
|||
{ |
|||
public class GetFeatureListResultDto |
|||
{ |
|||
public List<FeatureGroupDto> Groups { get; set; } |
|||
} |
|||
public List<FeatureGroupDto> Groups { get; set; } |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class UpdateFeatureDto |
|||
{ |
|||
public class UpdateFeatureDto |
|||
{ |
|||
public string Name { get; set; } |
|||
public string Name { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
} |
|||
public string Value { get; set; } |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class UpdateFeaturesDto |
|||
{ |
|||
public class UpdateFeaturesDto |
|||
{ |
|||
public List<UpdateFeatureDto> Features { get; set; } |
|||
} |
|||
} |
|||
public List<UpdateFeatureDto> Features { get; set; } |
|||
} |
|||
|
|||
@ -1,124 +1,121 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Features; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Authorize] |
|||
public class FeatureAppService : FeatureManagementAppServiceBase, IFeatureAppService |
|||
{ |
|||
[Authorize] |
|||
public class FeatureAppService : FeatureManagementAppServiceBase, IFeatureAppService |
|||
protected FeatureManagementOptions Options { get; } |
|||
protected IFeatureManager FeatureManager { get; } |
|||
protected IFeatureDefinitionManager FeatureDefinitionManager { get; } |
|||
|
|||
public FeatureAppService(IFeatureManager featureManager, |
|||
IFeatureDefinitionManager featureDefinitionManager, |
|||
IOptions<FeatureManagementOptions> options) |
|||
{ |
|||
protected FeatureManagementOptions Options { get; } |
|||
protected IFeatureManager FeatureManager { get; } |
|||
protected IFeatureDefinitionManager FeatureDefinitionManager { get; } |
|||
FeatureManager = featureManager; |
|||
FeatureDefinitionManager = featureDefinitionManager; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public FeatureAppService(IFeatureManager featureManager, |
|||
IFeatureDefinitionManager featureDefinitionManager, |
|||
IOptions<FeatureManagementOptions> options) |
|||
{ |
|||
FeatureManager = featureManager; |
|||
FeatureDefinitionManager = featureDefinitionManager; |
|||
Options = options.Value; |
|||
} |
|||
public virtual async Task<GetFeatureListResultDto> GetAsync([NotNull] string providerName, string providerKey) |
|||
{ |
|||
await CheckProviderPolicy(providerName, providerKey); |
|||
|
|||
public virtual async Task<GetFeatureListResultDto> GetAsync([NotNull] string providerName, string providerKey) |
|||
var result = new GetFeatureListResultDto |
|||
{ |
|||
await CheckProviderPolicy(providerName, providerKey); |
|||
Groups = new List<FeatureGroupDto>() |
|||
}; |
|||
|
|||
var result = new GetFeatureListResultDto |
|||
foreach (var group in FeatureDefinitionManager.GetGroups()) |
|||
{ |
|||
var groupDto = new FeatureGroupDto |
|||
{ |
|||
Groups = new List<FeatureGroupDto>() |
|||
Name = group.Name, |
|||
DisplayName = group.DisplayName.Localize(StringLocalizerFactory), |
|||
Features = new List<FeatureDto>() |
|||
}; |
|||
|
|||
foreach (var group in FeatureDefinitionManager.GetGroups()) |
|||
foreach (var featureDefinition in group.GetFeaturesWithChildren()) |
|||
{ |
|||
var groupDto = new FeatureGroupDto |
|||
if (providerName == TenantFeatureValueProvider.ProviderName && |
|||
CurrentTenant.Id == null && |
|||
providerKey == null && |
|||
!featureDefinition.IsAvailableToHost) |
|||
{ |
|||
Name = group.Name, |
|||
DisplayName = group.DisplayName.Localize(StringLocalizerFactory), |
|||
Features = new List<FeatureDto>() |
|||
}; |
|||
continue; |
|||
} |
|||
|
|||
foreach (var featureDefinition in group.GetFeaturesWithChildren()) |
|||
var feature = await FeatureManager.GetOrNullWithProviderAsync(featureDefinition.Name, providerName, providerKey); |
|||
groupDto.Features.Add(new FeatureDto |
|||
{ |
|||
if (providerName == TenantFeatureValueProvider.ProviderName && |
|||
CurrentTenant.Id == null && |
|||
providerKey == null && |
|||
!featureDefinition.IsAvailableToHost) |
|||
Name = featureDefinition.Name, |
|||
DisplayName = featureDefinition.DisplayName?.Localize(StringLocalizerFactory), |
|||
ValueType = featureDefinition.ValueType, |
|||
Description = featureDefinition.Description?.Localize(StringLocalizerFactory), |
|||
ParentName = featureDefinition.Parent?.Name, |
|||
Value = feature.Value, |
|||
Provider = new FeatureProviderDto |
|||
{ |
|||
continue; |
|||
Name = feature.Provider?.Name, |
|||
Key = feature.Provider?.Key |
|||
} |
|||
}); |
|||
} |
|||
|
|||
var feature = await FeatureManager.GetOrNullWithProviderAsync(featureDefinition.Name, providerName, providerKey); |
|||
groupDto.Features.Add(new FeatureDto |
|||
{ |
|||
Name = featureDefinition.Name, |
|||
DisplayName = featureDefinition.DisplayName?.Localize(StringLocalizerFactory), |
|||
ValueType = featureDefinition.ValueType, |
|||
Description = featureDefinition.Description?.Localize(StringLocalizerFactory), |
|||
ParentName = featureDefinition.Parent?.Name, |
|||
Value = feature.Value, |
|||
Provider = new FeatureProviderDto |
|||
{ |
|||
Name = feature.Provider?.Name, |
|||
Key = feature.Provider?.Key |
|||
} |
|||
}); |
|||
} |
|||
SetFeatureDepth(groupDto.Features, providerName, providerKey); |
|||
|
|||
SetFeatureDepth(groupDto.Features, providerName, providerKey); |
|||
result.Groups.Add(groupDto); |
|||
} |
|||
|
|||
result.Groups.Add(groupDto); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
public virtual async Task UpdateAsync([NotNull] string providerName, string providerKey, UpdateFeaturesDto input) |
|||
{ |
|||
await CheckProviderPolicy(providerName, providerKey); |
|||
|
|||
public virtual async Task UpdateAsync([NotNull] string providerName, string providerKey, UpdateFeaturesDto input) |
|||
foreach (var feature in input.Features) |
|||
{ |
|||
await CheckProviderPolicy(providerName, providerKey); |
|||
|
|||
foreach (var feature in input.Features) |
|||
{ |
|||
await FeatureManager.SetAsync(feature.Name, feature.Value, providerName, providerKey); |
|||
} |
|||
await FeatureManager.SetAsync(feature.Name, feature.Value, providerName, providerKey); |
|||
} |
|||
} |
|||
|
|||
protected virtual void SetFeatureDepth(List<FeatureDto> features, string providerName, string providerKey, |
|||
FeatureDto parentFeature = null, int depth = 0) |
|||
protected virtual void SetFeatureDepth(List<FeatureDto> features, string providerName, string providerKey, |
|||
FeatureDto parentFeature = null, int depth = 0) |
|||
{ |
|||
foreach (var feature in features) |
|||
{ |
|||
foreach (var feature in features) |
|||
if ((parentFeature == null && feature.ParentName == null) || (parentFeature != null && parentFeature.Name == feature.ParentName)) |
|||
{ |
|||
if ((parentFeature == null && feature.ParentName == null) || (parentFeature != null && parentFeature.Name == feature.ParentName)) |
|||
{ |
|||
feature.Depth = depth; |
|||
SetFeatureDepth(features, providerName, providerKey, feature, depth + 1); |
|||
} |
|||
feature.Depth = depth; |
|||
SetFeatureDepth(features, providerName, providerKey, feature, depth + 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task CheckProviderPolicy(string providerName, string providerKey) |
|||
protected virtual async Task CheckProviderPolicy(string providerName, string providerKey) |
|||
{ |
|||
string policyName; |
|||
if (providerName == TenantFeatureValueProvider.ProviderName && CurrentTenant.Id == null && providerKey == null) |
|||
{ |
|||
string policyName; |
|||
if (providerName == TenantFeatureValueProvider.ProviderName && CurrentTenant.Id == null && providerKey == null ) |
|||
{ |
|||
policyName = "FeatureManagement.ManageHostFeatures"; |
|||
} |
|||
else |
|||
policyName = "FeatureManagement.ManageHostFeatures"; |
|||
} |
|||
else |
|||
{ |
|||
policyName = Options.ProviderPolicies.GetOrDefault(providerName); |
|||
if (policyName.IsNullOrEmpty()) |
|||
{ |
|||
policyName = Options.ProviderPolicies.GetOrDefault(providerName); |
|||
if (policyName.IsNullOrEmpty()) |
|||
{ |
|||
throw new AbpException($"No policy defined to get/set permissions for the provider '{providerName}'. Use {nameof(FeatureManagementOptions)} to map the policy."); |
|||
} |
|||
throw new AbpException($"No policy defined to get/set permissions for the provider '{providerName}'. Use {nameof(FeatureManagementOptions)} to map the policy."); |
|||
} |
|||
|
|||
await AuthorizationService.CheckAsync(policyName); |
|||
} |
|||
|
|||
await AuthorizationService.CheckAsync(policyName); |
|||
} |
|||
} |
|||
|
|||
@ -1,14 +1,13 @@ |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public abstract class FeatureManagementAppServiceBase : ApplicationService |
|||
{ |
|||
public abstract class FeatureManagementAppServiceBase : ApplicationService |
|||
protected FeatureManagementAppServiceBase() |
|||
{ |
|||
protected FeatureManagementAppServiceBase() |
|||
{ |
|||
ObjectMapperContext = typeof(AbpFeatureManagementApplicationModule); |
|||
LocalizationResource = typeof(AbpFeatureManagementResource); |
|||
} |
|||
ObjectMapperContext = typeof(AbpFeatureManagementApplicationModule); |
|||
LocalizationResource = typeof(AbpFeatureManagementResource); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,12 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementApplicationAutoMapperProfile : Profile |
|||
{ |
|||
public class FeatureManagementApplicationAutoMapperProfile : Profile |
|||
public FeatureManagementApplicationAutoMapperProfile() |
|||
{ |
|||
public FeatureManagementApplicationAutoMapperProfile() |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,14 +1,13 @@ |
|||
using Volo.Abp.AspNetCore.Components.Server.Theming; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Blazor.Server |
|||
namespace Volo.Abp.FeatureManagement.Blazor.Server; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementBlazorModule), |
|||
typeof(AbpAspNetCoreComponentsServerThemingModule) |
|||
)] |
|||
public class AbpFeatureManagementBlazorServerModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementBlazorModule), |
|||
typeof(AbpAspNetCoreComponentsServerThemingModule) |
|||
)] |
|||
public class AbpFeatureManagementBlazorServerModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,14 +1,13 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Blazor.WebAssembly |
|||
namespace Volo.Abp.FeatureManagement.Blazor.WebAssembly; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementBlazorModule), |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule), |
|||
typeof(AbpFeatureManagementHttpApiClientModule) |
|||
)] |
|||
public class AbpFeatureManagementBlazorWebAssemblyModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementBlazorModule), |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule), |
|||
typeof(AbpFeatureManagementHttpApiClientModule) |
|||
)] |
|||
public class AbpFeatureManagementBlazorWebAssemblyModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
using Volo.Abp.AspNetCore.Components; |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Blazor |
|||
namespace Volo.Abp.FeatureManagement.Blazor; |
|||
|
|||
public abstract class AbpFeatureManagementComponentBase : AbpComponentBase |
|||
{ |
|||
public abstract class AbpFeatureManagementComponentBase : AbpComponentBase |
|||
protected AbpFeatureManagementComponentBase() |
|||
{ |
|||
protected AbpFeatureManagementComponentBase() |
|||
{ |
|||
LocalizationResource = typeof(AbpFeatureManagementResource); |
|||
} |
|||
LocalizationResource = typeof(AbpFeatureManagementResource); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,6 @@ |
|||
using System; |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
public static class FeatureManagementDomainErrorCodes |
|||
{ |
|||
public static class FeatureManagementDomainErrorCodes |
|||
{ |
|||
public const string FeatureValueInvalid = "Volo.Abp.FeatureManagement:InvalidFeatureValue"; |
|||
} |
|||
public const string FeatureValueInvalid = "Volo.Abp.FeatureManagement:InvalidFeatureValue"; |
|||
} |
|||
|
|||
@ -1,14 +1,13 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Serializable] |
|||
public class FeatureValueInvalidException : BusinessException |
|||
{ |
|||
[Serializable] |
|||
public class FeatureValueInvalidException : BusinessException |
|||
public FeatureValueInvalidException(string name) : |
|||
base(FeatureManagementDomainErrorCodes.FeatureValueInvalid) |
|||
{ |
|||
public FeatureValueInvalidException(string name) : |
|||
base(FeatureManagementDomainErrorCodes.FeatureValueInvalid) |
|||
{ |
|||
WithData("0", name); |
|||
} |
|||
WithData("0", name); |
|||
} |
|||
} |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Localization |
|||
namespace Volo.Abp.FeatureManagement.Localization; |
|||
|
|||
[LocalizationResourceName("AbpFeatureManagement")] |
|||
public class AbpFeatureManagementResource |
|||
{ |
|||
[LocalizationResourceName("AbpFeatureManagement")] |
|||
public class AbpFeatureManagementResource |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public static class FeatureManagementDbProperties |
|||
{ |
|||
public static class FeatureManagementDbProperties |
|||
{ |
|||
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix; |
|||
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix; |
|||
|
|||
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema; |
|||
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema; |
|||
|
|||
public const string ConnectionStringName = "AbpFeatureManagement"; |
|||
} |
|||
public const string ConnectionStringName = "AbpFeatureManagement"; |
|||
} |
|||
|
|||
@ -1,18 +1,17 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Collections; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementOptions |
|||
{ |
|||
public class FeatureManagementOptions |
|||
{ |
|||
public ITypeList<IFeatureManagementProvider> Providers { get; } |
|||
public ITypeList<IFeatureManagementProvider> Providers { get; } |
|||
|
|||
public Dictionary<string, string> ProviderPolicies { get; } |
|||
public Dictionary<string, string> ProviderPolicies { get; } |
|||
|
|||
public FeatureManagementOptions() |
|||
{ |
|||
Providers = new TypeList<IFeatureManagementProvider>(); |
|||
ProviderPolicies = new Dictionary<string, string>(); |
|||
} |
|||
public FeatureManagementOptions() |
|||
{ |
|||
Providers = new TypeList<IFeatureManagementProvider>(); |
|||
ProviderPolicies = new Dictionary<string, string>(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,42 +1,41 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Features; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public abstract class FeatureManagementProvider : IFeatureManagementProvider |
|||
{ |
|||
public abstract class FeatureManagementProvider : IFeatureManagementProvider |
|||
public abstract string Name { get; } |
|||
|
|||
protected IFeatureManagementStore Store { get; } |
|||
|
|||
protected FeatureManagementProvider(IFeatureManagementStore store) |
|||
{ |
|||
Store = store; |
|||
} |
|||
|
|||
public virtual bool Compatible(string providerName) |
|||
{ |
|||
return providerName == Name; |
|||
} |
|||
|
|||
public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey) |
|||
{ |
|||
return await Store.GetOrNullAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
public virtual async Task SetAsync(FeatureDefinition feature, string value, string providerKey) |
|||
{ |
|||
await Store.SetAsync(feature.Name, value, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
public virtual async Task ClearAsync(FeatureDefinition feature, string providerKey) |
|||
{ |
|||
await Store.DeleteAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
protected virtual Task<string> NormalizeProviderKeyAsync(string providerKey) |
|||
{ |
|||
public abstract string Name { get; } |
|||
|
|||
protected IFeatureManagementStore Store { get; } |
|||
|
|||
protected FeatureManagementProvider(IFeatureManagementStore store) |
|||
{ |
|||
Store = store; |
|||
} |
|||
|
|||
public virtual bool Compatible(string providerName) |
|||
{ |
|||
return providerName == Name; |
|||
} |
|||
|
|||
public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey) |
|||
{ |
|||
return await Store.GetOrNullAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
public virtual async Task SetAsync(FeatureDefinition feature, string value, string providerKey) |
|||
{ |
|||
await Store.SetAsync(feature.Name, value, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
public virtual async Task ClearAsync(FeatureDefinition feature, string providerKey) |
|||
{ |
|||
await Store.DeleteAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey)); |
|||
} |
|||
|
|||
protected virtual Task<string> NormalizeProviderKeyAsync(string providerKey) |
|||
{ |
|||
return Task.FromResult(providerKey); |
|||
} |
|||
return Task.FromResult(providerKey); |
|||
} |
|||
} |
|||
|
|||
@ -1,19 +1,18 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Serializable] |
|||
public class FeatureNameValue : NameValue |
|||
{ |
|||
[Serializable] |
|||
public class FeatureNameValue : NameValue |
|||
public FeatureNameValue() |
|||
{ |
|||
public FeatureNameValue() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
public FeatureNameValue(string name, string value) |
|||
{ |
|||
Name = name; |
|||
Value = value; |
|||
} |
|||
public FeatureNameValue(string name, string value) |
|||
{ |
|||
Name = name; |
|||
Value = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,19 +1,18 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Serializable] |
|||
public class FeatureNameValueWithGrantedProvider : NameValue |
|||
{ |
|||
[Serializable] |
|||
public class FeatureNameValueWithGrantedProvider : NameValue |
|||
{ |
|||
public FeatureValueProviderInfo Provider { get; set; } |
|||
public FeatureValueProviderInfo Provider { get; set; } |
|||
|
|||
public FeatureNameValueWithGrantedProvider([NotNull] string name, string value) |
|||
{ |
|||
Check.NotNull(name, nameof(name)); |
|||
public FeatureNameValueWithGrantedProvider([NotNull] string name, string value) |
|||
{ |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
Name = name; |
|||
Value = value; |
|||
} |
|||
Name = name; |
|||
Value = value; |
|||
} |
|||
} |
|||
|
|||
@ -1,27 +1,26 @@ |
|||
using System; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Serializable] |
|||
[IgnoreMultiTenancy] |
|||
public class FeatureValueCacheItem |
|||
{ |
|||
[Serializable] |
|||
[IgnoreMultiTenancy] |
|||
public class FeatureValueCacheItem |
|||
{ |
|||
public string Value { get; set; } |
|||
public string Value { get; set; } |
|||
|
|||
public FeatureValueCacheItem() |
|||
{ |
|||
public FeatureValueCacheItem() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
public FeatureValueCacheItem(string value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
public FeatureValueCacheItem(string value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
|
|||
public static string CalculateCacheKey(string name, string providerName, string providerKey) |
|||
{ |
|||
return "pn:" + providerName + ",pk:" + providerKey + ",n:" + name; |
|||
} |
|||
public static string CalculateCacheKey(string name, string providerName, string providerKey) |
|||
{ |
|||
return "pn:" + providerName + ",pk:" + providerKey + ",n:" + name; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,25 +1,24 @@ |
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public static class FeatureValueConsts |
|||
{ |
|||
public static class FeatureValueConsts |
|||
{ |
|||
/// <summary>
|
|||
/// Default value: 128
|
|||
/// </summary>
|
|||
public static int MaxNameLength { get; set;} = 128; |
|||
/// <summary>
|
|||
/// Default value: 128
|
|||
/// </summary>
|
|||
public static int MaxNameLength { get; set; } = 128; |
|||
|
|||
/// <summary>
|
|||
/// Default value: 64
|
|||
/// </summary>
|
|||
public static int MaxProviderNameLength { get; set;} = 64; |
|||
/// <summary>
|
|||
/// Default value: 64
|
|||
/// </summary>
|
|||
public static int MaxProviderNameLength { get; set; } = 64; |
|||
|
|||
/// <summary>
|
|||
/// Default value: 64
|
|||
/// </summary>
|
|||
public static int MaxProviderKeyLength { get; set;} = 64; |
|||
/// <summary>
|
|||
/// Default value: 64
|
|||
/// </summary>
|
|||
public static int MaxProviderKeyLength { get; set; } = 64; |
|||
|
|||
/// <summary>
|
|||
/// Default value: 128
|
|||
/// </summary>
|
|||
public static int MaxValueLength { get; set;} = 128; |
|||
} |
|||
/// <summary>
|
|||
/// Default value: 128
|
|||
/// </summary>
|
|||
public static int MaxValueLength { get; set; } = 128; |
|||
} |
|||
|
|||
@ -1,21 +1,20 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[Serializable] |
|||
public class FeatureValueProviderInfo |
|||
{ |
|||
[Serializable] |
|||
public class FeatureValueProviderInfo |
|||
{ |
|||
public string Name { get; } |
|||
public string Name { get; } |
|||
|
|||
public string Key { get; } |
|||
public string Key { get; } |
|||
|
|||
public FeatureValueProviderInfo([NotNull]string name, string key) |
|||
{ |
|||
Check.NotNull(name, nameof(name)); |
|||
public FeatureValueProviderInfo([NotNull] string name, string key) |
|||
{ |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
Name = name; |
|||
Key = key; |
|||
} |
|||
Name = name; |
|||
Key = key; |
|||
} |
|||
} |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public interface IFeatureManagementStore |
|||
{ |
|||
public interface IFeatureManagementStore |
|||
{ |
|||
Task<string> GetOrNullAsync(string name, string providerName, string providerKey); |
|||
Task<string> GetOrNullAsync(string name, string providerName, string providerKey); |
|||
|
|||
Task SetAsync(string name, string value, string providerName, string providerKey); |
|||
Task SetAsync(string name, string value, string providerName, string providerKey); |
|||
|
|||
Task DeleteAsync(string name, string providerName, string providerKey); |
|||
} |
|||
} |
|||
Task DeleteAsync(string name, string providerName, string providerKey); |
|||
} |
|||
|
|||
@ -1,38 +1,36 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore.Modeling; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore |
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
|
|||
public static class FeatureManagementDbContextModelCreatingExtensions |
|||
{ |
|||
public static class FeatureManagementDbContextModelCreatingExtensions |
|||
public static void ConfigureFeatureManagement( |
|||
this ModelBuilder builder) |
|||
{ |
|||
public static void ConfigureFeatureManagement( |
|||
this ModelBuilder builder) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
if (builder.IsTenantOnlyDatabase()) |
|||
{ |
|||
return; |
|||
} |
|||
if (builder.IsTenantOnlyDatabase()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
builder.Entity<FeatureValue>(b => |
|||
{ |
|||
b.ToTable(FeatureManagementDbProperties.DbTablePrefix + "FeatureValues", FeatureManagementDbProperties.DbSchema); |
|||
builder.Entity<FeatureValue>(b => |
|||
{ |
|||
b.ToTable(FeatureManagementDbProperties.DbTablePrefix + "FeatureValues", FeatureManagementDbProperties.DbSchema); |
|||
|
|||
b.ConfigureByConvention(); |
|||
b.ConfigureByConvention(); |
|||
|
|||
b.Property(x => x.Name).HasMaxLength(FeatureValueConsts.MaxNameLength).IsRequired(); |
|||
b.Property(x => x.Value).HasMaxLength(FeatureValueConsts.MaxValueLength).IsRequired(); |
|||
b.Property(x => x.ProviderName).HasMaxLength(FeatureValueConsts.MaxProviderNameLength); |
|||
b.Property(x => x.ProviderKey).HasMaxLength(FeatureValueConsts.MaxProviderKeyLength); |
|||
b.Property(x => x.Name).HasMaxLength(FeatureValueConsts.MaxNameLength).IsRequired(); |
|||
b.Property(x => x.Value).HasMaxLength(FeatureValueConsts.MaxValueLength).IsRequired(); |
|||
b.Property(x => x.ProviderName).HasMaxLength(FeatureValueConsts.MaxProviderNameLength); |
|||
b.Property(x => x.ProviderKey).HasMaxLength(FeatureValueConsts.MaxProviderKeyLength); |
|||
|
|||
b.HasIndex(x => new { x.Name, x.ProviderName, x.ProviderKey }).IsUnique(true); |
|||
b.HasIndex(x => new { x.Name, x.ProviderName, x.ProviderKey }).IsUnique(true); |
|||
|
|||
b.ApplyObjectExtensionMappings(); |
|||
}); |
|||
b.ApplyObjectExtensionMappings(); |
|||
}); |
|||
|
|||
builder.TryConfigureObjectExtensions<FeatureManagementDbContext>(); |
|||
} |
|||
builder.TryConfigureObjectExtensions<FeatureManagementDbContext>(); |
|||
} |
|||
} |
|||
|
|||
@ -1,8 +1,7 @@ |
|||
// This file is part of FeaturesClientProxy, you can customize it here
|
|||
// ReSharper disable once CheckNamespace
|
|||
namespace Volo.Abp.FeatureManagement.ClientProxies |
|||
namespace Volo.Abp.FeatureManagement.ClientProxies; |
|||
|
|||
public partial class FeaturesClientProxy |
|||
{ |
|||
public partial class FeaturesClientProxy |
|||
{ |
|||
} |
|||
} |
|||
|
|||
@ -1,18 +1,17 @@ |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
public static class FeatureManagementMongoDbContextExtensions |
|||
{ |
|||
public static class FeatureManagementMongoDbContextExtensions |
|||
public static void ConfigureFeatureManagement( |
|||
this IMongoModelBuilder builder) |
|||
{ |
|||
public static void ConfigureFeatureManagement( |
|||
this IMongoModelBuilder builder) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
builder.Entity<FeatureValue>(b => |
|||
{ |
|||
b.CollectionName = FeatureManagementDbProperties.DbTablePrefix + "FeatureValues"; |
|||
}); |
|||
} |
|||
builder.Entity<FeatureValue>(b => |
|||
{ |
|||
b.CollectionName = FeatureManagementDbProperties.DbTablePrefix + "FeatureValues"; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,12 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementWebAutoMapperProfile : Profile |
|||
{ |
|||
public class FeatureManagementWebAutoMapperProfile : Profile |
|||
public FeatureManagementWebAutoMapperProfile() |
|||
{ |
|||
public FeatureManagementWebAutoMapperProfile() |
|||
{ |
|||
//Create mappings.
|
|||
} |
|||
//Create mappings.
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,27 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "http://localhost:50650/", |
|||
"sslPort": 44341 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"Volo.Abp.FeatureManagement.Web": { |
|||
"commandName": "Project", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
}, |
|||
"applicationUrl": "https://localhost:5001;http://localhost:5000" |
|||
} |
|||
} |
|||
} |
|||
@ -1,11 +1,6 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
public class FeatureManagementApplicationTestBase : FeatureManagementTestBase<FeatureManagementApplicationTestModule> |
|||
{ |
|||
public class FeatureManagementApplicationTestBase : FeatureManagementTestBase<FeatureManagementApplicationTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementApplicationModule), |
|||
typeof(AbpFeatureManagementDomainTestModule) |
|||
)] |
|||
public class FeatureManagementApplicationTestModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementApplicationModule), |
|||
typeof(AbpFeatureManagementDomainTestModule) |
|||
)] |
|||
public class FeatureManagementApplicationTestModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,16 +1,15 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class NewtonsoftStringValueJsonConverter_Tests : StringValueJsonConverter_Tests |
|||
{ |
|||
public class NewtonsoftStringValueJsonConverter_Tests : StringValueJsonConverter_Tests |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
services.PreConfigure<AbpJsonOptions>(options => |
|||
{ |
|||
services.PreConfigure<AbpJsonOptions>(options => |
|||
{ |
|||
options.UseHybridSerializer = true; |
|||
}); |
|||
} |
|||
options.UseHybridSerializer = true; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@ -1,16 +1,15 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class SystemTextJsonStringValueJsonConverter_Tests : StringValueJsonConverter_Tests |
|||
{ |
|||
public class SystemTextJsonStringValueJsonConverter_Tests : StringValueJsonConverter_Tests |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
services.PreConfigure<AbpJsonOptions>(options => |
|||
{ |
|||
services.PreConfigure<AbpJsonOptions>(options => |
|||
{ |
|||
options.UseHybridSerializer = false; |
|||
}); |
|||
} |
|||
options.UseHybridSerializer = false; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
using Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementEntityFrameworkCoreTestModule) |
|||
)] |
|||
public class AbpFeatureManagementDomainTestModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementEntityFrameworkCoreTestModule) |
|||
)] |
|||
public class AbpFeatureManagementDomainTestModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
@ -1,7 +1,6 @@ |
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public abstract class FeatureManagementDomainTestBase : FeatureManagementTestBase<AbpFeatureManagementDomainTestModule> |
|||
{ |
|||
public abstract class FeatureManagementDomainTestBase : FeatureManagementTestBase<AbpFeatureManagementDomainTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,158 +1,156 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManager_Tests : FeatureManagementDomainTestBase |
|||
{ |
|||
public class FeatureManager_Tests : FeatureManagementDomainTestBase |
|||
private readonly IFeatureManager _featureManager; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IFeatureChecker _featureChecker; |
|||
|
|||
public FeatureManager_Tests() |
|||
{ |
|||
private readonly IFeatureManager _featureManager; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IFeatureChecker _featureChecker; |
|||
_featureManager = GetRequiredService<IFeatureManager>(); |
|||
_featureChecker = GetRequiredService<IFeatureChecker>(); |
|||
_currentTenant = GetRequiredService<ICurrentTenant>(); |
|||
} |
|||
|
|||
public FeatureManager_Tests() |
|||
{ |
|||
_featureManager = GetRequiredService<IFeatureManager>(); |
|||
_featureChecker = GetRequiredService<IFeatureChecker>(); |
|||
_currentTenant = GetRequiredService<ICurrentTenant>(); |
|||
} |
|||
[Fact] |
|||
public async Task Should_Get_A_FeatureValue_For_A_Provider() |
|||
{ |
|||
//Default values
|
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins |
|||
)).ShouldBeNull(); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis |
|||
)).ShouldBe(false.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount |
|||
)).ShouldBe("1"); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.BackupCount |
|||
)).ShouldBe("0"); |
|||
|
|||
//"Enterprise" edition values
|
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe(false.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe("3"); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.BackupCount, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe("5"); |
|||
|
|||
//"Ultimate" edition values
|
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe("10"); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.BackupCount, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe("10"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_A_FeatureValue_For_A_Provider() |
|||
[Fact] |
|||
public async Task Should_Change_Feature_Value_And_Refresh_Cache() |
|||
{ |
|||
var tenantId = Guid.NewGuid(); |
|||
|
|||
//It is "False" at the beginning
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
//Default values
|
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins |
|||
)).ShouldBeNull(); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis |
|||
)).ShouldBe(false.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount |
|||
)).ShouldBe("1"); |
|||
|
|||
(await _featureManager.GetOrNullDefaultAsync( |
|||
TestFeatureDefinitionProvider.BackupCount |
|||
)).ShouldBe("0"); |
|||
|
|||
//"Enterprise" edition values
|
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe(false.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe("3"); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.BackupCount, |
|||
TestEditionIds.Enterprise |
|||
)).ShouldBe("5"); |
|||
|
|||
//"Ultimate" edition values
|
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.SocialLogins, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.DailyAnalysis, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe(true.ToString().ToLowerInvariant()); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.ProjectCount, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe("10"); |
|||
|
|||
(await _featureManager.GetOrNullForEditionAsync( |
|||
TestFeatureDefinitionProvider.BackupCount, |
|||
TestEditionIds.Ultimate |
|||
)).ShouldBe("10"); |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeFalse(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Change_Feature_Value_And_Refresh_Cache() |
|||
//Set to "True" by host for the tenant
|
|||
using (_currentTenant.Change(null)) |
|||
{ |
|||
var tenantId = Guid.NewGuid(); |
|||
|
|||
//It is "False" at the beginning
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeFalse(); |
|||
} |
|||
|
|||
//Set to "True" by host for the tenant
|
|||
using (_currentTenant.Change(null)) |
|||
{ |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeFalse(); |
|||
await _featureManager.SetForTenantAsync(tenantId, TestFeatureDefinitionProvider.SocialLogins, "True"); |
|||
(await _featureManager.GetOrNullForTenantAsync(TestFeatureDefinitionProvider.SocialLogins, tenantId)).ShouldBe("True"); |
|||
} |
|||
|
|||
//Now, it should be "True"
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeTrue(); |
|||
} |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeFalse(); |
|||
await _featureManager.SetForTenantAsync(tenantId, TestFeatureDefinitionProvider.SocialLogins, "True"); |
|||
(await _featureManager.GetOrNullForTenantAsync(TestFeatureDefinitionProvider.SocialLogins, tenantId)).ShouldBe("True"); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public async Task Should_Get_FeatureValues_With_Provider_For_A_Provider() |
|||
//Now, it should be "True"
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
var featureNameValueWithGrantedProviders = await _featureManager.GetAllWithProviderAsync( |
|||
EditionFeatureValueProvider.ProviderName, |
|||
TestEditionIds.Enterprise.ToString() |
|||
); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.SocialLogins |
|||
&& x.Value == true.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.EmailSupport && |
|||
x.Value == true.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
//Default Value
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.DailyAnalysis && |
|||
x.Value == false.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == DefaultValueFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.UserCount && |
|||
x.Value == "20" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.ProjectCount && |
|||
x.Value == "3" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.BackupCount && |
|||
x.Value == "5" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
(await _featureChecker.IsEnabledAsync(TestFeatureDefinitionProvider.SocialLogins)).ShouldBeTrue(); |
|||
} |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public async Task Should_Get_FeatureValues_With_Provider_For_A_Provider() |
|||
{ |
|||
var featureNameValueWithGrantedProviders = await _featureManager.GetAllWithProviderAsync( |
|||
EditionFeatureValueProvider.ProviderName, |
|||
TestEditionIds.Enterprise.ToString() |
|||
); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.SocialLogins |
|||
&& x.Value == true.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.EmailSupport && |
|||
x.Value == true.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
//Default Value
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.DailyAnalysis && |
|||
x.Value == false.ToString().ToLowerInvariant() && |
|||
x.Provider.Name == DefaultValueFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.UserCount && |
|||
x.Value == "20" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.ProjectCount && |
|||
x.Value == "3" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
|
|||
featureNameValueWithGrantedProviders.ShouldContain(x => |
|||
x.Name == TestFeatureDefinitionProvider.BackupCount && |
|||
x.Value == "5" && |
|||
x.Provider.Name == EditionFeatureValueProvider.ProviderName); |
|||
} |
|||
|
|||
} |
|||
|
|||
@ -1,11 +1,6 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore |
|||
public class FeatureManagementStore_Tests : FeatureManagementStore_Tests<AbpFeatureManagementEntityFrameworkCoreTestModule> |
|||
{ |
|||
public class FeatureManagementStore_Tests : FeatureManagementStore_Tests<AbpFeatureManagementEntityFrameworkCoreTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,7 +1,6 @@ |
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore |
|||
namespace Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
|
|||
public class FeatureValueRepositoryTests : FeatureValueRepository_Tests<AbpFeatureManagementEntityFrameworkCoreTestModule> |
|||
{ |
|||
public class FeatureValueRepositoryTests : FeatureValueRepository_Tests<AbpFeatureManagementEntityFrameworkCoreTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,27 +1,25 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
[DependsOn( |
|||
typeof(FeatureManagementTestBaseModule), |
|||
typeof(AbpFeatureManagementMongoDbModule) |
|||
)] |
|||
public class AbpFeatureManagementMongoDbTestModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(FeatureManagementTestBaseModule), |
|||
typeof(AbpFeatureManagementMongoDbModule) |
|||
)] |
|||
public class AbpFeatureManagementMongoDbTestModule : AbpModule |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var stringArray = MongoDbFixture.ConnectionString.Split('?'); |
|||
var connectionString = stringArray[0].EnsureEndsWith('/') + |
|||
"Db_" + |
|||
Guid.NewGuid().ToString("N") + "/?" + stringArray[1]; |
|||
var stringArray = MongoDbFixture.ConnectionString.Split('?'); |
|||
var connectionString = stringArray[0].EnsureEndsWith('/') + |
|||
"Db_" + |
|||
Guid.NewGuid().ToString("N") + "/?" + stringArray[1]; |
|||
|
|||
Configure<AbpDbConnectionOptions>(options => |
|||
{ |
|||
options.ConnectionStrings.Default = connectionString; |
|||
}); |
|||
} |
|||
Configure<AbpDbConnectionOptions>(options => |
|||
{ |
|||
options.ConnectionStrings.Default = connectionString; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
[Collection(MongoTestCollection.Name)] |
|||
public class FeatureManagementStore_Tests : FeatureManagementStore_Tests<AbpFeatureManagementMongoDbTestModule> |
|||
{ |
|||
[Collection(MongoTestCollection.Name)] |
|||
public class FeatureManagementStore_Tests : FeatureManagementStore_Tests<AbpFeatureManagementMongoDbTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
[Collection(MongoTestCollection.Name)] |
|||
public class FeatureValueRepositoryTests : FeatureValueRepository_Tests<AbpFeatureManagementMongoDbTestModule> |
|||
{ |
|||
[Collection(MongoTestCollection.Name)] |
|||
public class FeatureValueRepositoryTests : FeatureValueRepository_Tests<AbpFeatureManagementMongoDbTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,22 +1,21 @@ |
|||
using System; |
|||
using Mongo2Go; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
public class MongoDbFixture : IDisposable |
|||
{ |
|||
public class MongoDbFixture : IDisposable |
|||
{ |
|||
private static readonly MongoDbRunner MongoDbRunner; |
|||
public static readonly string ConnectionString; |
|||
private static readonly MongoDbRunner MongoDbRunner; |
|||
public static readonly string ConnectionString; |
|||
|
|||
static MongoDbFixture() |
|||
{ |
|||
MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20); |
|||
ConnectionString = MongoDbRunner.ConnectionString; |
|||
} |
|||
static MongoDbFixture() |
|||
{ |
|||
MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20); |
|||
ConnectionString = MongoDbRunner.ConnectionString; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
MongoDbRunner?.Dispose(); |
|||
} |
|||
public void Dispose() |
|||
{ |
|||
MongoDbRunner?.Dispose(); |
|||
} |
|||
} |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.MongoDB |
|||
namespace Volo.Abp.FeatureManagement.MongoDB; |
|||
|
|||
[CollectionDefinition(Name)] |
|||
public class MongoTestCollection : ICollectionFixture<MongoDbFixture> |
|||
{ |
|||
[CollectionDefinition(Name)] |
|||
public class MongoTestCollection : ICollectionFixture<MongoDbFixture> |
|||
{ |
|||
public const string Name = "MongoDB Collection"; |
|||
} |
|||
} |
|||
public const string Name = "MongoDB Collection"; |
|||
} |
|||
|
|||
@ -1,14 +1,13 @@ |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Testing; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public abstract class FeatureManagementTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
public abstract class FeatureManagementTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using System; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class FeatureManagementTestData : ISingletonDependency |
|||
{ |
|||
public class FeatureManagementTestData : ISingletonDependency |
|||
{ |
|||
public Guid User1Id { get; } = Guid.NewGuid(); |
|||
} |
|||
public Guid User1Id { get; } = Guid.NewGuid(); |
|||
} |
|||
|
|||
@ -1,18 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public static class TestEditionIds |
|||
{ |
|||
public static class TestEditionIds |
|||
{ |
|||
public static Guid Regular { get; } |
|||
public static Guid Enterprise { get; } |
|||
public static Guid Ultimate { get; } |
|||
public static Guid Regular { get; } |
|||
public static Guid Enterprise { get; } |
|||
public static Guid Ultimate { get; } |
|||
|
|||
static TestEditionIds() |
|||
{ |
|||
Regular = Guid.Parse("532599ab-c0c0-4345-a04a-e322867b6e15"); |
|||
Enterprise = Guid.Parse("27e50758-1feb-436a-be4f-cae8519e0cb2"); |
|||
Ultimate = Guid.Parse("6ea78c22-be32-497e-aaba-a2332c564c5e"); |
|||
} |
|||
static TestEditionIds() |
|||
{ |
|||
Regular = Guid.Parse("532599ab-c0c0-4345-a04a-e322867b6e15"); |
|||
Enterprise = Guid.Parse("27e50758-1feb-436a-be4f-cae8519e0cb2"); |
|||
Ultimate = Guid.Parse("6ea78c22-be32-497e-aaba-a2332c564c5e"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,54 +1,53 @@ |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Validation.StringValues; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
namespace Volo.Abp.FeatureManagement; |
|||
|
|||
public class TestFeatureDefinitionProvider : FeatureDefinitionProvider |
|||
{ |
|||
public class TestFeatureDefinitionProvider : FeatureDefinitionProvider |
|||
public const string SocialLogins = "SocialLogins"; |
|||
public const string EmailSupport = "EmailSupport"; |
|||
public const string DailyAnalysis = "DailyAnalysis"; |
|||
public const string UserCount = "UserCount"; |
|||
public const string ProjectCount = "ProjectCount"; |
|||
public const string BackupCount = "BackupCount"; |
|||
|
|||
public override void Define(IFeatureDefinitionContext context) |
|||
{ |
|||
public const string SocialLogins = "SocialLogins"; |
|||
public const string EmailSupport = "EmailSupport"; |
|||
public const string DailyAnalysis = "DailyAnalysis"; |
|||
public const string UserCount = "UserCount"; |
|||
public const string ProjectCount = "ProjectCount"; |
|||
public const string BackupCount = "BackupCount"; |
|||
|
|||
public override void Define(IFeatureDefinitionContext context) |
|||
{ |
|||
var group = context.AddGroup("TestGroup"); |
|||
|
|||
group.AddFeature( |
|||
SocialLogins, |
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
EmailSupport, |
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
DailyAnalysis, |
|||
defaultValue: false.ToString().ToLowerInvariant(), //Optional, it is already false by default
|
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
UserCount, |
|||
defaultValue: "1", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 1000)) |
|||
); |
|||
|
|||
group.AddFeature( |
|||
ProjectCount, |
|||
defaultValue: "1", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 10)) |
|||
); |
|||
|
|||
group.AddFeature( |
|||
BackupCount, |
|||
defaultValue: "0", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(0, 10)) |
|||
); |
|||
} |
|||
var group = context.AddGroup("TestGroup"); |
|||
|
|||
group.AddFeature( |
|||
SocialLogins, |
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
EmailSupport, |
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
DailyAnalysis, |
|||
defaultValue: false.ToString().ToLowerInvariant(), //Optional, it is already false by default
|
|||
valueType: new ToggleStringValueType() |
|||
); |
|||
|
|||
group.AddFeature( |
|||
UserCount, |
|||
defaultValue: "1", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 1000)) |
|||
); |
|||
|
|||
group.AddFeature( |
|||
ProjectCount, |
|||
defaultValue: "1", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 10)) |
|||
); |
|||
|
|||
group.AddFeature( |
|||
BackupCount, |
|||
defaultValue: "0", |
|||
valueType: new FreeTextStringValueType(new NumericValueValidator(0, 10)) |
|||
); |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue