From e8a08817e2bf027a8c9ce8b880c98f8aed692d07 Mon Sep 17 00:00:00 2001 From: Liao Xin <93535922+liewstar@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:05:10 +0800 Subject: [PATCH 1/3] feat: support custom function, Management API and RBAC with Domains API (#10) * feat: Support parsing string * feat: simple check model * feat: update README * feat: support management api and rbac with domain api * feat: update pom.xml * feat: add tests for dynamically compiled code * feat: remove unused models and policies --- README.md | 1 + examples/abac_rule_with_domains_policy.csv | 2 +- examples/keymatch_policy.csv | 5 + pom.xml | 6 - src/main/java/org/casbin/Client.java | 167 +++++--- src/main/java/org/casbin/NewEnforcer.java | 1 + .../org/casbin/command/AbstractCommand.java | 12 + .../java/org/casbin/command/HelpCommand.java | 8 + .../org/casbin/command/ManagementCommand.java | 387 ++++++++++++++++++ .../org/casbin/command/OperationHandle.java | 5 + .../java/org/casbin/command/RBACCommand.java | 10 + .../command/RBACWithConditionsCommand.java | 10 + .../command/RBACWithDomainsCommand.java | 90 ++++ .../casbin/command/RoleManagerCommand.java | 10 + .../casbin/generate/CustomClassLoader.java | 7 + .../generate/DynamicClassGenerator.java | 126 ++++++ .../casbin/generate/JavaSourceFromString.java | 18 + src/main/java/org/casbin/util/Util.java | 49 +++ src/test/java/org/casbin/ClientTest.java | 107 +++-- 19 files changed, 908 insertions(+), 113 deletions(-) create mode 100644 examples/keymatch_policy.csv create mode 100644 src/main/java/org/casbin/command/AbstractCommand.java create mode 100644 src/main/java/org/casbin/command/HelpCommand.java create mode 100644 src/main/java/org/casbin/command/ManagementCommand.java create mode 100644 src/main/java/org/casbin/command/OperationHandle.java create mode 100644 src/main/java/org/casbin/command/RBACCommand.java create mode 100644 src/main/java/org/casbin/command/RBACWithConditionsCommand.java create mode 100644 src/main/java/org/casbin/command/RBACWithDomainsCommand.java create mode 100644 src/main/java/org/casbin/command/RoleManagerCommand.java create mode 100644 src/main/java/org/casbin/generate/CustomClassLoader.java create mode 100644 src/main/java/org/casbin/generate/DynamicClassGenerator.java create mode 100644 src/main/java/org/casbin/generate/JavaSourceFromString.java create mode 100644 src/main/java/org/casbin/util/Util.java diff --git a/README.md b/README.md index a3d3d9f..4c482ec 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ mvn clean install | `-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 `""` | diff --git a/examples/abac_rule_with_domains_policy.csv b/examples/abac_rule_with_domains_policy.csv index 095bebf..beb1ef8 100644 --- a/examples/abac_rule_with_domains_policy.csv +++ b/examples/abac_rule_with_domains_policy.csv @@ -3,4 +3,4 @@ p, r.domain == 'domain1', admin, domain1, data1, write p, r.domain == 'domain2', admin, domain2, data2, read p, r.domain == 'domain2', admin, domain2, data2, write g, alice, admin, domain1 -g, bob, admin, domain2 +g, bob, admin, domain2 \ No newline at end of file diff --git a/examples/keymatch_policy.csv b/examples/keymatch_policy.csv new file mode 100644 index 0000000..39c5966 --- /dev/null +++ b/examples/keymatch_policy.csv @@ -0,0 +1,5 @@ +p, alice, /alice_data/*, GET +p, alice, /alice_data/resource1, POST +p, bob, /alice_data/resource2, GET +p, bob, /bob_data/*, POST +p, cathy, /cathy_data, (GET)|(POST) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0dad7f2..c1c7c7f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,12 +8,6 @@ jar - - - - - - UTF-8 diff --git a/src/main/java/org/casbin/Client.java b/src/main/java/org/casbin/Client.java index d91d53e..b7ff039 100644 --- a/src/main/java/org/casbin/Client.java +++ b/src/main/java/org/casbin/Client.java @@ -1,89 +1,120 @@ package org.casbin; + import org.apache.commons.cli.*; -import org.casbin.jcasbin.exception.CasbinEffectorException; -import org.casbin.jcasbin.main.EnforceResult; +import org.casbin.command.*; +import org.casbin.generate.DynamicClassGenerator; +import org.casbin.jcasbin.util.function.CustomFunction; +import org.casbin.util.Util; + + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; public class Client { - private static void configureOptions(Options options) { - Option[] cliOptions = { - addOption("m", "model", true, "the path of the model file"), - addOption("p", "policy", true, "the path of the policy file"), - addOption("e", "enforce", true, "enforce"), - addOption("ex", "enforceEx", true, "enforceEx"), - addOption("ap", "addPolicy", true, "Add a policy rule to the storage"), - addOption("rp", "removePolicy", true, "Remove a policy rule from the storage") - }; - for (Option option : cliOptions) { - options.addOption(option); - } - } - private static Option addOption(String shortOpt, String longOpt, boolean hasArg, String description) { - return new Option(shortOpt, longOpt, hasArg, description); - } - public static Object run(String[] args) throws ParseException { - Options options = new Options(); - configureOptions(options); + private static final String RBAC_COMMAND = "rbac"; + private static final String RBAC_WITH_CONDITION_COMMAND = "rbac_with_condition"; + private static final String RBAC_WITH_DOMAINS_COMMAND = "rbac_with_domains"; + private static final String ROLEMANAGER_COMMAND = "role_manager"; + private static final String MANAGEMENT_COMMAND = "management"; - CommandLineParser parser = new DefaultParser(); - CommandLine cmd = parser.parse(options, args); + private static final Map COMMANDS = new HashMap<>(); - String model = cmd.getOptionValue("model"); - String policy = cmd.getOptionValue("policy"); - NewEnforcer enforcer = null; - try { - 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); - } + static { + COMMANDS.put(RBAC_COMMAND, new RBACCommand()); + COMMANDS.put(RBAC_WITH_CONDITION_COMMAND, new RBACWithConditionsCommand()); + COMMANDS.put(RBAC_WITH_DOMAINS_COMMAND, new RBACWithDomainsCommand()); + COMMANDS.put(ROLEMANAGER_COMMAND, new RoleManagerCommand()); + COMMANDS.put(MANAGEMENT_COMMAND, new ManagementCommand()); + } + + public static String run(String... args) { + String result = ""; 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()); + if(args == null || args.length == 0) { + printUsageMessageAndExit(""); + } + + Options options = new Options(); + Option option = new Option("m", "model", true, "the path of the model file or model text"); + options.addOption(option); + option = new Option("p", "policy", true, "the path of the policy file or policy text"); + options.addOption(option); + option = new Option("af", "addFunction", true, "add custom function"); + option.setRequired(false); + options.addOption(option); + + boolean hasAddFuntion = false; + for (String arg : args) { + if(arg.equals("-af") || arg.equals("-addFunction")) { + hasAddFuntion = true; + break; + } + } + + CommandLineParser parser = new DefaultParser(); + + CommandLine cmd = null; + if(hasAddFuntion) { + cmd = parser.parse(options, Arrays.stream(args).limit(7).toArray(String[]::new)); + } else { + cmd = parser.parse(options, Arrays.stream(args).limit(5).toArray(String[]::new)); + } + + if(cmd.hasOption("model") && cmd.hasOption("policy")) { + String model = cmd.getOptionValue("model"); + String policy = cmd.getOptionValue("policy"); + NewEnforcer enforcer = new NewEnforcer(model, policy); + + if (hasAddFuntion) { + String codes = cmd.getOptionValue("addFunction"); + String methodName = Util.getMethodName(codes); + CustomFunction customFunction = DynamicClassGenerator.generateClass(methodName, codes); + enforcer.addFunction(methodName, customFunction); + } + + String commandName = args[0]; + AbstractCommand command = COMMANDS.get(commandName); + + + + if(command != null) { + if(hasAddFuntion) { + result = command.run(enforcer, Arrays.copyOfRange(args, 7, args.length)); + } else { + result = command.run(enforcer, Arrays.copyOfRange(args, 5, args.length)); + } +// System.exit(0); } else { - System.out.println(allow); + printUsageMessageAndExit(commandName); } - 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; + + } else { + new HelpCommand().run(); + System.exit(1); } } catch (Exception e) { - System.out.println("unsupported effect:" + e.getMessage()); - System.exit(0); + e.printStackTrace(); + System.exit(1); } - return null; + return result; + } + + + private static void printUsageMessageAndExit(String commandName) throws Exception { + if (commandName.isEmpty()) { + System.out.println("Error: " + commandName + " not recognised"); + } + + new HelpCommand().run(); + System.exit(1); } public static void main(String[] args) throws ParseException { - Client cli = new Client(); - Object run = run(args); + run(args); } } diff --git a/src/main/java/org/casbin/NewEnforcer.java b/src/main/java/org/casbin/NewEnforcer.java index ebb94e9..31736f1 100644 --- a/src/main/java/org/casbin/NewEnforcer.java +++ b/src/main/java/org/casbin/NewEnforcer.java @@ -1,6 +1,7 @@ package org.casbin; import org.casbin.jcasbin.main.Enforcer; +import org.casbin.jcasbin.util.function.CustomFunction; import java.io.BufferedWriter; import java.io.File; diff --git a/src/main/java/org/casbin/command/AbstractCommand.java b/src/main/java/org/casbin/command/AbstractCommand.java new file mode 100644 index 0000000..e4d357a --- /dev/null +++ b/src/main/java/org/casbin/command/AbstractCommand.java @@ -0,0 +1,12 @@ +package org.casbin.command; + +import org.casbin.NewEnforcer; + +public abstract class AbstractCommand { + + protected AbstractCommand() { + + } + + public abstract String run(NewEnforcer enforcer, String... args) throws Exception; +} diff --git a/src/main/java/org/casbin/command/HelpCommand.java b/src/main/java/org/casbin/command/HelpCommand.java new file mode 100644 index 0000000..f8ed0b1 --- /dev/null +++ b/src/main/java/org/casbin/command/HelpCommand.java @@ -0,0 +1,8 @@ +package org.casbin.command; + +public class HelpCommand { + + public void run() { + System.out.println("Usage: java -jar casbin-java-cli.jar rbac|rbac_with_condition|rbac_with_domains|role_manager|management [options]"); + } +} diff --git a/src/main/java/org/casbin/command/ManagementCommand.java b/src/main/java/org/casbin/command/ManagementCommand.java new file mode 100644 index 0000000..9856fb5 --- /dev/null +++ b/src/main/java/org/casbin/command/ManagementCommand.java @@ -0,0 +1,387 @@ +package org.casbin.command; + +import org.apache.commons.cli.*; +import org.casbin.NewEnforcer; + +import java.util.HashMap; + +import java.util.Map; + +import static org.casbin.util.Util.*; + +public class ManagementCommand extends AbstractCommand{ + + private static final String ENFORCE = "enforce"; + private static final String ENFORCE_WITH_MATCHER = "enforceWithMatcher"; + private static final String ENFORCE_EX = "enforceEx"; + private static final String ENFORCE_EX_WITH_MATCHER = "enforceExWithMatcher"; + private static final String BATCH_ENFORCE = "batchEnforce"; + private static final String GET_ALL_SUBJECTS = "getAllSubjects"; + private static final String GET_ALL_NAMED_SUBJECTS = "getAllNamedSubjects"; + private static final String GET_ALL_OBJECTS = "getAllObjects"; + private static final String GET_ALL_NAMED_OBJECTS = "getAllNamedObjects"; + private static final String GET_ALL_ACTIONS = "getAllActions"; + private static final String GET_ALL_NAMED_ACTIONS = "getAllNamedActions"; + private static final String GET_ALL_ROLES = "getAllRoles"; + private static final String GET_ALL_NAMED_ROLES = "getAllNamedRoles"; + private static final String GET_POLICY = "getPolicy"; + private static final String GET_FILTERED_POLICY = "getFilteredPolicy"; + private static final String GET_NAMED_POLICY = "getNamedPolicy"; + private static final String GET_FILTERED_NAMED_POLICY = "getFilteredNamedPolicy"; + private static final String GET_GROUPING_POLICY = "getGroupingPolicy"; + private static final String GET_FILTERED_GROUPING_POLICY = "getFilteredGroupingPolicy"; + private static final String GET_NAMED_GROUPING_POLICY = "getNamedGroupingPolicy"; + private static final String GET_FILTERED_NAMED_GROUPING_POLICY = "getFilteredNamedGroupingPolicy"; + private static final String HAS_POLICY = "hasPolicy"; + private static final String HAS_NAMED_POLICY = "hasNamedPolicy"; + private static final String ADD_POLICY = "addPolicy"; + private static final String ADD_POLICIES = "addPolicies"; + private static final String ADD_NAMED_POLICY = "addNamedPolicy"; + private static final String ADD_NAMED_POLICIES = "addNamedPolicies"; + private static final String REMOVE_POLICY = "removePolicy"; + private static final String REMOVE_POLICIES = "removePolicies"; + private static final String REMOVE_FILTERED_POLICY = "removeFilteredPolicy"; + private static final String REMOVE_NAMED_POLICY = "removeNamedPolicy"; + private static final String REMOVE_NAMED_POLICIES = "removeNamedPolicies"; + private static final String REMOVE_FILTERED_NAMED_POLICY = "removeFilteredNamedPolicy"; + private static final String HAS_GROUPING_POLICY = "hasGroupingPolicy"; + private static final String HAS_NAMED_GROUPING_POLICY = "hasNamedGroupingPolicy"; + private static final String ADD_GROUPING_POLICY = "addGroupingPolicy"; + private static final String ADD_GROUPING_POLICIES = "addGroupingPolicies"; + private static final String ADD_NAMED_GROUPING_POLICY = "addNamedGroupingPolicy"; + private static final String ADD_NAMED_GROUPING_POLICIES = "addNamedGroupingPolicies"; + private static final String REMOVE_GROUPING_POLICY = "removeGroupingPolicy"; + private static final String REMOVE_GROUPING_POLICIES = "removeGroupingPolicies"; + private static final String REMOVE_FILTERED_GROUPING_POLICY = "removeFilteredGroupingPolicy"; + private static final String REMOVE_NAMED_GROUPING_POLICY = "removeNamedGroupingPolicy"; + private static final String REMOVE_FILTERED_NAMED_GROUPING_POLICY = "removeFilteredNamedGroupingPolicy"; + private static final String UPDATE_POLICY = "updatePolicy"; + private static final String LOAD_FILTERED_POLICY = "loadFilteredPolicy"; + private static final String UPDATE_GROUPING_POLICY = "updateGroupingPolicy"; + private static final String UPDATE_NAMED_GROUPING_POLICY = "updateNamedGroupingPolicy"; + + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + Options options = getOptions(); + + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + Map handlers = getStringOperationHandleMap(enforcer); + + try { + CommandLine cmd = parser.parse(options, args); + + String option = cmd.hasOption(ENFORCE) ? ENFORCE : + cmd.hasOption(ENFORCE_WITH_MATCHER) ? ENFORCE_WITH_MATCHER : + cmd.hasOption(ENFORCE_EX) ? ENFORCE_EX : + cmd.hasOption(ENFORCE_EX_WITH_MATCHER) ? ENFORCE_EX_WITH_MATCHER : + cmd.hasOption(BATCH_ENFORCE) ? BATCH_ENFORCE : + cmd.hasOption(GET_ALL_SUBJECTS) ? GET_ALL_SUBJECTS : + cmd.hasOption(GET_ALL_NAMED_SUBJECTS) ? GET_ALL_NAMED_SUBJECTS : + cmd.hasOption(GET_ALL_OBJECTS) ? GET_ALL_OBJECTS : + cmd.hasOption(GET_ALL_NAMED_OBJECTS) ? GET_ALL_NAMED_OBJECTS : + cmd.hasOption(GET_ALL_ACTIONS) ? GET_ALL_ACTIONS : + cmd.hasOption(GET_ALL_NAMED_ACTIONS) ? GET_ALL_NAMED_ACTIONS : + cmd.hasOption(GET_ALL_ROLES) ? GET_ALL_ROLES : + cmd.hasOption(GET_ALL_NAMED_ROLES) ? GET_ALL_NAMED_ROLES : + cmd.hasOption(GET_POLICY) ? GET_POLICY : + cmd.hasOption(GET_FILTERED_POLICY) ? GET_FILTERED_POLICY : + cmd.hasOption(GET_NAMED_POLICY) ? GET_NAMED_POLICY : + cmd.hasOption(GET_FILTERED_NAMED_POLICY) ? GET_FILTERED_NAMED_POLICY : + cmd.hasOption(GET_GROUPING_POLICY) ? GET_GROUPING_POLICY : + cmd.hasOption(GET_FILTERED_GROUPING_POLICY) ? GET_FILTERED_GROUPING_POLICY : + cmd.hasOption(GET_NAMED_GROUPING_POLICY) ? GET_NAMED_GROUPING_POLICY : + cmd.hasOption(GET_FILTERED_NAMED_GROUPING_POLICY) ? GET_FILTERED_NAMED_GROUPING_POLICY : + cmd.hasOption(HAS_POLICY) ? HAS_POLICY : + cmd.hasOption(HAS_NAMED_POLICY) ? HAS_NAMED_POLICY : + cmd.hasOption(ADD_POLICY) ? ADD_POLICY : + cmd.hasOption(ADD_POLICIES) ? ADD_POLICIES : + cmd.hasOption(ADD_NAMED_POLICY) ? ADD_NAMED_POLICY : + cmd.hasOption(ADD_NAMED_POLICIES) ? ADD_NAMED_POLICIES : + cmd.hasOption(REMOVE_POLICY) ? REMOVE_POLICY : + cmd.hasOption(REMOVE_POLICIES) ? REMOVE_POLICIES : + cmd.hasOption(REMOVE_FILTERED_POLICY) ? REMOVE_FILTERED_POLICY : + cmd.hasOption(REMOVE_NAMED_POLICY) ? REMOVE_NAMED_POLICY : + cmd.hasOption(REMOVE_NAMED_POLICIES) ? REMOVE_NAMED_POLICIES : + cmd.hasOption(REMOVE_FILTERED_NAMED_POLICY) ? REMOVE_FILTERED_NAMED_POLICY : + cmd.hasOption(HAS_GROUPING_POLICY) ? HAS_GROUPING_POLICY : + cmd.hasOption(HAS_NAMED_GROUPING_POLICY) ? HAS_NAMED_GROUPING_POLICY : + cmd.hasOption(ADD_GROUPING_POLICY) ? ADD_GROUPING_POLICY : + cmd.hasOption(ADD_GROUPING_POLICIES) ? ADD_GROUPING_POLICIES : + cmd.hasOption(ADD_NAMED_GROUPING_POLICY) ? ADD_NAMED_GROUPING_POLICY : + cmd.hasOption(ADD_NAMED_GROUPING_POLICIES) ? ADD_NAMED_GROUPING_POLICIES : + cmd.hasOption(REMOVE_GROUPING_POLICY) ? REMOVE_GROUPING_POLICY : + cmd.hasOption(REMOVE_GROUPING_POLICIES) ? REMOVE_GROUPING_POLICIES : + cmd.hasOption(REMOVE_FILTERED_GROUPING_POLICY) ? REMOVE_FILTERED_GROUPING_POLICY : + cmd.hasOption(REMOVE_NAMED_GROUPING_POLICY) ? REMOVE_NAMED_GROUPING_POLICY : + cmd.hasOption(REMOVE_FILTERED_NAMED_GROUPING_POLICY) ? REMOVE_FILTERED_NAMED_GROUPING_POLICY : + cmd.hasOption(UPDATE_POLICY) ? UPDATE_POLICY : + cmd.hasOption(LOAD_FILTERED_POLICY) ? LOAD_FILTERED_POLICY : + cmd.hasOption(UPDATE_GROUPING_POLICY) ? UPDATE_GROUPING_POLICY : + cmd.hasOption(UPDATE_NAMED_GROUPING_POLICY) ? UPDATE_NAMED_GROUPING_POLICY : null; + OperationHandle handle = handlers.get(option); + String[] params = cmd.getOptionValues(option); + String res = handle.handle(params); + enforcer.savePolicy(); + System.out.println(res); + return res; + } catch (Exception e) { + System.out.println(e.getMessage()); + formatter.printHelp("management", options); + } + return ""; + } + + private static Map getStringOperationHandleMap(NewEnforcer enforcer) { + Map handlers = new HashMap<>(); + + handlers.put(ENFORCE, params -> String.valueOf(enforcer.enforce(cutString(params[0])))); + handlers.put(ENFORCE_WITH_MATCHER, (params) -> String.valueOf(enforcer.enforceWithMatcher(params[0], cutString(params[1])))); + handlers.put(ENFORCE_EX, (params) -> String.valueOf(enforcer.enforceEx(cutString(params[0])))); + handlers.put(ENFORCE_EX_WITH_MATCHER, (params) -> String.valueOf(enforcer.enforceExWithMatcher(params[0], cutString(params[1])))); + handlers.put(BATCH_ENFORCE, (params) -> String.valueOf(enforcer.batchEnforce(parseNestedLists(params[0])))); + handlers.put(GET_ALL_SUBJECTS, (params) -> String.valueOf(enforcer.getAllSubjects())); + handlers.put(GET_ALL_NAMED_SUBJECTS, (params) -> String.valueOf(enforcer.getAllNamedSubjects(params[0]))); + handlers.put(GET_ALL_OBJECTS, (params) -> String.valueOf(enforcer.getAllObjects())); + handlers.put(GET_ALL_NAMED_OBJECTS, (params) -> String.valueOf(enforcer.getAllNamedObjects(params[0]))); + handlers.put(GET_ALL_ACTIONS, (params) -> String.valueOf(enforcer.getAllActions())); + handlers.put(GET_ALL_NAMED_ACTIONS, (params) -> String.valueOf(enforcer.getAllNamedActions(params[0]))); + handlers.put(GET_ALL_ROLES, (params) -> String.valueOf(enforcer.getAllRoles())); + handlers.put(GET_ALL_NAMED_ROLES, (params) -> String.valueOf(enforcer.getAllNamedRoles(params[0]))); + handlers.put(GET_POLICY, (params) -> String.valueOf(enforcer.getPolicy())); + handlers.put(GET_FILTERED_POLICY, (params) -> String.valueOf(enforcer.getFilteredPolicy(Integer.parseInt(params[0]), cutString(params[1])))); + handlers.put(GET_NAMED_POLICY, (params) -> String.valueOf(enforcer.getNamedPolicy(params[0]))); + handlers.put(GET_FILTERED_NAMED_POLICY, (params) -> String.valueOf(enforcer.getFilteredNamedPolicy(params[0], Integer.parseInt(params[1]), cutString(params[2])))); + handlers.put(GET_GROUPING_POLICY, (params) -> String.valueOf(enforcer.getGroupingPolicy())); + handlers.put(GET_FILTERED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.getFilteredGroupingPolicy(Integer.parseInt(params[0]), cutString(params[1])))); + handlers.put(GET_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.getNamedGroupingPolicy(params[0]))); + handlers.put(GET_FILTERED_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.getFilteredNamedGroupingPolicy(params[0], Integer.parseInt(params[1]), cutString(params[0])))); + handlers.put(HAS_POLICY, (params) -> String.valueOf(enforcer.hasPolicy(cutString(params[0])))); + handlers.put(HAS_NAMED_POLICY, (params) -> String.valueOf(enforcer.hasNamedPolicy(params[0], cutString(params[1])))); + handlers.put(ADD_POLICY, (params) -> String.valueOf(enforcer.addPolicy(cutString(params[0])))); + handlers.put(ADD_POLICIES, (params) -> String.valueOf(enforcer.addPolicies(parseNestedLists(params[0])))); + handlers.put(ADD_NAMED_POLICY, (params) -> String.valueOf(enforcer.addNamedPolicy(params[0], cutString(params[1])))); + handlers.put(ADD_NAMED_POLICIES, (params) -> String.valueOf(enforcer.addNamedPolicies(params[0], parseNestedLists(params[1])))); + handlers.put(REMOVE_POLICY, (params) -> String.valueOf(enforcer.removePolicy(cutString(params[0])))); + handlers.put(REMOVE_POLICIES, (params) -> String.valueOf(enforcer.removePolicies(parseNestedLists(params[0])))); + handlers.put(REMOVE_FILTERED_POLICY, (params) -> String.valueOf(enforcer.removeFilteredPolicy(Integer.parseInt(params[0]), cutString(params[1])))); + handlers.put(REMOVE_NAMED_POLICY, (params) -> String.valueOf(enforcer.removeNamedPolicy(params[0], cutString(params[1])))); + handlers.put(REMOVE_NAMED_POLICIES, (params) -> String.valueOf(enforcer.removeNamedPolicies(params[0], parseNestedLists(params[1])))); + handlers.put(REMOVE_FILTERED_NAMED_POLICY, (params) -> String.valueOf(enforcer.removeFilteredNamedPolicy(params[0], Integer.parseInt(params[1]), cutString(params[0])))); + handlers.put(HAS_GROUPING_POLICY, (params) -> String.valueOf(enforcer.hasGroupingPolicy(cutString(params[0])))); + handlers.put(HAS_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.hasNamedGroupingPolicy(params[0], cutString(params[1])))); + handlers.put(ADD_GROUPING_POLICY, (params) -> String.valueOf(enforcer.addGroupingPolicy(cutString(params[0])))); + handlers.put(ADD_GROUPING_POLICIES, (params) -> String.valueOf(enforcer.addGroupingPolicies(parseNestedLists(params[0])))); + handlers.put(ADD_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.addNamedGroupingPolicy(params[0], cutString(params[1])))); + handlers.put(ADD_NAMED_GROUPING_POLICIES, (params) -> String.valueOf(enforcer.addNamedGroupingPolicies(params[0], parseNestedLists(params[1])))); + handlers.put(REMOVE_GROUPING_POLICY, (params) -> String.valueOf(enforcer.removeGroupingPolicy(params[0]))); + handlers.put(REMOVE_GROUPING_POLICIES, (params) -> String.valueOf(enforcer.removeGroupingPolicies(parseNestedLists(params[0])))); + handlers.put(REMOVE_FILTERED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.removeFilteredGroupingPolicy(Integer.parseInt(params[0]), cutString(params[1])))); + handlers.put(REMOVE_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.removeNamedGroupingPolicy(params[0], cutString(params[1])))); + handlers.put(REMOVE_FILTERED_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.removeFilteredNamedGroupingPolicy(params[0], Integer.parseInt(params[1]), cutString(params[0])))); + handlers.put(UPDATE_POLICY, (params) -> String.valueOf(enforcer.updatePolicy(parseOrdinary(params[0]), parseOrdinary(params[1])))); + //handlers.put(LOAD_FILTERED_POLICY, (params) -> String.valueOf(enforcer.loadFilteredPolicy())); + handlers.put(UPDATE_GROUPING_POLICY, (params) -> String.valueOf(enforcer.updateGroupingPolicy(parseOrdinary(params[0]), parseOrdinary(params[1])))); + handlers.put(UPDATE_NAMED_GROUPING_POLICY, (params) -> String.valueOf(enforcer.updateNamedGroupingPolicy(params[0], parseOrdinary(params[1]), parseOrdinary(params[2])))); + + return handlers; + } + + + private static Options getOptions() { + Options options = new Options(); + + Option option = new Option("e", ENFORCE, false, "enforce access control"); + option.setArgs(1); + options.addOption(option); + + option = new Option("ewm", ENFORCE_WITH_MATCHER, false, "enforce access control with matcher"); + option.setArgs(2); + options.addOption(option); + + option = new Option("ex", ENFORCE_EX, false, "enforce access control exception"); + option.setArgs(1); + options.addOption(option); + + option = new Option("exwm", ENFORCE_EX_WITH_MATCHER, false, "enforce access control exception with matcher"); + option.setArgs(2); + options.addOption(option); + + option = new Option("be", BATCH_ENFORCE, false, "batch enforce access control"); + option.setArgs(1); + options.addOption(option); + + option = new Option("gas", GET_ALL_SUBJECTS, false, "get all subjects"); + options.addOption(option); + + option = new Option("gans", GET_ALL_NAMED_SUBJECTS, false, "get all named subjects"); + option.setArgs(1); + options.addOption(option); + + option = new Option("go", GET_ALL_OBJECTS, false, "get all objects"); + options.addOption(option); + + option = new Option("ganos", GET_ALL_NAMED_OBJECTS, false, "get all named objects"); + option.setArgs(1); + options.addOption(option); + + option = new Option("ga", GET_ALL_ACTIONS, false, "get all actions"); + options.addOption(option); + + option = new Option("ganas", GET_ALL_NAMED_ACTIONS, false, "get all named actions"); + option.setArgs(1); + options.addOption(option); + + option = new Option("grl", GET_ALL_ROLES, false, "get all roles"); + options.addOption(option); + + option = new Option("garnr", GET_ALL_NAMED_ROLES, false, "get all named roles"); + option.setArgs(1); + options.addOption(option); + + option = new Option("gp", GET_POLICY, false, "get policy"); + options.addOption(option); + + option = new Option("gfp", GET_FILTERED_POLICY, false, "get filtered policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("gnp", GET_NAMED_POLICY, false, "get named policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("gfnp", GET_FILTERED_NAMED_POLICY, false, "get filtered named policy"); + option.setArgs(3); + options.addOption(option); + + option = new Option("ggp", GET_GROUPING_POLICY, false, "get grouping policy"); + options.addOption(option); + + option = new Option("gfgp", GET_FILTERED_GROUPING_POLICY, false, "get filtered grouping policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("gnrp", GET_NAMED_GROUPING_POLICY, false, "get named grouping policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("gfngp", GET_FILTERED_NAMED_GROUPING_POLICY, false, "get filtered named grouping policy"); + option.setArgs(3); + options.addOption(option); + + option = new Option("hp", HAS_POLICY, false, "check if a policy exists"); + option.setArgs(1); + options.addOption(option); + + option = new Option("hnp", HAS_NAMED_POLICY, false, "check if a named policy exists"); + option.setArgs(2); + options.addOption(option); + + option = new Option("ap", ADD_POLICY, false, "add a policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("aps", ADD_POLICIES, false, "add multiple policies"); + option.setArgs(0); + options.addOption(option); + + option = new Option("anp", ADD_NAMED_POLICY, false, "add a named policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("ans", ADD_NAMED_POLICIES, false, "add multiple named policies"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rp", REMOVE_POLICY, false, "remove a policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("rps", REMOVE_POLICIES, false, "remove multiple policies"); + option.setArgs(1); + options.addOption(option); + + option = new Option("rfp", REMOVE_FILTERED_POLICY, false, "remove a policy by filter"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rnp", REMOVE_NAMED_POLICY, false, "remove a named policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rnps", REMOVE_NAMED_POLICIES, false, "remove multiple named policies"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rfnp", REMOVE_FILTERED_NAMED_POLICY, false, "remove a named policy by filter"); + option.setArgs(3); + options.addOption(option); + + option = new Option("hgp", HAS_GROUPING_POLICY, false, "check if a grouping policy exists"); + option.setArgs(1); + options.addOption(option); + + option = new Option("hnpgp", HAS_NAMED_GROUPING_POLICY, false, "check if a named grouping policy exists"); + option.setArgs(2); + options.addOption(option); + + option = new Option("agp", ADD_GROUPING_POLICY, false, "add a grouping policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("ags", ADD_GROUPING_POLICIES, false, "add multiple grouping policies"); + option.setArgs(1); + options.addOption(option); + + option = new Option("angp", ADD_NAMED_GROUPING_POLICY, false, "add a named grouping policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("angs", ADD_NAMED_GROUPING_POLICIES, false, "add multiple named grouping policies"); + option.setArgs(2); + options.addOption(option); + + option = new Option("agnex", REMOVE_GROUPING_POLICIES, false, "remove multiple grouping policies"); + option.setArgs(1); + options.addOption(option); + + option = new Option("rgp", REMOVE_GROUPING_POLICY, false, "remove a grouping policy"); + option.setArgs(1); + options.addOption(option); + + option = new Option("rgs", REMOVE_GROUPING_POLICIES, false, "remove multiple grouping policies"); + option.setArgs(1); + options.addOption(option); + + option = new Option("rgfp", REMOVE_FILTERED_GROUPING_POLICY, false, "remove a grouping policy by filter"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rngp", REMOVE_NAMED_GROUPING_POLICY, false, "remove a named grouping policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("rnfngp", REMOVE_FILTERED_NAMED_GROUPING_POLICY, false, "remove a named grouping policy by filter"); + option.setArgs(3); + options.addOption(option); + + option = new Option("up", UPDATE_POLICY, false, "update a policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("lfp", LOAD_FILTERED_POLICY, false, "load a filtered policy"); + options.addOption(option); + + option = new Option("ugp", UPDATE_GROUPING_POLICY, false, "update a grouping policy"); + option.setArgs(2); + options.addOption(option); + + option = new Option("ungp", UPDATE_NAMED_GROUPING_POLICY, false, "update a named grouping policy"); + option.setArgs(3); + options.addOption(option); + + return options; + } + + +} diff --git a/src/main/java/org/casbin/command/OperationHandle.java b/src/main/java/org/casbin/command/OperationHandle.java new file mode 100644 index 0000000..2f2ded0 --- /dev/null +++ b/src/main/java/org/casbin/command/OperationHandle.java @@ -0,0 +1,5 @@ +package org.casbin.command; + +public interface OperationHandle { + String handle(String[] params); +} diff --git a/src/main/java/org/casbin/command/RBACCommand.java b/src/main/java/org/casbin/command/RBACCommand.java new file mode 100644 index 0000000..3a20c36 --- /dev/null +++ b/src/main/java/org/casbin/command/RBACCommand.java @@ -0,0 +1,10 @@ +package org.casbin.command; + +import org.casbin.NewEnforcer; + +public class RBACCommand extends AbstractCommand{ + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + return ""; + } +} diff --git a/src/main/java/org/casbin/command/RBACWithConditionsCommand.java b/src/main/java/org/casbin/command/RBACWithConditionsCommand.java new file mode 100644 index 0000000..e26f0f1 --- /dev/null +++ b/src/main/java/org/casbin/command/RBACWithConditionsCommand.java @@ -0,0 +1,10 @@ +package org.casbin.command; + +import org.casbin.NewEnforcer; + +public class RBACWithConditionsCommand extends AbstractCommand{ + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + return ""; + } +} diff --git a/src/main/java/org/casbin/command/RBACWithDomainsCommand.java b/src/main/java/org/casbin/command/RBACWithDomainsCommand.java new file mode 100644 index 0000000..9ba49b4 --- /dev/null +++ b/src/main/java/org/casbin/command/RBACWithDomainsCommand.java @@ -0,0 +1,90 @@ +package org.casbin.command; + +import org.apache.commons.cli.*; +import org.casbin.NewEnforcer; + +import java.util.HashMap; +import java.util.Map; + + +public class RBACWithDomainsCommand extends AbstractCommand{ + + private static final String GET_USERS_FOR_ROLE_IN_DOMAIN = "getUsersForRoleInDomain"; + private static final String GET_ROLES_FOR_USER_IN_DOMAIN = "getRolesForUserInDomain"; + private static final String GET_PERMISSIONS_FOR_USER_IN_DOMAIN = "getPermissionsForUserInDomain"; + private static final String ADD_ROLE_FOR_USER_IN_DOMAIN = "addRoleForUserInDomain"; + private static final String DELETE_ROLE_FOR_USER_IN_DOMAIN = "deleteRoleForUserInDomain"; + private static final String DELETE_ROLES_FOR_USER_IN_DOMAIN = "deleteRolesForUserInDomain"; + + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + Options options = getOptions(); + + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + + Map handlers = getStringOperationHandleMap(enforcer); + + try { + CommandLine cmd = parser.parse(options, args); + + String option = cmd.hasOption(GET_USERS_FOR_ROLE_IN_DOMAIN) ? GET_USERS_FOR_ROLE_IN_DOMAIN : + cmd.hasOption(GET_ROLES_FOR_USER_IN_DOMAIN) ? GET_ROLES_FOR_USER_IN_DOMAIN : + cmd.hasOption(GET_PERMISSIONS_FOR_USER_IN_DOMAIN) ? GET_PERMISSIONS_FOR_USER_IN_DOMAIN : + cmd.hasOption(ADD_ROLE_FOR_USER_IN_DOMAIN) ? ADD_ROLE_FOR_USER_IN_DOMAIN : + cmd.hasOption(DELETE_ROLE_FOR_USER_IN_DOMAIN) ? DELETE_ROLE_FOR_USER_IN_DOMAIN : DELETE_ROLES_FOR_USER_IN_DOMAIN; + + OperationHandle handle = handlers.get(option); + String[] params = cmd.getOptionValues(option); + String res = handle.handle(params); + enforcer.savePolicy(); + System.out.println(res); + return res; + } catch (Exception e) { + System.out.println(e.getMessage()); + formatter.printHelp("rbac_with_domains", options); + } + return ""; + } + + private static Map getStringOperationHandleMap(NewEnforcer enforcer) { + Map handlers = new HashMap<>(); + handlers.put(GET_USERS_FOR_ROLE_IN_DOMAIN, (params) -> String.valueOf(enforcer.getUsersForRoleInDomain(params[0], params[1]))); + handlers.put(GET_ROLES_FOR_USER_IN_DOMAIN, (params) -> String.valueOf(enforcer.getRolesForUserInDomain(params[0], params[1]))); + handlers.put(GET_PERMISSIONS_FOR_USER_IN_DOMAIN, (params) -> String.valueOf(enforcer.getPermissionsForUserInDomain(params[0], params[1]))); + handlers.put(ADD_ROLE_FOR_USER_IN_DOMAIN, (params) -> String.valueOf(enforcer.addRoleForUserInDomain(params[0], params[1], params[2]))); + handlers.put(DELETE_ROLE_FOR_USER_IN_DOMAIN, (params) -> String.valueOf(enforcer.deleteRoleForUserInDomain(params[0], params[1], params[2]))); + handlers.put(DELETE_ROLES_FOR_USER_IN_DOMAIN, (params) -> String.valueOf(enforcer.deleteRolesForUser(params[0]))); + return handlers; + } + + private static Options getOptions() { + Options options = new Options(); + + Option option = new Option("gu", GET_USERS_FOR_ROLE_IN_DOMAIN, true, "retrieve the users that have a role within a domain"); + option.setArgs(2); + options.addOption(option); + + option = new Option("gr", GET_ROLES_FOR_USER_IN_DOMAIN, true, "retrieves the roles that a user has within a domain"); + option.setArgs(2); + options.addOption(option); + + option = new Option("gp", GET_PERMISSIONS_FOR_USER_IN_DOMAIN, true, "retrieves the permissions for a user or role within a domain"); + option.setArgs(2); + options.addOption(option); + + option = new Option("ar", ADD_ROLE_FOR_USER_IN_DOMAIN, true, "adds a role for a user within a domain. It returns false if the user already has the role (no changes made)"); + option.setArgs(3); + options.addOption(option); + + option = new Option("dr", DELETE_ROLE_FOR_USER_IN_DOMAIN, true, "removes a role for a user within a domain. It returns false if the user does not have the role (no changes made)"); + option.setArgs(3); + options.addOption(option); + + option = new Option("drs", DELETE_ROLES_FOR_USER_IN_DOMAIN, true, "removes all roles for a user within a domain. It returns false if the user does not have any roles (no changes made)"); + option.setArgs(1); + options.addOption(option); + + return options; + } +} diff --git a/src/main/java/org/casbin/command/RoleManagerCommand.java b/src/main/java/org/casbin/command/RoleManagerCommand.java new file mode 100644 index 0000000..d039021 --- /dev/null +++ b/src/main/java/org/casbin/command/RoleManagerCommand.java @@ -0,0 +1,10 @@ +package org.casbin.command; + +import org.casbin.NewEnforcer; + +public class RoleManagerCommand extends AbstractCommand{ + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + return ""; + } +} diff --git a/src/main/java/org/casbin/generate/CustomClassLoader.java b/src/main/java/org/casbin/generate/CustomClassLoader.java new file mode 100644 index 0000000..f21f21d --- /dev/null +++ b/src/main/java/org/casbin/generate/CustomClassLoader.java @@ -0,0 +1,7 @@ +package org.casbin.generate; + +public class CustomClassLoader extends ClassLoader { + public Class defineClass(String name, byte[] b) { + return super.defineClass(name, b, 0, b.length); + } +} diff --git a/src/main/java/org/casbin/generate/DynamicClassGenerator.java b/src/main/java/org/casbin/generate/DynamicClassGenerator.java new file mode 100644 index 0000000..8f18670 --- /dev/null +++ b/src/main/java/org/casbin/generate/DynamicClassGenerator.java @@ -0,0 +1,126 @@ +package org.casbin.generate; + + +import org.casbin.jcasbin.util.function.CustomFunction; + +import javax.tools.*; +import java.io.*; +import java.net.URI; +import java.util.*; + + +import static org.casbin.util.Util.*; + +public class DynamicClassGenerator { + + public static CustomFunction generateClass(String methodName, String methodCodes) { + String className = "CustomFunc"; + int argsNum = getArgsNum(methodCodes); + StringBuilder sb = new StringBuilder(); + + String codeSnippetOne = "import com.googlecode.aviator.runtime.type.AviatorBoolean;\n" + + "import com.googlecode.aviator.runtime.type.AviatorObject;\n" + + "import org.casbin.jcasbin.util.function.CustomFunction;\n" + + "import java.util.Map;\n" + + "import java.util.regex.Pattern;" + + "\n" + + " public class " + className + " extends CustomFunction {\n" + + " @Override\n" + + " public AviatorObject call(Map env, "; + + sb.append(codeSnippetOne); + for (int i = 0; i < argsNum; i++) { + if(i == argsNum - 1) { + sb.append("AviatorObject arg").append(i + 1); + } else { + sb.append("AviatorObject arg").append(i + 1).append(","); + } + } + sb.append(") {"); + + for (int i = 0; i < argsNum; i++) { + sb.append("String obj").append(i + 1).append("=getStringValue(arg").append(i + 1).append(", env);\n"); + } + + StringBuilder args = new StringBuilder(); + for (int i = 0; i < argsNum; i++) { + if(i == argsNum - 1) { + args.append("obj").append(i + 1); + } else { + args.append("obj").append(i + 1).append(","); + } + + } + sb.append("return AviatorBoolean.valueOf(").append(methodName).append("(").append(args).append("));}\n"); + sb.append("@Override\n" + "public String getName() {\n" + " return \"").append(methodName).append("\";\n").append("}\n"); + + sb.append("public static final String getStringValue(final AviatorObject arg,\n" + + " final Map env) {\n" + + " String result = null;\n" + + " final Object value = arg.getValue(env);\n" + + " if (value instanceof Character) {\n" + + " result = value.toString();\n" + + " } else {\n" + + " result = (String) value;\n" + + " }\n" + + " return result;\n" + + " }\n"); + + sb.append(methodCodes); + sb.append("}"); + try { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + DiagnosticCollector diagnostics = new DiagnosticCollector<>(); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + + InMemoryJavaFileManager customFileManager = new InMemoryJavaFileManager(fileManager); + + JavaFileObject sourceFile = new JavaSourceFromString(className, sb.toString()); + Iterable compilationUnits = Collections.singletonList(sourceFile); + + JavaCompiler.CompilationTask task = compiler.getTask(null, customFileManager, diagnostics, null, null, compilationUnits); + boolean success = task.call(); + if(success) { + byte[] classBytes = customFileManager.getClassBytes(className); + if(classBytes != null) { + CustomClassLoader loader = new CustomClassLoader(); + Class loadedClass = loader.defineClass(className, classBytes); + CustomFunction customFunction = (CustomFunction) loadedClass.getDeclaredConstructor().newInstance(); + return customFunction; + } + } + return null; + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + static class InMemoryJavaFileManager extends ForwardingJavaFileManager { + private final Map classBytesMap = new HashMap<>(); + + InMemoryJavaFileManager(StandardJavaFileManager fileManager) { + super(fileManager); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + classBytesMap.put(className, outputStream); + return new SimpleJavaFileObject(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind) { + @Override + public OutputStream openOutputStream() { + return outputStream; + } + }; + } + + public byte[] getClassBytes(String className) { + ByteArrayOutputStream outputStream = classBytesMap.get(className); + return outputStream != null ? outputStream.toByteArray() : null; + } + } +} + + diff --git a/src/main/java/org/casbin/generate/JavaSourceFromString.java b/src/main/java/org/casbin/generate/JavaSourceFromString.java new file mode 100644 index 0000000..cc5b327 --- /dev/null +++ b/src/main/java/org/casbin/generate/JavaSourceFromString.java @@ -0,0 +1,18 @@ +package org.casbin.generate; + +import javax.tools.SimpleJavaFileObject; +import java.net.URI; + +public class JavaSourceFromString extends SimpleJavaFileObject { + private final String code; + + JavaSourceFromString(String name, String code) { + super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } +} \ No newline at end of file diff --git a/src/main/java/org/casbin/util/Util.java b/src/main/java/org/casbin/util/Util.java new file mode 100644 index 0000000..62fe032 --- /dev/null +++ b/src/main/java/org/casbin/util/Util.java @@ -0,0 +1,49 @@ +package org.casbin.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Util { + public static List> parseNestedLists(String input) { + String innerString = input.substring(1, input.length() - 1); + String[] items = innerString.split("\\],\\["); + List> result = new ArrayList<>(); + for (String item : items) { + String cleanItem = item.replace("[", "").replace("]", ""); + List subList = Arrays.asList(cleanItem.split(",")); + result.add(subList); + } + return result; + } + + public static List parseOrdinary(String input) { + String trimmedInput = input.substring(1, input.length() - 1); + return Arrays.asList(trimmedInput.split(",")); + } + + public static String getMethodName(String methodCodes) { + String regex = "\\b(\\w+)\\s*\\("; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(methodCodes); + return matcher.find() ? matcher.group(1) : null; + } + + public static String[] cutString(String str) { + return str.replace(" ","").split(","); + } + + public static int getArgsNum(String methodCodes) { + String regex = "\\(([^)]*)\\)"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(methodCodes); + if (matcher.find()) { + String args = matcher.group(1); + String[] argList = args.split(","); + return argList.length; + } + return 0; + } +} diff --git a/src/test/java/org/casbin/ClientTest.java b/src/test/java/org/casbin/ClientTest.java index f275b66..bd60c50 100644 --- a/src/test/java/org/casbin/ClientTest.java +++ b/src/test/java/org/casbin/ClientTest.java @@ -1,58 +1,41 @@ package org.casbin; import org.apache.commons.cli.ParseException; -import org.casbin.jcasbin.main.Enforcer; import org.junit.Test; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class ClientTest { @Test public void testRBAC() throws ParseException { - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","alice,data1,read"}), true); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","alice,data1,write"}), false); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","alice,data2,read"}), true); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","alice,data2,write"}), true); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","bob,data1,read"}), false); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","bob,data1,write"}), false); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","bob,data2,read"}), false); - assertEquals(Client.run(new String[]{"-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv","-e","bob,data2,write"}), true); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "alice,data1,read"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "alice,data1,write"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "alice,data2,read"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "alice,data2,write"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "bob,data1,read"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "bob,data1,write"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "bob,data2,read"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "-e", "bob,data2,write"}), "true"); } @Test public void testABAC() throws ParseException { - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain1,data1,read"}), true); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain1,data1,write"}), true); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain2,data1,read"}), false); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain2,data1,write"}), false); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain1,data2,read"}), false); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain1,data2,write"}), false); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain2,data2,read"}), true); - assertEquals(Client.run(new String[]{"-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain2,data2,read"}), true); - } + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain1,data1,read"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain1,data1,write"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain2,data1,read"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","alice,domain2,data1,write"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain1,data2,read"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain1,data2,write"}), "false"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain2,data2,read"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-e","bob,domain2,data2,read"}), "true"); - @Test - public void testAddPolicy() throws ParseException { - String modelPath = "examples/rbac_model.conf"; - String policyPath = "examples/rbac_policy.csv"; - Enforcer enforcer = new Enforcer(modelPath, policyPath); - String policy = "aliceTest,data,read"; - assertEquals(Client.run(new String[]{"-m",modelPath,"-p",policyPath,"-ap",policy}), true); - enforcer.removePolicy(policy.split(",")); - enforcer.savePolicy(); } @Test - public void testRemovePolicy() throws ParseException { - String modelPath = "examples/rbac_model.conf"; - String policyPath = "examples/rbac_policy.csv"; - Enforcer enforcer = new Enforcer(modelPath, policyPath); - String policy = "alice,data1,read"; - assertEquals(Client.run(new String[]{"-m",modelPath,"-p",policyPath,"-rp",policy}), true); - enforcer.addPolicy(policy.split(",")); - enforcer.savePolicy(); + public void testAddAndRemovePolicy() throws ParseException { + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-ap","alice,domain1,data1,read"}), "true"); + assertEquals(Client.run(new String[]{"management","-m","examples/abac_rule_with_domains_model.conf","-p","examples/abac_rule_with_domains_policy.csv","-rp","alice,domain1,data1,read"}), "true"); } @Test @@ -76,8 +59,56 @@ public void testParseString() { "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")); + assertEquals(Client.run(new String[]{"management","-m",model,"-p",policy,"-e","alice,data1,read"}), "true"); } + @Test + public void testCustomFunction() throws ParseException { + String methodName = "keyMatchTest"; + String model = "[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) && regexMatch(r.act, p.act)\n"; + String func = "public static boolean "+methodName+"(String key1, String key2) {\n" + + " int i = key2.indexOf('*');\n" + + " if (i == -1) {\n" + + " return key1.equals(key2);\n" + + " }\n" + + "\n" + + " if (key1.length() > i) {\n" + + " return key1.substring(0, i).equals(key2.substring(0, i));\n" + + " }\n" + + " return key1.equals(key2.substring(0, i));\n" + + " }"; + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /alice_data/resource1, GET"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /alice_data/resource1, POST"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /alice_data/resource2, GET"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /alice_data/resource2, POST"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /bob_data/resource1, GET"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /bob_data/resource1, POST"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /bob_data/resource2, GET"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "alice, /bob_data/resource2, POST"}), "false"); + + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /alice_data/resource1, GET"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /alice_data/resource1, POST"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /alice_data/resource2, GET"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /alice_data/resource2, POST"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /bob_data/resource1, GET"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /bob_data/resource1, POST"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /bob_data/resource2, GET"}), "false"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "bob, /bob_data/resource2, POST"}), "true"); + + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "cathy, /cathy_data, GET"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "cathy, /cathy_data, POST"}), "true"); + assertEquals(Client.run(new String[]{"management", "-m", model, "-p", "examples/keymatch_policy.csv", "-af", func, "-e", "cathy, /cathy_data, DELETE"}), "false"); + + } + } From eee4fe93a964af70bf94f3566c9f04378e74496a Mon Sep 17 00:00:00 2001 From: Liao Xin <93535922+liewstar@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:36:38 +0800 Subject: [PATCH 2/3] feat: Use "casbin" command instead of "java -jar target/casbin-java-cli.jar" command (#14) * feat: Use "casbin" command instead of "java -jar target/casbin-java-cli.jar" command * fix: remove .sh suffix --- README.md | 10 +++++----- casbin | 2 ++ casbin.cmd | 5 +++++ 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100755 casbin create mode 100644 casbin.cmd diff --git a/README.md b/README.md index 4c482ec..9921991 100644 --- a/README.md +++ b/README.md @@ -33,32 +33,32 @@ mvn clean install - 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" + ./casbin -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" + ./casbin -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" + ./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -ex "alice, 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" + ./casbin -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" + ./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -rp "alice,data1,read" ``` > Remove Success diff --git a/casbin b/casbin new file mode 100755 index 0000000..00c2157 --- /dev/null +++ b/casbin @@ -0,0 +1,2 @@ +#!/bin/sh +java -jar target/casbin-java-cli.jar "$@" \ No newline at end of file diff --git a/casbin.cmd b/casbin.cmd new file mode 100644 index 0000000..70124d9 --- /dev/null +++ b/casbin.cmd @@ -0,0 +1,5 @@ +@echo off +setlocal +set JAR_PATH=target\casbin-java-cli.jar +java -jar "%JAR_PATH%" %* +endlocal \ No newline at end of file From 49b01e16a5cdedb280f276af4035b78b6b440fc9 Mon Sep 17 00:00:00 2001 From: Liao Xin <93535922+liewstar@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:28:20 +0800 Subject: [PATCH 3/3] fix: add enforce command (#15) --- README.md | 8 ++++---- src/main/java/org/casbin/Client.java | 2 ++ .../java/org/casbin/command/EnforceCommand.java | 15 +++++++++++++++ src/test/java/org/casbin/ClientTest.java | 5 +++++ 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/casbin/command/EnforceCommand.java diff --git a/README.md b/README.md index 9921991..5726c14 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,13 @@ mvn clean install - Check whether Alice has read permission on data1 ```shell - ./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -e "alice, data1, read" + ./casbin enforce -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data1" "read" ``` - > Allow + > Allowed ```shell - ./casbin -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" + ./casbin enforce -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" "alice" "data1" "read" ``` - > Allow + > Allowed - Check whether Alice has write permission for data2. If so, display the effective policy. diff --git a/src/main/java/org/casbin/Client.java b/src/main/java/org/casbin/Client.java index b7ff039..bb7e872 100644 --- a/src/main/java/org/casbin/Client.java +++ b/src/main/java/org/casbin/Client.java @@ -20,6 +20,7 @@ public class Client { private static final String RBAC_WITH_DOMAINS_COMMAND = "rbac_with_domains"; private static final String ROLEMANAGER_COMMAND = "role_manager"; private static final String MANAGEMENT_COMMAND = "management"; + private static final String ENFORCE_COMMAND = "enforce"; private static final Map COMMANDS = new HashMap<>(); @@ -29,6 +30,7 @@ public class Client { COMMANDS.put(RBAC_WITH_DOMAINS_COMMAND, new RBACWithDomainsCommand()); COMMANDS.put(ROLEMANAGER_COMMAND, new RoleManagerCommand()); COMMANDS.put(MANAGEMENT_COMMAND, new ManagementCommand()); + COMMANDS.put(ENFORCE_COMMAND, new EnforceCommand()); } public static String run(String... args) { diff --git a/src/main/java/org/casbin/command/EnforceCommand.java b/src/main/java/org/casbin/command/EnforceCommand.java new file mode 100644 index 0000000..04c16e8 --- /dev/null +++ b/src/main/java/org/casbin/command/EnforceCommand.java @@ -0,0 +1,15 @@ +package org.casbin.command; + +import org.casbin.NewEnforcer; + +public class EnforceCommand extends AbstractCommand { + @Override + public String run(NewEnforcer enforcer, String... args) throws Exception { + String subject = args[0]; + String object = args[1]; + String action = args[2]; + boolean res = enforcer.enforce(subject, object, action); + System.out.println(res ? "Allowed" : "Denied"); + return String.valueOf(res); + } +} diff --git a/src/test/java/org/casbin/ClientTest.java b/src/test/java/org/casbin/ClientTest.java index bd60c50..125a541 100644 --- a/src/test/java/org/casbin/ClientTest.java +++ b/src/test/java/org/casbin/ClientTest.java @@ -111,4 +111,9 @@ public void testCustomFunction() throws ParseException { } + @Test + public void testEnforce() { + assertEquals(Client.run(new String[]{"enforce","-m","examples/rbac_model.conf","-p","examples/rbac_policy.csv", "alice", "data1", "read"}), "true"); + } + }