Creating your own security access manager
The security access manager is used by OpenKM to check the user's security access level for nodes.
Conditions:
- The new Principal Adapter class must implement the "DbAccessManager" interface.
- The new Principal Adapter class must be declared in the package "com.openkm.plugin.access".
- The new Principal Adapter class must be annotated with "@PluginImplementation".
- The new Principal Adapter class must extend "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 the application plugin system will try to load it from there.
Do not omit 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 set its value to com.openkm.plugin.access.OwnSecurityManager.
For this change to take effect, we need to restart the application.
Method descriptions
The values of permissions in the following table are (more information in the Permission.java class):
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 |
Returns true when the user in the session has the grant. |
isGranted(NodeBase node, String user, int permissions) | Boolean | Returns true when the user has the grant. |
isGranted(NodeBase node, long nodeClass, int permissions) |
Boolean
|
Returns true when the user in the session has the grant. This method only makes sense when the 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;
}
}