Skip to content

Commit

Permalink
fix: update getImplicitPermissionsForUser API
Browse files Browse the repository at this point in the history
issue: casbin#174

Signed-off-by: tsund <[email protected]>
  • Loading branch information
shink committed Jun 11, 2021
1 parent be38837 commit 4d91e84
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 78 deletions.
5 changes: 4 additions & 1 deletion examples/rbac_with_pattern_policy.csv
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ g, cathy, pen_admin

g2, /book/*, book_group

g2, /book/:id, book_group
g2, /pen/:id, pen_group

g2, /book2/{id}, book_group
g2, /pen2/{id}, pen_group
g2, /pen2/{id}, pen_group
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2018 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.casbin.jcasbin.exception;

public class CasbinNameNotExistException extends RuntimeException {

public CasbinNameNotExistException(String message) {
super(message);
}

}
72 changes: 57 additions & 15 deletions src/main/java/org/casbin/jcasbin/main/CoreEnforcer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@
import org.casbin.jcasbin.model.Assertion;
import org.casbin.jcasbin.model.FunctionMap;
import org.casbin.jcasbin.model.Model;
import org.casbin.jcasbin.persist.Adapter;
import org.casbin.jcasbin.persist.Dispatcher;
import org.casbin.jcasbin.persist.WatcherEx;
import org.casbin.jcasbin.persist.FilteredAdapter;
import org.casbin.jcasbin.persist.Watcher;
import org.casbin.jcasbin.persist.*;
import org.casbin.jcasbin.rbac.DefaultRoleManager;
import org.casbin.jcasbin.rbac.RoleManager;
import org.casbin.jcasbin.util.BuiltInFunctions;
Expand All @@ -51,8 +47,8 @@ public class CoreEnforcer {

Adapter adapter;
Watcher watcher;
RoleManager rm;
Dispatcher dispatcher;
Map<String, RoleManager> rmMap;

private boolean enabled;
boolean autoSave;
Expand All @@ -67,14 +63,15 @@ public class CoreEnforcer {
int modelModCount;

void initialize() {
rm = new DefaultRoleManager(10);
rmMap = new HashMap<>();
eft = new DefaultEffector();
watcher = null;

enabled = true;
autoSave = true;
autoBuildRoleLinks = true;
dispatcher = null;
initRmMap();
}

/**
Expand Down Expand Up @@ -192,21 +189,21 @@ public void setDispatcher(Dispatcher dispatcher) {
}

/**
* getRoleManager gets the current role manager.
* getRmMap gets the current role manager map.
*
* @return the role manager of the enforcer.
* @return the role manager map of the enforcer.
*/
public RoleManager getRoleManager() {
return rm;
public Map<String, RoleManager> getRmMap() {
return rmMap;
}

/**
* SetRoleManager sets the current role manager.
* setRoleManager sets the current role manager for g.
*
* @param rm the role manager.
*/
public void setRoleManager(RoleManager rm) {
this.rm = rm;
setRoleManager("g", rm);
}

/**
Expand All @@ -233,6 +230,7 @@ public void loadPolicy() {
adapter.loadPolicy(model);
model.sortPoliciesByPriority();

clearRmMap();
model.printPolicy();
if (autoBuildRoleLinks) {
buildRoleLinks();
Expand All @@ -258,6 +256,8 @@ public void loadFilteredPolicy(Object filter) {
e.printStackTrace();
}
model.sortPoliciesByPriority();

initRmMap();
model.printPolicy();
if (autoBuildRoleLinks) {
buildRoleLinks();
Expand Down Expand Up @@ -295,6 +295,46 @@ public void savePolicy() {
}
}

/**
* setRoleManager sets role manager for ptype.
*
* @param ptype the policy type, can be "g", "g2", "g3", ..
* @param rm the role manager.
*/
public void setRoleManager(String ptype, RoleManager rm) {
rmMap.put(ptype, rm);
}

/**
* initRmMap initializes rmMap.
*/
private void initRmMap() {
if (!model.model.containsKey("g")) {
return;
}

for (String ptype : model.model.get("g").keySet()) {
if (rmMap.containsKey(ptype)) {
rmMap.get(ptype).clear();
} else {
rmMap.put(ptype, new DefaultRoleManager(10));
}
}
}

/**
* clearRmMap clears rmMap.
*/
private void clearRmMap() {
if (!model.model.containsKey("g")) {
return;
}

for (String ptype : model.model.get("g").keySet()) {
rmMap.get(ptype).clear();
}
}

/**
* enableEnforce changes the enforcing state of Casbin, when Casbin is
* disabled, all access will be allowed by the enforce() function.
Expand Down Expand Up @@ -339,8 +379,10 @@ public void enableAutoBuildRoleLinks(boolean autoBuildRoleLinks) {
* role inheritance relations.
*/
public void buildRoleLinks() {
rm.clear();
model.buildRoleLinks(rm);
for (RoleManager rm : rmMap.values()) {
rm.clear();
}
model.buildRoleLinks(rmMap);
}

/**
Expand Down
109 changes: 80 additions & 29 deletions src/main/java/org/casbin/jcasbin/main/Enforcer.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@

package org.casbin.jcasbin.main;

import org.casbin.jcasbin.exception.CasbinNameNotExistException;
import org.casbin.jcasbin.model.Assertion;
import org.casbin.jcasbin.model.FunctionMap;
import org.casbin.jcasbin.model.Model;
import org.casbin.jcasbin.persist.Adapter;
import org.casbin.jcasbin.persist.file_adapter.FileAdapter;
import org.casbin.jcasbin.rbac.RoleManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;

/**
* Enforcer = ManagementEnforcer + RBAC API.
Expand Down Expand Up @@ -115,10 +116,7 @@ public Enforcer(String modelPath, String policyFile, boolean enableLog) {
public List<String> getRolesForUser(String name) {
try {
return model.model.get("g").get("g").rm.getRoles(name);
} catch (IllegalArgumentException e) {
if (!"error: name does not exist".equals(e.getMessage())) {
throw e;
}
} catch (CasbinNameNotExistException ignored) {
}
return Collections.emptyList();
}
Expand All @@ -132,10 +130,7 @@ public List<String> getRolesForUser(String name) {
public List<String> getUsersForRole(String name) {
try {
return model.model.get("g").get("g").rm.getUsers(name);
} catch (IllegalArgumentException e) {
if (!"error: name does not exist".equals(e.getMessage())) {
throw e;
}
} catch (CasbinNameNotExistException ignored) {
}
return Collections.emptyList();
}
Expand Down Expand Up @@ -333,11 +328,28 @@ public boolean deletePermissionsForUser(String user) {
/**
* getPermissionsForUser gets permissions for a user or role.
*
* @param user the user.
* @param user the user.
* @param domain domain.
* @return the permissions, a permission is usually like (obj, act). It is actually the rule without the subject.
*/
public List<List<String>> getPermissionsForUser(String user) {
return getFilteredPolicy(0, user);
public List<List<String>> getPermissionsForUser(String user, String... domain) {
List<List<String>> permissions = new ArrayList<>();
for (Map.Entry<String, Assertion> entry : model.model.get("p").entrySet()) {
String ptype = entry.getKey();
Assertion ast = entry.getValue();
String[] args = new String[ast.tokens.length];
args[0] = user;

if (domain.length > 0) {
int index = getDomainIndex(ptype);
if (index < ast.tokens.length) {
args[index] = domain[0];
}
}
permissions.addAll(getFilteredPolicy(0, args));
}

return permissions;
}

/**
Expand Down Expand Up @@ -377,10 +389,7 @@ public boolean hasPermissionForUser(String user, List<String> permission) {
public List<String> getRolesForUserInDomain(String name, String domain) {
try {
return model.model.get("g").get("g").rm.getRoles(name, domain);
} catch (IllegalArgumentException e) {
if (!"error: name does not exist".equals(e.getMessage())) {
throw e;
}
} catch (CasbinNameNotExistException ignored) {
}
return Collections.emptyList();
}
Expand Down Expand Up @@ -432,16 +441,57 @@ public boolean deleteRoleForUserInDomain(String user, String role, String domain
* getRolesForUser("alice") can only get: ["role:admin"].
* But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
*
* @param name the user
* @param domain the domain
* @param name the user.
* @param domain the user's domain.
* @return implicit roles that a user has.
*/
public List<String> getImplicitRolesForUser(String name, String... domain) {
List<String> roles = this.rm.getRoles(name, domain);
List<String> res = new ArrayList<>(roles);
for (String n : roles) {
res.addAll(this.getImplicitRolesForUser(n, domain));
List<String> res = new ArrayList<>();
Deque<String> queue = new LinkedList<>();
queue.offerLast(name);

while (!queue.isEmpty()) {
name = queue.pollFirst();
for (RoleManager rm : rmMap.values()) {
List<String> roles = rm.getRoles(name, domain);
for (String role : roles) {
if (res.contains(role)) continue;
res.add(role);
queue.offerLast(role);
}
}
}

return res;
}

/**
* getImplicitUsersForRole gets implicit users for a role.
*
* @param name the role.
* @param domain the role's domain.
* @return implicit users that a role has.
*/
public List<String> getImplicitUsersForRole(String name, String... domain) {
Deque<String> queue = new LinkedList<>();
queue.offerLast(name);
List<String> res = new ArrayList<>();

while (!queue.isEmpty()) {
name = queue.pollFirst();
for (RoleManager rm : rmMap.values()) {
try {
List<String> users = rm.getUsers(name, domain);
for (String user : users) {
if (res.contains(user)) continue;
res.add(user);
queue.offerLast(user);
}
} catch (CasbinNameNotExistException ignored) {
}
}
}

return res;
}

Expand All @@ -456,16 +506,17 @@ public List<String> getImplicitRolesForUser(String name, String... domain) {
* getPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].
* But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
*
* @param user the user.
* @param user the user.
* @param domain the user's domain.
* @return implicit permissions for a user or role.
*/
public List<List<String>> getImplicitPermissionsForUser(String user) {
public List<List<String>> getImplicitPermissionsForUser(String user, String... domain) {
List<String> roles = new ArrayList<>();
roles.add(user);
roles.addAll(this.getImplicitRolesForUser(user));
roles.addAll(getImplicitRolesForUser(user, domain));
List<List<String>> res = new ArrayList<>();
for (String n : roles) {
res.addAll(this.getPermissionsForUser(n));
for (String role : roles) {
res.addAll(this.getPermissionsForUser(role, domain));
}
return res;
}
Expand Down
16 changes: 15 additions & 1 deletion src/main/java/org/casbin/jcasbin/main/InternalEnforcer.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.casbin.jcasbin.main;

import org.casbin.jcasbin.model.Assertion;
import org.casbin.jcasbin.model.Model;
import org.casbin.jcasbin.persist.BatchAdapter;
import org.casbin.jcasbin.persist.UpdatableAdapter;
Expand Down Expand Up @@ -107,7 +108,7 @@ boolean addPolicies(String sec, String ptype, List<List<String>> rules) {
* @param rules the rules.
*/
public void buildIncrementalRoleLinks(Model.PolicyOperations op, String ptype, List<List<String>> rules) {
model.buildIncrementalRoleLinks(rm, op, "g", ptype, rules);
model.buildIncrementalRoleLinks(rmMap, op, "g", ptype, rules);
}

/**
Expand Down Expand Up @@ -301,4 +302,17 @@ boolean removeFilteredPolicy(String sec, String ptype, int fieldIndex, String...

return true;
}

int getDomainIndex(String ptype) {
Assertion ast = model.model.get("p").get(ptype);
String pattern = String.format("%s_dom", ptype);
int index = ast.tokens.length;
for (int i = 0; i < ast.tokens.length; i++) {
if (ast.tokens[i].equals(pattern)) {
index = i;
break;
}
}
return index;
}
}
Loading

0 comments on commit 4d91e84

Please sign in to comment.