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 d910f09..1387eb4 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 @@ -60,9 +60,15 @@ public class UnshareHandler { Set usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getMap().keySet()); usersInSharedFolder.removeAll(users); - if (users==null || users.size()==0 || usersInSharedFolder.size()<=1) + if (users==null || users.size()==0) return unshareAll(login, ses, sharedItem); - + + if (usersInSharedFolder.size()<=1) { + if (users.size()==1 && users.contains(login)) + return unshareAll(sharedItem.getOwner(), ses , sharedItem); + else return unshareAll(login, ses, sharedItem); + } + try { ses.getWorkspace().getLockManager().lock(sharedNode.getPath(), true, true, 0,login); }catch (LockException e) { @@ -82,7 +88,6 @@ public class UnshareHandler { private String unshareAll(String login, Session ses, SharedFolder item) throws StorageHubException, BackendGenericError, RepositoryException{ log.info("unshare all called"); - authChecker.checkAdministratorControl(ses, item); if (!login.equals(item.getOwner())) throw new UserNotAuthorizedException("user "+login+" not authorized to unshare all"); @@ -166,7 +171,7 @@ public class UnshareHandler { item.getUsers().getMap().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try { newUsersNode.setProperty(entry.getKey(), (String)entry.getValue()); } catch (Exception e) { - log.error("error adding property to shared node users node under "+item.getId()); + log.error("error adding property to shared node users node under {}",item.getId()); }}); acm.setPolicy(sharedFolderNode.getPath(), acls); diff --git a/src/main/java/org/gcube/data/access/storagehub/services/ACLManager.java b/src/main/java/org/gcube/data/access/storagehub/services/ACLManager.java index 31941ac..9227378 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/ACLManager.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/ACLManager.java @@ -2,11 +2,13 @@ package org.gcube.data.access.storagehub.services; import java.security.Principal; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.jcr.Node; +import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.security.AccessControlEntry; @@ -14,11 +16,13 @@ import javax.jcr.security.AccessControlManager; import javax.jcr.security.Privilege; import javax.servlet.ServletContext; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; 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; @@ -43,6 +47,7 @@ import org.gcube.common.storagehub.model.items.SharedFolder; import org.gcube.common.storagehub.model.items.VreFolder; import org.gcube.common.storagehub.model.types.ACLList; import org.gcube.data.access.storagehub.AuthorizationChecker; +import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.handlers.CredentialHandler; import org.gcube.data.access.storagehub.handlers.Node2ItemConverter; import org.gcube.smartgears.utils.InnerMethodName; @@ -117,10 +122,10 @@ public class ACLManager { return new ACLList(acls); } - - + + /** - * Set a new AccessType for a user in a shared folder + * Set a new AccessType for a user in a shared folder or VRE folder * * * @param String user @@ -138,15 +143,19 @@ public class ACLManager { InnerMethodName.instance.set("setACLById"); Session ses = null; try{ + ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - + Node node = ses.getNodeByIdentifier(id); Item item = node2Item.getItem(node, Excludes.ALL); - + if (!(item instanceof SharedFolder)) throw new InvalidItemException("the item is not a shared folder"); - + + if (item.getOwner().equals(user)) + throw new UserNotAuthorizedException("owner acl cannot be changed"); + authChecker.checkAdministratorControl(ses, (SharedFolder) item); SharedFolder folder = ((SharedFolder)item); @@ -154,17 +163,17 @@ public class ACLManager { if (folder.isVreFolder()) { if (accessType!=AccessType.ADMINISTRATOR) throw new InvalidCallParameters("acls in vreFolder cannot be changed, only new admin can be set"); - + org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)ses).getUserManager(); String groupId = folder.getTitle(); - + Group group = (Group)usrManager.getAuthorizable(groupId); User authUser = (User)usrManager.getAuthorizable(user); - + if (!group.isMember(authUser)) throw new InvalidCallParameters("user "+user+" is not in the group "+groupId); - + String path = node.getPath(); AccessControlManager acm = ses.getAccessControlManager(); JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path); @@ -176,8 +185,14 @@ public class ACLManager { } else { - //TODO: probably must be changed with the shared set - if (!((SharedFolder) item).getUsers().getMap().containsKey(user)) + NodeIterator sharedSet = node.getSharedSet(); + boolean found = false; + while (sharedSet.hasNext() && !found) { + Node current = sharedSet.nextNode(); + if (current.getPath().startsWith(Utils.getWorkspacePath(user).toPath())) + found = true; + } + if (!found) throw new InvalidCallParameters("shared folder with id "+item.getId()+" is not shared with user "+user); String path = node.getPath(); @@ -200,7 +215,7 @@ public class ACLManager { acm.setPolicy(path, acls); ses.save(); } - + }catch(RepositoryException re){ log.error("jcr error extracting archive", re); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re)); @@ -213,8 +228,74 @@ public class ACLManager { } } - - + + /** + * remove right for a user only on VRE folder + * + * + * @param String user + * @param accessType accessType + * + * @exception {@link RepositoryException} when a generic jcr error occurs + * @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder + * @exception {@link InvalidCallParameters} when the folder is not shared with the specified user + * @exception {@link InvalidItemException} when the folder is not share + */ + /*@DELETE + @Consumes(MediaType.TEXT_PLAIN) + @Path("{id}/acls/{user}") + public void removeACL(@PathParam("user") String user) { + InnerMethodName.instance.set("removeACLById"); + Session ses = null; + try{ + ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + + Node node = ses.getNodeByIdentifier(id); + + Item item = node2Item.getItem(node, Excludes.ALL); + + if (!(item instanceof SharedFolder)) + throw new InvalidItemException("the item is not a shared folder"); + + authChecker.checkAdministratorControl(ses, (SharedFolder) item); + + SharedFolder folder = ((SharedFolder)item); + + if (folder.isVreFolder()) { + AccessControlManager acm = ses.getAccessControlManager(); + JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath()); + + + AccessControlEntry entryToDelete= null; + for (AccessControlEntry ace :acls.getAccessControlEntries()) { + if (ace.getPrincipal().getName().equals(user)) { + entryToDelete = ace; + break; + } + + } + if (entryToDelete!=null) + acls.removeAccessControlEntry(entryToDelete); + else return; + + acm.setPolicy(folder.getPath(), acls); + ses.save(); + log.debug("removed Access control entry for user {}",user); + + } else throw new InvalidCallParameters("remove acl can be called only on VRE folder"); + + }catch(RepositoryException re){ + log.error("jcr error extracting archive", re); + GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re)); + }catch(StorageHubException she ){ + log.error(she.getErrorMessage(), she); + GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); + }finally{ + if (ses!=null) + ses.logout(); + } + }*/ + @GET @Path("{id}/acls/write") public Boolean canWriteInto() { diff --git a/src/main/java/org/gcube/data/access/storagehub/services/ItemsManager.java b/src/main/java/org/gcube/data/access/storagehub/services/ItemsManager.java index deee7a5..dce3abd 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/ItemsManager.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/ItemsManager.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.Deque; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.zip.Deflater; import java.util.zip.ZipOutputStream; @@ -44,7 +43,6 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.FilenameUtils; -import org.gcube.accounting.datamodel.usagerecords.StorageUsageRecord; import org.gcube.common.authorization.control.annotations.AuthorizationControl; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.encryption.StringEncrypter; @@ -61,7 +59,6 @@ import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters; import org.gcube.common.storagehub.model.exceptions.InvalidItemException; import org.gcube.common.storagehub.model.exceptions.ItemLockedException; import org.gcube.common.storagehub.model.exceptions.StorageHubException; -import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; import org.gcube.common.storagehub.model.items.AbstractFileItem; import org.gcube.common.storagehub.model.items.FolderItem; import org.gcube.common.storagehub.model.items.Item; @@ -86,7 +83,6 @@ import org.gcube.data.access.storagehub.handlers.Node2ItemConverter; import org.gcube.data.access.storagehub.handlers.StorageBackendHandler; import org.gcube.data.access.storagehub.handlers.TrashHandler; import org.gcube.data.access.storagehub.handlers.VersionHandler; -import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend; import org.gcube.smartgears.utils.InnerMethodName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/webapp/WEB-INF/README b/src/main/webapp/WEB-INF/README index 397c151..6476e3b 100644 --- a/src/main/webapp/WEB-INF/README +++ b/src/main/webapp/WEB-INF/README @@ -25,7 +25,7 @@ no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001). Version -------------------------------------------------- -1.0.7-SNAPSHOT (2019-08-01) +1.0.7-SNAPSHOT (2019-09-16) Please see the file named "changelog.xml" in this directory for the release notes.