This is an automated email from the ASF dual-hosted git repository. tisonkun pushed a commit to branch fix/conditional-role-matching in repository https://gitbox.apache.org/repos/asf/casbin-jcasbin.git
commit e4356b7083e6cdfa3f40377ff02a102ad80b3ecb Author: tison <[email protected]> AuthorDate: Mon Oct 26 13:58:08 2026 +0800 fix: preserve conditional roles when registering name matching --- .../java/org/casbin/jcasbin/main/CoreEnforcer.java | 17 ++++---- .../jcasbin/rbac/ConditionalRoleManager.java | 21 +++++++--- src/main/java/org/casbin/jcasbin/rbac/Role.java | 14 ++----- .../org/casbin/jcasbin/main/ModelUnitTest.java | 47 ++++++++++++++++++++++ .../casbin/jcasbin/main/RoleManagerUnitTest.java | 17 ++++++++ 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java b/src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java index b1b16f5..119c628 100644 --- a/src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java +++ b/src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java @@ -835,16 +835,15 @@ public class CoreEnforcer { * @return whether the matching function was successfully added. */ public boolean addNamedMatchingFunc(String ptype, String name, BiPredicate<String, String> fn) { - if (rmMap.containsKey(ptype)) { - DomainManager rm = (DomainManager) rmMap.get(ptype); - rm.addMatchingFunc(name, fn); -// clearRmMap(); -// if (autoBuildRoleLinks) { -// buildRoleLinks(); -// } - return true; + RoleManager rm = rmMap.get(ptype); + if (rm instanceof DomainManager) { + ((DomainManager) rm).addMatchingFunc(name, fn); + } else if (rm instanceof DefaultRoleManager) { + ((DefaultRoleManager) rm).addMatchingFunc(name, fn); + } else { + return false; } - return false; + return true; } /** diff --git a/src/main/java/org/casbin/jcasbin/rbac/ConditionalRoleManager.java b/src/main/java/org/casbin/jcasbin/rbac/ConditionalRoleManager.java index 6ab5dc3..d9fd671 100644 --- a/src/main/java/org/casbin/jcasbin/rbac/ConditionalRoleManager.java +++ b/src/main/java/org/casbin/jcasbin/rbac/ConditionalRoleManager.java @@ -34,12 +34,23 @@ public class ConditionalRoleManager extends DefaultRoleManager{ this.domainMatchingFunc = domainMatchingFunc; } + @Override + public void addMatchingFunc(String name, BiPredicate<String, String> matchingFunc) { + Collection<Role> roles = this.allRoles.values(); + this.matchingFunc = matchingFunc; + clear(); + copyRoles(roles); + } + void copyFrom(ConditionalRoleManager other) { - other.allRoles.values().forEach(user -> { - user.roles.keySet().forEach(roleName -> { - addLink(user.getName(), roleName); - getRole(user.getName()).copyLinkConditions(user, roleName); - }); + copyRoles(other.allRoles.values()); + } + + private void copyRoles(Collection<Role> roles) { + roles.forEach(user -> { + user.roles.keySet().forEach(roleName -> addLink(user.getName(), roleName)); + // Conditions can be registered before their links are added. + getRole(user.getName()).copyLinkConditions(user); }); } diff --git a/src/main/java/org/casbin/jcasbin/rbac/Role.java b/src/main/java/org/casbin/jcasbin/rbac/Role.java index 9353dc2..065b138 100644 --- a/src/main/java/org/casbin/jcasbin/rbac/Role.java +++ b/src/main/java/org/casbin/jcasbin/rbac/Role.java @@ -173,17 +173,9 @@ class Role { return linkConditionFuncMap; } - void copyLinkConditions(Role other, String roleName) { - other.linkConditionFuncMap.forEach((key, fn) -> { - if (key.getRoleName().equals(roleName)) { - linkConditionFuncMap.put(key, fn); - } - }); - other.linkConditionFuncParamsMap.forEach((key, params) -> { - if (key.getRoleName().equals(roleName)) { - linkConditionFuncParamsMap.put(key, params); - } - }); + void copyLinkConditions(Role other) { + linkConditionFuncMap.putAll(other.linkConditionFuncMap); + linkConditionFuncParamsMap.putAll(other.linkConditionFuncParamsMap); } void setLinkConditionFuncParams(Role role, String domain, String... params){ diff --git a/src/test/java/org/casbin/jcasbin/main/ModelUnitTest.java b/src/test/java/org/casbin/jcasbin/main/ModelUnitTest.java index 919a96b..5f75594 100644 --- a/src/test/java/org/casbin/jcasbin/main/ModelUnitTest.java +++ b/src/test/java/org/casbin/jcasbin/main/ModelUnitTest.java @@ -278,6 +278,53 @@ public class ModelUnitTest { assertFalse(e.enforce("alice", "tenantB", "data", "read")); } + @DataProvider(name = "conditionalRoleMatching") + public Object[][] conditionalRoleMatching() { + return new Object[][] {{"g", false}, {"g2", false}, {"g", true}, {"g2", true}}; + } + + @Test(dataProvider = "conditionalRoleMatching") + public void testNamedRoleMatchingPreservesConditions(String ptype, boolean withDomain) { + Model m = new Model(); + m.addDef("r", "r", "sub, dom, obj, act"); + m.addDef("p", "p", "sub, dom, obj, act"); + m.addDef("g", ptype, withDomain ? "_, _, _, (_, _)" : "_, _, (_, _)"); + m.addDef("e", "e", "some(where (p.eft == allow))"); + m.addDef("m", "m", ptype + (withDomain ? "(r.sub, p.sub, r.dom)" : "(r.sub, p.sub)") + + " && r.dom == p.dom && r.obj == p.obj && r.act == p.act"); + Enforcer e = new Enforcer(m); + e.addPolicy("admin", "tenantA", "data", "read"); + if (withDomain) { + e.addNamedGroupingPolicy(ptype, "alice", "admin", "tenantA", "deny", "_"); + e.addNamedGroupingPolicy(ptype, "bob*", "admin", "tenantA", "_", "_"); + e.addNamedDomainLinkConditionFunc(ptype, "alice", "admin", "tenantA", params -> "allow".equals(params[0])); + e.setNamedDomainLinkConditionFuncParams(ptype, "alice", "admin", "tenantA", "deny", "_"); + } else { + e.addNamedGroupingPolicy(ptype, "alice", "admin", "deny", "_"); + e.addNamedGroupingPolicy(ptype, "bob*", "admin", "_", "_"); + e.addNamedLinkConditionFunc(ptype, "alice", "admin", params -> "allow".equals(params[0])); + e.setNamedLinkConditionFuncParams(ptype, "alice", "admin", "deny", "_"); + } + assertFalse(e.enforce("alice", "tenantA", "data", "read")); + assertFalse(e.enforce("bob1", "tenantA", "data", "read")); + + assertTrue(e.addNamedMatchingFunc(ptype, "keyMatch", BuiltInFunctions::keyMatch)); + assertFalse(e.enforce("alice", "tenantA", "data", "read")); + assertTrue(e.enforce("bob1", "tenantA", "data", "read")); + assertTrue(e.addNamedMatchingFunc(ptype, "keyMatch", BuiltInFunctions::keyMatch)); + assertFalse(e.enforce("alice", "tenantA", "data", "read")); + + if (withDomain) { + e.setNamedDomainLinkConditionFuncParams(ptype, "alice", "admin", "tenantA", "allow", "_"); + } else { + e.setNamedLinkConditionFuncParams(ptype, "alice", "admin", "allow", "_"); + } + assertTrue(e.enforce("alice", "tenantA", "data", "read")); + assertTrue(e.addNamedMatchingFunc(ptype, "exact", String::equals)); + assertTrue(e.enforce("alice", "tenantA", "data", "read")); + assertFalse(e.enforce("bob1", "tenantA", "data", "read")); + } + @Test public void testRBACModelWithDomainsAtRuntime() { Enforcer e = new Enforcer("examples/rbac_with_domains_model.conf"); diff --git a/src/test/java/org/casbin/jcasbin/main/RoleManagerUnitTest.java b/src/test/java/org/casbin/jcasbin/main/RoleManagerUnitTest.java index 51809eb..ab97293 100644 --- a/src/test/java/org/casbin/jcasbin/main/RoleManagerUnitTest.java +++ b/src/test/java/org/casbin/jcasbin/main/RoleManagerUnitTest.java @@ -18,6 +18,7 @@ package org.casbin.jcasbin.main; import org.casbin.jcasbin.rbac.DefaultRoleManager; +import org.casbin.jcasbin.rbac.ConditionalRoleManager; import org.casbin.jcasbin.rbac.DomainManager; import org.casbin.jcasbin.rbac.RoleManager; import org.casbin.jcasbin.util.BuiltInFunctions; @@ -30,6 +31,22 @@ import java.util.Collections; * @author Yixiang Zhao (@seriouszyx) **/ public class RoleManagerUnitTest { + @Test + public void testMatchingPreservesConditionsRegisteredBeforeLinks() { + ConditionalRoleManager rm = new ConditionalRoleManager(10); + rm.addLinkConditionFunc("alice", "admin", params -> "allow".equals(params[0])); + rm.setLinkConditionFuncParams("alice", "admin", "deny"); + rm.addMatchingFunc("keyMatch", BuiltInFunctions::keyMatch); + rm.addLink("alice", "admin"); + TestUtil.testHasRole(rm, "alice", "admin", false); + + rm.setLinkConditionFuncParams("alice", "admin", "allow"); + TestUtil.testHasRole(rm, "alice", "admin", true); + rm.addMatchingFunc("exact", String::equals); + rm.setLinkConditionFuncParams("alice", "admin", "deny"); + TestUtil.testHasRole(rm, "alice", "admin", false); + } + @Test public void testRole() { RoleManager rm = new DefaultRoleManager(3); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
