From 3ca3e705341cde7fca8606f81231c0e6b3c3cacb Mon Sep 17 00:00:00 2001 From: Lucio Lelii Date: Thu, 14 Feb 2019 11:01:59 +0000 Subject: [PATCH] git-svn-id: https://svn.d4science-ii.research-infrastructures.eu/gcube/branches/data-access/storagehub-webapp/1.0@177129 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../gcube/data/access/storagehub/Utils.java | 4 +- .../handlers/Item2NodeConverter.java | 6 +- .../storagehub/handlers/TrashHandler.java | 2 +- .../storagehub/handlers/UnshareHandler.java | 2 +- .../storagehub/handlers/VersionHandler.java | 2 +- .../storagehub/services/ACLManager.java | 92 ++++++++++++++++++- .../storagehub/services/ItemsCreator.java | 39 +++++--- .../storagehub/services/ItemsManager.java | 4 +- 8 files changed, 127 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/gcube/data/access/storagehub/Utils.java b/src/main/java/org/gcube/data/access/storagehub/Utils.java index eeef0d9..2ad6643 100644 --- a/src/main/java/org/gcube/data/access/storagehub/Utils.java +++ b/src/main/java/org/gcube/data/access/storagehub/Utils.java @@ -298,7 +298,7 @@ public class Utils { //to inherit hidden property //item.setHidden(destinationItem.isHidden()); - Node newNode = new Item2NodeConverter().getNode(ses, destinationNode, item); + Node newNode = new Item2NodeConverter().getNode(destinationNode, item); if (accountingHandler!=null) accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false); return newNode; @@ -319,7 +319,7 @@ public class Utils { //to inherit hidden property //item.setHidden(destinationItem.isHidden()); - Node newNode = new Item2NodeConverter().getNode(ses, destinationNode, gcubeItem); + Node newNode = new Item2NodeConverter().getNode(destinationNode, gcubeItem); //TODO: accounting for GCUBEITEM //accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false); return newNode; diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/Item2NodeConverter.java b/src/main/java/org/gcube/data/access/storagehub/handlers/Item2NodeConverter.java index 474d662..750ce11 100644 --- a/src/main/java/org/gcube/data/access/storagehub/handlers/Item2NodeConverter.java +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/Item2NodeConverter.java @@ -44,7 +44,7 @@ public class Item2NodeConverter { private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class); - public Node getNode(Session session, Node parentNode, T item){ + public Node getNode(Node parentNode, T item){ try { String primaryType= ClassHandler.instance().getNodeType(item.getClass()); Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType); @@ -180,7 +180,7 @@ public class Item2NodeConverter { return fields; } - public void replaceContent(Session session, Node node, F item, ItemAction action){ + public void replaceContent(Node node, F item, ItemAction action){ try { node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value()); @@ -215,7 +215,7 @@ public class Item2NodeConverter { } - public void updateMetadataNode(Session session, Node node, Map meta, String login){ + public void updateMetadataNode(Node node, Map meta, String login){ try { //TODO: make a method to update item not only metadata, check if the new metadata has an intersection with the old one to remove properties not needed diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/TrashHandler.java b/src/main/java/org/gcube/data/access/storagehub/handlers/TrashHandler.java index a1a3b93..598924c 100644 --- a/src/main/java/org/gcube/data/access/storagehub/handlers/TrashHandler.java +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/TrashHandler.java @@ -139,7 +139,7 @@ public class TrashHandler { log.debug("creating node"); - Node newTrashItemNode = item2Node.getNode(ses, trashFolder, trashItem); + Node newTrashItemNode = item2Node.getNode(trashFolder, trashItem); ses.save(); log.debug("calling jcr move"); 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 b19a26d..e6e8d3b 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 @@ -245,7 +245,7 @@ public class UnshareHandler { //to inherit hidden property //item.setHidden(destinationItem.isHidden()); - Node newNode = item2Node.getNode(ses, destinationNode, item); + Node newNode = item2Node.getNode(destinationNode, item); return newNode; } } diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/VersionHandler.java b/src/main/java/org/gcube/data/access/storagehub/handlers/VersionHandler.java index a97628a..d4e0353 100644 --- a/src/main/java/org/gcube/data/access/storagehub/handlers/VersionHandler.java +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/VersionHandler.java @@ -26,7 +26,7 @@ public class VersionHandler { try { Node contentNode = node.getNode(NodeConstants.CONTENT_NAME); contentNode.addMixin(JcrConstants.MIX_VERSIONABLE); - }catch(Exception e ) { + }catch(Throwable e ) { logger.warn("cannot create versioned content node",e); } } 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 03746ba..cfcc619 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 @@ -1,16 +1,21 @@ package org.gcube.data.access.storagehub.services; +import java.security.Principal; import java.util.ArrayList; import java.util.List; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; +import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.security.AccessControlEntry; +import javax.jcr.security.AccessControlManager; import javax.jcr.security.Privilege; import javax.servlet.ServletContext; +import javax.ws.rs.FormParam; 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; @@ -20,13 +25,19 @@ import javax.ws.rs.core.MediaType; import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; +import org.gcube.common.storagehub.model.Excludes; import org.gcube.common.storagehub.model.acls.ACL; import org.gcube.common.storagehub.model.acls.AccessType; import org.gcube.common.storagehub.model.exceptions.BackendGenericError; +import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters; +import org.gcube.common.storagehub.model.exceptions.InvalidItemException; import org.gcube.common.storagehub.model.exceptions.StorageHubException; +import org.gcube.common.storagehub.model.items.Item; +import org.gcube.common.storagehub.model.items.SharedFolder; import org.gcube.common.storagehub.model.types.ACLList; import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.handlers.CredentialHandler; +import org.gcube.data.access.storagehub.handlers.Node2ItemConverter; import org.gcube.smartgears.utils.InnerMethodName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,9 +57,18 @@ public class ACLManager { @Context ServletContext context; + + @Inject Node2ItemConverter node2Item; + @Inject AuthorizationChecker authChecker; + /** + * returns the AccessType for all the users in a shared folder + * + * @exception {@link RepositoryException} when a generic jcr error occurs + * @exception {@link UserNotAuthorizedException} when the caller is not authorized to access to the shared folder + */ @Produces(MediaType.APPLICATION_JSON) @GET @Path("{id}/acls") @@ -77,10 +97,10 @@ public class ACLManager { } }catch(RepositoryException re){ - log.error("jcr error extracting archive", re); - GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re)); + log.error("jcr error getting acl", re); + GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re)); }catch(StorageHubException she ){ - log.error("error creating file item", she); + log.error("error getting acl", she); GXOutboundErrorResponse.throwException(she); }finally{ if (ses!=null) @@ -90,4 +110,70 @@ public class ACLManager { } + /** + * Set a new AccessType for a user in a shared 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 + */ + @PUT + @Path("{id}/acls") + public void setACL(@FormParam("user") String user, @FormParam("access") AccessType accessType) { + 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) || ((SharedFolder) item).isVreFolder() ) + throw new InvalidItemException("the item is not a shared folder"); + + authChecker.checkAdministratorControl(ses, (SharedFolder) item); + + if (!((SharedFolder) item).getUsers().getMap().containsKey(user)) + throw new InvalidCallParameters("shared folder with id "+item.getId()+" is not shared with user "+user); + + String path = node.getPath(); + + AccessControlManager acm = ses.getAccessControlManager(); + JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path); + Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) }; + + AccessControlEntry aceToDelete = null;; + Principal principal = AccessControlUtils.getPrincipal(ses, user); + for (AccessControlEntry ace : acls.getAccessControlEntries()) + if (ace.getPrincipal().equals(principal)) { + aceToDelete = ace; + break; + } + + + if (aceToDelete!= null) + acls.removeAccessControlEntry(aceToDelete); + acls.addAccessControlEntry(principal, userPrivileges); + 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)); + }catch(StorageHubException she ){ + log.error("error setting acl", she); + GXOutboundErrorResponse.throwException(she); + }finally{ + if (ses!=null) + ses.logout(); + } + + } + } diff --git a/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java b/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java index 86e90eb..ed583ba 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java @@ -15,9 +15,13 @@ import java.util.concurrent.Future; import javax.inject.Inject; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; +import javax.jcr.NodeIterator; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; +import javax.jcr.lock.LockManager; import javax.servlet.ServletContext; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; @@ -32,6 +36,7 @@ import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.jackrabbit.commons.cnd.TemplateBuilderFactory.NodeDefinitionTemplateBuilder; import org.apache.tika.config.TikaConfig; import org.apache.tika.detect.Detector; import org.apache.tika.io.TikaInputStream; @@ -49,6 +54,7 @@ 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.GCubeItem; +import org.gcube.common.storagehub.model.items.SharedFolder; import org.gcube.common.storagehub.model.types.ItemAction; import org.gcube.contentmanagement.blobstorage.service.IClient; import org.gcube.data.access.storagehub.AuthorizationChecker; @@ -207,7 +213,6 @@ public class ItemsCreator { @POST @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces(MediaType.TEXT_PLAIN) @Path("/{id}/create/FILE") public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name, @FormDataParam("description") String description, @@ -218,26 +223,34 @@ public class ItemsCreator { Session ses = null; String toReturn = null; try{ - if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null"); + if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null or empty"); final String login = AuthorizationProvider.instance.get().getClient().getId(); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); Node destination = ses.getNodeByIdentifier(id); - + log.info("create file called with filename {} in dir {} ", name, destination.getPath() ); if (!node2Item.checkNodeType(destination, FolderItem.class)) throw new InvalidItemException("the destination item is not a folder"); - - ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login); + + LockManager lockManager = ses.getWorkspace().getLockManager(); + lockManager.lock(destination.getPath(), false, true, 0,login); + log.info("session: {}",ses.toString()); Node newNode; try { newNode = createFileItemInternally(ses, destination, stream, name, description, login); + ses.save(); } finally { - ses.getWorkspace().getLockManager().unlock(destination.getPath()); + log.info("session: {}",ses.toString()); + try { + lockManager.unlock(destination.getPath()); + }catch(LockException e) { + log.warn("error unlocking item id {} with path {}",destination.getIdentifier(), destination.getPath(), e); + } } versionHandler.checkinContentNode(newNode, ses); @@ -249,9 +262,14 @@ public class ItemsCreator { }catch(StorageHubException she ){ log.error("error creating file item", she); GXOutboundErrorResponse.throwException(she); - } finally{ - if (ses!=null) + }catch(Throwable e ){ + log.error("unexpected error", e); + GXOutboundErrorResponse.throwException(new BackendGenericError(e)); + }finally{ + if (ses!=null && ses.isLive()) { + log.info("session closed"); ses.logout(); + } } return toReturn; @@ -277,11 +295,10 @@ public class ItemsCreator { authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false); versionHandler.checkoutContentNode(newNode, ses); log.trace("replacing content of class {}",item.getContent().getClass()); - item2Node.replaceContent(ses, newNode,item, ItemAction.UPDATED); + item2Node.replaceContent(newNode,item, ItemAction.UPDATED); }catch(PathNotFoundException pnf) { - log.info("creating new node"); authChecker.checkWriteAuthorizationControl(ses, destinationNode.getIdentifier(), true); - newNode = item2Node.getNode(ses, destinationNode, item); + newNode = item2Node.getNode(destinationNode, item); versionHandler.makeVersionableContent(newNode, ses); } 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 245b549..15688a0 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 @@ -796,7 +796,7 @@ public class ItemsManager { log.info("copying storage Id {} to newPath {} and the id returned by storage is {}", oldStorageId, newPath, newStorageID); ((AbstractFileItem) item).getContent().setStorageId(newStorageID); ((AbstractFileItem) item).getContent().setRemotePath(newPath); - item2Node.replaceContent(ses, newNode, (AbstractFileItem) item, ItemAction.CLONED); + item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED); } Utils.setPropertyOnChangeNode(newNode, login, ItemAction.CLONED); @@ -905,7 +905,7 @@ public class ItemsManager { ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,login); try { - item2Node.updateMetadataNode(ses, nodeToUpdate, metadata.getMap(), login); + item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), login); ses.save(); }finally { ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());