Skip to content

Commit 6d3cb37

Browse files
authored
feat: Support eval with dynamic request value type (#360)
Signed-off-by: Taoyuesong <634774653@qq.com>
1 parent e133b78 commit 6d3cb37

5 files changed

Lines changed: 71 additions & 3 deletions

File tree

Casbin.UnitTests/Fixtures/TestModelFixture.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ public class TestModelFixture
9595
public static readonly string RbacWithIndexMatcherModelText = ReadTestFile("rbac_with_index_matcher_model.conf");
9696
public static readonly string RbacWithIndexMatcherPolicyText = ReadTestFile("rbac_with_index_matcher_policy.csv");
9797

98+
// https://github.com/casbin/Casbin.NET/issues/354
99+
public static readonly string AbacWithDynamicValueTypeModelText = ReadTestFile("abac_with_dynamic_value_type_model.conf");
100+
public static readonly string AbacWithDynamicValueTypePolicyText = ReadTestFile("abac_with_dynamic_value_type_policy.csv");
101+
98102
public static IModel GetNewAbacModel() => GetNewTestModel(AbacModelText);
99103

100104
public static IModel GetNewAbacWithEvalModel() => GetNewTestModel(AbacWithEvalModelText, AbacWithEvalPolicyText);

Casbin.UnitTests/ModelTests/ModelTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,25 @@ public void TestRbacWithIndexMatcher()
752752
Assert.True(e.Enforce(rule, "Admin", "/api/transactions/getTransactions", "POST"));
753753
}
754754

755+
[Fact]
756+
public void TestAbacWithDynamicValueType()
757+
{
758+
Enforcer e = new(TestModelFixture.GetNewTestModel(
759+
TestModelFixture.AbacWithDynamicValueTypeModelText,
760+
TestModelFixture.AbacWithDynamicValueTypePolicyText));
761+
var sub = new { Name = "bob" };
762+
var obj1 = new { Object = "/data1", Property1 = "prop-1" };
763+
var obj2 = new { Object = "/data2", Property2 = "prop-2" };
764+
var obj3 = new { Object = "/data2", Property3 = "prop-3" };
765+
Assert.True(e.Enforce(sub, obj1, "read"));
766+
Assert.True(e.Enforce(sub, obj2, "read"));
767+
Assert.False(e.Enforce(sub, obj3, "read"));
768+
// Request again to test the cache hit logic.
769+
Assert.True(e.Enforce(sub, obj1, "read"));
770+
Assert.True(e.Enforce(sub, obj2, "read"));
771+
Assert.False(e.Enforce(sub, obj3, "read"));
772+
}
773+
755774
public class TestResource
756775
{
757776
public TestResource(string name, string owner)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act, rule
6+
7+
[policy_effect]
8+
e = some(where (p.eft == allow))
9+
10+
[matchers]
11+
m = r.sub.Name == p.sub && \
12+
r.obj.Object == p.obj && \
13+
r.act == p.act && \
14+
eval(p.rule)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
p, bob, /data1, read, r.obj.Property1 == "prop-1"
2+
p, bob, /data2, read, r.obj.Property2 == "prop-2"

Casbin/Evaluation/ExpressionHandler.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal class ExpressionHandler : IExpressionHandler
1818
private Interpreter _interpreter;
1919
#endif
2020

21+
private bool TryCompile { get; set; } = true;
22+
2123
public ExpressionHandler()
2224
{
2325
_interpreter = CreateInterpreter();
@@ -76,13 +78,23 @@ public bool Invoke<TRequest, TPolicy>(in EnforceContext context, string expressi
7678
return func(request, policy);
7779
}
7880

79-
if (_cachePool.TryGetFunc(expressionString,
80-
out Func<TRequest, TPolicy, bool> genericFunc) is not false)
81+
if (_cachePool.TryGetFunc(expressionString, out Func<TRequest, TPolicy, bool> genericFunc))
82+
{
83+
return genericFunc is not null && genericFunc(request, policy);
84+
}
85+
86+
if (TryCompile is false)
8187
{
88+
genericFunc = CompileExpression<TRequest, TPolicy>(in context, expressionString);
89+
_cachePool.SetFunc(expressionString, genericFunc);
8290
return genericFunc(request, policy);
8391
}
8492

85-
genericFunc = CompileExpression<TRequest, TPolicy>(in context, expressionString);
93+
if (TryCompileExpression(in context, expressionString, out genericFunc) is false)
94+
{
95+
_cachePool.SetFunc(expressionString, genericFunc);
96+
return false;
97+
}
8698
_cachePool.SetFunc(expressionString, genericFunc);
8799
return genericFunc(request, policy);
88100
}
@@ -96,6 +108,23 @@ private Func<TRequest, TPolicy, bool> CompileExpression<TRequest, TPolicy>(in En
96108
context.View.RequestType, context.View.PolicyType);
97109
}
98110

111+
private bool TryCompileExpression<TRequest, TPolicy>(in EnforceContext context,
112+
string expressionString, out Func<TRequest, TPolicy, bool> func)
113+
where TRequest : IRequestValues
114+
where TPolicy : IPolicyValues
115+
{
116+
try
117+
{
118+
func = CompileExpression<TRequest, TPolicy>(in context, expressionString);
119+
}
120+
catch (Exception)
121+
{
122+
func = null;
123+
return false;
124+
}
125+
return true;
126+
}
127+
99128
private Interpreter CreateInterpreter()
100129
{
101130
var interpreter = new Interpreter();

0 commit comments

Comments
 (0)