Skip to content

Commit

Permalink
feat: remove file extension limit for model and policy files (#26)
Browse files Browse the repository at this point in the history
* fix: processing line breaks in parameters

* refactor: add content format validation for model and policy input

* feat: update README.md
  • Loading branch information
liewstar authored Nov 25, 2024
1 parent 49231e0 commit bad4575
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 49 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mvn clean install
```
> {"allow":true,"explain":null}
```shell
./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"
./casbin enforce -m "[request_definition]\nr = sub, obj, act\n[policy_definition]\np = sub, obj, act\n[role_definition]\ng = _, _\n[policy_effect]\ne = some(where (p.eft == allow))\n[matchers]\nm = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act" -p "p, alice, data1, read\np, bob, data2, write\np, data2_admin, data2, read\np, data2_admin, data2, write\ng, alice, data2_admin" "alice" "data1" "read"
```
> {"allow":true,"explain":null}

Expand Down
13 changes: 8 additions & 5 deletions src/main/java/org/casbin/Client.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.casbin;


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

import java.util.*;


public class Client {

public static String run(String... args) {
Expand All @@ -25,12 +23,18 @@ public static String run(String... args) {
return result;
}

CommandLine cmd = getCmd(Arrays.copyOfRange(args, 1, args.length));
// processing line breaks in parameters
String[] processedArgs = new String[args.length];
processedArgs[0] = args[0];
for (int i = 1; i < args.length; i++) {
processedArgs[i] = args[i] != null ? args[i].replace("\\n", "\n") : null;
}

CommandLine cmd = getCmd(Arrays.copyOfRange(processedArgs, 1, processedArgs.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);
Expand All @@ -50,7 +54,6 @@ public static String run(String... args) {
return result;
}


private static void printUsageMessageAndExit(String commandName) throws Exception {
if (commandName.isEmpty()) {
System.out.println("Error: " + commandName + " not recognised");
Expand Down
91 changes: 48 additions & 43 deletions src/main/java/org/casbin/NewEnforcer.java
Original file line number Diff line number Diff line change
@@ -1,72 +1,77 @@
package org.casbin;

import org.casbin.jcasbin.main.Enforcer;
import org.casbin.jcasbin.util.function.CustomFunction;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NewEnforcer extends Enforcer {

private static final Pattern MODEL_SECTION_PATTERN = Pattern.compile(
"\\[request_definition\\].*?" +
"\\[policy_definition\\].*?" +
"\\[policy_effect\\].*?" +
"\\[matchers\\]",
Pattern.DOTALL
);

private static final Pattern POLICY_LINE_PATTERN = Pattern.compile(
"^\\s*(p|g),.*",
Pattern.MULTILINE
);

public NewEnforcer(String modelPath, String policyFile) {
super(parse(modelPath, ".conf"), parse(policyFile, ".csv"));
super(parse(modelPath, true), parse(policyFile, false));
}

public static String parse(String string, String suffix) {
string = string.replace("|","\n");
boolean isFile = string.endsWith(suffix);
if(suffix.equals(".conf")) {
if(isFile) {
try {
simpleCheck(new String(Files.readAllBytes(Paths.get(string)), StandardCharsets.UTF_8));
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
simpleCheck(string);
public static String parse(String input, boolean isModel) {
if (input == null || input.trim().isEmpty()) {
throw new IllegalArgumentException("Input cannot be null or empty");
}

// Check if input is an existing file
File file = new File(input);
if (file.exists() && file.isFile()) {
return input;
}

// If not a file, validate content format
if (isModel) {
if (!isValidModelContent(input)) {
throw new IllegalArgumentException("Invalid model format. Model must contain required sections: [request_definition], [policy_definition], [policy_effect], and [matchers]");
}
} else {
if (!input.trim().isEmpty() && !isValidPolicyContent(input)) {
throw new IllegalArgumentException("Invalid policy format. Policy must contain lines starting with 'p,' or 'g,' or be empty");
}
}
return isFile ? string : writeToTempFile(string, suffix);

// If content is valid, write to temp file
return writeToTempFile(input);
}

private static boolean isValidModelContent(String content) {
return MODEL_SECTION_PATTERN.matcher(content).find();
}

public static String writeToTempFile(String str, String suffix) {
private static boolean isValidPolicyContent(String content) {
return content.trim().isEmpty() || POLICY_LINE_PATTERN.matcher(content).find();
}

public static String writeToTempFile(String content) {
File tempFile = null;
try {
tempFile = File.createTempFile("default", suffix);
tempFile = File.createTempFile("casbin_temp_", "");
tempFile.deleteOnExit();
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))) {
writer.write(str);
writer.write(content);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Error creating temporary file", e);
}
return tempFile.getAbsolutePath();
}

private static void simpleCheck(String fileString) {
fileString = fileString.replace(" ","");
String[] requiredSubstrings = {"[request_definition]", "[policy_definition]", "[policy_effect]", "[matchers]", "r=", "p=", "e=", "m="};
List<String> missingSubstrings = new ArrayList<>();

for (String substring : requiredSubstrings) {
Pattern pattern = Pattern.compile(Pattern.quote(substring));
Matcher matcher = pattern.matcher(fileString);
if (!matcher.find()) {
missingSubstrings.add(substring);
}
}

if(!missingSubstrings.isEmpty()) {
throw new RuntimeException("missing required sections: " + String.join(", ", missingSubstrings));
}
}
}

0 comments on commit bad4575

Please sign in to comment.