diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj
index 16c2c6c76..6a5cac13d 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN.Abp.Features.Validation.Redis.csproj
@@ -8,7 +8,6 @@
-
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/AbpRedisRequiresLimitFeatureOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/AbpRedisRequiresLimitFeatureOptions.cs
index ae09acb15..af8fb5248 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/AbpRedisRequiresLimitFeatureOptions.cs
+++ b/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; }
- ///
- /// 失败重试次数
- /// default: 3
- ///
- public int FailedRetryCount { get; set; } = 3;
- ///
- /// 失败重试间隔 ms
- /// default: 1000
- ///
- public int FailedRetryInterval { get; set; } = 1000;
AbpRedisRequiresLimitFeatureOptions IOptions.Value
{
get { return this; }
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/check.lua b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/check.lua
index 5a96ae20a..d0ade3b74 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/check.lua
+++ b/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]))
\ No newline at end of file
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/process.lua b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/process.lua
index 9585c4990..fc8ef5307 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/Lua/process.lua
+++ b/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]))
\ No newline at end of file
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureChecker.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureChecker.cs
index c07e601e5..690df549f 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.Validation.Redis/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureChecker.cs
+++ b/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)
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationModule.cs
index 07ec363e1..7fb56873b 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationModule.cs
+++ b/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(options =>
+ {
+ options.MapDefaultEffectPolicys();
+ });
}
}
}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationOptions.cs
new file mode 100644
index 000000000..f26d98f0c
--- /dev/null
+++ b/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> EffectPolicys { get; }
+ public AbpFeaturesValidationOptions()
+ {
+ EffectPolicys = new Dictionary>();
+ }
+ ///
+ /// 变更功能限制策略时长计算方法
+ ///
+ /// 限制策略
+ /// 自定义的计算方法
+ ///
+ /// 返回值一定要是秒钟刻度
+ ///
+ public void MapEffectPolicy(LimitPolicy policy,[NotNull] Func 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; });
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/FeaturesValidationInterceptor.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/FeaturesValidationInterceptor.cs
index 4035664fd..5093d4bff 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/FeaturesValidationInterceptor.cs
+++ b/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 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(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;
}
}
}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/LimitPolicy.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/LimitPolicy.cs
index b09e07ba7..587e13675 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/LimitPolicy.cs
+++ b/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
{
+ ///
+ /// 按分钟限制
+ ///
+ Minute = 0,
///
/// 按小时限制
///
- Hours = 0,
+ Hours = 10,
///
/// 按天限制
///
- Days = 1,
+ Days = 20,
///
/// 按周限制
///
- Weeks = 2,
+ Weeks = 30,
///
/// 按月限制
///
- Month = 3,
+ Month = 40,
///
/// 按年限制
///
- Years = 4
+ Years = 50
}
}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureAttribute.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureAttribute.cs
index 1d19af4e5..23e39ec48 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureAttribute.cs
+++ b/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
{
///
/// 单个功能的调用量限制
///
+ ///
+ /// 需要对于限制时长和限制上限功能区分,以便于更细粒度的限制
+ ///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresLimitFeatureAttribute : Attribute
{
@@ -17,18 +22,33 @@ namespace LINGYUN.Abp.Features.Validation
///
public int DefaultLimit { get; }
///
- /// 功能名称
+ /// 限制上限名称
///
- public string Feature { get; }
+ public string LimitFeature { get; }
+ ///
+ /// 默认限制时长
+ ///
+ public int DefaultInterval { get; }
+ ///
+ /// 限制时长名称
+ ///
+ 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;
}
}
}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureContext.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureContext.cs
index 568b0f793..7e15f1e4f 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features/LINGYUN/Abp/Features/Validation/RequiresLimitFeatureContext.cs
+++ b/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
///
public LimitPolicy Policy { get; }
///
+ /// 限制时长
+ ///
+ public int Interval { get; }
+ ///
/// 功能限制时长
///
public int Limit { get; }
///
- /// 功能名称
+ /// 功能限制次数名称
///
- public string Feature { get; }
+ public string LimitFeature { get; }
- private Lazy>> effectPolicysLazy;
- private IDictionary> 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>>(() => CreateFeatureLimitPolicy());
+ Interval = interval;
+ LimitFeature = limitFeature;
+ Options = options;
}
///
- /// 获取生效时间戳
+ /// 获取生效时间跨度,单位:s
///
///
public long GetEffectTicks()
{
- return effectPolicys[Policy](Limit);
- }
-
- protected IDictionary> CreateFeatureLimitPolicy()
- {
- return new Dictionary>()
- {
- { 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);
}
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Redis.Tests/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureCheckerTests.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Redis.Tests/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureCheckerTests.cs
index 642ab3aa6..56d23ad92 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Redis.Tests/LINGYUN/Abp/Features/Validation/Redis/RedisRequiresLimitFeatureCheckerTests.cs
+++ b/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>().Value;
RequiresLimitFeatureChecker = GetRequiredService();
TestValidationFeatureClass = GetRequiredService();
}
@@ -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(async () =>
{
await RequiresLimitFeatureChecker.CheckAsync(context);
- }
- catch(Exception ex)
- {
- ex.ShouldBeOfType();
- }
+ });
+ Thread.Sleep(61000);
+ // it's ok
+ await RequiresLimitFeatureChecker.ProcessAsync(context);
}
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs
index 2f8f68595..16ee3c2e4 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs
+++ b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/AbpFeaturesValidationTestModule.cs
@@ -13,10 +13,14 @@ namespace LINGYUN.Abp.Features.Validation
{
Configure(options =>
{
- options.Map(TestFeatureNames.TestFeature1, (feature) =>
+ options.Map(TestFeatureNames.TestLimitFeature, (feature) =>
{
return 2.ToString();
});
+ options.Map(TestFeatureNames.TestIntervalFeature, (feature) =>
+ {
+ return 1.ToString();
+ });
});
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FakeRequiresFeatureLimitChecker.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FakeRequiresFeatureLimitChecker.cs
index 41929b8be..231ebe6ad 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FakeRequiresFeatureLimitChecker.cs
+++ b/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 limitFeatures;
+ private readonly IDictionary limitFeatures;
public FakeRequiresFeatureLimitChecker()
{
- limitFeatures = new Dictionary();
+ limitFeatures = new Dictionary();
}
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;
+ }
+ }
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FeaturesValidationTests.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FeaturesValidationTests.cs
index e330f5c93..24ab8ccec 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/FeaturesValidationTests.cs
+++ b/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(async () =>
{
- await TestValidationFeatureClass.Test1HoursAsync();
+ await TestValidationFeatureClass.Test1MinuteAsync();
});
+
+ Thread.Sleep(61000);
+ await TestValidationFeatureClass.Test1MinuteAsync();
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureDefinitionProvider.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureDefinitionProvider.cs
index 73bdf8c1a..726e40ac8 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureDefinitionProvider.cs
+++ b/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)));
}
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureNames.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureNames.cs
index 3224a0cb4..5916df1c6 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestFeatureNames.cs
+++ b/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";
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestValidationFeatureClass.cs b/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestValidationFeatureClass.cs
index bb75c3442..6d7cb355e 100644
--- a/aspnet-core/tests/LINGYUN.Abp.Features.Validation.Tests/LINGYUN/Abp/Features/Validation/TestValidationFeatureClass.cs
+++ b/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;
}