Skip to content

Commit c0a9668

Browse files
authored
feat: use reflection and support Management API (#18)
1 parent 49b01e1 commit c0a9668

18 files changed

+365
-699
lines changed

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mvn clean install
2424
| `-p, --policy` | The path of the policy file or policy text | y | Please wrap it with `""` and separate each line with `\|` |
2525
| `-e, --enforce` | Check permissions | n | Please wrap it with `""` |
2626
| `-ex, --enforceEx` | Check permissions and get which policy it is | n | Please wrap it with `""` |
27-
| `-af, --addFuntion` | Add custom funtion | n | Please wrap it with `""` and separate each line with `\|` |
27+
| `-AF, --addFuntion` | Add custom funtion | n | Please wrap it with `""` and separate each line with `\|` |
2828
| `-ap, --addPolicy` | Add a policy rule to the policy file | n | Please wrap it with `""` |
2929
| `-rp, --removePolicy` | Remove a policy rule from the policy file | n | Please wrap it with `""` |
3030

@@ -35,30 +35,30 @@ mvn clean install
3535
```shell
3636
./casbin enforce -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data1" "read"
3737
```
38-
> Allowed
38+
> {"allow":true,"explain":null}
3939
```shell
4040
./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"
4141
```
42-
> Allowed
42+
> {"allow":true,"explain":null}
4343

4444
- Check whether Alice has write permission for data2. If so, display the effective policy.
4545

4646
```shell
47-
./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -ex "alice, data2, write"
47+
./casbin enforceEx -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
4848
```
49-
> true Reason: [alice, data2, write]
49+
> {"allow":true,"explain":["data2_admin","data2","write"]}
5050

5151
- Add a policy to the policy file
5252

5353
```shell
54-
./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -ap "alice, data2, write"
54+
./casbin addPolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
5555
```
56-
> Add Success
56+
> {"allow":true,"explain":null}
5757

5858
- Delete a policy from the policy file
5959

6060
```shell
61-
./casbin -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" -rp "alice,data1,read"
61+
./casbin removePolicy -m "examples/rbac_model.conf" -p "examples/rbac_policy.csv" "alice" "data2" "write"
6262
```
63-
> Remove Success
63+
> {"allow":true,"explain":null}
6464

examples/basic_model.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[policy_effect]
8+
e = some(where (p.eft == allow))
9+
10+
[matchers]
11+
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

examples/basic_policy.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
p, alice, data1, read
2+
p, bob, data2, write

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
<version>1.4</version>
2626
</dependency>
2727

28+
<dependency>
29+
<groupId>com.fasterxml.jackson.core</groupId>
30+
<artifactId>jackson-databind</artifactId>
31+
<version>2.13.4.2</version>
32+
</dependency>
33+
2834
<dependency>
2935
<groupId>junit</groupId>
3036
<artifactId>junit</artifactId>

src/main/java/org/casbin/Client.java

Lines changed: 37 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,15 @@
22

33

44
import org.apache.commons.cli.*;
5-
import org.casbin.command.*;
65
import org.casbin.generate.DynamicClassGenerator;
76
import org.casbin.jcasbin.util.function.CustomFunction;
87
import org.casbin.util.Util;
98

10-
11-
import java.util.Arrays;
12-
import java.util.HashMap;
13-
import java.util.Map;
9+
import java.util.*;
1410

1511

1612
public class Client {
1713

18-
private static final String RBAC_COMMAND = "rbac";
19-
private static final String RBAC_WITH_CONDITION_COMMAND = "rbac_with_condition";
20-
private static final String RBAC_WITH_DOMAINS_COMMAND = "rbac_with_domains";
21-
private static final String ROLEMANAGER_COMMAND = "role_manager";
22-
private static final String MANAGEMENT_COMMAND = "management";
23-
private static final String ENFORCE_COMMAND = "enforce";
24-
25-
private static final Map<String, AbstractCommand> COMMANDS = new HashMap<>();
26-
27-
static {
28-
COMMANDS.put(RBAC_COMMAND, new RBACCommand());
29-
COMMANDS.put(RBAC_WITH_CONDITION_COMMAND, new RBACWithConditionsCommand());
30-
COMMANDS.put(RBAC_WITH_DOMAINS_COMMAND, new RBACWithDomainsCommand());
31-
COMMANDS.put(ROLEMANAGER_COMMAND, new RoleManagerCommand());
32-
COMMANDS.put(MANAGEMENT_COMMAND, new ManagementCommand());
33-
COMMANDS.put(ENFORCE_COMMAND, new EnforceCommand());
34-
}
35-
3614
public static String run(String... args) {
3715
String result = "";
3816

@@ -41,64 +19,25 @@ public static String run(String... args) {
4119
printUsageMessageAndExit("");
4220
}
4321

44-
Options options = new Options();
45-
Option option = new Option("m", "model", true, "the path of the model file or model text");
46-
options.addOption(option);
47-
option = new Option("p", "policy", true, "the path of the policy file or policy text");
48-
options.addOption(option);
49-
option = new Option("af", "addFunction", true, "add custom function");
50-
option.setRequired(false);
51-
options.addOption(option);
52-
53-
boolean hasAddFuntion = false;
54-
for (String arg : args) {
55-
if(arg.equals("-af") || arg.equals("-addFunction")) {
56-
hasAddFuntion = true;
57-
break;
58-
}
59-
}
22+
String commandName = args[0];
6023

61-
CommandLineParser parser = new DefaultParser();
24+
CommandLine cmd = getCmd(Arrays.copyOfRange(args, 1, args.length));
25+
String model = cmd.getOptionValue("model");
26+
String policy = cmd.getOptionValue("policy");
27+
NewEnforcer enforcer = new NewEnforcer(model, policy);
6228

63-
CommandLine cmd = null;
64-
if(hasAddFuntion) {
65-
cmd = parser.parse(options, Arrays.stream(args).limit(7).toArray(String[]::new));
66-
} else {
67-
cmd = parser.parse(options, Arrays.stream(args).limit(5).toArray(String[]::new));
68-
}
6929

70-
if(cmd.hasOption("model") && cmd.hasOption("policy")) {
71-
String model = cmd.getOptionValue("model");
72-
String policy = cmd.getOptionValue("policy");
73-
NewEnforcer enforcer = new NewEnforcer(model, policy);
74-
75-
if (hasAddFuntion) {
76-
String codes = cmd.getOptionValue("addFunction");
77-
String methodName = Util.getMethodName(codes);
78-
CustomFunction customFunction = DynamicClassGenerator.generateClass(methodName, codes);
79-
enforcer.addFunction(methodName, customFunction);
80-
}
81-
82-
String commandName = args[0];
83-
AbstractCommand command = COMMANDS.get(commandName);
84-
85-
86-
87-
if(command != null) {
88-
if(hasAddFuntion) {
89-
result = command.run(enforcer, Arrays.copyOfRange(args, 7, args.length));
90-
} else {
91-
result = command.run(enforcer, Arrays.copyOfRange(args, 5, args.length));
92-
}
93-
// System.exit(0);
94-
} else {
95-
printUsageMessageAndExit(commandName);
96-
}
97-
98-
} else {
99-
new HelpCommand().run();
100-
System.exit(1);
30+
if(cmd.hasOption("AF")) {
31+
String codes = cmd.getOptionValue("AF");
32+
String methodName = Util.getMethodName(codes);
33+
CustomFunction customFunction = DynamicClassGenerator.generateClass(methodName, codes);
34+
enforcer.addFunction(methodName, customFunction);
10135
}
36+
CommandExecutor commandExecutor = new CommandExecutor(enforcer, commandName, cmd.getArgs());
37+
Object o = commandExecutor.outputResult();
38+
System.out.println(o);
39+
return o.toString();
40+
10241
} catch (Exception e) {
10342
e.printStackTrace();
10443
System.exit(1);
@@ -111,12 +50,31 @@ private static void printUsageMessageAndExit(String commandName) throws Exceptio
11150
if (commandName.isEmpty()) {
11251
System.out.println("Error: " + commandName + " not recognised");
11352
}
114-
115-
new HelpCommand().run();
53+
// new HelpCommand().run();
11654
System.exit(1);
11755
}
11856

11957
public static void main(String[] args) throws ParseException {
12058
run(args);
12159
}
60+
61+
private static CommandLine getCmd(String[] args) throws ParseException {
62+
Options options = new Options();
63+
64+
Option option = new Option("AF", "AddFunction", true, "add function");
65+
option.setArgs(1);
66+
option.setRequired(false);
67+
options.addOption(option);
68+
69+
option = new Option("m", "model", true, "the path of the model file or model text");
70+
option.hasArg();
71+
options.addOption(option);
72+
73+
option = new Option("p", "policy", true, "the path of the policy file or policy text");
74+
option.hasArg();
75+
options.addOption(option);
76+
77+
CommandLineParser parser = new DefaultParser();
78+
return parser.parse(options, args);
79+
}
12280
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package org.casbin;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.casbin.jcasbin.main.EnforceResult;
6+
import org.casbin.jcasbin.main.Enforcer;
7+
import org.casbin.resp.ResponseBody;
8+
9+
import java.lang.reflect.InvocationTargetException;
10+
import java.lang.reflect.Method;
11+
import java.lang.reflect.Type;
12+
import java.util.*;
13+
14+
public class CommandExecutor {
15+
16+
private NewEnforcer enforcer;
17+
18+
private String inputMethodName;
19+
20+
private String[] inputVal;
21+
22+
public CommandExecutor(NewEnforcer enforcer, String inputMethodName, String[] inputVal) {
23+
this.enforcer = enforcer;
24+
this.inputMethodName = inputMethodName;
25+
this.inputVal = inputVal;
26+
}
27+
28+
public String outputResult() throws InvocationTargetException, IllegalAccessException, JsonProcessingException {
29+
Class<? extends Enforcer> clazz = enforcer.getClass();
30+
Method[] methods = clazz.getMethods();
31+
32+
ResponseBody responseBody = new ResponseBody(null, null);
33+
for (Method method : methods) {
34+
String methodName = method.getName();
35+
if(methodName.equals(inputMethodName)) {
36+
Type[] genericParameterTypes = method.getGenericParameterTypes();
37+
Object[] convertedParams = new Object[genericParameterTypes.length];
38+
Class<?> returnType = method.getReturnType();
39+
40+
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>")) {
41+
convertedParams[0] = inputVal[0];
42+
convertedParams[1] = Arrays.asList(inputVal[1].split(","));
43+
convertedParams[2] = Arrays.asList(inputVal[2].split(","));
44+
} 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>")) {
45+
convertedParams[0] = Arrays.asList(inputVal[0].split(","));
46+
convertedParams[1] = Arrays.asList(inputVal[1].split(","));
47+
} else {
48+
for (int i = 0; i < genericParameterTypes.length; i++) {
49+
if(genericParameterTypes[i] == int.class) {
50+
convertedParams[i] = Integer.valueOf(inputVal[i]);
51+
} else if(genericParameterTypes[i] == String.class) {
52+
convertedParams[i] = inputVal[i];
53+
} else if(genericParameterTypes[i] == Object[].class || genericParameterTypes[i] == String[].class) {
54+
convertedParams[i] = Arrays.copyOfRange(inputVal, i, inputVal.length);
55+
} else if (genericParameterTypes[i] == String[][].class) {
56+
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
57+
String[][] res = new String[arr.length][];
58+
for (int i1 = 0; i1 < res.length; i1++) {
59+
res[i1] = arr[i1].split(",");
60+
}
61+
convertedParams[i] = res;
62+
} else if (genericParameterTypes[i].getTypeName().equals("java.util.List<java.lang.String>")) {
63+
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
64+
convertedParams[i] = Arrays.asList(arr);
65+
} else if (genericParameterTypes[i].getTypeName().equals("java.util.List<java.util.List<java.lang.String>>")) {
66+
List<List<String>> res = new ArrayList<>();
67+
String[] arr = Arrays.copyOfRange(inputVal, i, inputVal.length);
68+
for (String s : arr) {
69+
List<String> ans = new ArrayList<>();
70+
Collections.addAll(ans, s.split(","));
71+
res.add(ans);
72+
}
73+
convertedParams[i] = res;
74+
}
75+
}
76+
}
77+
78+
Object invoke = method.invoke(enforcer, convertedParams);
79+
if(returnType == boolean.class) {
80+
responseBody.setAllow((Boolean) invoke);
81+
} else if (returnType == List.class) {
82+
responseBody.setExplain((ArrayList<?>) invoke);
83+
} else if (returnType == EnforceResult.class) {
84+
responseBody.setAllow(((EnforceResult) invoke).isAllow());
85+
responseBody.setExplain((ArrayList<?>) ((EnforceResult) invoke).getExplain());
86+
}
87+
enforcer.savePolicy();
88+
break;
89+
}
90+
}
91+
ObjectMapper mapper = new ObjectMapper();
92+
return mapper.writeValueAsString(responseBody);
93+
}
94+
}

src/main/java/org/casbin/command/AbstractCommand.java

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/main/java/org/casbin/command/EnforceCommand.java

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/main/java/org/casbin/command/HelpCommand.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)