package org.gcube.data.access.storagehub.handlers; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.jcr.Node; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; 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; import org.apache.jackrabbit.core.security.principal.PrincipalImpl; 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.InvalidCallParameters; import org.gcube.common.storagehub.model.exceptions.NotFoundException; 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.SHUBUser; import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jakarta.inject.Inject; public class UserHandler { private static final Logger log = LoggerFactory.getLogger(UserHandler.class); @Inject UnshareHandler unshareHandler; @Inject AuthorizationChecker authChecker; @Inject TrashHandler trashHandler; @Inject GroupHandler groupHandler; @Inject PathUtil pathUtil; public List getAllUsers(JackrabbitSession session) throws Throwable { List users = null; Iterator result = session.getUserManager().findAuthorizables(new Query() { @Override public void build(QueryBuilder builder) { builder.setSelector(User.class); } }); Set usersSet = new HashSet<>(); String adminUser = Constants.ADMIN_USER; Node homeNode = session.getNode("/Home"); while (result.hasNext()) { Authorizable user = result.next(); log.debug("user {} found", user.getPrincipal().getName()); if (user.getPrincipal().getName().equals(adminUser)) continue; long homeVersion = -1; try { Node userHome = homeNode.getNode(user.getPrincipal().getName()); if (userHome.hasProperty(Constants.HOME_VERSION_PROP)) homeVersion = userHome.getProperty(Constants.HOME_VERSION_PROP).getLong(); else homeVersion = 0; usersSet.add(new SHUBUser(user.getPrincipal().getName(), homeVersion)); } catch (Exception e) { log.warn("error retrieving user {} home", user.getPrincipal().getName()); } } users = new ArrayList<>(usersSet); Collections.sort(users); return users; } public SHUBUser getUser(JackrabbitSession session, String userId) throws StorageHubException, RepositoryException { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); Authorizable authorizable = usrManager.getAuthorizable(userId); if (authorizable != null && !authorizable.isGroup()) { long homeVersion = -1; try { Node homeNode = session.getNode("/Home"); Node userHome = homeNode.getNode(authorizable.getPrincipal().getName()); if (userHome.hasProperty(Constants.HOME_VERSION_PROP)) homeVersion = userHome.getProperty(Constants.HOME_VERSION_PROP).getLong(); else homeVersion = 0; } catch (Exception e) { log.warn("error retrieving user {} home", authorizable.getPrincipal().getName(), e); } return new SHUBUser(authorizable.getPrincipal().getName(), homeVersion); } else throw new NotFoundException("user", userId); } public String createUser(JackrabbitSession session, String user, String password) throws StorageHubException, RepositoryException { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); User createdUser = usrManager.createUser(user, password); String userId = createdUser.getID(); Node homeNode = session.getNode("/Home"); Node userHome = homeNode.addNode(user, "nthl:home"); userHome.setProperty(Constants.HOME_VERSION_PROP, 1l); // creating workspace folder FolderCreationParameters wsFolderParameters = FolderCreationParameters.builder() .name(Constants.WORKSPACE_ROOT_FOLDER_NAME).description("workspace of " + user).author(user) .on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(wsFolderParameters, null, true); // creating thrash folder FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder() .name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of " + user).author(user) .on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(trashFolderParameters, null, true); // creating Vre container folder FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder() .name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of " + user) .author(user).on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(vreFolderParameters, null, true); // creating inbox folder FolderCreationParameters inboxFolderParameters = FolderCreationParameters.builder() .name(Constants.INBOX_FOLDER_NAME).description("inbox of " + user).author(user) .on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(inboxFolderParameters, null, true); // creating outbox folder FolderCreationParameters outboxFolderParameters = FolderCreationParameters.builder() .name(Constants.OUTBOX_FOLDER_NAME).description("outbox of " + user).author(user) .on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(outboxFolderParameters, null, true); return userId; } public String updateHomeUserToLatestVersion(JackrabbitSession session, String user) throws StorageHubException, RepositoryException { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); Authorizable auth = usrManager.getAuthorizable(user); if (auth == null || auth.isGroup()) throw new InvalidCallParameters("invalid user passed"); Node homeNode = session.getNode("/Home"); Node userHome = homeNode.getNode(user); if (userHome == null) throw new BackendGenericError("home for user {} not found"); /* * //creating workspace folder FolderCreationParameters wsFolderParameters = * FolderCreationParameters.builder().name(Constants.WORKSPACE_ROOT_FOLDER_NAME) * .description("workspace of "+user).author(user).on(userHome.getIdentifier()). * with(session).build(); Utils.createFolderInternally(wsFolderParameters, null, * true); */ // updating thrash folder if (!userHome.hasProperty(Constants.HOME_VERSION_PROP) || userHome.getProperty(Constants.HOME_VERSION_PROP).getLong() < 1) { org.gcube.common.storagehub.model.Path workspacePath = Paths.append(Paths.getPath(userHome.getPath()), Constants.WORKSPACE_ROOT_FOLDER_NAME); Boolean oldTrashExists = session .nodeExists(Paths.append(workspacePath, Constants.TRASH_ROOT_FOLDER_NAME).toPath()); if (oldTrashExists) session.move(Paths.append(workspacePath, Constants.TRASH_ROOT_FOLDER_NAME).toPath(), Paths.append(Paths.getPath(userHome.getPath()), Constants.TRASH_ROOT_FOLDER_NAME).toPath()); else { FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder() .name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of " + user).author(user) .on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(trashFolderParameters, null, true); } Boolean oldVresExists = session .nodeExists(Paths.append(workspacePath, Constants.OLD_VRE_FOLDER_PARENT_NAME).toPath()); if (oldVresExists) session.move(Paths.append(workspacePath, Constants.OLD_VRE_FOLDER_PARENT_NAME).toPath(), Paths.append(Paths.getPath(userHome.getPath()), Constants.PERSONAL_VRES_FOLDER_PARENT_NAME) .toPath()); else { // creating Vre container folder FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder() .name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of " + user) .author(user).on(userHome.getIdentifier()).with(session).build(); Utils.createFolderInternally(vreFolderParameters, null, true); } } /* * //creating inbox folder FolderCreationParameters inboxFolderParameters = * FolderCreationParameters.builder().name(Constants.INBOX_FOLDER_NAME). * description("inbox of "+user).author(user).on(userHome.getIdentifier()).with( * session).build(); Utils.createFolderInternally(inboxFolderParameters, null, * true); * * //creating outbox folder FolderCreationParameters outboxFolderParameters = * FolderCreationParameters.builder().name(Constants.OUTBOX_FOLDER_NAME). * description("outbox of "+user).author(user).on(userHome.getIdentifier()).with * (session).build(); Utils.createFolderInternally(outboxFolderParameters, null, * true); */ userHome.setProperty(Constants.HOME_VERSION_PROP, 1l); return user; } public String deleteUser(JackrabbitSession session, String user) throws StorageHubException, RepositoryException { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); User authorizable = (User) 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, it should never happen", user); return user; } public List getGroupsPerUser(JackrabbitSession session, String user) throws RepositoryException { List groups = new ArrayList<>(); org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager(); User authUser = (User) usrManager.getAuthorizable(new PrincipalImpl(user)); Iterator groupsAuth = authUser.memberOf(); while (groupsAuth.hasNext()) { Authorizable group = groupsAuth.next(); groups.add(group.getPrincipal().getName()); } return groups; } 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(session, group.getPrincipal().getName(), user); 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 = pathUtil.getHome(user); org.gcube.common.storagehub.model.Path workspacePath = pathUtil.getWorkspacePath(user); try { Node workspaceNode = session.getNode(workspacePath.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); } catch (PathNotFoundException e) { log.warn("{} workspace dir {} was already deleted", user, homePath.toPath()); } try { org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(user, session); Node trashNode = session.getNode(trashPath.toPath()); List trashItems = Utils.getItemList(trashNode, Excludes.ALL, null, true, null); trashHandler.removeOnlyNodesContent(session, trashItems); } catch (PathNotFoundException e) { log.warn("{} trash dir {} was already deleted", user, homePath.toPath()); } try { Node homeNode = session.getNode(homePath.toPath()); homeNode.remove(); } catch (PathNotFoundException e) { log.warn("{} home dir {} was already deleted", user, homePath.toPath()); } } }