diff --git a/NetCasbin.UnitTest/BuiltInFunctionTest.cs b/NetCasbin.UnitTest/BuiltInFunctionTest.cs index 4ba98ff2..e45e6b16 100644 --- a/NetCasbin.UnitTest/BuiltInFunctionTest.cs +++ b/NetCasbin.UnitTest/BuiltInFunctionTest.cs @@ -23,9 +23,9 @@ public class BuiltInFunctionTest [Theory] [MemberData(nameof(ipMatchTestData))] - public void TestIPMatch(string key1, string key2, bool exceptResult) + public void TestIPMatch(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.IPMatch(key1, key2)); } @@ -44,9 +44,9 @@ public void TestIPMatch(string key1, string key2, bool exceptResult) [Theory] [MemberData(nameof(regexMatchTestData))] - public void TestRegexMatch(string key1, string key2, bool exceptResult) + public void TestRegexMatch(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.RegexMatch(key1, key2)); } @@ -65,9 +65,9 @@ public void TestRegexMatch(string key1, string key2, bool exceptResult) [Theory] [MemberData(nameof(keyMatchTestData))] - public void TestKeyMatch(string key1, string key2, bool exceptResult) + public void TestKeyMatch(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.KeyMatch(key1, key2)); } @@ -105,9 +105,9 @@ public void TestKeyMatch(string key1, string key2, bool exceptResult) [Theory] [MemberData(nameof(KeyMatch2TestData))] - public void TestKeyMatch2(string key1, string key2, bool exceptResult) + public void TestKeyMatch2(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.KeyMatch2(key1, key2)); } @@ -141,9 +141,9 @@ public void TestKeyMatch2(string key1, string key2, bool exceptResult) [Theory] [MemberData(nameof(KeyMatch3TestData))] - public void TestKeyMatch3(string key1, string key2, bool exceptResult) + public void TestKeyMatch3(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.KeyMatch3(key1, key2)); } @@ -166,10 +166,58 @@ public void TestKeyMatch3(string key1, string key2, bool exceptResult) [Theory] [MemberData(nameof(KeyMatch4TestData))] - public void TestKeyMatch4(string key1, string key2, bool exceptResult) + public void TestKeyMatch4(string key1, string key2, bool expectedResult) { - Assert.Equal(exceptResult, + Assert.Equal(expectedResult, BuiltInFunctions.KeyMatch4(key1, key2)); } + + public static IEnumerable GlobMatchTestData = new[] + { + new object[] {"/foo", "/foo", true}, + new object[] {"/foo", "/foo*", true}, + new object[] {"/foo", "/foo/*", false}, + new object[] {"/foo/bar", "/foo", false}, + new object[] {"/foo/bar", "/foo*", false}, + new object[] {"/foo/bar", "/foo/*", true}, + new object[] {"/foobar", "/foo", false}, + new object[] {"/foobar", "/foo*", true}, + new object[] {"/foobar", "/foo/*", false}, + new object[] {"/foo", "*/foo", true}, + new object[] {"/foo", "*/foo*", true}, + new object[] {"/foo", "*/foo/*", false}, + new object[] {"/foo/bar", "*/foo", false}, + new object[] {"/foo/bar", "*/foo*", false}, + new object[] {"/foo/bar", "*/foo/*", true}, + new object[] {"/foobar", "*/foo", false}, + new object[] {"/foobar", "*/foo*", true}, + new object[] {"/foobar", "*/foo/*", false}, + new object[] {"/prefix/foo", "*/foo", false}, + new object[] {"/prefix/foo", "*/foo*", false}, + new object[] {"/prefix/foo", "*/foo/*", false}, + new object[] {"/prefix/foo/bar", "*/foo", false}, + new object[] {"/prefix/foo/bar", "*/foo*", false}, + new object[] {"/prefix/foo/bar", "*/foo/*", false}, + new object[] {"/prefix/foobar", "*/foo", false}, + new object[] {"/prefix/foobar", "*/foo*", false}, + new object[] {"/prefix/foobar", "*/foo/*", false}, + new object[] {"/prefix/subprefix/foo", "*/foo", false}, + new object[] {"/prefix/subprefix/foo", "*/foo*", false}, + new object[] {"/prefix/subprefix/foo", "*/foo/*", false}, + new object[] {"/prefix/subprefix/foo/bar", "*/foo", false}, + new object[] {"/prefix/subprefix/foo/bar", "*/foo*", false}, + new object[] {"/prefix/subprefix/foo/bar", "*/foo/*", false}, + new object[] {"/prefix/subprefix/foobar", "*/foo", false}, + new object[] {"/prefix/subprefix/foobar", "*/foo*", false}, + new object[] {"/prefix/subprefix/foobar", "*/foo/*", false}, + }; + + [Theory] + [MemberData(nameof(GlobMatchTestData))] + public void TestGlobMatch(string key1, string key2, bool expectedResult) + { + Assert.Equal(expectedResult, + BuiltInFunctions.GlobMatch(key1, key2)); + } } } diff --git a/NetCasbin/Model/FunctionMap.cs b/NetCasbin/Model/FunctionMap.cs index 90469208..bc33c348 100644 --- a/NetCasbin/Model/FunctionMap.cs +++ b/NetCasbin/Model/FunctionMap.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using NetCasbin.Util; using NetCasbin.Util.Function; namespace NetCasbin.Model @@ -21,12 +20,13 @@ public static FunctionMap LoadFunctionMap() FunctionDict = new Dictionary() }; - map.AddFunction("keyMatch", new KeyMatchFunc()); + map.AddFunction("keyMatch", new KeyMatchFunc()); map.AddFunction("keyMatch2", new KeyMatch2Func()); map.AddFunction("keyMatch3", new KeyMatch3Func()); map.AddFunction("keyMatch4", new KeyMatch4Func()); map.AddFunction("regexMatch", new RegexMatchFunc()); map.AddFunction("ipMatch", new IPMatchFunc()); + map.AddFunction("globMatch", new GlobMatchFunc()); return map; } } diff --git a/NetCasbin/NetCasbin.csproj b/NetCasbin/NetCasbin.csproj index ba6d32e2..3b60120c 100644 --- a/NetCasbin/NetCasbin.csproj +++ b/NetCasbin/NetCasbin.csproj @@ -25,6 +25,7 @@ + diff --git a/NetCasbin/Util/BuiltInFunctions.cs b/NetCasbin/Util/BuiltInFunctions.cs index e01b2c55..812d7c0d 100644 --- a/NetCasbin/Util/BuiltInFunctions.cs +++ b/NetCasbin/Util/BuiltInFunctions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Text.RegularExpressions; +using DotNet.Globbing; using NetCasbin.Abstractions; using NetCasbin.Extensions; using NetCasbin.Rbac; @@ -188,6 +189,17 @@ public static bool RegexMatch(string key1, string key2) return Regex.Match(key1, key2).Success; } + /// + /// Determines whether key1 matches the globbing pattern of key2 + /// + /// The keyword to match + /// The Globbing pattern + /// Whether key1 matches key2. + public static bool GlobMatch(string key1, string key2) + { + return Glob.Parse(key2).IsMatch(key1); + } + /// /// GenerateGFunction is the factory method of the g(_, _) function. /// diff --git a/NetCasbin/Util/Function/GlobMatchFunc.cs b/NetCasbin/Util/Function/GlobMatchFunc.cs new file mode 100644 index 00000000..affd2a68 --- /dev/null +++ b/NetCasbin/Util/Function/GlobMatchFunc.cs @@ -0,0 +1,20 @@ +using System; +using System.Net; +using NetCasbin.Abstractions; + +namespace NetCasbin.Util.Function +{ + public class GlobMatchFunc : AbstractFunction + { + protected override Delegate GetFunc() + { + Func call = BuiltInFunctions.GlobMatch; + return call; + } + + public GlobMatchFunc() : base("globMatch") + { + + } + } +}