From 8d9c1b329a5bd659f2926e4dbce9b052b4cd9bbc Mon Sep 17 00:00:00 2001 From: Liao Xin <93535922+liewstar@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:33:05 +0800 Subject: [PATCH] feat: support some functions of the editor (#9) * feat: Support parsing string * feat: simple check model * feat: update README --- README.md | 30 ++++---- src/main/java/org/casbin/Client.java | 85 +++++++++++++---------- src/main/java/org/casbin/NewEnforcer.java | 71 +++++++++++++++++++ src/test/java/org/casbin/ClientTest.java | 26 +++++++ 4 files changed, 164 insertions(+), 48 deletions(-) create mode 100644 src/main/java/org/casbin/NewEnforcer.java diff --git a/README.md b/README.md index 1144b9e..a3d3d9f 100644 --- a/README.md +++ b/README.md @@ -18,42 +18,46 @@ mvn clean install ``` ## Options -| options | description | must | -|-----------------------|----------------------------------------------|------| -| `-m, --model` | The path of the model file | y | -| `-p, --policy` | The path of the policy file | y | -| `-e, --enforce` | Check permissions | n | -| `-ex, --enforceEx` | Check permissions and get which policy it is | n | -| `-ap, --addPolicy` | Add a policy rule to the policy file | n | -| `-rp, --removePolicy` | Remove a policy rule from the policy file | n | +| 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 `""` | +| `-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 - Check whether Alice has read permission on data1 ```shell - java -jar target/casbin-java-cli.jar -m examples/rbac_model.conf -p examples/rbac_policy.csv -e alice,data1,read + java -jar target/casbin-java-cli.jar -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -e "alice, data1, read" ``` > Allow + ```shell + java -jar target/casbin-java-cli.jar -m "[request_definition]|r = sub, obj, act|[policy_definition]|p = sub, obj, act|[role_definition]|g = _, _|[policy_effect]|e = some(where (p.eft == allow))|[matchers]|m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act" -p "p, alice, data1, read|p, bob, data2, write|p, data2_admin, data2, read|p, data2_admin, data2, write|g, alice, data2_admin" -e "alice, data1, read" + ``` + > Allow - Check whether Alice has write permission for data2. If so, display the effective policy. ```shell - java -jar target/casbin-java-cli.jar -m examples/rbac_model.conf -p examples/rbac_policy.csv -ex alice,data2,write + java -jar target/casbin-java-cli.jar -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -ex "alice, data2, write" ``` - > EnforceResult{allow=true, explain=[data2_admin, data2, write]} + > true Reason: [alice, data2, write] - Add a policy to the policy file ```shell - java -jar target/casbin-java-cli.jar -m examples/rbac_model.conf -p examples/rbac_policy.csv -ap alice,data2,write + java -jar target/casbin-java-cli.jar -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -ap "alice, data2, write" ``` > Add Success - Delete a policy from the policy file ```shell - java -jar target/casbin-java-cli.jar -m examples/rbac_model.conf -p examples/rbac_policy.csv -rp alice,data1,read + java -jar target/casbin-java-cli.jar -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -rp "alice,data1,read" ``` > Remove Success diff --git a/src/main/java/org/casbin/Client.java b/src/main/java/org/casbin/Client.java index bcc1e7c..d91d53e 100644 --- a/src/main/java/org/casbin/Client.java +++ b/src/main/java/org/casbin/Client.java @@ -1,8 +1,9 @@ package org.casbin; import org.apache.commons.cli.*; -import org.casbin.jcasbin.exception.CasbinConfigException; -import org.casbin.jcasbin.main.Enforcer; +import org.casbin.jcasbin.exception.CasbinEffectorException; +import org.casbin.jcasbin.main.EnforceResult; + public class Client { private static void configureOptions(Options options) { @@ -29,46 +30,60 @@ public static Object run(String[] args) throws ParseException { CommandLineParser parser = new DefaultParser(); CommandLine cmd = parser.parse(options, args); - String modelPath = cmd.getOptionValue("model"); - String policyPath = cmd.getOptionValue("policy"); - Enforcer enforcer = null; + String model = cmd.getOptionValue("model"); + String policy = cmd.getOptionValue("policy"); + NewEnforcer enforcer = null; try { - enforcer = new Enforcer(modelPath, policyPath); - } catch (CasbinConfigException ex) { - ex.printStackTrace(); + enforcer = new NewEnforcer(model, policy); + } catch (NullPointerException | CasbinEffectorException | UnsupportedOperationException e) { + System.out.println("unsupported effect:" + e.getMessage()); + System.exit(0); + } catch (Exception e) { + System.out.println(e.getMessage()); + System.exit(0); } - if(cmd.hasOption("enforce")) { - String enforceArgs = cmd.getOptionValue("enforce").replace(" ",""); - boolean result = enforcer.enforce(enforceArgs.split(",")); - System.out.println(result ? "Allow" : "Ban"); - return result; - } else if (cmd.hasOption("enforceEx")) { - String enforceArgs = cmd.getOptionValue("enforceEx").replace(" ",""); - boolean result = enforcer.enforceEx(enforceArgs.split(",")).isAllow(); - System.out.println(result ? "Allow" : "Ban"); - return result; - }else if (cmd.hasOption("addPolicy")){ - String policyArgs = cmd.getOptionValue("addPolicy").replace(" ",""); - boolean result = enforcer.addPolicy(policyArgs.split(",")); - System.out.println(result ? "Add Success" : "Add Failed"); - enforcer.savePolicy(); - return result; - }else if (cmd.hasOption("removePolicy")){ - String policyArgs = cmd.getOptionValue("removePolicy").replace(" ",""); - boolean result = enforcer.removePolicy(policyArgs.split(",")); - System.out.println(result ? "Remove Success" : "Remove Failed"); - enforcer.savePolicy(); - return result; - }else { - System.out.println("Command Error"); - return null; + try { + if(cmd.hasOption("enforce")) { + String enforceArgs = cmd.getOptionValue("enforce").replace(" ",""); + boolean result = enforcer.enforce(enforceArgs.split(",")); + System.out.println(result ? "Allow" : "Ban"); + return result; + } else if (cmd.hasOption("enforceEx")) { + String enforceArgs = cmd.getOptionValue("enforceEx").replace(" ",""); + EnforceResult enforceResult = enforcer.enforceEx(enforceArgs.split(",")); + boolean allow = enforceResult.isAllow(); + if(allow) { + System.out.printf("%s Reason: %s", allow, enforceResult.getExplain()); + } else { + System.out.println(allow); + } + return allow; + }else if (cmd.hasOption("addPolicy")){ + String policyArgs = cmd.getOptionValue("addPolicy").replace(" ",""); + boolean result = enforcer.addPolicy(policyArgs.split(",")); + System.out.println(result ? "Add Success" : "Add Failed"); + enforcer.savePolicy(); + return result; + }else if (cmd.hasOption("removePolicy")){ + String policyArgs = cmd.getOptionValue("removePolicy").replace(" ",""); + boolean result = enforcer.removePolicy(policyArgs.split(",")); + System.out.println(result ? "Remove Success" : "Remove Failed"); + enforcer.savePolicy(); + return result; + }else { + System.out.println("Command Error"); + return null; + } + } catch (Exception e) { + System.out.println("unsupported effect:" + e.getMessage()); + System.exit(0); } + return null; } public static void main(String[] args) throws ParseException { Client cli = new Client(); - Object run = cli.run(args); - System.out.println(run); + Object run = run(args); } } diff --git a/src/main/java/org/casbin/NewEnforcer.java b/src/main/java/org/casbin/NewEnforcer.java new file mode 100644 index 0000000..ebb94e9 --- /dev/null +++ b/src/main/java/org/casbin/NewEnforcer.java @@ -0,0 +1,71 @@ +package org.casbin; + +import org.casbin.jcasbin.main.Enforcer; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class NewEnforcer extends Enforcer { + + public NewEnforcer(String modelPath, String policyFile) { + super(parse(modelPath, ".conf"), parse(policyFile, ".csv")); + } + + public static String parse(String string, String suffix) { + string = string.replace("|","\n"); + boolean isFile = string.endsWith(suffix); + if(suffix.equals(".conf")) { + if(isFile) { + try { + simpleCheck(new String(Files.readAllBytes(Paths.get(string)), StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + simpleCheck(string); + } + } + return isFile ? string : writeToTempFile(string, suffix); + } + + public static String writeToTempFile(String str, String suffix) { + File tempFile = null; + try { + tempFile = File.createTempFile("default", suffix); + tempFile.deleteOnExit(); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))) { + writer.write(str); + } + } catch (IOException e) { + e.printStackTrace(); + } + return tempFile.getAbsolutePath(); + } + + private static void simpleCheck(String fileString) { + fileString = fileString.replace(" ",""); + String[] requiredSubstrings = {"[request_definition]", "[policy_definition]", "[policy_effect]", "[matchers]", "r=", "p=", "e=", "m="}; + List missingSubstrings = new ArrayList<>(); + + for (String substring : requiredSubstrings) { + Pattern pattern = Pattern.compile(Pattern.quote(substring)); + Matcher matcher = pattern.matcher(fileString); + if (!matcher.find()) { + missingSubstrings.add(substring); + } + } + + if(!missingSubstrings.isEmpty()) { + throw new RuntimeException("missing required sections: " + String.join(", ", missingSubstrings)); + } + } +} \ No newline at end of file diff --git a/src/test/java/org/casbin/ClientTest.java b/src/test/java/org/casbin/ClientTest.java index 30a2d6f..f275b66 100644 --- a/src/test/java/org/casbin/ClientTest.java +++ b/src/test/java/org/casbin/ClientTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class ClientTest { @@ -54,4 +55,29 @@ public void testRemovePolicy() throws ParseException { enforcer.savePolicy(); } + @Test + public void testParseString() { + String model = "[request_definition]\n" + + "r = sub, obj, act\n" + + "\n" + + "[policy_definition]\n" + + "p = sub, obj, act\n" + + "\n" + + "[role_definition]\n" + + "g = _, _\n" + + "\n" + + "[policy_effect]\n" + + "e = some(where (p.eft == allow))\n" + + "\n" + + "[matchers]\n" + + "m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act"; + String policy = "p, alice, data1, read\n" + + "p, bob, data2, write\n" + + "p, data2_admin, data2, read\n" + + "p, data2_admin, data2, write\n" + + "g, alice, data2_admin"; + NewEnforcer enforce = new NewEnforcer(model, policy); + assertTrue(enforce.enforce("alice", "data1", "read")); + } + }