Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions src/test/java/org/casbin/jcasbin/main/InOperatorBugTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.casbin.jcasbin.main;

import org.testng.annotations.Test;
import java.io.File;
import java.io.FileWriter;
import static org.testng.Assert.*;

/**
* Test for the 'in' operator bug with tuple literals
* Issue: 'in' of matcher doesn't work: "m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || r.obj in ('data2', 'data3')"
*/
public class InOperatorBugTest {

@Test
public void testInOperatorWithTupleLiterals() throws Exception {
File modelFile = null;
File policyFile = null;

try {
// Create temporary model and policy files
modelFile = File.createTempFile("test_in_op_model", ".conf");
policyFile = File.createTempFile("test_in_op_policy", ".csv");

// Write model with matcher containing "in" operator with tuple literals
String modelText = "[request_definition]\n" +
"r = sub, obj, act\n" +
"\n" +
"[policy_definition]\n" +
"p = sub, obj, act\n" +
"\n" +
"[role_definition]\n" +
"g = _, _\n" +
"\n" +
"[policy_effect]\n" +
"e = some(where (p.eft == allow))\n" +
"\n" +
"[matchers]\n" +
"m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || r.obj in ('data2', 'data3')\n";

try (FileWriter writer = new FileWriter(modelFile)) {
writer.write(modelText);
}

// Write policy
String policyText = "p, reader, data1, read\n" +
"p, writer, data1, write\n" +
"\n" +
"g, alice, reader\n";

try (FileWriter writer = new FileWriter(policyFile)) {
writer.write(policyText);
}

// Create enforcer
Enforcer e = new Enforcer(modelFile.getAbsolutePath(), policyFile.getAbsolutePath());

// Test 1: Should allow access because alice is a reader and wants to read data1
assertTrue(e.enforce("alice", "data1", "read"));

// Test 2: Should allow access because data2 is in the tuple ('data2', 'data3')
// even though alice doesn't have explicit permission for data2
assertTrue(e.enforce("alice", "data2", "read"));

// Test 3: Should allow access because data3 is in the tuple ('data2', 'data3')
// The tuple check bypasses the role-based access control
assertTrue(e.enforce("alice", "data3", "write"));

// Test 4: Should deny access because data4 is not in the tuple and alice is not a writer
assertFalse(e.enforce("alice", "data4", "write"));

// Test 5: Even a user without any role can access data2/data3 due to tuple matching
assertTrue(e.enforce("bob", "data2", "read"));
assertTrue(e.enforce("bob", "data3", "write"));

// Test 6: User without role cannot access data outside the tuple
assertFalse(e.enforce("bob", "data4", "write"));
} finally {
// Clean up temporary files
if (modelFile != null && modelFile.exists()) {
modelFile.delete();
}
if (policyFile != null && policyFile.exists()) {
policyFile.delete();
}
}
}
}