diff --git a/Casbin.Benchmark/TestHelper.cs b/Casbin.Benchmark/TestHelper.cs
index 95f70c4..83874ba 100644
--- a/Casbin.Benchmark/TestHelper.cs
+++ b/Casbin.Benchmark/TestHelper.cs
@@ -6,7 +6,7 @@ public static class TestHelper
{
public static string GetTestFilePath(string fileName)
{
- return Path.Combine("examples", fileName);
+ return Path.Combine("Examples", fileName);
}
}
}
diff --git a/Casbin.UnitTests/Casbin.UnitTests.csproj b/Casbin.UnitTests/Casbin.UnitTests.csproj
index fa89d12..3ada8fd 100644
--- a/Casbin.UnitTests/Casbin.UnitTests.csproj
+++ b/Casbin.UnitTests/Casbin.UnitTests.csproj
@@ -4,7 +4,7 @@
net9.0;net8.0;net7.0;net6.0;net5.0;netcoreapp3.1;net462;net461;net452
full
false
- 10.0
+ latest
false
diff --git a/Casbin.UnitTests/examples/abac_comment.conf b/Casbin.UnitTests/Examples/abac_comment.conf
similarity index 100%
rename from Casbin.UnitTests/examples/abac_comment.conf
rename to Casbin.UnitTests/Examples/abac_comment.conf
diff --git a/Casbin.UnitTests/examples/abac_model.conf b/Casbin.UnitTests/Examples/abac_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/abac_model.conf
rename to Casbin.UnitTests/Examples/abac_model.conf
diff --git a/Casbin.UnitTests/examples/abac_rule_model.conf b/Casbin.UnitTests/Examples/abac_rule_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/abac_rule_model.conf
rename to Casbin.UnitTests/Examples/abac_rule_model.conf
diff --git a/Casbin.UnitTests/examples/abac_rule_policy.csv b/Casbin.UnitTests/Examples/abac_rule_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/abac_rule_policy.csv
rename to Casbin.UnitTests/Examples/abac_rule_policy.csv
diff --git a/Casbin.UnitTests/examples/abac_with_dynamic_value_type_model.conf b/Casbin.UnitTests/Examples/abac_with_dynamic_value_type_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/abac_with_dynamic_value_type_model.conf
rename to Casbin.UnitTests/Examples/abac_with_dynamic_value_type_model.conf
diff --git a/Casbin.UnitTests/examples/abac_with_dynamic_value_type_policy.csv b/Casbin.UnitTests/Examples/abac_with_dynamic_value_type_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/abac_with_dynamic_value_type_policy.csv
rename to Casbin.UnitTests/Examples/abac_with_dynamic_value_type_policy.csv
diff --git a/Casbin.UnitTests/examples/backslash_feed_model.conf b/Casbin.UnitTests/Examples/backslash_feed_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/backslash_feed_model.conf
rename to Casbin.UnitTests/Examples/backslash_feed_model.conf
diff --git a/Casbin.UnitTests/examples/backslash_feed_policy.csv b/Casbin.UnitTests/Examples/backslash_feed_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/backslash_feed_policy.csv
rename to Casbin.UnitTests/Examples/backslash_feed_policy.csv
diff --git a/Casbin.UnitTests/examples/basic_inverse_policy.csv b/Casbin.UnitTests/Examples/basic_inverse_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/basic_inverse_policy.csv
rename to Casbin.UnitTests/Examples/basic_inverse_policy.csv
diff --git a/Casbin.UnitTests/examples/basic_model.conf b/Casbin.UnitTests/Examples/basic_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/basic_model.conf
rename to Casbin.UnitTests/Examples/basic_model.conf
diff --git a/Casbin.UnitTests/examples/basic_policy.csv b/Casbin.UnitTests/Examples/basic_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/basic_policy.csv
rename to Casbin.UnitTests/Examples/basic_policy.csv
diff --git a/Casbin.UnitTests/examples/basic_policy_for_async_adapter_test.csv b/Casbin.UnitTests/Examples/basic_policy_for_async_adapter_test.csv
similarity index 100%
rename from Casbin.UnitTests/examples/basic_policy_for_async_adapter_test.csv
rename to Casbin.UnitTests/Examples/basic_policy_for_async_adapter_test.csv
diff --git a/Casbin.UnitTests/examples/basic_with_root_model.conf b/Casbin.UnitTests/Examples/basic_with_root_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/basic_with_root_model.conf
rename to Casbin.UnitTests/Examples/basic_with_root_model.conf
diff --git a/Casbin.UnitTests/examples/basic_without_resources_model.conf b/Casbin.UnitTests/Examples/basic_without_resources_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/basic_without_resources_model.conf
rename to Casbin.UnitTests/Examples/basic_without_resources_model.conf
diff --git a/Casbin.UnitTests/examples/basic_without_resources_policy.csv b/Casbin.UnitTests/Examples/basic_without_resources_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/basic_without_resources_policy.csv
rename to Casbin.UnitTests/Examples/basic_without_resources_policy.csv
diff --git a/Casbin.UnitTests/examples/basic_without_users_model.conf b/Casbin.UnitTests/Examples/basic_without_users_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/basic_without_users_model.conf
rename to Casbin.UnitTests/Examples/basic_without_users_model.conf
diff --git a/Casbin.UnitTests/examples/basic_without_users_policy.csv b/Casbin.UnitTests/Examples/basic_without_users_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/basic_without_users_policy.csv
rename to Casbin.UnitTests/Examples/basic_without_users_policy.csv
diff --git a/Casbin.UnitTests/examples/comma_quotations_model.conf b/Casbin.UnitTests/Examples/comma_quotations_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/comma_quotations_model.conf
rename to Casbin.UnitTests/Examples/comma_quotations_model.conf
diff --git a/Casbin.UnitTests/examples/comma_quotations_policy.csv b/Casbin.UnitTests/Examples/comma_quotations_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/comma_quotations_policy.csv
rename to Casbin.UnitTests/Examples/comma_quotations_policy.csv
diff --git a/Casbin.UnitTests/examples/group_with_domain_model.conf b/Casbin.UnitTests/Examples/group_with_domain_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/group_with_domain_model.conf
rename to Casbin.UnitTests/Examples/group_with_domain_model.conf
diff --git a/Casbin.UnitTests/examples/group_with_domain_policy.csv b/Casbin.UnitTests/Examples/group_with_domain_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/group_with_domain_policy.csv
rename to Casbin.UnitTests/Examples/group_with_domain_policy.csv
diff --git a/Casbin.UnitTests/examples/ipmatch_model.conf b/Casbin.UnitTests/Examples/ipmatch_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/ipmatch_model.conf
rename to Casbin.UnitTests/Examples/ipmatch_model.conf
diff --git a/Casbin.UnitTests/examples/ipmatch_policy.csv b/Casbin.UnitTests/Examples/ipmatch_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/ipmatch_policy.csv
rename to Casbin.UnitTests/Examples/ipmatch_policy.csv
diff --git a/Casbin.UnitTests/examples/keymatch2_model.conf b/Casbin.UnitTests/Examples/keymatch2_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/keymatch2_model.conf
rename to Casbin.UnitTests/Examples/keymatch2_model.conf
diff --git a/Casbin.UnitTests/examples/keymatch2_policy.csv b/Casbin.UnitTests/Examples/keymatch2_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/keymatch2_policy.csv
rename to Casbin.UnitTests/Examples/keymatch2_policy.csv
diff --git a/Casbin.UnitTests/examples/keymatch_custom_model.conf b/Casbin.UnitTests/Examples/keymatch_custom_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/keymatch_custom_model.conf
rename to Casbin.UnitTests/Examples/keymatch_custom_model.conf
diff --git a/Casbin.UnitTests/examples/keymatch_model.conf b/Casbin.UnitTests/Examples/keymatch_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/keymatch_model.conf
rename to Casbin.UnitTests/Examples/keymatch_model.conf
diff --git a/Casbin.UnitTests/examples/keymatch_policy.csv b/Casbin.UnitTests/Examples/keymatch_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/keymatch_policy.csv
rename to Casbin.UnitTests/Examples/keymatch_policy.csv
diff --git a/Casbin.UnitTests/examples/multiple_type_model.conf b/Casbin.UnitTests/Examples/multiple_type_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/multiple_type_model.conf
rename to Casbin.UnitTests/Examples/multiple_type_model.conf
diff --git a/Casbin.UnitTests/examples/multiple_type_policy.csv b/Casbin.UnitTests/Examples/multiple_type_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/multiple_type_policy.csv
rename to Casbin.UnitTests/Examples/multiple_type_policy.csv
diff --git a/Casbin.UnitTests/examples/priority_explicit_deny_override_model.conf b/Casbin.UnitTests/Examples/priority_explicit_deny_override_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/priority_explicit_deny_override_model.conf
rename to Casbin.UnitTests/Examples/priority_explicit_deny_override_model.conf
diff --git a/Casbin.UnitTests/examples/priority_explicit_deny_override_policy.csv b/Casbin.UnitTests/Examples/priority_explicit_deny_override_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/priority_explicit_deny_override_policy.csv
rename to Casbin.UnitTests/Examples/priority_explicit_deny_override_policy.csv
diff --git a/Casbin.UnitTests/examples/priority_explicit_model.conf b/Casbin.UnitTests/Examples/priority_explicit_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/priority_explicit_model.conf
rename to Casbin.UnitTests/Examples/priority_explicit_model.conf
diff --git a/Casbin.UnitTests/examples/priority_explicit_policy.csv b/Casbin.UnitTests/Examples/priority_explicit_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/priority_explicit_policy.csv
rename to Casbin.UnitTests/Examples/priority_explicit_policy.csv
diff --git a/Casbin.UnitTests/examples/priority_indeterminate_policy.csv b/Casbin.UnitTests/Examples/priority_indeterminate_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/priority_indeterminate_policy.csv
rename to Casbin.UnitTests/Examples/priority_indeterminate_policy.csv
diff --git a/Casbin.UnitTests/examples/priority_model.conf b/Casbin.UnitTests/Examples/priority_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/priority_model.conf
rename to Casbin.UnitTests/Examples/priority_model.conf
diff --git a/Casbin.UnitTests/examples/priority_policy.csv b/Casbin.UnitTests/Examples/priority_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/priority_policy.csv
rename to Casbin.UnitTests/Examples/priority_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_comment.conf b/Casbin.UnitTests/Examples/rbac_comment.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_comment.conf
rename to Casbin.UnitTests/Examples/rbac_comment.conf
diff --git a/Casbin.UnitTests/examples/rbac_in_operator_model.conf b/Casbin.UnitTests/Examples/rbac_in_operator_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_in_operator_model.conf
rename to Casbin.UnitTests/Examples/rbac_in_operator_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_in_operator_policy.csv b/Casbin.UnitTests/Examples/rbac_in_operator_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_in_operator_policy.csv
rename to Casbin.UnitTests/Examples/rbac_in_operator_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_model.conf b/Casbin.UnitTests/Examples/rbac_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_model.conf
rename to Casbin.UnitTests/Examples/rbac_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_multiple_eval_model.conf b/Casbin.UnitTests/Examples/rbac_multiple_eval_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_multiple_eval_model.conf
rename to Casbin.UnitTests/Examples/rbac_multiple_eval_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_multiple_eval_policy.csv b/Casbin.UnitTests/Examples/rbac_multiple_eval_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_multiple_eval_policy.csv
rename to Casbin.UnitTests/Examples/rbac_multiple_eval_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_multiple_rolemanager_model.conf b/Casbin.UnitTests/Examples/rbac_multiple_rolemanager_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_multiple_rolemanager_model.conf
rename to Casbin.UnitTests/Examples/rbac_multiple_rolemanager_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_multiple_rolemanager_policy.csv b/Casbin.UnitTests/Examples/rbac_multiple_rolemanager_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_multiple_rolemanager_policy.csv
rename to Casbin.UnitTests/Examples/rbac_multiple_rolemanager_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_policy.csv b/Casbin.UnitTests/Examples/rbac_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_policy.csv
rename to Casbin.UnitTests/Examples/rbac_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_policy_for_async_watcher_test.csv b/Casbin.UnitTests/Examples/rbac_policy_for_async_watcher_test.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_policy_for_async_watcher_test.csv
rename to Casbin.UnitTests/Examples/rbac_policy_for_async_watcher_test.csv
diff --git a/Casbin.UnitTests/examples/rbac_policy_for_watcher_test.csv b/Casbin.UnitTests/Examples/rbac_policy_for_watcher_test.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_policy_for_watcher_test.csv
rename to Casbin.UnitTests/Examples/rbac_policy_for_watcher_test.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_deny_model.conf b/Casbin.UnitTests/Examples/rbac_with_deny_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_deny_model.conf
rename to Casbin.UnitTests/Examples/rbac_with_deny_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_with_deny_policy.csv b/Casbin.UnitTests/Examples/rbac_with_deny_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_deny_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_deny_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_domains_model.conf b/Casbin.UnitTests/Examples/rbac_with_domains_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_domains_model.conf
rename to Casbin.UnitTests/Examples/rbac_with_domains_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_with_domains_policy.csv b/Casbin.UnitTests/Examples/rbac_with_domains_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_domains_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_domains_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_domains_policy2.csv b/Casbin.UnitTests/Examples/rbac_with_domains_policy2.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_domains_policy2.csv
rename to Casbin.UnitTests/Examples/rbac_with_domains_policy2.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_hierarchy_policy.csv b/Casbin.UnitTests/Examples/rbac_with_hierarchy_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_hierarchy_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_hierarchy_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_hierarchy_with_domains_policy.csv b/Casbin.UnitTests/Examples/rbac_with_hierarchy_with_domains_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_hierarchy_with_domains_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_hierarchy_with_domains_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_index_matcher_model.conf b/Casbin.UnitTests/Examples/rbac_with_index_matcher_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_index_matcher_model.conf
rename to Casbin.UnitTests/Examples/rbac_with_index_matcher_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_with_index_matcher_policy.csv b/Casbin.UnitTests/Examples/rbac_with_index_matcher_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_index_matcher_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_index_matcher_policy.csv
diff --git a/Casbin.UnitTests/examples/rbac_with_not_deny_model.conf b/Casbin.UnitTests/Examples/rbac_with_not_deny_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_not_deny_model.conf
rename to Casbin.UnitTests/Examples/rbac_with_not_deny_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_with_resource_roles_model.conf b/Casbin.UnitTests/Examples/rbac_with_resource_roles_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_resource_roles_model.conf
rename to Casbin.UnitTests/Examples/rbac_with_resource_roles_model.conf
diff --git a/Casbin.UnitTests/examples/rbac_with_resource_roles_policy.csv b/Casbin.UnitTests/Examples/rbac_with_resource_roles_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/rbac_with_resource_roles_policy.csv
rename to Casbin.UnitTests/Examples/rbac_with_resource_roles_policy.csv
diff --git a/Casbin.UnitTests/examples/saa_model.conf b/Casbin.UnitTests/Examples/saa_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/saa_model.conf
rename to Casbin.UnitTests/Examples/saa_model.conf
diff --git a/Casbin.UnitTests/examples/saa_rbac_policy.csv b/Casbin.UnitTests/Examples/saa_rbac_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/saa_rbac_policy.csv
rename to Casbin.UnitTests/Examples/saa_rbac_policy.csv
diff --git a/Casbin.UnitTests/examples/subject_priority_model.conf b/Casbin.UnitTests/Examples/subject_priority_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/subject_priority_model.conf
rename to Casbin.UnitTests/Examples/subject_priority_model.conf
diff --git a/Casbin.UnitTests/examples/subject_priority_model_with_domain.conf b/Casbin.UnitTests/Examples/subject_priority_model_with_domain.conf
similarity index 100%
rename from Casbin.UnitTests/examples/subject_priority_model_with_domain.conf
rename to Casbin.UnitTests/Examples/subject_priority_model_with_domain.conf
diff --git a/Casbin.UnitTests/examples/subject_priority_policy.csv b/Casbin.UnitTests/Examples/subject_priority_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/subject_priority_policy.csv
rename to Casbin.UnitTests/Examples/subject_priority_policy.csv
diff --git a/Casbin.UnitTests/examples/subject_priority_policy_with_domain.csv b/Casbin.UnitTests/Examples/subject_priority_policy_with_domain.csv
similarity index 100%
rename from Casbin.UnitTests/examples/subject_priority_policy_with_domain.csv
rename to Casbin.UnitTests/Examples/subject_priority_policy_with_domain.csv
diff --git a/Casbin.UnitTests/examples/support_count_model.conf b/Casbin.UnitTests/Examples/support_count_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/support_count_model.conf
rename to Casbin.UnitTests/Examples/support_count_model.conf
diff --git a/Casbin.UnitTests/examples/tabs_model.conf b/Casbin.UnitTests/Examples/tabs_model.conf
similarity index 100%
rename from Casbin.UnitTests/examples/tabs_model.conf
rename to Casbin.UnitTests/Examples/tabs_model.conf
diff --git a/Casbin.UnitTests/examples/tabs_policy.csv b/Casbin.UnitTests/Examples/tabs_policy.csv
similarity index 100%
rename from Casbin.UnitTests/examples/tabs_policy.csv
rename to Casbin.UnitTests/Examples/tabs_policy.csv
diff --git a/Casbin.UnitTests/examples/tokens_with_substring_relation_abac.conf b/Casbin.UnitTests/Examples/tokens_with_substring_relation_abac.conf
similarity index 100%
rename from Casbin.UnitTests/examples/tokens_with_substring_relation_abac.conf
rename to Casbin.UnitTests/Examples/tokens_with_substring_relation_abac.conf
diff --git a/Casbin.UnitTests/examples/tokens_with_substring_relation_abac.csv b/Casbin.UnitTests/Examples/tokens_with_substring_relation_abac.csv
similarity index 100%
rename from Casbin.UnitTests/examples/tokens_with_substring_relation_abac.csv
rename to Casbin.UnitTests/Examples/tokens_with_substring_relation_abac.csv
diff --git a/Casbin.UnitTests/examples/tokens_with_substring_relation_rbac.conf b/Casbin.UnitTests/Examples/tokens_with_substring_relation_rbac.conf
similarity index 100%
rename from Casbin.UnitTests/examples/tokens_with_substring_relation_rbac.conf
rename to Casbin.UnitTests/Examples/tokens_with_substring_relation_rbac.conf
diff --git a/Casbin.UnitTests/examples/tokens_with_substring_relation_rbac.csv b/Casbin.UnitTests/Examples/tokens_with_substring_relation_rbac.csv
similarity index 100%
rename from Casbin.UnitTests/examples/tokens_with_substring_relation_rbac.csv
rename to Casbin.UnitTests/Examples/tokens_with_substring_relation_rbac.csv
diff --git a/Casbin.UnitTests/GenericTests/GenericFunctionTest.cs b/Casbin.UnitTests/GenericTests/GenericFunctionTest.cs
new file mode 100644
index 0000000..0b46474
--- /dev/null
+++ b/Casbin.UnitTests/GenericTests/GenericFunctionTest.cs
@@ -0,0 +1,69 @@
+using System;
+using Casbin.Model;
+using Casbin.UnitTests.Util;
+using DynamicExpresso;
+using Xunit;
+
+namespace Casbin.UnitTests.GenericTests;
+
+public class GenericFunctionTest
+{
+ [Fact]
+ public void TestGenericFunction()
+ {
+ Interpreter interpreter = new();
+ RequestValues r = Request.CreateValues("A", 1);
+ PolicyValues p = Policy.CreateValues("A", 1);
+ interpreter.SetFunction("equal", new Func(
+ (a, b) => a == b)
+ );
+ interpreter.SetFunction("equal", new Func(
+ (a, b) => a == b)
+ );
+
+ Func, PolicyValues, bool> func1 =
+ ExpressionUtil.Compile(interpreter, "equal(r.Value2, p.Value2) && equal(r.Value2, p.Value2)",
+ nameof(r), in r, nameof(p), in p);
+
+ Assert.True(func1(Request.CreateValues("A", 1), Policy.CreateValues("A", 1)));
+ Assert.False(func1(Request.CreateValues("A", 1), Policy.CreateValues("A", 2)));
+ Assert.False(func1(Request.CreateValues("B", 1), Policy.CreateValues("B", 2)));
+ }
+
+#if !NET452
+ [Fact]
+ public void TestGenericFunctionModel()
+ {
+ Enforcer e = new Enforcer(DefaultModel.NewModelFromText(
+ """
+ [request_definition]
+ r = obj1, obj2
+
+ [policy_definition]
+ p = _
+
+ [policy_effect]
+ e = some(where (p.eft == allow))
+
+ [matchers]
+ m = max(r.obj1, r.obj2) > 2
+ """));
+
+ e.AddFunction("max", new Func(
+ // ReSharper disable once ConvertClosureToMethodGroup
+ (a, b) => Math.Max(a, b)
+ ));
+ Assert.True(e.Enforce(1, 3));
+ Assert.False(e.Enforce(1, 2));
+ Assert.False(e.Enforce("1", "111"));
+
+ e.AddFunction("max", new Func(
+ (a, b) => Math.Max(a.Length, b.Length)
+ ));
+ Assert.True(e.Enforce(1, 3));
+ Assert.False(e.Enforce(1, 2));
+ Assert.True(e.Enforce("1", "111"));
+ }
+#endif
+
+}
diff --git a/Casbin.UnitTests/GenericTests/GenericMatcherTest.cs b/Casbin.UnitTests/GenericTests/GenericMatcherTest.cs
index e533c3b..fce505a 100644
--- a/Casbin.UnitTests/GenericTests/GenericMatcherTest.cs
+++ b/Casbin.UnitTests/GenericTests/GenericMatcherTest.cs
@@ -1,5 +1,7 @@
using System;
+using Casbin.Evaluation;
using Casbin.Model;
+using Casbin.UnitTests.Util;
using DynamicExpresso;
using Xunit;
@@ -10,11 +12,12 @@ public class GenericMatcherTest
[Fact]
public void TestGenericMatcher()
{
+ Interpreter interpreter = new();
RequestValues r = Request.CreateValues("A", 1);
PolicyValues p = Policy.CreateValues("A", 1);
- Func, PolicyValues, bool> func1 = Compile(
- "r.Value1 == p.Value1 && r.Value2 == p.Value2",
- nameof(r), in r, nameof(p), in p);
+ Func, PolicyValues, bool> func1 =
+ ExpressionUtil.Compile(interpreter, "r.Value1 == p.Value1 && r.Value2 == p.Value2",
+ nameof(r), in r, nameof(p), in p);
Assert.True(func1(Request.CreateValues("A", 1), Policy.CreateValues("A", 1)));
Assert.False(func1(Request.CreateValues("A", 1), Policy.CreateValues("A", 2)));
@@ -22,25 +25,15 @@ public void TestGenericMatcher()
RequestValues r2 = Request.CreateValues("A", 1, "read");
PolicyValues p2 = Policy.CreateValues("A", 1, "read");
- Func, PolicyValues, bool> func2 = Compile(
- "r2.Value1 == p2.Value1 && r2.Value2 == p2.Value2 && r2.Value3 == p2.Value3",
- nameof(r2), in r2, nameof(p2), in p2);
+ Func, PolicyValues, bool> func2 =
+ ExpressionUtil.Compile(interpreter, "r2.Value1 == p2.Value1 && r2.Value2 == p2.Value2 && r2.Value3 == p2.Value3",
+ nameof(r2), in r2, nameof(p2), in p2);
Assert.True(func2(Request.CreateValues("A", 1, "read"), Policy.CreateValues("A", 1, "read")));
Assert.False(func2(Request.CreateValues("A", 1, "read"), Policy.CreateValues("A", 2, "read")));
Assert.False(func2(Request.CreateValues("B", 1, "read"), Policy.CreateValues("B", 2, "read")));
}
- private static Func Compile
- (
- string expressionText,
- string requestType, in TRequest r,
- string policyType, in TPolicy p)
- where TRequest : struct, IRequestValues where TPolicy : IPolicyValues
- {
- Interpreter interpreter = new();
- return interpreter.ParseAsDelegate>(
- expressionText, requestType, policyType
- );
- }
+
+
}
diff --git a/Casbin.UnitTests/ModelTests/EnforcerTest.cs b/Casbin.UnitTests/ModelTests/EnforcerTest.cs
index 64eb87b..5b00b17 100644
--- a/Casbin.UnitTests/ModelTests/EnforcerTest.cs
+++ b/Casbin.UnitTests/ModelTests/EnforcerTest.cs
@@ -69,7 +69,7 @@ public void TestEnforceWithoutAutoLoadPolicy()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
IEnforcer e = new Enforcer(m, a, new EnforcerOptions { AutoLoadPolicy = false });
Assert.Empty(e.GetPolicy());
@@ -118,7 +118,7 @@ public void TestKeyMatchModelInMemory()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
Enforcer e = new(m, a);
@@ -179,7 +179,7 @@ public async Task TestKeyMatchModelInMemoryAsync()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
Enforcer e = new(m, a);
@@ -240,7 +240,7 @@ public void TestKeyMatchModelInMemoryDeny()
m.AddDef("e", "e", "!some(where (p.eft == deny))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
Enforcer e = new(m, a);
@@ -671,7 +671,7 @@ public void TestInitEmpty()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
e.SetModel(m);
e.SetAdapter(a);
@@ -691,7 +691,7 @@ public async Task TestInitEmptyAsync()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- FileAdapter a = new("examples/keymatch_policy.csv");
+ FileAdapter a = new("Examples/keymatch_policy.csv");
e.SetModel(m);
e.SetAdapter(a);
@@ -711,7 +711,7 @@ public void TestInitEmptyByInputStream()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- using (FileStream fs = new("examples/keymatch_policy.csv", FileMode.Open, FileAccess.Read,
+ using (FileStream fs = new("Examples/keymatch_policy.csv", FileMode.Open, FileAccess.Read,
FileShare.ReadWrite))
{
FileAdapter a = new(fs);
@@ -734,7 +734,7 @@ public async Task TestInitEmptyByInputStreamAsync()
m.AddDef("e", "e", "some(where (p.eft == allow))");
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)");
- using (FileStream fs = new("examples/keymatch_policy.csv", FileMode.Open, FileAccess.Read,
+ using (FileStream fs = new("Examples/keymatch_policy.csv", FileMode.Open, FileAccess.Read,
FileShare.ReadWrite))
{
FileAdapter a = new(fs);
@@ -753,7 +753,7 @@ public async Task TestInitEmptyByInputStreamAsync()
[Fact]
public void TestReloadPolicy()
{
- Enforcer e = new("examples/rbac_model.conf", "examples/rbac_policy.csv");
+ Enforcer e = new("Examples/rbac_model.conf", "Examples/rbac_policy.csv");
e.LoadPolicy();
TestGetPolicy(e,
@@ -764,7 +764,7 @@ public void TestReloadPolicy()
[Fact]
public async Task TestReloadPolicyAsync()
{
- Enforcer e = new("examples/rbac_model.conf", "examples/rbac_policy.csv");
+ Enforcer e = new("Examples/rbac_model.conf", "Examples/rbac_policy.csv");
await e.LoadPolicyAsync();
TestGetPolicy(e,
@@ -775,7 +775,7 @@ public async Task TestReloadPolicyAsync()
[Fact]
public void TestSavePolicy()
{
- Enforcer e = new("examples/rbac_model.conf", "examples/rbac_policy.csv");
+ Enforcer e = new("Examples/rbac_model.conf", "Examples/rbac_policy.csv");
e.SavePolicy();
}
@@ -783,7 +783,7 @@ public void TestSavePolicy()
[Fact]
public async Task TestSavePolicyAsync()
{
- Enforcer e = new("examples/rbac_model.conf", "examples/rbac_policy.csv");
+ Enforcer e = new("Examples/rbac_model.conf", "Examples/rbac_policy.csv");
await e.SavePolicyAsync();
}
@@ -791,7 +791,7 @@ public async Task TestSavePolicyAsync()
[Fact]
public void TestSavePolicyWithoutBasicModel()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
e.SavePolicy();
}
@@ -799,7 +799,7 @@ public void TestSavePolicyWithoutBasicModel()
[Fact]
public async Task TestSavePolicyWithoutBasicModelAsync()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
await e.SavePolicyAsync();
}
@@ -807,7 +807,7 @@ public async Task TestSavePolicyWithoutBasicModelAsync()
[Fact]
public void TestClearPolicy()
{
- Enforcer e = new("examples/rbac_model.conf", "examples/rbac_policy.csv");
+ Enforcer e = new("Examples/rbac_model.conf", "Examples/rbac_policy.csv");
e.ClearPolicy();
}
@@ -819,7 +819,7 @@ public void TestClearPolicy()
[Fact]
public void TestEnableEnforce()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
e.EnableEnforce(false);
TestEnforce(e, "alice", "data1", "read", true);
@@ -846,7 +846,7 @@ public void TestEnableEnforce()
[Fact]
public void TestEnableLog()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv")
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv")
{
Logger = new MockLogger(_testOutputHelper)
};
@@ -875,7 +875,7 @@ public void TestEnableLog()
[Fact]
public void TestEnableAutoSave()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
e.EnableAutoSave(false);
// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
@@ -914,7 +914,7 @@ public void TestEnableAutoSave()
[Fact]
public async Task TestEnableAutoSaveAsync()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy_for_async_adapter_test.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy_for_async_adapter_test.csv");
e.EnableAutoSave(false);
// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
@@ -953,8 +953,8 @@ public async Task TestEnableAutoSaveAsync()
[Fact]
public void TestInitWithAdapter()
{
- FileAdapter adapter = new("examples/basic_policy.csv");
- Enforcer e = new("examples/basic_model.conf", adapter);
+ FileAdapter adapter = new("Examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", adapter);
TestEnforce(e, "alice", "data1", "read", true);
TestEnforce(e, "alice", "data1", "write", false);
@@ -969,7 +969,7 @@ public void TestInitWithAdapter()
[Fact]
public void TestRoleLinks()
{
- Enforcer e = new("examples/rbac_model.conf");
+ Enforcer e = new("Examples/rbac_model.conf");
e.EnableAutoBuildRoleLinks(false);
e.BuildRoleLinks();
e.Enforce("user501", "data9", "read");
@@ -978,8 +978,8 @@ public void TestRoleLinks()
[Fact]
public void TestGetAndSetModel()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
- Enforcer e2 = new("examples/basic_with_root_model.conf", "examples/basic_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
+ Enforcer e2 = new("Examples/basic_with_root_model.conf", "Examples/basic_policy.csv");
TestEnforce(e, "root", "data1", "read", false);
@@ -991,8 +991,8 @@ public void TestGetAndSetModel()
[Fact]
public void TestGetAndSetAdapterInMem()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy.csv");
- Enforcer e2 = new("examples/basic_model.conf", "examples/basic_inverse_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy.csv");
+ Enforcer e2 = new("Examples/basic_model.conf", "Examples/basic_inverse_policy.csv");
TestEnforce(e, "alice", "data1", "read", true);
TestEnforce(e, "alice", "data1", "write", false);
@@ -1008,8 +1008,8 @@ public void TestGetAndSetAdapterInMem()
[Fact]
public async Task TestGetAndSetAdapterInMemAsync()
{
- Enforcer e = new("examples/basic_model.conf", "examples/basic_policy_for_async_adapter_test.csv");
- Enforcer e2 = new("examples/basic_model.conf", "examples/basic_inverse_policy.csv");
+ Enforcer e = new("Examples/basic_model.conf", "Examples/basic_policy_for_async_adapter_test.csv");
+ Enforcer e2 = new("Examples/basic_model.conf", "Examples/basic_inverse_policy.csv");
await TestEnforceAsync(e, "alice", "data1", "read", true);
await TestEnforceAsync(e, "alice", "data1", "write", false);
@@ -1025,11 +1025,11 @@ public async Task TestGetAndSetAdapterInMemAsync()
[Fact]
public void TestSetAdapterFromFile()
{
- Enforcer e = new("examples/basic_model.conf");
+ Enforcer e = new("Examples/basic_model.conf");
TestEnforce(e, "alice", "data1", "read", false);
- FileAdapter a = new("examples/basic_policy.csv");
+ FileAdapter a = new("Examples/basic_policy.csv");
e.SetAdapter(a);
e.LoadPolicy();
TestEnforce(e, "alice", "data1", "read", true);
@@ -1046,11 +1046,11 @@ public void TestSetAdapterFromFile()
[Fact]
public async Task TestSetAdapterFromFileAsync()
{
- Enforcer e = new("examples/basic_model.conf");
+ Enforcer e = new("Examples/basic_model.conf");
await TestEnforceAsync(e, "alice", "data1", "read", false);
- FileAdapter a = new("examples/basic_policy_for_async_adapter_test.csv");
+ FileAdapter a = new("Examples/basic_policy_for_async_adapter_test.csv");
e.SetAdapter(a);
await e.LoadPolicyAsync();
await TestEnforceAsync(e, "alice", "data1", "read", true);
diff --git a/Casbin.UnitTests/ModelTests/RbacApiTest.cs b/Casbin.UnitTests/ModelTests/RbacApiTest.cs
index 036e224..32834db 100644
--- a/Casbin.UnitTests/ModelTests/RbacApiTest.cs
+++ b/Casbin.UnitTests/ModelTests/RbacApiTest.cs
@@ -423,8 +423,8 @@ public void TestGetImplicitPermissionsForUserWithDomain()
TestGetImplicitPermissions(e, "alice", AsList(
AsList("alice", "domain1", "data2", "read"),
- AsList("role:writer", "domain1", "data1", "write"),
- AsList("role:reader", "domain1", "data1", "read")),
+ AsList("role:reader", "domain1", "data1", "read"),
+ AsList("role:writer", "domain1", "data1", "write")),
"domain1");
}
diff --git a/Casbin.UnitTests/RbacTests/GroupRoleManagerTest.cs b/Casbin.UnitTests/RbacTests/GroupRoleManagerTest.cs
index 57067be..f0d309d 100644
--- a/Casbin.UnitTests/RbacTests/GroupRoleManagerTest.cs
+++ b/Casbin.UnitTests/RbacTests/GroupRoleManagerTest.cs
@@ -9,7 +9,7 @@ public class GroupRoleManagerTest
[Fact]
public void TestGroupRoleManager()
{
- Enforcer e = new("examples/group_with_domain_model.conf", "examples/group_with_domain_policy.csv");
+ Enforcer e = new("Examples/group_with_domain_model.conf", "Examples/group_with_domain_policy.csv");
GroupRoleManager roleManager = new(10);
e.SetRoleManager("g", roleManager);
e.SetRoleManager("g2", roleManager);
diff --git a/Casbin.UnitTests/Util/ExpressionUtil.cs b/Casbin.UnitTests/Util/ExpressionUtil.cs
new file mode 100644
index 0000000..090eb25
--- /dev/null
+++ b/Casbin.UnitTests/Util/ExpressionUtil.cs
@@ -0,0 +1,20 @@
+using System;
+using Casbin.Model;
+using DynamicExpresso;
+
+namespace Casbin.UnitTests.Util;
+
+public static class ExpressionUtil
+{
+ public static Func Compile
+ (
+ Interpreter interpreter, string expressionText,
+ string requestType, in TRequest r,
+ string policyType, in TPolicy p)
+ where TRequest : struct, IRequestValues where TPolicy : IPolicyValues
+ {
+ return interpreter.ParseAsDelegate>(
+ expressionText, requestType, policyType
+ );
+ }
+}
diff --git a/Casbin/EnforceView.cs b/Casbin/EnforceView.cs
index 21c0b32..74a1cce 100644
--- a/Casbin/EnforceView.cs
+++ b/Casbin/EnforceView.cs
@@ -127,13 +127,11 @@ public static string TransformMatcher(in EnforceView view, string matcher)
Regex reg = new Regex(perfix + $@"{view.RequestType}\.{tokenPair.Key}" + suffix);
matcher = reg.Replace(matcher, $"{view.RequestType}[{tokenPair.Value}]");
}
-
foreach (KeyValuePair tokenPair in view.PolicyAssertion.Tokens)
{
Regex reg = new Regex(perfix + $@"{view.PolicyType}\.{tokenPair.Key}" + suffix);
matcher = reg.Replace(matcher, $"{view.PolicyType}[{tokenPair.Value}]");
}
-
return matcher;
}
@@ -142,13 +140,11 @@ public static string TransformMatcher(in EnforceView view, string matcher)
Regex reg = new Regex(perfix + $@"{view.RequestType}\.{tokenPair.Key}" + suffix);
matcher = reg.Replace(matcher, $"{view.RequestType}.Value{tokenPair.Value + 1}");
}
-
foreach (KeyValuePair tokenPair in view.PolicyAssertion.Tokens)
{
Regex reg = new Regex(perfix + $@"{view.PolicyType}\.{tokenPair.Key}" + suffix);
matcher = reg.Replace(matcher, $"{view.PolicyType}.Value{tokenPair.Value + 1}");
}
-
return matcher;
}
}
diff --git a/Casbin/Extensions/Enforcer/ManagementEnforcerExtension.cs b/Casbin/Extensions/Enforcer/ManagementEnforcerExtension.cs
index 502d819..43b373e 100644
--- a/Casbin/Extensions/Enforcer/ManagementEnforcerExtension.cs
+++ b/Casbin/Extensions/Enforcer/ManagementEnforcerExtension.cs
@@ -14,17 +14,14 @@ public static class ManagementEnforcerExtension
///
/// The name of the new function.
/// The function.
- public static void AddFunction(this IEnforcer enforcer, string name, Delegate function) =>
+ public static void AddFunction(this IEnforcer enforcer, string name, T function) where T : Delegate
+ {
enforcer.Model.ExpressionHandler.SetFunction(name, function);
-
- ///
- /// Adds a customized function.
- ///
- ///
- /// The name of the new function.
- /// The function.
- public static void AddFunction(this IEnforcer enforcer, string name, Func function) =>
- AddFunction(enforcer, name, (Delegate)function);
+ if (enforcer.AutoCleanEnforceCache)
+ {
+ enforcer.ClearCache();
+ }
+ }
#region "p" (Store) Management
diff --git a/Casbin/Extensions/Enforcer/RbacEnforcerExtension.cs b/Casbin/Extensions/Enforcer/RbacEnforcerExtension.cs
index 9821121..b5ddfe2 100644
--- a/Casbin/Extensions/Enforcer/RbacEnforcerExtension.cs
+++ b/Casbin/Extensions/Enforcer/RbacEnforcerExtension.cs
@@ -523,19 +523,17 @@ public static IEnumerable GetImplicitRolesForUser(this IEnforcer enforce
foreach (string role in roles)
{
- if (roleSet.Contains(role))
+ if (roleSet.Add(role))
{
- continue;
+ queue.Enqueue(role);
}
-
- roleSet.Add(role);
- queue.Enqueue(role);
}
}
}
-
roleSet.Remove(name);
- return roleSet;
+ var roleList = roleSet.ToList();
+ roleList.Sort();
+ return roleList;
}
///