From 747234b26056503b610e20909fcb221691b30bd7 Mon Sep 17 00:00:00 2001 From: sukidayou <77531556+sukidayou@users.noreply.github.com> Date: Fri, 17 Jan 2025 18:32:30 +0800 Subject: [PATCH] feat: sync keyMatch5 from Go to Java (#449) --- examples/keymatch5_model.conf | 11 +++++++ examples/keymatch5_policy.csv | 2 ++ .../casbin/jcasbin/util/BuiltInFunctions.java | 11 +++++-- .../main/BuiltInFunctionsUnitTest.java | 32 +++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 examples/keymatch5_model.conf create mode 100644 examples/keymatch5_policy.csv diff --git a/examples/keymatch5_model.conf b/examples/keymatch5_model.conf new file mode 100644 index 00000000..cec28e64 --- /dev/null +++ b/examples/keymatch5_model.conf @@ -0,0 +1,11 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = r.sub == p.sub && keyMatch5(r.obj, p.obj) && regexMatch(r.act, p.act) \ No newline at end of file diff --git a/examples/keymatch5_policy.csv b/examples/keymatch5_policy.csv new file mode 100644 index 00000000..456a4f0e --- /dev/null +++ b/examples/keymatch5_policy.csv @@ -0,0 +1,2 @@ +p, alice, /alice_data/{resource}/.*, GET +p, alice, /alice_data2/{id}/using/{resId}/.*, GET \ No newline at end of file diff --git a/src/main/java/org/casbin/jcasbin/util/BuiltInFunctions.java b/src/main/java/org/casbin/jcasbin/util/BuiltInFunctions.java index 4c4aa743..6af38333 100644 --- a/src/main/java/org/casbin/jcasbin/util/BuiltInFunctions.java +++ b/src/main/java/org/casbin/jcasbin/util/BuiltInFunctions.java @@ -37,6 +37,7 @@ public class BuiltInFunctions { private static final Pattern KEY_MATCH2_PATTERN = Pattern.compile(":[^/]+"); private static final Pattern KEY_MATCH3_PATTERN = Pattern.compile("\\{[^/]+\\}"); + private static final Pattern KEY_MATCH5_PATTERN = Pattern.compile("\\{[^/]+\\}"); /** * validate the variadic string parameter size @@ -206,10 +207,14 @@ public static boolean keyMatch4(String key1, String key2) { */ public static boolean keyMatch5(String key1, String key2) { int i = key1.indexOf('?'); - if (i == -1) { - return key1.equals(key2); + if (i != -1) { + key1 = key1.substring(0,i); } - return key1.substring(0, i).equals(key2); + + key2 = key2.replace("/*", "/.*"); + key2 = KEY_MATCH5_PATTERN.matcher(key2).replaceAll("[^/]+"); + + return regexMatch(key1, "^" + key2 + "$"); } /** diff --git a/src/test/java/org/casbin/jcasbin/main/BuiltInFunctionsUnitTest.java b/src/test/java/org/casbin/jcasbin/main/BuiltInFunctionsUnitTest.java index 0419e1c9..bd5ce457 100644 --- a/src/test/java/org/casbin/jcasbin/main/BuiltInFunctionsUnitTest.java +++ b/src/test/java/org/casbin/jcasbin/main/BuiltInFunctionsUnitTest.java @@ -127,11 +127,43 @@ public void testKeyMatch4Func() { @Test public void testKeyMatch5Func() { + testKeyMatch5("/alice_data/hello/123", "/alice_data/{resource}/.*", true); + testKeyMatch5("/parent/child?status=1&type=2", "/parent/child", true); testKeyMatch5("/parent?status=1&type=2", "/parent/child", false); + testKeyMatch5("/parent/child/?status=1&type=2", "/parent/child/", true); testKeyMatch5("/parent/child/?status=1&type=2", "/parent/child", false); testKeyMatch5("/parent/child?status=1&type=2", "/parent/child/", false); + + testKeyMatch5("/foo", "/foo", true); + testKeyMatch5("/foo", "/foo*", true); + testKeyMatch5("/foo", "/foo/*", false); + testKeyMatch5("/foo/bar", "/foo", false); + testKeyMatch5("/foo/bar", "/foo*", false); + testKeyMatch5("/foo/bar", "/foo/*", true); + testKeyMatch5("/foobar", "/foo", false); + testKeyMatch5("/foobar", "/foo*", false); + testKeyMatch5("/foobar", "/foo/*", false); + + testKeyMatch5("/", "/{resource}", false); + testKeyMatch5("/resource1", "/{resource}", true); + testKeyMatch5("/myid", "/{id}/using/{resId}", false); + testKeyMatch5("/myid/using/myresid", "/{id}/using/{resId}", true); + + testKeyMatch5("/proxy/myid", "/proxy/{id}/*", false); + testKeyMatch5("/proxy/myid/", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res/res2", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res/res2/res3", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/", "/proxy/{id}/*", false); + + testKeyMatch5("/proxy/myid?status=1&type=2", "/proxy/{id}/*", false); + testKeyMatch5("/proxy/myid/", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res?status=1&type=2", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res/res2?status=1&type=2", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/myid/res/res2/res3?status=1&type=2", "/proxy/{id}/*", true); + testKeyMatch5("/proxy/", "/proxy/{id}/*", false); } @Test