diff --git a/examples/haslink_synchronized_model.conf b/examples/haslink_synchronized_model.conf new file mode 100644 index 00000000..33b43c45 --- /dev/null +++ b/examples/haslink_synchronized_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj + +[policy_definition] +p = sub, obj, eft + +[role_definition] +g = _, _ + +[policy_effect] +e = !some(where (p.eft == deny)) + +[matchers] +m = r.sub == p.sub && g(r.obj, p.obj) diff --git a/src/main/java/org/casbin/jcasbin/rbac/DefaultRoleManager.java b/src/main/java/org/casbin/jcasbin/rbac/DefaultRoleManager.java index e85efa7a..0589db90 100644 --- a/src/main/java/org/casbin/jcasbin/rbac/DefaultRoleManager.java +++ b/src/main/java/org/casbin/jcasbin/rbac/DefaultRoleManager.java @@ -176,7 +176,7 @@ public void deleteLink(String name1, String name2, String... domain) { * hasLink determines whether role: name1 inherits role: name2. domain is a prefix to the roles. */ @Override - public boolean hasLink(String name1, String name2, String... domain) { + public synchronized boolean hasLink(String name1, String name2, String... domain) { if (name1.equals(name2) || (this.matchingFunc != null && this.matchingFunc.test(name1, name2))) { return true; } diff --git a/src/test/java/org/casbin/jcasbin/main/EnforcerUnitTest.java b/src/test/java/org/casbin/jcasbin/main/EnforcerUnitTest.java index d442b7ca..0d37556f 100644 --- a/src/test/java/org/casbin/jcasbin/main/EnforcerUnitTest.java +++ b/src/test/java/org/casbin/jcasbin/main/EnforcerUnitTest.java @@ -19,17 +19,21 @@ import org.casbin.jcasbin.model.Model; import org.casbin.jcasbin.persist.Adapter; import org.casbin.jcasbin.persist.file_adapter.FileAdapter; +import org.casbin.jcasbin.util.BuiltInFunctions; import org.casbin.jcasbin.util.EnforceContext; import org.casbin.jcasbin.util.Util; import org.junit.Assert; import org.junit.Test; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CountDownLatch; import static java.util.Arrays.asList; import static org.casbin.jcasbin.main.CoreEnforcer.newModel; @@ -632,6 +636,64 @@ public void testMultiplePolicyDefinitions() { testEnforceWithContext(e, enforceContext, new AbacAPIUnitTest.TestEvalRule("alice", 30), "/data1", "read", true); } + @Test + public void testHasLinkSynchronized(){ + File testingDir = null; + try { + testingDir = Files.createTempDirectory("testingDir").toFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + File f = null; + try { + f = File.createTempFile("policies", null, testingDir); + } catch (IOException e) { + throw new RuntimeException(e); + } + + FileAdapter a = new FileAdapter(f.getAbsolutePath()); + + Enforcer e = new Enforcer("examples/haslink_synchronized_model.conf", a); + + e.enableAutoSave(true); + e.addNamedMatchingFunc("g", "keyMatch4", BuiltInFunctions::keyMatch4); + + // 添加 gs 角色的关系 + String[][] gs = new String[1001][3]; + gs[0] = new String[]{"admin@alice.co", "temp", "alice"}; + for (int i = 0; i < 1000; i++) { + gs[i+1] = new String[]{i + "@alice.co", "temp", "alice"}; + } + e.addGroupingPolicies(gs); + + String[][] policy = {{"alice", "/data", "allow"}}; + e.addPolicies(policy); + e.savePolicy(); + + int n = 100; + CountDownLatch countDownLatch = new CountDownLatch(n); + + for (int i = 0; i < n; i++) { + int finalI = i; + new Thread(() -> { + boolean res = e.enforce("alice", "data"); + if (!res){ + System.out.println("result failure: " + finalI); + } + countDownLatch.countDown(); + }).start(); + } + + try { + countDownLatch.await(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + System.out.println("Done!"); + } + public static class TestSub{ private String name;