Browse Source

Merge pull request #89 from colinin/3.1

More granular limiting functionality
pull/115/head
cKey 5 years ago
committed by GitHub
parent
commit
905d9e4037
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj
  2. 10
      aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/AbpRedisRequiresLimitFeatureOptions.cs
  3. 2
      aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/check.lua
  4. 2
      aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/process.lua
  5. 4
      aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureChecker.cs
  6. 5
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationModule.cs
  7. 47
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationOptions.cs
  8. 34
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/FeaturesValidationInterceptor.cs
  9. 16
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/LimitPolicy.cs
  10. 34
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureAttribute.cs
  11. 42
      aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureContext.cs
  12. 24
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Redis.Tests/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureCheckerTests.cs
  13. 6
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs
  14. 47
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FakeRequiresFeatureLimitChecker.cs
  15. 11
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FeaturesValidationTests.cs
  16. 6
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureDefinitionProvider.cs
  17. 4
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureNames.cs
  18. 38
      aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestValidationFeatureClass.cs

1
aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj

@ -8,7 +8,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.7" />
<PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="StackExchange.Redis" Version="2.0.593" />
<PackageReference Include="Volo.Abp.Core" Version="3.1.0" />
</ItemGroup>

10
aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/AbpRedisRequiresLimitFeatureOptions.cs

@ -8,16 +8,6 @@ namespace LINGYUN.Abp.Features.Validation.Redis
public string Configuration { get; set; }
public string InstanceName { get; set; }
public ConfigurationOptions ConfigurationOptions { get; set; }
/// <summary>
/// 失败重试次数
/// default: 3
/// </summary>
public int FailedRetryCount { get; set; } = 3;
/// <summary>
/// 失败重试间隔 ms
/// default: 1000
/// </summary>
public int FailedRetryInterval { get; set; } = 1000;
AbpRedisRequiresLimitFeatureOptions IOptions<AbpRedisRequiresLimitFeatureOptions>.Value
{
get { return this; }

2
aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/check.lua

@ -1,4 +1,4 @@
if (redis.call('EXISTS', KEYS[1]) == 0) then
redis.call('SETEX',KEYS[1],ARGV[1], 0)
return 0
end
return tonumber(redis.call('GET', KEYS[1]))

2
aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/process.lua

@ -1,6 +1,6 @@
if (redis.call('EXISTS',KEYS[1]) ~= 0) then
redis.call('INCRBY',KEYS[1], 1)
else
redis.call('SETEX',KEYS[1],ARGV[1],0)
redis.call('SETEX',KEYS[1],ARGV[1],1)
end
return tonumber(redis.call('GET',KEYS[1]))

4
aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureChecker.cs

@ -99,9 +99,9 @@ namespace LINGYUN.Abp.Features.Validation.Redis
{
if (_currentTenant.IsAvailable)
{
return $"{_instance}t:RequiresLimitFeature;t:{_currentTenant.Id};f:{context.Feature}";
return $"{_instance}t:RequiresLimitFeature;t:{_currentTenant.Id};f:{context.LimitFeature}";
}
return $"{_instance}c:RequiresLimitFeature;f:{context.Feature}";
return $"{_instance}c:RequiresLimitFeature;f:{context.LimitFeature}";
}
private void RegistenConnectionEvent(ConnectionMultiplexer connection)

5
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationModule.cs

@ -10,6 +10,11 @@ namespace LINGYUN.Abp.Features.Validation
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.OnRegistred(FeaturesValidationInterceptorRegistrar.RegisterIfNeeded);
Configure<AbpFeaturesValidationOptions>(options =>
{
options.MapDefaultEffectPolicys();
});
}
}
}

47
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationOptions.cs

@ -0,0 +1,47 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using Volo.Abp;
namespace LINGYUN.Abp.Features.Validation
{
public class AbpFeaturesValidationOptions
{
public IDictionary<LimitPolicy, Func<int, long>> EffectPolicys { get; }
public AbpFeaturesValidationOptions()
{
EffectPolicys = new Dictionary<LimitPolicy, Func<int, long>>();
}
/// <summary>
/// 变更功能限制策略时长计算方法
/// </summary>
/// <param name="policy">限制策略</param>
/// <param name="func">自定义的计算方法</param>
/// <remarks>
/// 返回值一定要是秒钟刻度
/// </remarks>
public void MapEffectPolicy(LimitPolicy policy,[NotNull] Func<int, long> func)
{
Check.NotNull(func, nameof(func));
if (EffectPolicys.ContainsKey(policy))
{
EffectPolicys[policy] = func;
}
else
{
EffectPolicys.Add(policy, func);
}
}
internal void MapDefaultEffectPolicys()
{
MapEffectPolicy(LimitPolicy.Minute, (time) => { return (long)(DateTimeOffset.UtcNow.AddMinutes(time) - DateTimeOffset.UtcNow).TotalSeconds; });
MapEffectPolicy(LimitPolicy.Hours, (time) => { return (long)(DateTimeOffset.UtcNow.AddHours(time) - DateTimeOffset.UtcNow).TotalSeconds; });
MapEffectPolicy(LimitPolicy.Days, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time) - DateTimeOffset.UtcNow).TotalSeconds; });
MapEffectPolicy(LimitPolicy.Weeks, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time * 7) - DateTimeOffset.UtcNow).TotalSeconds; });
MapEffectPolicy(LimitPolicy.Month, (time) => { return (long)(DateTimeOffset.UtcNow.AddMonths(time) - DateTimeOffset.UtcNow).TotalSeconds; });
MapEffectPolicy(LimitPolicy.Years, (time) => { return (long)(DateTimeOffset.UtcNow.AddYears(time) - DateTimeOffset.UtcNow).TotalSeconds; });
}
}
}

34
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/FeaturesValidationInterceptor.cs

@ -1,4 +1,5 @@
using System.Reflection;
using Microsoft.Extensions.Options;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection;
@ -11,14 +12,17 @@ namespace LINGYUN.Abp.Features.Validation
public class FeaturesValidationInterceptor : AbpInterceptor, ITransientDependency
{
private readonly IFeatureChecker _featureChecker;
private readonly AbpFeaturesValidationOptions _options;
private readonly IRequiresLimitFeatureChecker _limitFeatureChecker;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
public FeaturesValidationInterceptor(
IFeatureChecker featureChecker,
IRequiresLimitFeatureChecker limitFeatureChecker,
IFeatureDefinitionManager featureDefinitionManager)
IFeatureDefinitionManager featureDefinitionManager,
IOptions<AbpFeaturesValidationOptions> options)
{
_options = options.Value;
_featureChecker = featureChecker;
_limitFeatureChecker = limitFeatureChecker;
_featureDefinitionManager = featureDefinitionManager;
@ -41,10 +45,12 @@ namespace LINGYUN.Abp.Features.Validation
return;
}
// 获取功能限制上限
var limit = await _featureChecker.GetAsync(limitFeature.LimitFeature, limitFeature.DefaultLimit);
// 获取功能限制时长
var limit = await _featureChecker.GetAsync(limitFeature.Feature, limitFeature.DefaultLimit);
var limitFeatureContext = new RequiresLimitFeatureContext(limitFeature.Feature, limitFeature.Policy, limit);
var interval = await _featureChecker.GetAsync(limitFeature.IntervalFeature, limitFeature.DefaultInterval);
// 必要的上下文参数
var limitFeatureContext = new RequiresLimitFeatureContext(limitFeature.LimitFeature, _options, limitFeature.Policy, interval, limit);
// 检查次数限制
await PreCheckFeatureAsync(limitFeatureContext);
// 执行代理方法
@ -69,14 +75,22 @@ namespace LINGYUN.Abp.Features.Validation
var limitFeature = methodInfo.GetCustomAttribute<RequiresLimitFeatureAttribute>(false);
if (limitFeature != null)
{
var featureDefinition = _featureDefinitionManager.GetOrNull(limitFeature.Feature);
if (featureDefinition != null &&
typeof(NumericValueValidator).IsAssignableFrom(featureDefinition.ValueType.Validator.GetType()))
// 限制次数定义的不是范围参数,则不参与限制功能
var featureLimitDefinition = _featureDefinitionManager.GetOrNull(limitFeature.LimitFeature);
if (featureLimitDefinition == null ||
!typeof(NumericValueValidator).IsAssignableFrom(featureLimitDefinition.ValueType.Validator.GetType()))
{
return null;
}
// 时长刻度定义的不是范围参数,则不参与限制功能
var featureIntervalDefinition = _featureDefinitionManager.GetOrNull(limitFeature.IntervalFeature);
if (featureIntervalDefinition == null ||
!typeof(NumericValueValidator).IsAssignableFrom(featureIntervalDefinition.ValueType.Validator.GetType()))
{
return limitFeature;
return null;
}
}
return null;
return limitFeature;
}
}
}

16
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/LimitPolicy.cs

@ -1,26 +1,30 @@
namespace LINGYUN.Abp.Features.Validation
{
public enum LimitPolicy
public enum LimitPolicy : byte
{
/// <summary>
/// 按分钟限制
/// </summary>
Minute = 0,
/// <summary>
/// 按小时限制
/// </summary>
Hours = 0,
Hours = 10,
/// <summary>
/// 按天限制
/// </summary>
Days = 1,
Days = 20,
/// <summary>
/// 按周限制
/// </summary>
Weeks = 2,
Weeks = 30,
/// <summary>
/// 按月限制
/// </summary>
Month = 3,
Month = 40,
/// <summary>
/// 按年限制
/// </summary>
Years = 4
Years = 50
}
}

34
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureAttribute.cs

@ -1,10 +1,15 @@
using System;
using JetBrains.Annotations;
using System;
using Volo.Abp;
namespace LINGYUN.Abp.Features.Validation
{
/// <summary>
/// 单个功能的调用量限制
/// </summary>
/// <remarks>
/// 需要对于限制时长和限制上限功能区分,以便于更细粒度的限制
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresLimitFeatureAttribute : Attribute
{
@ -17,18 +22,33 @@ namespace LINGYUN.Abp.Features.Validation
/// </summary>
public int DefaultLimit { get; }
/// <summary>
/// 功能名称
/// 限制上限名称
/// </summary>
public string Feature { get; }
public string LimitFeature { get; }
/// <summary>
/// 默认限制时长
/// </summary>
public int DefaultInterval { get; }
/// <summary>
/// 限制时长名称
/// </summary>
public string IntervalFeature { get; }
public RequiresLimitFeatureAttribute(
string feature,
[NotNull] string limitFeature,
[NotNull] string intervalFeature,
LimitPolicy policy = LimitPolicy.Month,
int defaultLimit = 1)
int defaultLimit = 1,
int defaultInterval = 1)
{
DefaultLimit = defaultLimit;
Check.NotNullOrWhiteSpace(limitFeature, nameof(limitFeature));
Check.NotNullOrWhiteSpace(intervalFeature, nameof(intervalFeature));
Policy = policy;
Feature = feature;
LimitFeature = limitFeature;
DefaultLimit = defaultLimit;
IntervalFeature = intervalFeature;
DefaultInterval = defaultInterval;
}
}
}

42
aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureContext.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.Features.Validation
namespace LINGYUN.Abp.Features.Validation
{
public class RequiresLimitFeatureContext
{
@ -10,47 +7,40 @@ namespace LINGYUN.Abp.Features.Validation
/// </summary>
public LimitPolicy Policy { get; }
/// <summary>
/// 限制时长
/// </summary>
public int Interval { get; }
/// <summary>
/// 功能限制时长
/// </summary>
public int Limit { get; }
/// <summary>
/// 功能名称
/// 功能限制次数名称
/// </summary>
public string Feature { get; }
public string LimitFeature { get; }
private Lazy<IDictionary<LimitPolicy, Func<int, long>>> effectPolicysLazy;
private IDictionary<LimitPolicy, Func<int, long>> effectPolicys => effectPolicysLazy.Value;
public AbpFeaturesValidationOptions Options { get; }
public RequiresLimitFeatureContext(
string feature,
string limitFeature,
AbpFeaturesValidationOptions options,
LimitPolicy policy = LimitPolicy.Month,
int interval = 1,
int limit = 1)
{
Limit = limit;
Policy = policy;
Feature = feature;
effectPolicysLazy = new Lazy<IDictionary<LimitPolicy, Func<int, long>>>(() => CreateFeatureLimitPolicy());
Interval = interval;
LimitFeature = limitFeature;
Options = options;
}
/// <summary>
/// 获取生效时间
/// 获取生效时间跨度,单位:s
/// </summary>
/// <returns></returns>
public long GetEffectTicks()
{
return effectPolicys[Policy](Limit);
}
protected IDictionary<LimitPolicy, Func<int, long>> CreateFeatureLimitPolicy()
{
return new Dictionary<LimitPolicy, Func<int, long>>()
{
{ LimitPolicy.Days, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time) - DateTimeOffset.UtcNow).TotalSeconds; } },
{ LimitPolicy.Hours, (time) => { return (long)(DateTimeOffset.UtcNow.AddHours(time) - DateTimeOffset.UtcNow).TotalSeconds; } },
{ LimitPolicy.Month, (time) => { return (long)(DateTimeOffset.UtcNow.AddMonths(time) - DateTimeOffset.UtcNow).TotalSeconds; } },
{ LimitPolicy.Weeks, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time * 7) - DateTimeOffset.UtcNow).TotalSeconds; } },
{ LimitPolicy.Years, (time) => { return (long)(DateTimeOffset.UtcNow.AddYears(time) - DateTimeOffset.UtcNow).TotalSeconds; } }
};
return Options.EffectPolicys[Policy](Interval);
}
}
}

24
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Redis.Tests/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureCheckerTests.cs

@ -1,5 +1,7 @@
using Shouldly;
using Microsoft.Extensions.Options;
using Shouldly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Authorization;
using Xunit;
@ -8,10 +10,12 @@ namespace LINGYUN.Abp.Features.Validation.Redis
{
public class RedisRequiresLimitFeatureCheckerTests : AbpFeaturesValidationRedisTestBase
{
protected AbpFeaturesValidationOptions Options { get; }
protected IRequiresLimitFeatureChecker RequiresLimitFeatureChecker { get; }
protected TestValidationFeatureClass TestValidationFeatureClass { get; }
public RedisRequiresLimitFeatureCheckerTests()
{
Options = GetRequiredService<IOptions<AbpFeaturesValidationOptions>>().Value;
RequiresLimitFeatureChecker = GetRequiredService<IRequiresLimitFeatureChecker>();
TestValidationFeatureClass = GetRequiredService<TestValidationFeatureClass>();
}
@ -19,35 +23,33 @@ namespace LINGYUN.Abp.Features.Validation.Redis
[Fact]
public virtual async Task Check_Test_Async()
{
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestFeature1, LimitPolicy.Days, 10);
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestLimitFeature, Options, LimitPolicy.Minute);
await RequiresLimitFeatureChecker.CheckAsync(context);
}
[Fact]
public virtual async Task Process_Test_Async()
{
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestFeature1, LimitPolicy.Days, 10);
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestLimitFeature, Options, LimitPolicy.Minute);
await RequiresLimitFeatureChecker.ProcessAsync(context);
}
[Fact]
public virtual async Task Check_Limit_Test_Async()
{
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestFeature1, LimitPolicy.Days, 5);
var context = new RequiresLimitFeatureContext(TestFeatureNames.TestLimitFeature, Options, LimitPolicy.Minute, 1 ,5);
await RequiresLimitFeatureChecker.ProcessAsync(context);
await RequiresLimitFeatureChecker.ProcessAsync(context);
await RequiresLimitFeatureChecker.ProcessAsync(context);
await RequiresLimitFeatureChecker.ProcessAsync(context);
await RequiresLimitFeatureChecker.ProcessAsync(context);
await RequiresLimitFeatureChecker.ProcessAsync(context);
try
await Assert.ThrowsAsync<AbpAuthorizationException>(async () =>
{
await RequiresLimitFeatureChecker.CheckAsync(context);
}
catch(Exception ex)
{
ex.ShouldBeOfType<AbpAuthorizationException>();
}
});
Thread.Sleep(61000);
// it's ok
await RequiresLimitFeatureChecker.ProcessAsync(context);
}
}
}

6
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs

@ -13,10 +13,14 @@ namespace LINGYUN.Abp.Features.Validation
{
Configure<FakeFeatureOptions>(options =>
{
options.Map(TestFeatureNames.TestFeature1, (feature) =>
options.Map(TestFeatureNames.TestLimitFeature, (feature) =>
{
return 2.ToString();
});
options.Map(TestFeatureNames.TestIntervalFeature, (feature) =>
{
return 1.ToString();
});
});
}
}

47
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FakeRequiresFeatureLimitChecker.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -11,34 +12,58 @@ namespace LINGYUN.Abp.Features.Validation
[ExposeServices(typeof(IRequiresLimitFeatureChecker))]
public class FakeRequiresFeatureLimitChecker : IRequiresLimitFeatureChecker
{
private readonly IDictionary<string, int> limitFeatures;
private readonly IDictionary<string, LimitFeature> limitFeatures;
public FakeRequiresFeatureLimitChecker()
{
limitFeatures = new Dictionary<string, int>();
limitFeatures = new Dictionary<string, LimitFeature>();
}
public virtual Task CheckAsync(RequiresLimitFeatureContext context, CancellationToken cancellation = default)
{
if (!limitFeatures.ContainsKey(context.Feature))
if (limitFeatures.ContainsKey(context.LimitFeature))
{
limitFeatures.Add(context.Feature, 0);
}
if (limitFeatures[context.Feature] > context.Limit)
{
throw new AbpAuthorizationException("已经超出功能次数限制,请联系管理员");
if (limitFeatures[context.LimitFeature].ExprieTime <= DateTime.Now)
{
limitFeatures.Remove(context.LimitFeature);
return Task.CompletedTask;
}
if (limitFeatures[context.LimitFeature].Limit + 1 > context.Limit)
{
throw new AbpAuthorizationException("已经超出功能次数限制,请联系管理员");
}
}
return Task.CompletedTask;
}
public Task ProcessAsync(RequiresLimitFeatureContext context, CancellationToken cancellation = default)
{
if (!limitFeatures.ContainsKey(context.Feature))
if (!limitFeatures.ContainsKey(context.LimitFeature))
{
limitFeatures.Add(context.LimitFeature, new LimitFeature(1, DateTime.Now.AddSeconds(context.GetEffectTicks())));
}
else
{
limitFeatures.Add(context.Feature, 1);
limitFeatures[context.LimitFeature].Invoke(1);
}
limitFeatures[context.Feature] += 1;
return Task.CompletedTask;
}
}
public class LimitFeature
{
public int Limit { get; private set; }
public DateTime ExprieTime { get; }
public LimitFeature(int limit, DateTime exprieTime)
{
Limit = limit;
ExprieTime = exprieTime;
}
public void Invoke(int count)
{
Limit += count;
}
}
}

11
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FeaturesValidationTests.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Authorization;
using Volo.Abp.MultiTenancy;
@ -23,14 +24,16 @@ namespace LINGYUN.Abp.Features.Validation
using (CurrentTenant.Change(ParseNullableGuid(tenantId)))
{
// it's ok
await TestValidationFeatureClass.Test1HoursAsync();
await TestValidationFeatureClass.Test1HoursAsync();
await TestValidationFeatureClass.Test1HoursAsync();
await TestValidationFeatureClass.Test1MinuteAsync();
await TestValidationFeatureClass.Test1MinuteAsync();
await Assert.ThrowsAsync<AbpAuthorizationException>(async () =>
{
await TestValidationFeatureClass.Test1HoursAsync();
await TestValidationFeatureClass.Test1MinuteAsync();
});
Thread.Sleep(61000);
await TestValidationFeatureClass.Test1MinuteAsync();
}
}

6
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureDefinitionProvider.cs

@ -9,9 +9,13 @@ namespace LINGYUN.Abp.Features.Validation
{
var featureGroup = context.AddGroup(TestFeatureNames.GroupName);
featureGroup.AddFeature(
name: TestFeatureNames.TestFeature1,
name: TestFeatureNames.TestLimitFeature,
defaultValue: 100.ToString(),
valueType: new ToggleStringValueType(new NumericValueValidator(1, 1000)));
featureGroup.AddFeature(
name: TestFeatureNames.TestIntervalFeature,
defaultValue: 1.ToString(),
valueType: new ToggleStringValueType(new NumericValueValidator(1, 1000)));
}
}
}

4
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureNames.cs

@ -4,6 +4,8 @@
{
public const string GroupName = "Abp.Features.Validation.Tests";
public const string TestFeature1 = GroupName + ".TestFeature1";
public const string TestLimitFeature = GroupName + ".TestLimitFeature";
public const string TestIntervalFeature = GroupName + ".TestIntervalFeature";
}
}

38
aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestValidationFeatureClass.cs

@ -7,42 +7,10 @@ namespace LINGYUN.Abp.Features.Validation
{
public class TestValidationFeatureClass : ITransientDependency
{
[RequiresLimitFeature(TestFeatureNames.TestFeature1, LimitPolicy.Days, 1)]
public virtual Task Test1DaysAsync()
[RequiresLimitFeature(TestFeatureNames.TestLimitFeature, TestFeatureNames.TestIntervalFeature, LimitPolicy.Minute)]
public virtual Task Test1MinuteAsync()
{
Console.WriteLine("this limit 1 days feature");
return Task.CompletedTask;
}
[RequiresLimitFeature(TestFeatureNames.TestFeature1, LimitPolicy.Month, 1)]
public virtual Task Test1MonthsAsync()
{
Console.WriteLine("this limit 1 month feature");
return Task.CompletedTask;
}
[RequiresLimitFeature(TestFeatureNames.TestFeature1, LimitPolicy.Weeks, 1)]
public virtual Task Test1WeeksAsync()
{
Console.WriteLine("this limit 1 weeks feature");
return Task.CompletedTask;
}
[RequiresLimitFeature(TestFeatureNames.TestFeature1, LimitPolicy.Hours, 1)]
public virtual Task Test1HoursAsync()
{
Console.WriteLine("this limit 1 hours feature");
return Task.CompletedTask;
}
[RequiresLimitFeature(TestFeatureNames.TestFeature1, LimitPolicy.Years, 1)]
public virtual Task Test1YearsAsync()
{
Console.WriteLine("this limit 1 years feature");
Console.WriteLine("this limit 1 minute feature");
return Task.CompletedTask;
}

Loading…
Cancel
Save