Creating your own security access manager
The security access manager is used by the OpenKM to check the user security access level of the nodes.
Conditions:
- The new Principal Adapter class must implement the "DbAccessManager" interface.
- The new Principal Adapter class must be declared under the package "com.openkm.plugin.access".
- The new Principal Adapter class must be annotated with "@PluginImplementation".
- The new Principal Adapter class must extend of "BasePlugin".
Security access manager interface:
package com.openkm.plugin.access;
import com.openkm.core.AccessDeniedException;
import com.openkm.core.DatabaseException;
import com.openkm.core.PathNotFoundException;
import com.openkm.db.bean.NodeBase;
import com.openkm.principal.PrincipalAdapterException;
import net.xeoh.plugins.base.Plugin;
/**
* Check user permissions on documents and folders.
*
* @author pavila
*/
public interface DbAccessManager extends Plugin {
void checkPermission(NodeBase node, int permissions) throws AccessDeniedException, PathNotFoundException, DatabaseException;
boolean isGranted(NodeBase node, int permissions) throws DatabaseException, PathNotFoundException;
boolean isGranted(NodeBase node, String user, int permissions) throws PrincipalAdapterException, DatabaseException, PathNotFoundException;
boolean isGranted(NodeBase node, long nodeClass, int permissions) throws DatabaseException;
}
The new class must be loaded into the package com.openkm.plugin.access because application plugins system will try to load from there.
Do not miss the tag @PluginImplementation otherwise, the application plugin system will not be able to retrieve the new class.
More information at Register a new plugin.
To enable the new Security access manager go to Administration > Configuration parameters > find the parameter named security.access.manager and modify the value with com.openkm.plugin.access.OwnSecurityManager
To take effect this change we need to restart the application.
Methods description
In the next table the values of permissions are ( more information in the class Permission.java ):
0 | NONE |
1 | READ |
2 | WRITE |
4 | DELETE |
8 | SECURITY |
16 | MOVE |
1024 | DOWNLOAD |
2048 | START WORKFLOW |
4096 | COMPACT HISTORY |
8192 | METADATA |
Method | Type | Description |
---|---|---|
checkPermission(NodeBase node, int permissions) | void |
Description |
isGranted(NodeBase node, int permissions) | Boolean |
Return true when the user in the session has the grant. |
isGranted(NodeBase node, String user, int permissions) | Boolean | Return true when the user has the grant. |
isGranted(NodeBase node, long nodeClass, int permissions) |
Boolean
|
Return true when the user in the session has the grant. This method only has sense when file plan is enabled. |
Example of Security access manager implementation
package com.openkm.plugin.access;
import com.openkm.core.AccessDeniedException;
import com.openkm.core.Config;
import com.openkm.core.DatabaseException;
import com.openkm.core.PathNotFoundException;
import com.openkm.db.bean.NodeBase;
import com.openkm.db.bean.NodeClass;
import com.openkm.db.service.NodeBaseSrv;
import com.openkm.db.service.NodeClassSrv;
import com.openkm.module.common.CommonAuthModule;
import com.openkm.plugin.BasePlugin;
import com.openkm.plugin.fileplan.security.FilePlanAccessManager;
import com.openkm.principal.PrincipalAdapterException;
import com.openkm.principal.PrincipalUtils;
import com.openkm.util.StackTraceUtils;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Check user permissions on documents and folders.
*
* @see com.openkm.plugin.access.DbRecursiveAccessManager
*/
@PluginImplementation
public class DbSimpleAccessManager extends BasePlugin implements DbAccessManager {
private static final Logger log = LoggerFactory.getLogger(DbSimpleAccessManager.class);
@Autowired
private CommonAuthModule commonAuthModule;
@Autowired
private NodeClassSrv nodeClassSrv;
@Autowired
private NodeBaseSrv nodeBaseSrv;
/**
* Check for permissions.
*/
public void checkPermission(NodeBase node, int permissions) throws AccessDeniedException, PathNotFoundException, DatabaseException {
if (!isGranted(node, permissions)) {
String nodePath = nodeBaseSrv.getPathFromUuid(node.getUuid());
throw new AccessDeniedException(node.getUuid() + " : " + nodePath);
}
}
/**
* Check for permissions.
*/
@Override
public boolean isGranted(NodeBase node, int permissions) throws DatabaseException {
String userId = PrincipalUtils.getUser();
Set<String> roles = PrincipalUtils.getRoles();
return isGranted(node, userId, roles, permissions);
}
/**
* Check for permissions.
*/
@Override
public boolean isGranted(NodeBase node, String user, int permissions) throws PrincipalAdapterException, DatabaseException {
List<String> roles = commonAuthModule.getRolesByUser(user);
return isGranted(node, user, new HashSet<>(roles), permissions);
}
@Override
public boolean isGranted(NodeBase node, long nodeClass, int permissions) throws DatabaseException {
NodeClass nc = nodeClassSrv.findByPk(nodeClass);
FilePlanAccessManager accessManager = nodeClassSrv.findAccessManagerByClassName(nc.getAccessManagerClassName());
return accessManager.isGranted(node, nodeClass, PrincipalUtils.getUser(), PrincipalUtils.getRoles(), permissions);
}
/**
* Check for permissions.
*/
private boolean isGranted(NodeBase node, String user, Set<String> roles, int permissions) {
log.debug("isGranted({}, {})", node.getUuid(), permissions);
boolean access;
if (user != null) {
if (Config.SYSTEM_USER.equals(user) || Config.ADMIN_USER.equals(user)) {
// An okmAdmin user has total access
access = true;
} else {
if (roles.contains(Config.DEFAULT_ADMIN_ROLE)) {
// An user with AdminRole has total access
access = true;
} else {
access = checkProperties(node.getUserPermissions(), node.getRolePermissions(), user, roles, permissions);
}
}
} else {
access = true;
log.info("*****************************************************");
StackTraceUtils.logTrace(log);
log.info("*****************************************************");
}
log.debug("isGranted: {}", access);
return access;
}
/**
* Check access properties
*/
private boolean checkProperties(Map<String, Integer> usersPerms, Map<String, Integer> rolesPerms, String user,
Set<String> roles, int perms) {
log.debug("checkProperties({}, {}, {}, {})", usersPerms, rolesPerms, roles, perms);
boolean access = false;
// Fist try with user permissions
Integer userPerms = usersPerms.get(user);
if (userPerms != null && (perms & userPerms) != 0) {
log.debug("checkProperties: {}", true);
return true;
}
// If there is no user specific access, try with roles permissions
for (String role : roles) {
Integer rolePerms = rolesPerms.get(role);
if (rolePerms != null && (perms & rolePerms) != 0) {
log.debug("checkProperties: {}", true);
return true;
}
}
log.debug("checkProperties: {}", access);
return access;
}
}