Skip to content

Commit 536d194

Browse files
authored
feat: support rbac-with-conditions for jcasbin (#392)
1 parent c7d1c21 commit 536d194

14 files changed

+843
-28
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, dom, obj, act
3+
4+
[policy_definition]
5+
p = sub, dom, obj, act
6+
7+
[role_definition]
8+
g = _, _, _, (_, _)
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
p, alice, domain1, data1, read
2+
p, alice, domain1, data1, write
3+
p, data2_admin, domain2, data2, read
4+
p, data2_admin, domain2, data2, write
5+
p, data3_admin, domain3, data3, read
6+
p, data3_admin, domain3, data3, write
7+
p, data4_admin, domain4, data4, read
8+
p, data4_admin, domain4, data4, write
9+
p, data5_admin, domain5, data5, read
10+
p, data5_admin, domain5, data5, write
11+
p, data6_admin, domain6, data6, read
12+
p, data6_admin, domain6, data6, write
13+
p, data7_admin, domain7, data7, read
14+
p, data7_admin, domain7, data7, write
15+
p, data8_admin, domain8, data8, read
16+
p, data8_admin, domain8, data8, write
17+
18+
g, alice, data2_admin, domain2, 0000-01-01 00:00:00, 0000-01-02 00:00:00
19+
g, alice, data3_admin, domain3, 0000-01-01 00:00:00, 9999-12-30 00:00:00
20+
g, alice, data4_admin, domain4, _, _
21+
g, alice, data5_admin, domain5, _, 9999-12-30 00:00:00
22+
g, alice, data6_admin, domain6, _, 0000-01-02 00:00:00
23+
g, alice, data7_admin, domain7, 0000-01-01 00:00:00, _
24+
g, alice, data8_admin, domain8, 9999-12-30 00:00:00, _
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[role_definition]
8+
g = _, _, (_, _)
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
p, alice, data1, read
2+
p, alice, data1, write
3+
p, data2_admin, data2, read
4+
p, data2_admin, data2, write
5+
p, data3_admin, data3, read
6+
p, data3_admin, data3, write
7+
p, data4_admin, data4, read
8+
p, data4_admin, data4, write
9+
p, data5_admin, data5, read
10+
p, data5_admin, data5, write
11+
p, data6_admin, data6, read
12+
p, data6_admin, data6, write
13+
p, data7_admin, data7, read
14+
p, data7_admin, data7, write
15+
p, data8_admin, data8, read
16+
p, data8_admin, data8, write
17+
18+
g, alice, data2_admin, 0000-01-01 00:00:00, 0000-01-02 00:00:00
19+
g, alice, data3_admin, 0000-01-01 00:00:00, 9999-12-30 00:00:00
20+
g, alice, data4_admin, _, _
21+
g, alice, data5_admin, _, 9999-12-30 00:00:00
22+
g, alice, data6_admin, _, 0000-01-02 00:00:00
23+
g, alice, data7_admin, 0000-01-01 00:00:00, _
24+
g, alice, data8_admin, 9999-12-30 00:00:00, _

src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java

Lines changed: 114 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@
3333
import org.casbin.jcasbin.model.Model;
3434
import org.casbin.jcasbin.persist.*;
3535
import org.casbin.jcasbin.persist.file_adapter.FileAdapter;
36-
import org.casbin.jcasbin.rbac.DomainManager;
37-
import org.casbin.jcasbin.rbac.RoleManager;
36+
import org.casbin.jcasbin.rbac.*;
3837
import org.casbin.jcasbin.util.BuiltInFunctions;
3938
import org.casbin.jcasbin.util.EnforceContext;
4039
import org.casbin.jcasbin.util.Util;
4140

4241
import java.util.*;
4342
import java.util.function.BiPredicate;
43+
import java.util.function.Function;
4444

4545
/**
4646
* CoreEnforcer defines the core functionality of an enforcer.
@@ -55,6 +55,7 @@ public class CoreEnforcer {
5555
Watcher watcher;
5656
Dispatcher dispatcher;
5757
Map<String, RoleManager> rmMap;
58+
Map<String, ConditionalRoleManager> condRmMap;
5859

5960
private boolean enabled;
6061
boolean autoSave;
@@ -67,6 +68,7 @@ public class CoreEnforcer {
6768

6869
void initialize() {
6970
rmMap = new HashMap<>();
71+
condRmMap = new HashMap<>();
7072
eft = new DefaultEffector();
7173
watcher = null;
7274

@@ -287,6 +289,7 @@ public void loadPolicy() {
287289
}
288290
if (autoBuildRoleLinks) {
289291
buildRoleLinks();
292+
buildConditionalRoleLinks();
290293
}
291294
}
292295

@@ -317,6 +320,7 @@ public void loadFilteredPolicy(Object filter) {
317320
}
318321
if (autoBuildRoleLinks) {
319322
buildRoleLinks();
323+
buildConditionalRoleLinks();
320324
}
321325
}
322326

@@ -372,8 +376,31 @@ private void initRmMap() {
372376
for (String ptype : model.model.get("g").keySet()) {
373377
if (rmMap.containsKey(ptype)) {
374378
rmMap.get(ptype).clear();
375-
} else {
376-
addOrUpdateDomainManagerMatching(ptype);
379+
continue;
380+
}
381+
Assertion assertion = model.model.get("g").get(ptype);
382+
int token_length = (assertion.tokens != null ? assertion.tokens.length : 0);
383+
int paramsToken_length = (assertion.paramsTokens != null ? assertion.paramsTokens.length : 0);
384+
if (token_length <= 2 && paramsToken_length == 0) {
385+
assertion.rm = new DomainManager(10);
386+
rmMap.put(ptype, assertion.rm);
387+
}
388+
if (token_length <= 2 && paramsToken_length != 0) {
389+
assertion.condRM =new ConditionalRoleManager(10);
390+
condRmMap.put(ptype, assertion.condRM);
391+
}
392+
if (token_length > 2) {
393+
if (paramsToken_length == 0) {
394+
assertion.rm = new DomainManager(10);
395+
rmMap.put(ptype, assertion.rm);
396+
} else {
397+
assertion.condRM = new ConditionalRoleManager(10);
398+
condRmMap.put(ptype, assertion.condRM);
399+
}
400+
String matchFun = "keyMatch(r_dom, p_dom)";
401+
if (model.model.get("m").get("m").value.contains(matchFun)) {
402+
addNamedDomainMatchingFunc(ptype, "g", BuiltInFunctions::keyMatch);
403+
}
377404
}
378405
}
379406
}
@@ -409,7 +436,9 @@ private void clearRmMap() {
409436
}
410437

411438
for (String ptype : model.model.get("g").keySet()) {
412-
rmMap.get(ptype).clear();
439+
if (rmMap.get(ptype) != null) {
440+
rmMap.get(ptype).clear();
441+
}
413442
}
414443
}
415444

@@ -466,10 +495,21 @@ public void enableAcceptJsonRequest(boolean acceptJsonRequest) {
466495
* role inheritance relations.
467496
*/
468497
public void buildRoleLinks() {
469-
for (RoleManager rm : rmMap.values()) {
470-
rm.clear();
498+
if (!rmMap.isEmpty()) {
499+
for (RoleManager rm : rmMap.values()) {
500+
rm.clear();
501+
}
502+
model.buildRoleLinks(rmMap);
503+
}
504+
}
505+
506+
public void buildConditionalRoleLinks(){
507+
if (!condRmMap.isEmpty()) {
508+
for (ConditionalRoleManager condRm : condRmMap.values()) {
509+
condRm.clear();
510+
}
511+
model.buildConditionalRoleLinks(condRmMap);
471512
}
472-
model.buildRoleLinks(rmMap);
473513
}
474514

475515
/**
@@ -499,8 +539,17 @@ private EnforceResult enforce(String matcher, Object... rvals) {
499539
Assertion ast = entry.getValue();
500540

501541
RoleManager rm = ast.rm;
502-
AviatorFunction aviatorFunction = BuiltInFunctions.GenerateGFunctionClass.generateGFunction(key, rm);
503-
gFunctions.put(key, aviatorFunction);
542+
if (rm != null){
543+
AviatorFunction aviatorFunction = BuiltInFunctions.GenerateGFunctionClass.generateGFunction(key, rm);
544+
gFunctions.put(key, aviatorFunction);
545+
}
546+
547+
ConditionalRoleManager condRM = ast.condRM;
548+
if (condRM != null){
549+
AviatorFunction aviatorFunction = BuiltInFunctions.GenerateConditionalGFunctionClass.generateConditionalGFunction(key, condRM);
550+
gFunctions.put(key, aviatorFunction);
551+
}
552+
504553
}
505554
}
506555
for (AviatorFunction f : gFunctions.values()) {
@@ -736,10 +785,10 @@ public boolean addNamedMatchingFunc(String ptype, String name, BiPredicate<Strin
736785
if (rmMap.containsKey(ptype)) {
737786
DomainManager rm = (DomainManager) rmMap.get(ptype);
738787
rm.addMatchingFunc(name, fn);
739-
clearRmMap();
740-
if (autoBuildRoleLinks) {
741-
buildRoleLinks();
742-
}
788+
// clearRmMap();
789+
// if (autoBuildRoleLinks) {
790+
// buildRoleLinks();
791+
// }
743792
return true;
744793
}
745794
return false;
@@ -761,6 +810,57 @@ public boolean addNamedDomainMatchingFunc(String ptype, String name, BiPredicate
761810
return false;
762811
}
763812

813+
/**
814+
* addNamedLinkConditionFunc Add condition function fn for Link userName->roleName,
815+
* when fn returns true, Link is valid, otherwise invalid
816+
*/
817+
public boolean addNamedLinkConditionFunc(String ptype, String user, String role, Function<String[], Boolean> fn){
818+
if (condRmMap.containsKey(ptype)){
819+
ConditionalRoleManager condRm = condRmMap.get(ptype);
820+
condRm.addLinkConditionFunc(user, role, fn);
821+
return true;
822+
}
823+
return false;
824+
}
825+
826+
/**
827+
* addNamedDomainLinkConditionFunc Add condition function fn for Link userName-> {roleName, domain},
828+
* when fn returns true, Link is valid, otherwise invalid
829+
*/
830+
public boolean addNamedDomainLinkConditionFunc(String ptype, String user, String role, String domain, Function<String[], Boolean> fn) {
831+
if (condRmMap.containsKey(ptype)){
832+
ConditionalRoleManager condRm = condRmMap.get(ptype);
833+
condRm.addDomainLinkConditionFunc(user, role, domain, fn);
834+
return true;
835+
}
836+
return false;
837+
}
838+
839+
/**
840+
* setNamedLinkConditionFuncParams Sets the parameters of the condition function fn for Link userName->roleName
841+
*/
842+
public boolean setNamedLinkConditionFuncParams(String ptype, String user, String role, String... params){
843+
if (condRmMap.containsKey(ptype)){
844+
ConditionalRoleManager condRm = condRmMap.get(ptype);
845+
condRm.setLinkConditionFuncParams(user, role, params);
846+
return true;
847+
}
848+
return false;
849+
}
850+
851+
/**
852+
* setNamedDomainLinkConditionFuncParams Sets the parameters of the condition function fn
853+
* for Link userName->{roleName, domain}
854+
*/
855+
public boolean setNamedDomainLinkConditionFuncParams(String ptype, String user, String role, String domain, String... params){
856+
if (condRmMap.containsKey(ptype)){
857+
ConditionalRoleManager condRm = condRmMap.get(ptype);
858+
condRm.setDomainLinkConditionFuncParams(user, role, domain, params);
859+
return true;
860+
}
861+
return false;
862+
}
863+
764864
private void getRTokens(Map<String, Object> parameters, String rType, Object... rvals) {
765865
String[] requestTokens = model.model.get("r").get(rType).tokens;
766866
if(requestTokens.length != rvals.length) {

0 commit comments

Comments
 (0)