393 lines
15 KiB
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());
|
|
}
|
|
}
|
|
}
|