diff --git a/README.md b/README.md index 19a9343..303369a 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,15 @@ mvn clean install ``` ## Options -| options | description | must | remark | -|-----------------------|----------------------------------------------|------|-----------------------------------------------------------| -| `-m, --model` | The path of the model file or model text | y | Please wrap it with `""` and separate each line with `\|` | -| `-p, --policy` | The path of the policy file or policy text | y | Please wrap it with `""` and separate each line with `\|` | -| `-e, --enforce` | Check permissions | n | Please wrap it with `""` | -| `-ex, --enforceEx` | Check permissions and get which policy it is | n | Please wrap it with `""` | -| `-AF, --addFuntion` | Add custom funtion | n | Please wrap it with `""` and separate each line with `\|` | -| `-ap, --addPolicy` | Add a policy rule to the policy file | n | Please wrap it with `""` | -| `-rp, --removePolicy` | Remove a policy rule from the policy file | n | Please wrap it with `""` | +| options | description | must | remark | +|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------|-----------------------------------------------------------| +| `-m, --model` | The path of the model file or model text | y | Please wrap it with `""` and separate each line with `\|` | +| `-p, --policy` | The path of the policy file or policy text | y | Please wrap it with `""` and separate each line with `\|` | +| `-e, --enforce` | Check permissions | n | Please wrap it with `""` | +| `-ex, --enforceEx` | Check permissions and get which policy it is | n | Please wrap it with `""` | +| `-AF, --addFuntion` | Add custom funtion using text or function file.
file format see [function.conf](https://github.com/jcasbin/casbin-java-cli/blob/master/examples/keymatch_function.conf) | n | Please wrap it with `""` and separate each line with `\|` | +| `-ap, --addPolicy` | Add a policy rule to the policy file | n | Please wrap it with `""` | +| `-rp, --removePolicy` | Remove a policy rule from the policy file | n | Please wrap it with `""` | ## Get started diff --git a/examples/keymatch_function.conf b/examples/keymatch_function.conf new file mode 100644 index 0000000..831b3f5 --- /dev/null +++ b/examples/keymatch_function.conf @@ -0,0 +1,25 @@ +[function_definition] +public static boolean keyMatchTest(String key1, String key2) { + int i = key2.indexOf('*'); + if (i == -1) { + return key1.equals(key2); + } + + if (key1.length() > i) { + return key1.substring(0, i).equals(key2.substring(0, i)); + } + return key1.equals(key2.substring(0, i)); +} + +[function_definition] +public static boolean keyMatchTest2(String key1, String key2) { + int i = key2.indexOf('*'); + if (i == -1) { + return key1.equals(key2); + } + + if (key1.length() > i) { + return key1.substring(0, i).equals(key2.substring(0, i)); + } + return key1.equals(key2.substring(0, i)); +} diff --git a/src/main/java/org/casbin/Client.java b/src/main/java/org/casbin/Client.java index a2dadf2..f5763ee 100644 --- a/src/main/java/org/casbin/Client.java +++ b/src/main/java/org/casbin/Client.java @@ -43,10 +43,12 @@ public static String run(String... args) { NewEnforcer enforcer = new NewEnforcer(model, policy); if(cmd.hasOption("AF")) { - String codes = cmd.getOptionValue("AF"); - String methodName = Util.getMethodName(codes); - CustomFunction customFunction = DynamicClassGenerator.generateClass(methodName, codes); - enforcer.addFunction(methodName, customFunction); + List codes = Util.parse(cmd.getOptionValue("AF")); + for (String code : codes) { + String methodName = Util.getMethodName(code); + CustomFunction customFunction = DynamicClassGenerator.generateClass(methodName, code); + enforcer.addFunction(methodName, customFunction); + } } CommandExecutor commandExecutor = new CommandExecutor(enforcer, commandName, cmd.getArgs()); Object o = commandExecutor.outputResult(); @@ -110,7 +112,7 @@ private static void printHelpMessage() { " Options:\n" + " -m, --model The path of the model file or model text. Please wrap it with \"\" and separate each line with \"|\"\n" + " -p, --policy The path of the policy file or policy text. Please wrap it with \"\" and separate each line with \"|\"\n" + - " -AF, --addFunction Add custom function. Please wrap it with \"\" and separate each line with \"|\"\n" + + " -AF, --addFunction The path of the function file or function text. Please wrap it with \"\" and separate each line with \"|\"\n" + "\n" + " args:\n" + " Parameters required for the method\n" + diff --git a/src/main/java/org/casbin/util/Util.java b/src/main/java/org/casbin/util/Util.java index 56f0ce4..e1413ea 100644 --- a/src/main/java/org/casbin/util/Util.java +++ b/src/main/java/org/casbin/util/Util.java @@ -1,5 +1,9 @@ package org.casbin.util; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,4 +30,30 @@ public static int getArgsNum(String methodCodes) { } return 0; } + + /** + * Parse the input string to get the function definitions List + * @param input + * @return List of function definitions + */ + public static List parse(String input) throws IOException { + if (input == null || input.trim().isEmpty()) { + throw new IllegalArgumentException("Input cannot be null or empty"); + } + List codes = new ArrayList<>(); + + // Check if input is an existing file + File file = new File(input); + if (file.exists() && file.isFile()) { + String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); + + String[] lines = content.split("\\[function_definition\\]"); + for (int i = 1; i < lines.length; i++) { + codes.add(lines[i].trim()); + } + } else { + codes.add(input); + } + return codes; + } } diff --git a/src/test/java/org/casbin/ClientTest.java b/src/test/java/org/casbin/ClientTest.java index b3df73e..a9c2b1b 100644 --- a/src/test/java/org/casbin/ClientTest.java +++ b/src/test/java/org/casbin/ClientTest.java @@ -116,6 +116,41 @@ public void testCustomFunction() throws ParseException { assertEquals(Client.run(new String[]{"enforce", "-m", model, "-p", "examples/keymatch_policy.csv", "-AF", func, "cathy", "/cathy_data", "POST"}), "{\"allow\":true,\"explain\":null}"); assertEquals(Client.run(new String[]{"enforce", "-m", model, "-p", "examples/keymatch_policy.csv", "-AF", func, "cathy", "/cathy_data", "DELETE"}), "{\"allow\":false,\"explain\":null}"); + // test add Function using file + String methodName2 = "keyMatchTest2"; + String model2 = "[request_definition]\n" + + "r = sub, obj, act\n" + + "\n" + + "[policy_definition]\n" + + "p = sub, obj, act\n" + + "\n" + + "[policy_effect]\n" + + "e = some(where (p.eft == allow))\n" + + "\n" + + "[matchers]\n" + + "m = r.sub == p.sub && " + methodName + "(r.obj, p.obj) && " + methodName2 + "(r.obj, p.obj)" + "&& regexMatch(r.act, p.act)\n"; + + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/alice_data/resource1", "GET"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/alice_data/resource1", "POST"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/alice_data/resource2", "GET"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/alice_data/resource2", "POST"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/bob_data/resource1", "GET"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/bob_data/resource1", "POST"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/bob_data/resource2", "GET"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "alice", "/bob_data/resource2", "POST"}), "{\"allow\":false,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/alice_data/resource1", "GET"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/alice_data/resource1", "POST"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/alice_data/resource2", "GET"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/alice_data/resource2", "POST"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/bob_data/resource1", "GET"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/bob_data/resource1", "POST"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/bob_data/resource2", "GET"}), "{\"allow\":false,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "bob", "/bob_data/resource2", "POST"}), "{\"allow\":true,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "cathy", "/cathy_data", "GET"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "cathy", "/cathy_data", "POST"}), "{\"allow\":true,\"explain\":null}"); + assertEquals(Client.run(new String[]{"enforce", "-m", model2, "-p", "examples/keymatch_policy.csv", "-AF", "examples/keymatch_function.conf", "cathy", "/cathy_data", "DELETE"}), "{\"allow\":false,\"explain\":null}"); } @Test