212 lines
8.4 KiB
Java
212 lines
8.4 KiB
Java
package org.gcube.data.access.storagehub;
|
|
|
|
import java.util.List;
|
|
|
|
import jakarta.inject.Inject;
|
|
import jakarta.inject.Singleton;
|
|
import javax.jcr.Node;
|
|
import javax.jcr.RepositoryException;
|
|
import javax.jcr.Session;
|
|
|
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
import org.apache.jackrabbit.api.security.user.Authorizable;
|
|
import org.apache.jackrabbit.api.security.user.Group;
|
|
import org.apache.jackrabbit.api.security.user.UserManager;
|
|
import org.gcube.common.storagehub.model.Excludes;
|
|
import org.gcube.common.storagehub.model.acls.ACL;
|
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
import org.gcube.common.storagehub.model.items.Item;
|
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
|
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
*
|
|
*
|
|
* the caller must be authorized, so i'm not passing the login also if it works on behalf of an user
|
|
*
|
|
*
|
|
*/
|
|
@Singleton
|
|
public class AuthorizationChecker {
|
|
|
|
private static Logger log = LoggerFactory.getLogger(AuthorizationChecker.class);
|
|
|
|
@Inject
|
|
Node2ItemConverter node2Item;
|
|
|
|
@Inject
|
|
PathUtil pathUtil;
|
|
|
|
@Inject
|
|
ACLManagerInterface aclManager;
|
|
|
|
public void checkReadAuthorizationControl(Session session, String userToCheck, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
|
|
|
Node node = session.getNodeByIdentifier(id);
|
|
|
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
|
|
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id+": it's not a valid StorageHub node");
|
|
|
|
//checking if the item is in the owner trash folder
|
|
if(item instanceof TrashItem && item.getParentPath().equals(pathUtil.getTrashPath(userToCheck, session).toPath()))
|
|
return;
|
|
|
|
if (!item.isShared() && item.getOwner()!=null && item.getOwner().equals(userToCheck)) return;
|
|
|
|
if (hasParentPublicFolder(session, item)) return;
|
|
|
|
//TODO: remove when messages will be passed to a new system
|
|
String parentPath = item.getParentPath();
|
|
if (parentPath.endsWith("hl:attachments") && (parentPath.contains("/OutBox/") || parentPath.contains("/InBox/"))) {
|
|
return ;
|
|
}
|
|
|
|
if (item.isShared()) {
|
|
//SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
|
|
//if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return;
|
|
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
|
List<ACL> acls = aclManager.get(item, session);
|
|
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
|
Authorizable userAuthorizable = userManager.getAuthorizable(userToCheck);
|
|
for (ACL entry: acls) {
|
|
log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPricipal());
|
|
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
|
|
|
if (authorizable==null) {
|
|
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPricipal());
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
if (!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) return;
|
|
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
|
|
}catch (Throwable e) {
|
|
log.warn("someting went wrong checking authorizations",e);
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id);
|
|
|
|
}
|
|
|
|
|
|
private boolean hasParentPublicFolder(Session session, Item item) {
|
|
if(item==null || item.getParentPath()==null) return false;
|
|
if (item.getParentPath().replaceAll("/Home/[^/]*/"+Constants.WORKSPACE_ROOT_FOLDER_NAME,"").isEmpty() || item.getParentPath().replaceAll(Constants.SHARED_FOLDER_PATH, "").isEmpty()) {
|
|
if (item instanceof FolderItem folder)
|
|
return folder.isPublicItem();
|
|
else return false;
|
|
} else {
|
|
if (item instanceof FolderItem folder)
|
|
try {
|
|
return (folder.isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(folder.getParentId(), session, Excludes.ALL)));
|
|
}catch (Throwable e) {
|
|
log.warn("error checking public parents",e);
|
|
return false;
|
|
}
|
|
else
|
|
try {
|
|
return hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
|
|
}catch (Throwable e) {
|
|
log.warn("error checking public parents",e);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//newItem means that a new item will be created and id is the destination directory
|
|
public void checkWriteAuthorizationControl(Session session, String userToCheck, Item item, Node node, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
if (item==null) throw new UserNotAuthorizedException("Not valid StorageHub node");
|
|
|
|
if (Constants.WRITE_PROTECTED_FOLDER.contains(item.getName()) || Constants.WRITE_PROTECTED_FOLDER.contains(item.getTitle()))
|
|
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId()+": it's a protected folder");
|
|
|
|
if (item.isShared()) {
|
|
|
|
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
|
List<ACL> acls = aclManager.get(item, session);
|
|
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
|
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
|
|
//put it in a different method
|
|
for (ACL entry: acls) {
|
|
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
|
if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
|
for (AccessType privilege : entry.getAccessTypes()){
|
|
if (isNewItem && privilege!=AccessType.READ_ONLY)
|
|
return;
|
|
else
|
|
if (!isNewItem &&
|
|
(privilege==AccessType.ADMINISTRATOR || privilege==AccessType.WRITE_ALL || (privilege==AccessType.WRITE_OWNER && item.getOwner().equals(userToCheck))))
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
} else
|
|
if(item.getOwner().equals(userToCheck))
|
|
return;
|
|
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId());
|
|
}
|
|
|
|
//newItem means that a new item will be created and id is the destination directory
|
|
public void checkWriteAuthorizationControl(Session session, String userToCheck , String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
//in case of newItem the id is the parent otherwise the old node to replace
|
|
Node node = session.getNodeByIdentifier(id);
|
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
|
checkWriteAuthorizationControl(session, userToCheck, item, node, isNewItem);
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* checks if item with {id} can be moved
|
|
*
|
|
*/
|
|
public void checkMoveOpsForProtectedFolders(Session session, String id) throws InvalidCallParameters, BackendGenericError, RepositoryException {
|
|
Node node = session.getNodeByIdentifier(id);
|
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
|
|
|
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
|
|
throw new InvalidCallParameters("protected folder cannot be moved or deleted");
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* checks if {userToCheck} is an admin for {item}
|
|
*
|
|
*/
|
|
public void checkAdministratorControl(Session session, String userToCheck, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
|
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+": it's not a valid StorageHub node");
|
|
|
|
if (item.isShared()) {
|
|
List<ACL> acls = aclManager.get(item, session);
|
|
|
|
for (ACL entry: acls) {
|
|
if (entry.getPricipal().equals(userToCheck)) {
|
|
for (AccessType privilege : entry.getAccessTypes()){
|
|
if (privilege==AccessType.ADMINISTRATOR)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
throw new UserNotAuthorizedException("The user "+userToCheck+" is not an administrator of node with id "+item.getId());
|
|
}
|
|
|
|
}
|