storagehub/src/main/java/org/gcube/data/access/storagehub/handlers/UserHandler.java

393 lines
15 KiB
Java

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<SHUBUser> getAllUsers(JackrabbitSession session) throws Throwable {
List<SHUBUser> users = null;
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(User.class);
}
});
Set<SHUBUser> 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<String> getGroupsPerUser(JackrabbitSession session, String user)
throws RepositoryException {
List<String> groups = new ArrayList<>();
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
User authUser = (User) usrManager.getAuthorizable(new PrincipalImpl(user));
Iterator<Group> 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<Authorizable> groups = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> 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<Node> sharedWithUserChecker = new Predicate<Node>() {
@Override
public boolean test(Node t) {
try {
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
return true;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
List<SharedFolder> 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<String> 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<Item> 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<Item> 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());
}
}
}