diff --git a/Casbin.UnitTest/UtilTests/BuiltInFunctionTest.cs b/Casbin.UnitTest/UtilTests/BuiltInFunctionTest.cs index dfa3e101..e6de2b91 100644 --- a/Casbin.UnitTest/UtilTests/BuiltInFunctionTest.cs +++ b/Casbin.UnitTest/UtilTests/BuiltInFunctionTest.cs @@ -172,6 +172,24 @@ public void TestKeyMatch4(string key1, string key2, bool expectedResult) BuiltInFunctions.KeyMatch4(key1, key2)); } + public static IEnumerable KeyMatch5TestData = new[] + { + new object[] { "/parent/child?status=1&type=2", "/parent/child", true}, + new object[] { "/parent?status=1&type=2", "/parent/child", false}, + + new object[] { "/parent/child/?status=1&type=2", "/parent/child/", true}, + new object[] { "/parent/child/?status=1&type=2", "/parent/child", false}, + new object[] { "/parent/child?status=1&type=2", "/parent/child/", false} + }; + + [Theory] + [MemberData(nameof(KeyMatch5TestData))] + public void TestKeyMatch5(string key1, string key2, bool expectedResult) + { + Assert.Equal(expectedResult, + BuiltInFunctions.KeyMatch5(key1, key2)); + } + public static IEnumerable GlobMatchTestData = new[] { new object[] {"/foo", "/foo", true}, diff --git a/Casbin/Model/FunctionMap.cs b/Casbin/Model/FunctionMap.cs index 5d9f1361..af8513ca 100644 --- a/Casbin/Model/FunctionMap.cs +++ b/Casbin/Model/FunctionMap.cs @@ -24,6 +24,7 @@ internal static FunctionMap LoadFunctionMap() map.AddFunction("keyMatch2", BuiltInFunctions.KeyMatch2); map.AddFunction("keyMatch3", BuiltInFunctions.KeyMatch3); map.AddFunction("keyMatch4", BuiltInFunctions.KeyMatch4); + map.AddFunction("keyMatch5", BuiltInFunctions.KeyMatch5); map.AddFunction("regexMatch", BuiltInFunctions.RegexMatch); map.AddFunction("ipMatch", BuiltInFunctions.IPMatch); map.AddFunction("globMatch", BuiltInFunctions.GlobMatch); diff --git a/Casbin/Util/BuiltInFunctions.cs b/Casbin/Util/BuiltInFunctions.cs index e0a23b63..55b0a135 100644 --- a/Casbin/Util/BuiltInFunctions.cs +++ b/Casbin/Util/BuiltInFunctions.cs @@ -128,6 +128,22 @@ public static bool KeyMatch4(string key1, string key2) return true; } + /// + /// KeyMatch determines whether key1 matches the pattern of key2 and ignores the parameters in key2. + /// For example, "/foo/bar?status=1&type=2" matches "/foo/bar" + /// + /// The first argument. + /// The second argument. + /// + public static bool KeyMatch5(string key1, string key2) + { + var key1Span = key1.AsSpan(); + var key2Span = key2.AsSpan(); + int index = key1Span.IndexOf('?'); + return index is -1 + ? key1Span.Equals(key2Span, StringComparison.Ordinal) + : key1Span.Slice(0, index).Equals(key2Span, StringComparison.Ordinal); + } /// /// Determines whether IP address ip1 matches the pattern of IP address ip2,