diff --git a/Casbin.UnitTests/Fixtures/TestModelFixture.cs b/Casbin.UnitTests/Fixtures/TestModelFixture.cs index 3ed8f92..6c9e66a 100644 --- a/Casbin.UnitTests/Fixtures/TestModelFixture.cs +++ b/Casbin.UnitTests/Fixtures/TestModelFixture.cs @@ -91,6 +91,10 @@ public class TestModelFixture public static readonly string BackslashLineFeedModelText = ReadTestFile("backslash_feed_model.conf"); public static readonly string BackslashLineFeedPolicyText = ReadTestFile("backslash_feed_policy.csv"); + // https://github.com/casbin/Casbin.NET/issues/353 + public static readonly string RbacWithIndexMatcherModelText = ReadTestFile("rbac_with_index_matcher_model.conf"); + public static readonly string RbacWithIndexMatcherPolicyText = ReadTestFile("rbac_with_index_matcher_policy.csv"); + public static IModel GetNewAbacModel() => GetNewTestModel(AbacModelText); public static IModel GetNewAbacWithEvalModel() => GetNewTestModel(AbacWithEvalModelText, AbacWithEvalPolicyText); diff --git a/Casbin.UnitTests/ModelTests/ModelTest.cs b/Casbin.UnitTests/ModelTests/ModelTest.cs index dbeeb98..7ff6c68 100644 --- a/Casbin.UnitTests/ModelTests/ModelTest.cs +++ b/Casbin.UnitTests/ModelTests/ModelTest.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; using Casbin.Model; using Casbin.UnitTests.Fixtures; using Casbin.UnitTests.Mock; @@ -728,6 +730,28 @@ public void TestAccidentalCacheRead() TestEnforce(e, "alice", "data", "1read", false); } + [Fact] + public void TestRbacWithIndexMatcher() + { + Enforcer e = new(TestModelFixture.GetNewTestModel( + TestModelFixture.RbacWithIndexMatcherModelText, + TestModelFixture.RbacWithIndexMatcherPolicyText)); + e.BuildRoleLinks(); + var rule = new Dictionary> + { + ["CompanyData"] = new() { ["CompanyIsActive"] = "True", ["BusinessRole"] = "Role1" } + }; + Assert.True(e.Enforce(rule, "WebApp", "/api/transactions/getTransactions", "POST")); + Assert.False(e.Enforce(rule, "Admin", "/api/transactions/getTransactions", "POST")); + + rule = new Dictionary> + { + ["CompanyData"] = new() { ["CompanyIsActive"] = "False", ["BusinessRole"] = "Role1" } + }; + Assert.False(e.Enforce(rule, "WebApp", "/api/transactions/getTransactions", "POST")); + Assert.True(e.Enforce(rule, "Admin", "/api/transactions/getTransactions", "POST")); + } + public class TestResource { public TestResource(string name, string owner) diff --git a/Casbin.UnitTests/examples/rbac_with_index_matcher_model.conf b/Casbin.UnitTests/examples/rbac_with_index_matcher_model.conf new file mode 100644 index 0000000..b148c3c --- /dev/null +++ b/Casbin.UnitTests/examples/rbac_with_index_matcher_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = rule, sub, obj, act + +[policy_definition] +p = sub_rule, sub, obj, act + +[role_definition] +g = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) + +[matchers] +m = eval(p.sub_rule) && g(r.sub, p.sub) && keyMatch3(r.obj, p.obj) && (p.act == "*" || regexMatch(r.act, p.act)) diff --git a/Casbin.UnitTests/examples/rbac_with_index_matcher_policy.csv b/Casbin.UnitTests/examples/rbac_with_index_matcher_policy.csv new file mode 100644 index 0000000..00e1923 --- /dev/null +++ b/Casbin.UnitTests/examples/rbac_with_index_matcher_policy.csv @@ -0,0 +1,2 @@ +p, r.rule["CompanyData"]["CompanyIsActive"] == "True" && (r.rule["CompanyData"]["BusinessRole"] == "Role1" || r.rule["CompanyData"]["BusinessRole"] == "Role2"), WebApp, /api/transactions/getTransactions, POST +p, r.rule["CompanyData"]["CompanyIsActive"] == "False" && (r.rule["CompanyData"]["BusinessRole"] == "Role1" || r.rule["CompanyData"]["BusinessRole"] == "Role2"), Admin, /api/transactions/getTransactions, POST diff --git a/Casbin/EnforceView.cs b/Casbin/EnforceView.cs index cc0dc99..21c0b32 100644 --- a/Casbin/EnforceView.cs +++ b/Casbin/EnforceView.cs @@ -118,8 +118,8 @@ public static EnforceView CreateWithMatcher( [SuppressMessage("ReSharper", "UseDeconstruction")] public static string TransformMatcher(in EnforceView view, string matcher) { - string perfix = @"(?<=(\s|^|\||&|!|=|\(|\)|<|>|,|\+|-|\*|\/|\\)\s*)"; - string suffix = @"(?=\s*(\s|$|\||&|!|=|\(|\)|<|>|,|\+|-|\*|\/|\\|\.|in))"; + string perfix = @"(?<=(\s|^|\||&|!|=|\(|\)|<|>|,|\+|-|\*|\/|\\|\[)\s*)"; + string suffix = @"(?=\s*(\s|$|\||&|!|=|\(|\)|<|>|,|\+|-|\*|\/|\\|\[|\]|\.|in))"; if (view.SupportGeneric is false) { foreach (KeyValuePair tokenPair in view.RequestAssertion.Tokens)