398 lines
15 KiB
Java
398 lines
15 KiB
Java
package org.gcube.data.access.storagehub.services.delegates;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
import javax.jcr.ItemNotFoundException;
|
|
import javax.jcr.Node;
|
|
import javax.jcr.NodeIterator;
|
|
import javax.jcr.PathNotFoundException;
|
|
import javax.jcr.RepositoryException;
|
|
import javax.jcr.security.AccessControlEntry;
|
|
import javax.jcr.security.AccessControlManager;
|
|
import javax.jcr.security.Privilege;
|
|
|
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
|
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.commons.jackrabbit.authorization.AccessControlUtils;
|
|
import org.gcube.common.security.ContextBean;
|
|
import org.gcube.common.security.ContextBean.Type;
|
|
import org.gcube.common.security.providers.SecretManagerProvider;
|
|
import org.gcube.common.storagehub.model.Excludes;
|
|
import org.gcube.common.storagehub.model.Paths;
|
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
|
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.items.Item;
|
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
|
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
|
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.TrashHandler;
|
|
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
|
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
|
import org.gcube.data.access.storagehub.services.GroupManager;
|
|
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import jakarta.inject.Inject;
|
|
import jakarta.inject.Singleton;
|
|
|
|
@Singleton
|
|
public class GroupManagerDelegate {
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
|
|
|
@Inject
|
|
PathUtil pathUtil;
|
|
|
|
@Inject
|
|
TrashHandler trashHandler;
|
|
|
|
@Inject
|
|
ACLManagerInterface aclManagerDelegate;
|
|
|
|
private final StoragehubRepository repository = StoragehubRepository.repository;
|
|
|
|
public List<String> getGroups(JackrabbitSession session) throws RepositoryException {
|
|
List<String> groups = new ArrayList<>();
|
|
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
|
|
|
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
|
|
@Override
|
|
public <T> void build(QueryBuilder<T> builder) {
|
|
builder.setSelector(Group.class);
|
|
}
|
|
});
|
|
|
|
while (result.hasNext()) {
|
|
Authorizable group = result.next();
|
|
log.info("group {} found", group.getPrincipal().getName());
|
|
groups.add(group.getPrincipal().getName());
|
|
}
|
|
return groups;
|
|
|
|
}
|
|
|
|
public void createGroup(JackrabbitSession session, String groupId, AccessType accessType, String folderOwner,
|
|
boolean useDefaultStorage) throws StorageHubException, Throwable {
|
|
|
|
log.info("create group called with groupid {} , accessType {} and folderOwner {}", groupId, accessType,
|
|
folderOwner);
|
|
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
|
|
|
Group createdGroup = usrManager.createGroup(groupId);
|
|
|
|
User user = (User) usrManager.getAuthorizable(folderOwner);
|
|
|
|
createVreFolder(session, groupId, accessType != null ? accessType : AccessType.WRITE_OWNER, folderOwner,
|
|
useDefaultStorage);
|
|
|
|
boolean success = this.internalAddUserToGroup(session, createdGroup, user);
|
|
|
|
if (!success)
|
|
log.warn("the user have not been added to the group");
|
|
else
|
|
log.debug("the user have been added to the group");
|
|
|
|
}
|
|
|
|
public void deleteGroup(JackrabbitSession session, String group) throws RepositoryException {
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
|
Authorizable authorizable = usrManager.getAuthorizable(group);
|
|
if (authorizable != null && authorizable.isGroup())
|
|
authorizable.remove();
|
|
|
|
try {
|
|
Node node = this.getFolderNodeRelatedToGroup(session, group);
|
|
List<Item> workspaceItems = Utils.getItemList(node, Excludes.GET_ONLY_CONTENT, null, true, null);
|
|
trashHandler.removeOnlyNodesContent(session, workspaceItems);
|
|
node.removeSharedSet();
|
|
} catch (Exception e) {
|
|
log.warn("vreFolder {} not found, removing only the group", group);
|
|
}
|
|
|
|
}
|
|
|
|
public void addAdministratorToGroup(JackrabbitSession session, String groupId, String userId)
|
|
throws StorageHubException, Throwable {
|
|
Objects.nonNull(groupId);
|
|
Objects.nonNull(userId);
|
|
|
|
Node vreFolder = this.getFolderNodeRelatedToGroup(session, groupId);
|
|
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession) session).getUserManager();
|
|
|
|
Group group = (Group) usrManager.getAuthorizable(groupId);
|
|
User authUser = (User) usrManager.getAuthorizable(userId);
|
|
|
|
if (group == null)
|
|
throw new NotFoundException("group", groupId);
|
|
if (authUser == null)
|
|
throw new NotFoundException("user", userId);
|
|
if (!group.isMember(authUser))
|
|
throw new InvalidCallParameters(String.format("user %s is not in the group %s", userId, groupId));
|
|
|
|
aclManagerDelegate.update(userId, vreFolder , AccessType.ADMINISTRATOR, session);
|
|
|
|
/*
|
|
AccessControlManager acm = session.getAccessControlManager();
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
|
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
Principal principal = AccessControlUtils.getPrincipal(session, userId);
|
|
acls.addAccessControlEntry(principal, userPrivileges);
|
|
acm.setPolicy(vreFolder.getPath(), acls);
|
|
*/
|
|
}
|
|
|
|
public void removeAdministratorFromGroup(JackrabbitSession session, String groupId, String userId)
|
|
throws StorageHubException, Throwable {
|
|
|
|
Objects.nonNull(groupId);
|
|
Objects.nonNull(userId);
|
|
|
|
if (!this.getGroupAdministators(session, groupId).contains(userId))
|
|
throw new InvalidCallParameters(String.format("user %s is not admin of the group %s", userId, groupId));
|
|
|
|
Node vreFolder = this.getFolderNodeRelatedToGroup(session, groupId);
|
|
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession) session).getUserManager();
|
|
|
|
Group group = (Group) usrManager.getAuthorizable(groupId);
|
|
User authUser = (User) usrManager.getAuthorizable(userId);
|
|
|
|
if (group == null)
|
|
throw new NotFoundException("group", groupId);
|
|
if (authUser == null)
|
|
throw new NotFoundException("user", userId);
|
|
|
|
AccessControlManager acm = session.getAccessControlManager();
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
|
|
|
|
AccessControlEntry toRemove = null;
|
|
for (AccessControlEntry acl : acls.getAccessControlEntries())
|
|
if (acl.getPrincipal().getName().equals(userId)) {
|
|
toRemove = acl;
|
|
break;
|
|
}
|
|
|
|
acls.removeAccessControlEntry(toRemove);
|
|
acm.setPolicy(vreFolder.getPath(), acls);
|
|
|
|
}
|
|
|
|
public List<String> getGroupAdministators(JackrabbitSession session, String groupId) throws Throwable {
|
|
|
|
List<String> users = new ArrayList<String>();
|
|
Node node = getFolderNodeRelatedToGroup(session, groupId);
|
|
AccessControlManager acm = session.getAccessControlManager();
|
|
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, node.getPath());
|
|
|
|
for (AccessControlEntry acl : acls.getAccessControlEntries())
|
|
for (Privilege pr : acl.getPrivileges()) {
|
|
if (pr.getName().equals(AccessType.ADMINISTRATOR.getValue())) {
|
|
users.add(acl.getPrincipal().getName());
|
|
}
|
|
|
|
}
|
|
|
|
return users;
|
|
}
|
|
|
|
public void addUserToGroup(JackrabbitSession session, String userId, String groupId) 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 (user == null)
|
|
throw new InvalidCallParameters("user " + userId + " not exists");
|
|
|
|
if (group.isMember(user))
|
|
throw new InvalidCallParameters("user " + userId + " is already member of group " + groupId);
|
|
|
|
this.internalAddUserToGroup(session, group, user);
|
|
|
|
}
|
|
|
|
public boolean removeUserFromGroup(JackrabbitSession session, String groupId, String userId)
|
|
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(String.format("user %s is not in the group %s", userId, groupId));
|
|
|
|
// delete folder on user
|
|
String folderName = group.getPrincipal().getName();
|
|
Node folder = getFolderNodeRelatedToGroup(session, folderName);
|
|
|
|
// Removing the ACL for the user
|
|
AccessControlManager acm = session.getAccessControlManager();
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
|
AccessControlEntry entryToDelete = null;
|
|
for (AccessControlEntry ace : acls.getAccessControlEntries()) {
|
|
if (ace.getPrincipal().getName().equals(userId)) {
|
|
entryToDelete = ace;
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (entryToDelete != null)
|
|
acls.removeAccessControlEntry(entryToDelete);
|
|
|
|
boolean found = false;
|
|
NodeIterator ni = folder.getSharedSet();
|
|
while (ni.hasNext()) {
|
|
Node node = ni.nextNode();
|
|
if (node.getPath().startsWith(pathUtil.getVREsPath(userId, session).toPath())) {
|
|
node.removeShare();
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
log.warn("sharing not removed for user {} ", userId);
|
|
|
|
return group.removeMember(user);
|
|
}
|
|
|
|
public List<String> getUsersBelongingToGroup(JackrabbitSession session, String groupId)
|
|
throws StorageHubException, RepositoryException {
|
|
List<String> users = new ArrayList<>();
|
|
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
|
|
|
Group group = (Group) usrManager.getAuthorizable(groupId);
|
|
|
|
Iterator<Authorizable> it = group.getMembers();
|
|
|
|
while (it.hasNext()) {
|
|
Authorizable user = it.next();
|
|
users.add(user.getPrincipal().getName());
|
|
}
|
|
return users;
|
|
|
|
}
|
|
|
|
public Node getFolderNodeRelatedToGroup(JackrabbitSession session, String name)
|
|
throws ItemNotFoundException, 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");
|
|
}
|
|
|
|
if (vreFolder == null) {
|
|
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 ItemNotFoundException("vre folder not found for group " + name);
|
|
return vreFolder;
|
|
}
|
|
|
|
private void createVreFolder(JackrabbitSession session, String groupId, AccessType defaultAccessType, String owner,
|
|
boolean useDefaultStorage) throws Exception {
|
|
|
|
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
|
|
|
String name = groupId;
|
|
|
|
String currentScope = SecretManagerProvider.get().getContext();
|
|
ContextBean bean = new ContextBean(currentScope);
|
|
while (!bean.is(Type.INFRASTRUCTURE)) {
|
|
bean = bean.enclosingScope();
|
|
}
|
|
String root = bean.toString().replaceAll("/", "");
|
|
|
|
String displayName = groupId.replaceAll(root + "-[^\\-]*\\-(.*)", "$1");
|
|
|
|
log.info("creating vreFolder with name {} and title {} and owner {} and default storage {}", name, displayName,
|
|
owner, useDefaultStorage);
|
|
|
|
FolderCreationParameters folderParameters;
|
|
if (!useDefaultStorage)
|
|
folderParameters = FolderCreationParameters.builder().onRepository("gcube-minio")
|
|
.withParameters(Collections.singletonMap("bucketName", name + "-gcube-vre")).name(name)
|
|
.description("VREFolder for " + groupId).author(owner).on(sharedRootNode.getIdentifier())
|
|
.with(session).build();
|
|
else
|
|
folderParameters = FolderCreationParameters.builder().name(name).description("VREFolder for " + groupId)
|
|
.author(owner).on(sharedRootNode.getIdentifier()).with(session).build();
|
|
|
|
Node folder = Utils.createFolderInternally(folderParameters, null, useDefaultStorage);
|
|
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
|
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
|
|
folder.setProperty(NodeProperty.TITLE.toString(), name);
|
|
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), displayName);
|
|
session.save();
|
|
|
|
AccessControlManager acm = session.getAccessControlManager();
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
|
|
|
/*
|
|
* Privilege[] adminPrivileges = new Privilege[] {
|
|
* acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
* acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,
|
|
* AuthorizationProvider.instance.get().getClient().getId()), adminPrivileges );
|
|
*/
|
|
|
|
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
|
|
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session, groupId), usersPrivileges);
|
|
acm.setPolicy(folder.getPath(), acls);
|
|
|
|
log.debug("vrefolder created with id {}", folder.getIdentifier());
|
|
}
|
|
|
|
private boolean internalAddUserToGroup(JackrabbitSession session, Group group, User user)
|
|
throws RepositoryException, StorageHubException {
|
|
boolean success = group.addMember(user);
|
|
session.save();
|
|
String folderName = group.getPrincipal().getName();
|
|
Node folder = this.getFolderNodeRelatedToGroup(session, folderName);
|
|
|
|
String userPath = Paths.append(pathUtil.getVREsPath(user.getPrincipal().getName(), session), folderName)
|
|
.toPath();
|
|
log.debug("creating folder in user path {} from {}", userPath, folder.getPath());
|
|
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(), userPath, false);
|
|
|
|
try {
|
|
session.getNode(userPath);
|
|
log.debug("the new folder exists ({}) ", userPath);
|
|
} catch (PathNotFoundException e) {
|
|
log.debug("the new folder doesn't exists ({}) ", userPath);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
}
|