2018-05-28 12:01:01 +02:00
|
|
|
package org.gcube.data.access.storagehub.services;
|
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
import java.security.Principal;
|
2018-05-28 12:01:01 +02:00
|
|
|
import java.util.ArrayList;
|
2019-09-16 16:36:26 +02:00
|
|
|
import java.util.Iterator;
|
2018-05-28 12:01:01 +02:00
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import javax.enterprise.context.RequestScoped;
|
|
|
|
import javax.inject.Inject;
|
2019-02-14 12:01:59 +01:00
|
|
|
import javax.jcr.Node;
|
2019-09-16 16:36:26 +02:00
|
|
|
import javax.jcr.NodeIterator;
|
2018-10-25 16:33:23 +02:00
|
|
|
import javax.jcr.RepositoryException;
|
2018-05-28 12:01:01 +02:00
|
|
|
import javax.jcr.Session;
|
|
|
|
import javax.jcr.security.AccessControlEntry;
|
2019-02-14 12:01:59 +01:00
|
|
|
import javax.jcr.security.AccessControlManager;
|
2018-05-28 12:01:01 +02:00
|
|
|
import javax.jcr.security.Privilege;
|
|
|
|
import javax.servlet.ServletContext;
|
2019-05-22 17:47:15 +02:00
|
|
|
import javax.ws.rs.Consumes;
|
2019-09-16 16:36:26 +02:00
|
|
|
import javax.ws.rs.DELETE;
|
2018-05-28 12:01:01 +02:00
|
|
|
import javax.ws.rs.GET;
|
2019-02-14 12:01:59 +01:00
|
|
|
import javax.ws.rs.PUT;
|
2018-05-28 12:01:01 +02:00
|
|
|
import javax.ws.rs.Path;
|
|
|
|
import javax.ws.rs.PathParam;
|
|
|
|
import javax.ws.rs.Produces;
|
2019-09-16 16:36:26 +02:00
|
|
|
import javax.ws.rs.QueryParam;
|
2018-05-28 12:01:01 +02:00
|
|
|
import javax.ws.rs.core.Context;
|
|
|
|
import javax.ws.rs.core.MediaType;
|
2019-03-26 17:09:26 +01:00
|
|
|
import javax.ws.rs.core.Response;
|
2018-05-28 12:01:01 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
2019-07-29 16:26:08 +02:00
|
|
|
import org.apache.jackrabbit.api.security.user.Group;
|
|
|
|
import org.apache.jackrabbit.api.security.user.User;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
2019-02-14 12:01:59 +01:00
|
|
|
import org.gcube.common.storagehub.model.Excludes;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.gcube.common.storagehub.model.acls.ACL;
|
|
|
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
2019-02-14 12:01:59 +01:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
2019-05-30 18:26:14 +02:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
2019-06-05 18:00:57 +02:00
|
|
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
2019-02-14 12:01:59 +01:00
|
|
|
import org.gcube.common.storagehub.model.items.Item;
|
|
|
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
2019-07-29 16:26:08 +02:00
|
|
|
import org.gcube.common.storagehub.model.items.VreFolder;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.gcube.common.storagehub.model.types.ACLList;
|
|
|
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
2019-09-16 16:36:26 +02:00
|
|
|
import org.gcube.data.access.storagehub.Utils;
|
2018-07-03 12:15:35 +02:00
|
|
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
2019-02-14 12:01:59 +01:00
|
|
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
2018-07-05 16:26:08 +02:00
|
|
|
import org.gcube.smartgears.utils.InnerMethodName;
|
2019-05-22 17:47:15 +02:00
|
|
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2018-06-29 16:59:24 +02:00
|
|
|
@Path("items")
|
2018-05-28 12:01:01 +02:00
|
|
|
public class ACLManager {
|
|
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
RepositoryInitializer repository;
|
|
|
|
|
|
|
|
@RequestScoped
|
|
|
|
@PathParam("id")
|
|
|
|
String id;
|
|
|
|
|
|
|
|
@Context
|
|
|
|
ServletContext context;
|
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
|
|
|
|
@Inject Node2ItemConverter node2Item;
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2018-05-28 12:01:01 +02:00
|
|
|
@Inject
|
|
|
|
AuthorizationChecker authChecker;
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2018-05-28 12:01:01 +02:00
|
|
|
@GET
|
|
|
|
@Path("{id}/acls")
|
2019-03-26 17:40:44 +01:00
|
|
|
@Produces(MediaType.APPLICATION_JSON)
|
2018-05-28 12:01:01 +02:00
|
|
|
public ACLList getACL() {
|
2018-07-05 16:26:08 +02:00
|
|
|
InnerMethodName.instance.set("getACLById");
|
2018-05-28 12:01:01 +02:00
|
|
|
Session ses = null;
|
|
|
|
List<ACL> acls = new ArrayList<>();
|
|
|
|
try{
|
2018-07-03 12:15:35 +02:00
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2018-05-28 12:01:01 +02:00
|
|
|
authChecker.checkReadAuthorizationControl(ses, id);
|
2018-06-05 15:33:36 +02:00
|
|
|
String path = ses.getNodeByIdentifier(id).getPath();
|
|
|
|
log.info("checking acces for path {}",path);
|
|
|
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(ses, path );
|
2018-05-28 12:01:01 +02:00
|
|
|
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
|
|
|
|
ACL acl = new ACL();
|
|
|
|
acl.setPricipal(aclEntry.getPrincipal().getName());
|
|
|
|
List<AccessType> types = new ArrayList<>();
|
|
|
|
for (Privilege priv : aclEntry.getPrivileges())
|
|
|
|
try {
|
|
|
|
types.add(AccessType.fromValue(priv.getName()));
|
|
|
|
}catch (Exception e) {
|
|
|
|
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
|
|
|
|
}
|
|
|
|
acl.setAccessTypes(types);
|
|
|
|
acls.add(acl);
|
|
|
|
}
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(RepositoryException re){
|
2019-02-14 12:01:59 +01:00
|
|
|
log.error("jcr error getting acl", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re));
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(StorageHubException she ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2018-05-28 12:01:01 +02:00
|
|
|
}finally{
|
|
|
|
if (ses!=null)
|
|
|
|
ses.logout();
|
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
return new ACLList(acls);
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2018-05-28 12:01:01 +02:00
|
|
|
}
|
2019-09-16 16:36:26 +02:00
|
|
|
|
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
/**
|
2019-09-16 16:36:26 +02:00
|
|
|
* Set a new AccessType for a user in a shared folder or VRE folder
|
2019-02-14 12:01:59 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* @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
|
2019-05-22 17:47:15 +02:00
|
|
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
2019-02-14 12:01:59 +01:00
|
|
|
@Path("{id}/acls")
|
2019-05-22 17:47:15 +02:00
|
|
|
public void setACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
2019-02-14 12:01:59 +01:00
|
|
|
InnerMethodName.instance.set("setACLById");
|
|
|
|
Session ses = null;
|
|
|
|
try{
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
Node node = ses.getNodeByIdentifier(id);
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-05-22 17:47:15 +02:00
|
|
|
if (!(item instanceof SharedFolder))
|
2019-02-14 12:01:59 +01:00
|
|
|
throw new InvalidItemException("the item is not a shared folder");
|
2019-09-16 16:36:26 +02:00
|
|
|
|
|
|
|
if (item.getOwner().equals(user))
|
|
|
|
throw new UserNotAuthorizedException("owner acl cannot be changed");
|
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
|
|
|
|
|
2019-05-22 17:47:15 +02:00
|
|
|
SharedFolder folder = ((SharedFolder)item);
|
|
|
|
|
|
|
|
if (folder.isVreFolder()) {
|
|
|
|
if (accessType!=AccessType.ADMINISTRATOR)
|
|
|
|
throw new InvalidCallParameters("acls in vreFolder cannot be changed, only new admin can be set");
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)ses).getUserManager();
|
|
|
|
|
|
|
|
String groupId = folder.getTitle();
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
Group group = (Group)usrManager.getAuthorizable(groupId);
|
|
|
|
User authUser = (User)usrManager.getAuthorizable(user);
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
if (!group.isMember(authUser))
|
|
|
|
throw new InvalidCallParameters("user "+user+" is not in the group "+groupId);
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
String path = node.getPath();
|
|
|
|
AccessControlManager acm = ses.getAccessControlManager();
|
|
|
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path);
|
|
|
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
|
|
Principal principal = AccessControlUtils.getPrincipal(ses, user);
|
|
|
|
acls.addAccessControlEntry(principal, userPrivileges);
|
|
|
|
acm.setPolicy(path, acls);
|
|
|
|
ses.save();
|
2019-05-22 17:47:15 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2019-09-16 16:36:26 +02:00
|
|
|
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)
|
2019-05-22 17:47:15 +02:00
|
|
|
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();
|
|
|
|
}
|
2019-09-16 16:36:26 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
}catch(RepositoryException re){
|
|
|
|
log.error("jcr error extracting archive", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
|
|
|
|
}catch(StorageHubException she ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2019-02-14 12:01:59 +01:00
|
|
|
}finally{
|
|
|
|
if (ses!=null)
|
|
|
|
ses.logout();
|
|
|
|
}
|
2019-05-22 17:47:15 +02:00
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
}
|
2019-09-16 16:36:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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();
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
2019-05-30 18:26:14 +02:00
|
|
|
@GET
|
2019-06-05 18:10:22 +02:00
|
|
|
@Path("{id}/acls/write")
|
|
|
|
public Boolean canWriteInto() {
|
2019-06-05 18:00:57 +02:00
|
|
|
InnerMethodName.instance.set("canWriteIntoFolder");
|
2019-05-30 18:26:14 +02:00
|
|
|
Session ses = null;
|
|
|
|
Boolean canWrite = false;
|
|
|
|
try{
|
2019-06-05 18:10:22 +02:00
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2019-06-05 18:00:57 +02:00
|
|
|
Node node = ses.getNodeByIdentifier(id);
|
|
|
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
|
|
|
if (!(item instanceof FolderItem))
|
|
|
|
throw new InvalidItemException("this method can be applied only to folder");
|
|
|
|
|
2019-05-30 18:26:14 +02:00
|
|
|
try {
|
|
|
|
authChecker.checkWriteAuthorizationControl(ses, id, true);
|
|
|
|
}catch (UserNotAuthorizedException e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}catch(RepositoryException re){
|
|
|
|
log.error("jcr error getting acl", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re));
|
|
|
|
}catch(StorageHubException she ){
|
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
|
|
}finally{
|
|
|
|
if (ses!=null)
|
|
|
|
ses.logout();
|
|
|
|
}
|
|
|
|
return canWrite;
|
|
|
|
}
|
2019-02-14 12:01:59 +01:00
|
|
|
|
2018-05-28 12:01:01 +02:00
|
|
|
}
|