Skip to content

Commit

Permalink
feat: change the instruction mapping to reflection and support manage…
Browse files Browse the repository at this point in the history
…mentApi
  • Loading branch information
liewstar committed Oct 19, 2024
1 parent 8d9c1b3 commit d0f4cc1
Show file tree
Hide file tree
Showing 17 changed files with 610 additions and 126 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `""` |

Expand All @@ -32,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 enforce -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data1" "read"
```
> Allow
> {"allow":true,"explain":null}
```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 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
> {"allow":true,"explain":null}

- 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 enforceEx -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
```
> true Reason: [alice, data2, write]
> {"allow":true,"explain":["data2_admin","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 addPolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
```
> Add Success
> {"allow":true,"explain":null}

- 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 removePolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
```
> Remove Success
> {"allow":true,"explain":null}

2 changes: 2 additions & 0 deletions casbin
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
java -jar target/casbin-java-cli.jar "$@"
5 changes: 5 additions & 0 deletions casbin.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@echo off
setlocal
set JAR_PATH=target\casbin-java-cli.jar
java -jar "%JAR_PATH%" %*
endlocal
2 changes: 1 addition & 1 deletion examples/abac_rule_with_domains_policy.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 11 additions & 0 deletions examples/basic_model.conf
Original file line number Diff line number Diff line change
@@ -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 && r.obj == p.obj && r.act == p.act
2 changes: 2 additions & 0 deletions examples/basic_policy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
p, alice, data1, read
p, bob, data2, write
5 changes: 5 additions & 0 deletions examples/keymatch_policy.csv
Original file line number Diff line number Diff line change
@@ -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)
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@

<packaging>jar</packaging>

<!-- <parent>-->
<!-- <groupId>org.sonatype.oss</groupId>-->
<!-- <artifactId>oss-parent</artifactId>-->
<!-- <version>7</version>-->
<!-- </parent>-->

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Expand Down
133 changes: 62 additions & 71 deletions src/main/java/org/casbin/Client.java
Original file line number Diff line number Diff line change
@@ -1,89 +1,80 @@
package org.casbin;


import org.apache.commons.cli.*;
import org.casbin.jcasbin.exception.CasbinEffectorException;
import org.casbin.jcasbin.main.EnforceResult;
import org.casbin.generate.DynamicClassGenerator;
import org.casbin.jcasbin.util.function.CustomFunction;
import org.casbin.util.Util;

import java.util.*;

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);
public class Client {

CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
public static String run(String... args) {
String result = "";

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);
}
if(args == null || args.length == 0) {
printUsageMessageAndExit("");
}

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;
String commandName = args[0];

CommandLine cmd = getCmd(Arrays.copyOfRange(args, 1, args.length));
String model = cmd.getOptionValue("model");
String policy = cmd.getOptionValue("policy");
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);
}
CommandExecutor commandExecutor = new CommandExecutor(enforcer, commandName, cmd.getArgs());
Object o = commandExecutor.outputResult();
System.out.println(o);
return o.toString();

} 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);
}

private static CommandLine getCmd(String[] args) throws ParseException {
Options options = new Options();

Option option = new Option("AF", "AddFunction", true, "add function");
option.setArgs(1);
option.setRequired(false);
options.addOption(option);

option = new Option("m", "model", true, "the path of the model file or model text");
option.hasArg();
options.addOption(option);

option = new Option("p", "policy", true, "the path of the policy file or policy text");
option.hasArg();
options.addOption(option);

CommandLineParser parser = new DefaultParser();
return parser.parse(options, args);
}
}
94 changes: 94 additions & 0 deletions src/main/java/org/casbin/CommandExecutor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.casbin;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.casbin.jcasbin.main.EnforceResult;
import org.casbin.jcasbin.main.Enforcer;
import org.casbin.resp.ResponseBody;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;

public class CommandExecutor {

private NewEnforcer enforcer;

private String inputMethodName;

private String[] inputVal;

public CommandExecutor(NewEnforcer enforcer, String inputMethodName, String[] inputVal) {
this.enforcer = enforcer;
this.inputMethodName = inputMethodName;
this.inputVal = inputVal;
}

public String outputResult() throws InvocationTargetException, IllegalAccessException, JsonProcessingException {
Class<? extends Enforcer> clazz = enforcer.getClass();
Method[] methods = clazz.getMethods();

ResponseBody responseBody = new ResponseBody(null, null);
for (Method method : methods) {
String methodName = method.getName();
if(methodName.equals(inputMethodName)) {
Type[] genericParameterTypes = method.getGenericParameterTypes();
Object[] convertedParams = new Object[genericParameterTypes.length];
Class<?> returnType = method.getReturnType();

if(genericParameterTypes.length == 3 && genericParameterTypes[0] == String.class && genericParameterTypes[1].getTypeName().equals("java.util.List<java.lang.String>") && genericParameterTypes[2].getTypeName().equals("java.util.List<java.lang.String>")) {
convertedParams[0] = inputVal[0];
convertedParams[1] = Arrays.asList(inputVal[1].split(","));
convertedParams[2] = Arrays.asList(inputVal[2].split(","));
} else if(genericParameterTypes.length == 2 && genericParameterTypes[0].getTypeName().equals("java.util.List<java.lang.String>") && genericParameterTypes[1].getTypeName().equals("java.util.List<java.lang.String>")) {
convertedParams[0] = Arrays.asList(inputVal[0].split(","));
convertedParams[1] = Arrays.asList(inputVal[1].split(","));
} else {
for (int i = 0; i < genericParameterTypes.length; i++) {
if(genericParameterTypes[i] == int.class) {
convertedParams[i] = Integer.valueOf(inputVal[i]);
} else if(genericParameterTypes[i] == String.class) {
convertedParams[i] = inputVal[i];
} else if(genericParameterTypes[i] == Object[].class || genericParameterTypes[i] == String[].class) {
convertedParams[i] = Arrays.copyOfRange(inputVal, i, inputVal.length);
} else if (genericParameterTypes[i] == String[][].class) {
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
String[][] res = new String[arr.length][];
for (int i1 = 0; i1 < res.length; i1++) {
res[i1] = arr[i1].split(",");
}
convertedParams[i] = res;
} else if (genericParameterTypes[i].getTypeName().equals("java.util.List<java.lang.String>")) {
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
convertedParams[i] = Arrays.asList(arr);
} else if (genericParameterTypes[i].getTypeName().equals("java.util.List<java.util.List<java.lang.String>>")) {
List<List<String>> res = new ArrayList<>();
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
for (String s : arr) {
List<String> ans = new ArrayList<>();
Collections.addAll(ans, s.split(","));
res.add(ans);
}
convertedParams[i] = res;
}
}
}

Object invoke = method.invoke(enforcer, convertedParams);
if(returnType == boolean.class) {
responseBody.setAllow((Boolean) invoke);
} else if (returnType == List.class) {
responseBody.setExplain((ArrayList<?>) invoke);
} else if (returnType == EnforceResult.class) {
responseBody.setAllow(((EnforceResult) invoke).isAllow());
responseBody.setExplain((ArrayList<?>) ((EnforceResult) invoke).getExplain());
}
enforcer.savePolicy();
break;
}
}
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(responseBody);
}
}
1 change: 1 addition & 0 deletions src/main/java/org/casbin/NewEnforcer.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/casbin/generate/CustomClassLoader.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading

0 comments on commit d0f4cc1

Please sign in to comment.