diff --git a/src/main/java/org/gcube/data/access/storagehub/Utils.java b/src/main/java/org/gcube/data/access/storagehub/Utils.java index 7c8f944..3819390 100644 --- a/src/main/java/org/gcube/data/access/storagehub/Utils.java +++ b/src/main/java/org/gcube/data/access/storagehub/Utils.java @@ -7,7 +7,6 @@ import java.io.OutputStream; import java.net.URL; import java.security.MessageDigest; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.Deque; import java.util.HashSet; @@ -25,7 +24,6 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.lock.Lock; import javax.jcr.lock.LockException; -import javax.jcr.nodetype.NodeType; import javax.jcr.query.Query; import javax.jcr.version.Version; @@ -302,29 +300,22 @@ public class Utils { public static void getAllContentIds(Session ses, Set idsToDelete, Item itemToDelete, VersionHandler versionHandler) throws Exception{ if (itemToDelete instanceof AbstractFileItem) { Node currentNode = ses.getNodeByIdentifier(itemToDelete.getId()); - List versions = null; - try { - versions = versionHandler.getContentVersionHistory(currentNode, ses); - }catch (Exception e) { - logger.warn("versions cannot be retrieved for node with id {}",itemToDelete.getId()); - } + List versions = versionHandler.getContentVersionHistory(currentNode, ses); - if (versions!= null) { - versions.forEach(v -> { - try { - String storageId =v.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString(); - idsToDelete.add(storageId); - logger.info("retrieved StorageId {} for version {}", storageId, v.getName()); - } catch (Exception e) { - logger.warn("error retreiving sotrageId version for item with id {}",itemToDelete.getId(),e); - } - }); + versions.forEach(v -> { + try { + String storageId =v.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString(); + idsToDelete.add(storageId); + logger.info("retrieved StorageId {} for version {}", storageId, v.getName()); + } catch (Exception e) { + logger.warn("error retreiving sotrageId version for item with id {}",itemToDelete.getId(),e); + } + }); - } else - logger.info("not versionable node type found of type {}", currentNode.getPrimaryNodeType().getName().toString()); idsToDelete.add(((AbstractFileItem) itemToDelete).getContent().getStorageId()); }else if (itemToDelete instanceof FolderItem) { + if (itemToDelete.isShared()) return; List items = Utils.getItemList(ses.getNodeByIdentifier(itemToDelete.getId()), Excludes.GET_ONLY_CONTENT , null, true, null); for (Item item: items) getAllContentIds(ses, idsToDelete, item, versionHandler); diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/GroupHandler.java b/src/main/java/org/gcube/data/access/storagehub/handlers/GroupHandler.java new file mode 100644 index 0000000..336ac8d --- /dev/null +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/GroupHandler.java @@ -0,0 +1,76 @@ +package org.gcube.data.access.storagehub.handlers; + +import javax.inject.Singleton; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.api.JackrabbitSession; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.User; +import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters; +import org.gcube.common.storagehub.model.exceptions.InvalidItemException; +import org.gcube.common.storagehub.model.exceptions.StorageHubException; +import org.gcube.common.storagehub.model.types.NodeProperty; +import org.gcube.data.access.storagehub.Constants; +import org.gcube.data.access.storagehub.Utils; +import org.gcube.data.access.storagehub.services.GroupManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class GroupHandler { + + private static final Logger log = LoggerFactory.getLogger(GroupManager.class); + + public boolean removeUserFromGroup(String groupId, String userId, JackrabbitSession session) throws StorageHubException, RepositoryException { + org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); + + Group group = (Group)usrManager.getAuthorizable(groupId); + User user = (User)usrManager.getAuthorizable(userId); + + if (!group.isMember(user)) + throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId); + + //delete folder on user + String folderName = group.getPrincipal().getName(); + Node folder = getVreFolderNode(session, folderName); + + NodeIterator ni = folder.getSharedSet(); + while (ni.hasNext()) { + Node node = ni.nextNode(); + if (node.getPath().startsWith(Utils.getWorkspacePath(user.getPrincipal().getName()).toPath())) { + node.removeShare(); + break; + } + } + + return group.removeMember(user); + + } + + public Node getVreFolderNode(JackrabbitSession session, String name) throws InvalidItemException, RepositoryException { + Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH); + + Node vreFolder = null; + try { + vreFolder = sharedRootNode.getNode(name); + }catch (PathNotFoundException e) { + log.debug("is an old HL VRE"); + } + + NodeIterator nodes = sharedRootNode.getNodes(); + while (nodes.hasNext()) { + Node node = nodes.nextNode(); + if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) { + vreFolder= node; + break; + } + } + + if (vreFolder==null) throw new InvalidItemException("vre folder not found"); + return vreFolder; + } + +} diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/UnshareHandler.java b/src/main/java/org/gcube/data/access/storagehub/handlers/UnshareHandler.java index 7f3764e..7bd0e41 100644 --- a/src/main/java/org/gcube/data/access/storagehub/handlers/UnshareHandler.java +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/UnshareHandler.java @@ -54,8 +54,16 @@ public class UnshareHandler { @Inject Item2NodeConverter item2Node; - + public String unshare(Session ses, Set users, Node sharedNode, String login) throws RepositoryException, StorageHubException{ + return _unshare(ses, users, sharedNode, login, true); + } + + public String unshareForRemoval(Session ses, Set users, Node sharedNode, String login) throws RepositoryException, StorageHubException{ + return _unshare(ses, users, sharedNode, login, false); + } + + public String _unshare(Session ses, Set users, Node sharedNode, String login, boolean withCopyOnUnshare) throws RepositoryException, StorageHubException{ Item item = node2Item.getItem(sharedNode, Excludes.ALL); if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder()) return null; @@ -65,12 +73,12 @@ public class UnshareHandler { usersInSharedFolder.removeAll(users); if (users==null || users.size()==0) - return unshareAll(login, ses, sharedItem); + return unshareAll(login, ses, sharedItem, false); if (usersInSharedFolder.size()<=1) { if (users.size()==1 && users.contains(login)) - return unshareAll(sharedItem.getOwner(), ses , sharedItem); - else return unshareAll(login, ses, sharedItem); + return unshareAll(sharedItem.getOwner(), ses , sharedItem, false); + else return unshareAll(login, ses, sharedItem, false); } try { @@ -88,8 +96,9 @@ public class UnshareHandler { } } - - private String unshareAll(String login, Session ses, SharedFolder item) throws StorageHubException, BackendGenericError, RepositoryException{ + + + private String unshareAll(String login, Session ses, SharedFolder item, boolean withCopyCreation) throws StorageHubException, BackendGenericError, RepositoryException{ log.info("unshare all called"); if (!login.equals(item.getOwner())) @@ -103,51 +112,79 @@ public class UnshareHandler { throw new ItemLockedException(e); } - Node unsharedNode; + String unsharedNodeIdentifier =null; try { log.debug("user list is empty, I'm going to remove also the shared dir"); - //take the admin folder and remove his clone then move the shared folder from share to the user home and change the folder type - String adminDirPath = (String)item.getUsers().getMap().get(login); - String[] splitString = adminDirPath.split("/"); - String parentDirectoryId = splitString[0]; - String directoryName = splitString[1]; - Node parentNode = ses.getNodeByIdentifier(parentDirectoryId); - log.debug("parent node path is {}/{}",parentNode.getPath(), directoryName); + + if (withCopyCreation) { + + //take the admin folder and remove his clone then move the shared folder from share to the user home and change the folder type - Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName)); - adminNode.removeShare(); + /* + String adminDirPath = (String)item.getUsers().getMap().get(login); + String[] splitString = adminDirPath.split("/"); + String parentDirectoryId = splitString[0]; + String directoryName = splitString[1]; + Node parentNode = ses.getNodeByIdentifier(parentDirectoryId); + log.debug("parent node path is {}/{}",parentNode.getPath(), directoryName); + Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName)); + adminNode.removeShare(); */ - unsharedNode = createUnsharedFolder(ses, parentNode, directoryName, item.getDescription(), login); + Node sharedOwnerNode = null; + NodeIterator it = sharedItemNode.getSharedSet(); + while(it.hasNext()) { + Node node = it.nextNode(); + + log.info("[UNSHARE] checking node {} starts with {} ",node.getPath(),Utils.getHome(login).toPath()); + + if (node.getPath().startsWith(Utils.getHome(login).toPath())) { + sharedOwnerNode =node; + break; + } + } + Node shareParent = sharedOwnerNode.getParent(); - List itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null); + sharedOwnerNode.removeShare(); - for (Item itemCopy: itemsToCopy) { - Node itemToCopyNode = ses.getNodeByIdentifier(itemCopy.getId()); - log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath()); - ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName())); + Node unsharedNode = createUnsharedFolder(ses, shareParent , item.getTitle() , item.getDescription(), login); + + List itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null); + + for (Item itemCopy: itemsToCopy) { + Node itemToCopyNode = ses.getNodeByIdentifier(itemCopy.getId()); + log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath()); + ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName())); + } + + unsharedNode.getNode(NodeProperty.ACCOUNTING.toString()).remove(); + ses.move(sharedItemNode.getNode(NodeProperty.ACCOUNTING.toString()).getPath(), String.format("%s/%s",unsharedNode.getPath(), NodeProperty.ACCOUNTING.toString())); + + //set owner of all the unshared items to the caller + item2Node.updateOwnerOnSubTree(unsharedNode, login); + + accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), "ALL", ses, unsharedNode, false); + + unsharedNodeIdentifier = unsharedNode.getIdentifier(); + + ses.save(); } - unsharedNode.getNode(NodeProperty.ACCOUNTING.toString()).remove(); - ses.move(sharedItemNode.getNode(NodeProperty.ACCOUNTING.toString()).getPath(), String.format("%s/%s",unsharedNode.getPath(), NodeProperty.ACCOUNTING.toString())); - - //set owner of all the unshared items to the caller - item2Node.updateOwnerOnSubTree(unsharedNode, login); - - accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), "ALL", ses, unsharedNode, false); - + sharedItemNode.removeSharedSet(); ses.save(); + + log.debug("all the users have been removed, the folder is totally unshared"); + + }catch(Throwable t) { log.error("erro unsharing all",t); throw t; }finally { ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath()); } - sharedItemNode.removeSharedSet(); - ses.save(); - log.debug("all the users have been removed, the folder is totally unshared"); - return unsharedNode.getIdentifier(); + return unsharedNodeIdentifier; + } @@ -156,12 +193,12 @@ public class UnshareHandler { private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{ log.info("unshare caller"); - + if (login.equals(item.getOwner())) throw new InvalidCallParameters("the caller is the owner, the folder cannot be unshared"); Node sharedFolderNode =ses.getNodeByIdentifier(item.getId()); - + Node shareNode = getUserSharingNode(login, ses, item); log.debug("removed Access control entry for user {}",login); @@ -190,11 +227,11 @@ public class UnshareHandler { } } } - + String parentId = shareNode.getParent().getIdentifier(); - + shareNode.removeShare(); - + AccessControlManager acm = ses.getAccessControlManager(); JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath()); @@ -210,7 +247,7 @@ public class UnshareHandler { acls.removeAccessControlEntry(entryToDelete); acm.setPolicy(sharedFolderNode.getPath(), acls); - + accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), login, ses, sharedItemNode, false); ses.save(); @@ -246,9 +283,9 @@ public class UnshareHandler { } } } - + userShareNode.removeShare(); - + AccessControlEntry entryToDelete= null; for (AccessControlEntry ace :acls.getAccessControlEntries()) { if (ace.getPrincipal().getName().equals(user)) { diff --git a/src/main/java/org/gcube/data/access/storagehub/services/GroupManager.java b/src/main/java/org/gcube/data/access/storagehub/services/GroupManager.java index 6d4f326..fa64535 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/GroupManager.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/GroupManager.java @@ -1,6 +1,7 @@ package org.gcube.data.access.storagehub.services; -import static org.gcube.data.access.storagehub.Roles.*; +import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE; +import static org.gcube.data.access.storagehub.Roles.VREMANAGER_ROLE; import java.security.Principal; import java.util.ArrayList; @@ -10,7 +11,6 @@ import java.util.Objects; import javax.inject.Inject; import javax.jcr.Node; -import javax.jcr.NodeIterator; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.security.AccessControlEntry; @@ -48,7 +48,6 @@ import org.gcube.common.storagehub.model.Excludes; 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.InvalidItemException; import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; import org.gcube.common.storagehub.model.items.Item; @@ -60,6 +59,7 @@ import org.gcube.data.access.storagehub.StorageHubAppllicationManager; import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.exception.MyAuthException; import org.gcube.data.access.storagehub.handlers.CredentialHandler; +import org.gcube.data.access.storagehub.handlers.GroupHandler; import org.gcube.data.access.storagehub.handlers.TrashHandler; import org.gcube.data.access.storagehub.handlers.VRE; import org.gcube.data.access.storagehub.handlers.VREManager; @@ -88,6 +88,9 @@ public class GroupManager { @Inject VREManager vreManager; + @Inject + GroupHandler groupHandler; + @Inject Node2ItemConverter node2Item; @@ -192,7 +195,7 @@ public class GroupManager { authorizable.remove(); try { - Node node = getVreFolderNode(session, group); + Node node = groupHandler.getVreFolderNode(session, group); List workspaceItems = Utils.getItemList(node, Excludes.GET_ONLY_CONTENT, null, true, null); trashHandler.removeNodes(session, workspaceItems); node.removeSharedSet(); @@ -230,7 +233,7 @@ public class GroupManager { session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - Node vreFolder = getVreFolderNode(session, groupId); + Node vreFolder = groupHandler.getVreFolderNode(session, groupId); if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) )) authChecker.checkAdministratorControl(session, node2Item.getItem(vreFolder, Excludes.ALL)); @@ -283,7 +286,7 @@ public class GroupManager { Objects.nonNull(userId); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - Node vreFolder = getVreFolderNode(session, groupId); + Node vreFolder = groupHandler.getVreFolderNode(session, groupId); if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) )) authChecker.checkAdministratorControl(session, node2Item.getItem(vreFolder, Excludes.ALL)); @@ -407,7 +410,7 @@ public class GroupManager { boolean success = group.addMember(user); session.save(); String folderName = group.getPrincipal().getName(); - Node folder = getVreFolderNode(session, folderName); + Node folder = groupHandler.getVreFolderNode(session, folderName); String userPath = String.format("%s%s/%s",Utils.getWorkspacePath(user.getPrincipal().getName()).toPath(),Constants.VRE_FOLDER_PARENT_NAME, folderName); log.debug("creating folder in user path {} from {}", userPath, folder.getPath() ); @@ -438,30 +441,9 @@ public class GroupManager { throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation"); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - - org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); - - Group group = (Group)usrManager.getAuthorizable(groupId); - User user = (User)usrManager.getAuthorizable(userId); - - if (!group.isMember(user)) - throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId); - - //delete folder on user - String folderName = group.getPrincipal().getName(); - Node folder = getVreFolderNode(session, folderName); - - NodeIterator ni = folder.getSharedSet(); - while (ni.hasNext()) { - Node node = ni.nextNode(); - if (node.getPath().startsWith(Utils.getWorkspacePath(user.getPrincipal().getName()).toPath())) { - node.removeShare(); - break; - } - } - - success = group.removeMember(user); - + + success = groupHandler.removeUserFromGroup(groupId, userId, session); + session.save(); }catch(StorageHubException she ){ log.error(she.getErrorMessage(), she); @@ -560,29 +542,7 @@ public class GroupManager { log.debug("vrefolder created with id {}",folder.getIdentifier()); } - private Node getVreFolderNode(JackrabbitSession session, String name) throws InvalidItemException, RepositoryException { - Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH); - - Node vreFolder = null; - try { - vreFolder = sharedRootNode.getNode(name); - }catch (PathNotFoundException e) { - log.debug("is an old HL VRE"); - } - - NodeIterator nodes = sharedRootNode.getNodes(); - while (nodes.hasNext()) { - Node node = nodes.nextNode(); - if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) { - vreFolder= node; - break; - } - } - - if (vreFolder==null) throw new InvalidItemException("vre folder not found"); - return vreFolder; - } - + private boolean isValidGroupForContext(String group){ String currentContext = ScopeProvider.instance.get(); String expectedGroupId= currentContext.replace("/", "-").substring(1); diff --git a/src/main/java/org/gcube/data/access/storagehub/services/UserManager.java b/src/main/java/org/gcube/data/access/storagehub/services/UserManager.java index 5defa11..3a6b0c7 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/UserManager.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/UserManager.java @@ -7,6 +7,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.jcr.Node; @@ -27,6 +28,7 @@ import javax.ws.rs.core.Response; 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.Query; import org.apache.jackrabbit.api.security.user.QueryBuilder; import org.apache.jackrabbit.api.security.user.User; @@ -34,19 +36,20 @@ import org.apache.jackrabbit.core.security.principal.PrincipalImpl; import org.gcube.common.authorization.control.annotations.AuthorizationControl; import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; import org.gcube.common.storagehub.model.Excludes; +import org.gcube.common.storagehub.model.Paths; import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.IdNotFoundException; import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; import org.gcube.common.storagehub.model.items.Item; import org.gcube.common.storagehub.model.items.SharedFolder; -import org.gcube.common.storagehub.model.types.NodeProperty; import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.StorageHubAppllicationManager; import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.exception.MyAuthException; import org.gcube.data.access.storagehub.handlers.CredentialHandler; +import org.gcube.data.access.storagehub.handlers.GroupHandler; import org.gcube.data.access.storagehub.handlers.TrashHandler; import org.gcube.data.access.storagehub.handlers.UnshareHandler; import org.gcube.smartgears.annotations.ManagedBy; @@ -72,6 +75,9 @@ public class UserManager { @Inject TrashHandler trashHandler; + @Inject + GroupHandler groupHandler; + @Inject AuthorizationChecker authChecker; @@ -204,72 +210,27 @@ public class UserManager { InnerMethodName.instance.set("deleteUser"); JackrabbitSession session = null; - String userId = null; try { session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); - - try { - - Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH); - - Predicate sharedWithUserChecker = new Predicate() { - - @Override - public boolean test(Node t) { - try { - authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier()); - return !t.getProperty(NodeProperty.IS_VRE_FOLDER.toString()).getBoolean() ; - } catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) { - return false; - } - } - }; - - List items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class); - - for (SharedFolder item: items) { - - if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue; - - - String title = item.getTitle(); - log.debug("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath()); - String owner = item.getOwner(); - - Set usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user); - - try { - unshareHandler.unshare(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user); - }catch (Throwable e) { - log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e); - } - } - } catch (Throwable t) { - log.warn("error getting folder shared with ", t); - } - - org.gcube.common.storagehub.model.Path homePath = Utils.getHome(user); - org.gcube.common.storagehub.model.Path workspacePath = Utils.getWorkspacePath(user); - - try { - Node workspaceNode = session.getNode(workspacePath.toPath()); - Node homeNode = session.getNode(homePath.toPath()); - List workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null); - trashHandler.removeOnlyNodesContent(session, workspaceItems); - homeNode.remove(); - } catch (PathNotFoundException e) { - log.warn("{} home dir was already deleted", user); - } + User authorizable = (User) usrManager.getAuthorizable(new PrincipalImpl(user)); - Authorizable authorizable = usrManager.getAuthorizable(new PrincipalImpl(user)); + if (authorizable!=null) + removeUserFromBelongingGroup(session, authorizable, usrManager); + else log.warn("user was already deleted from jackrabbit, trying to delete folders"); + + unshareUsersFolders(session, user); + + removeUserHomeAndDeleteFiles(session, user); + + //FINALIZE user removal if (authorizable!=null && !authorizable.isGroup()) { log.info("removing user {}", user); authorizable.remove(); - } else log.warn("the user {} was already deleted", user); + } else log.warn("the user {} was already deleted, it should never happen", user); session.save(); }catch(StorageHubException she ){ @@ -283,7 +244,93 @@ public class UserManager { session.logout(); } - return userId; + return user; } + private void removeUserFromBelongingGroup(JackrabbitSession session, User authorizable, org.apache.jackrabbit.api.security.user.UserManager usrManager) throws RepositoryException, StorageHubException { + Iterator groups = session.getUserManager().findAuthorizables(new Query() { + + @Override + public void build(QueryBuilder builder) { + builder.setSelector(Group.class); + } + }); + + + + String user = authorizable.getPrincipal().getName(); + while(groups.hasNext()) { + Authorizable group = groups.next(); + log.info("group found {}", group.getPrincipal().getName() ); + if (group.isGroup() && ((Group)group).isMember(authorizable)) { + + boolean success = groupHandler.removeUserFromGroup(group.getPrincipal().getName(), user, session); + log.warn("user {} {} removed from vre {}",user,success?"":"not" ,group.getPrincipal().getName()); + } + } + } + + private void unshareUsersFolders(JackrabbitSession session, String user){ + try { + + Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH); + + Predicate sharedWithUserChecker = new Predicate() { + + @Override + public boolean test(Node t) { + try { + authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier()); + return true; + } catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) { + return false; + } + } + }; + + List items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class); + + log.debug(" Shared folder to unshare found are {}", items.size()); + + for (SharedFolder item: items) { + String title = item.getTitle(); + log.debug("in list folder name {} with title {} and path {} ",item.getName(), title, item.getPath()); + if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue; + if (item.isVreFolder()) continue; + + log.info("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath()); + String owner = item.getOwner(); + + Set usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user); + + try { + unshareHandler.unshareForRemoval(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user); + }catch (Throwable e) { + log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e); + } + } + } catch (Throwable t) { + log.warn("error getting folder shared with {}",user, t); + } + } + + private void removeUserHomeAndDeleteFiles(JackrabbitSession session, String user) throws RepositoryException, StorageHubException { + org.gcube.common.storagehub.model.Path homePath = Utils.getHome(user); + org.gcube.common.storagehub.model.Path workspacePath = Utils.getWorkspacePath(user); + org.gcube.common.storagehub.model.Path trashPath = Paths.append(workspacePath, Constants.TRASH_ROOT_FOLDER_NAME); + + try { + Node workspaceNode = session.getNode(workspacePath.toPath()); + Node homeNode = session.getNode(homePath.toPath()); + Node trashNode = session.getNode(trashPath.toPath()); + List workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null).stream().filter(i -> !i.isShared()).collect(Collectors.toList()); + trashHandler.removeOnlyNodesContent(session, workspaceItems); + List itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null); + trashHandler.removeOnlyNodesContent(session, itemsToDelete); + homeNode.remove(); + } catch (PathNotFoundException e) { + log.warn("{} home dir was already deleted", user); + } + } + } diff --git a/src/main/java/org/gcube/data/access/storagehub/services/admin/NodeManagerAdmin.java b/src/main/java/org/gcube/data/access/storagehub/services/admin/NodeManagerAdmin.java new file mode 100644 index 0000000..afc20b8 --- /dev/null +++ b/src/main/java/org/gcube/data/access/storagehub/services/admin/NodeManagerAdmin.java @@ -0,0 +1,125 @@ +package org.gcube.data.access.storagehub.services.admin; + +import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE; + +import java.util.ArrayList; +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletContext; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.jackrabbit.api.JackrabbitSession; +import org.gcube.common.authorization.control.annotations.AuthorizationControl; +import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; +import org.gcube.common.storagehub.model.Excludes; +import org.gcube.common.storagehub.model.exceptions.BackendGenericError; +import org.gcube.common.storagehub.model.exceptions.StorageHubException; +import org.gcube.common.storagehub.model.items.Item; +import org.gcube.common.storagehub.model.service.ItemList; +import org.gcube.data.access.storagehub.StorageHubAppllicationManager; +import org.gcube.data.access.storagehub.Utils; +import org.gcube.data.access.storagehub.exception.MyAuthException; +import org.gcube.data.access.storagehub.handlers.CredentialHandler; +import org.gcube.data.access.storagehub.services.RepositoryInitializer; +import org.gcube.smartgears.utils.InnerMethodName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("admin/nodes") +public class NodeManagerAdmin { + + private static final Logger log = LoggerFactory.getLogger(NodeManagerAdmin.class); + + RepositoryInitializer repository = StorageHubAppllicationManager.repository; + + @Context ServletContext context; + + @RequestScoped + @PathParam("id") + String id; + + @GET + @Produces(MediaType.TEXT_PLAIN) + @Path("byPath") + @AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class) + public String getNode(@QueryParam("path") String path){ + InnerMethodName.instance.set("getNodeByPathAdmin"); + + String toReturn= null; + Session session = null; + try{ + session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + + Node node = session.getNode(path); + toReturn = infoNodeParser(node); + }catch(RepositoryException re ){ + log.error("jcr error getting children by path", re); + GXOutboundErrorResponse.throwException(new BackendGenericError(re)); + }finally{ + if (session!=null) { + session.logout(); + } + } + return toReturn; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{id}/children") + @AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class) + public List getNodes(@QueryParam("pattern") String namePattern){ + InnerMethodName.instance.set("getNodesChildrenAdmin"); + + List nodes =new ArrayList<>(); + Session session = null; + try{ + session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + + Node nodeParent = session.getNodeByIdentifier(id); + NodeIterator nIt = null; + if (namePattern==null) + nIt = nodeParent.getNodes(); + else + nIt = nodeParent.getNodes(namePattern); + while (nIt.hasNext()) { + Node node = nIt.nextNode(); + nodes.add(infoNodeParser(node)); + } + + }catch(RepositoryException re ){ + log.error("jcr error getting children by path", re); + GXOutboundErrorResponse.throwException(new BackendGenericError(re)); + } finally{ + if (session!=null) { + session.logout(); + } + } + return nodes; + } + + private String infoNodeParser(Node node) throws RepositoryException { + /* + PropertyIterator pIt = node.getProperties(); + while (pIt.hasNext()) { + Property prop = pIt.nextProperty(); + prop.get + }*/ + + return node.getIdentifier()+" "+node.getName()+" "+node.getPrimaryNodeType().getName(); + } + +}