You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
storagehub/src/main/java/org/gcube/data/access/storagehub/services/UserManager.java

293 lines
10 KiB
Java

package org.gcube.data.access.storagehub.services;
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 javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.query.QueryResult;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
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.apache.poi.hpsf.Array;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
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.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("users")
@ManagedBy(StorageHubAppllicationManager.class)
public class UserManager {
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
@Context ServletContext context;
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
UnshareHandler unshareHandler;
@Inject
TrashHandler trashHandler;
@Inject
AuthorizationChecker authChecker;
@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getUsers(){
InnerMethodName.instance.set("getUsers");
JackrabbitSession session = null;
List<String> users = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(User.class);
}
});
Set<String> usersSet= new HashSet<>();
String adminUser = context.getInitParameter(Constants.ADMIN_PARAM_NAME);
while (result.hasNext()) {
Authorizable user = result.next();
log.debug("user {} found",user.getPrincipal().getName());
if (user.getPrincipal().getName().equals(adminUser)) continue;
usersSet.add(user.getPrincipal().getName());
}
users = new ArrayList<>(usersSet);
Collections.sort(users);
}catch(Exception e) {
log.error("jcr error getting users", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (session!=null)
session.logout();
}
return users;
}
@GET
@Path("{user}")
public String getUser(@PathParam("user") String user){
InnerMethodName.instance.set("getUser");
JackrabbitSession session = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Authorizable authorizable = usrManager.getAuthorizable(user);
if (authorizable != null && !authorizable.isGroup())
return authorizable.getPrincipal().getName();
log.debug("user {} not found", user);
}catch(Exception e) {
log.error("jcr error getting user", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (session!=null)
session.logout();
}
GXOutboundErrorResponse.throwException(new IdNotFoundException(user));
return null;
}
@POST
@Path("")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
InnerMethodName.instance.set("createUser");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
User createdUser = usrManager.createUser(user, password);
userId = createdUser.getID();
Node homeNode = session.getNode("/Home");
Node userHome = homeNode.addNode(user, "nthl:home");
//creating workspace folder
Node workspaceFolder = Utils.createFolderInternally(session, userHome, Constants.WORKSPACE_ROOT_FOLDER_NAME, "workspace of "+user, false, user, null);
//creating thrash folder
Utils.createFolderInternally(session, workspaceFolder, Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
//creating Vre container folder
Utils.createFolderInternally(session, workspaceFolder, Constants.VRE_FOLDER_PARENT_NAME, "special folder container of "+user, false, user, null);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
}
return userId;
}
@DELETE
@Path("{user}")
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteUser(@PathParam("user") final String user){
InnerMethodName.instance.set("deleteUser");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
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 !t.getProperty(NodeProperty.IS_VRE_FOLDER.toString()).getBoolean() ;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
List<SharedFolder> items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class);
for (SharedFolder item: items) {
if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue;
String title = item.getTitle();
log.debug("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.unshare(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 ", t);
}
org.gcube.common.storagehub.model.Path homePath = Utils.getHome(user);
org.gcube.common.storagehub.model.Path workspacePath = Utils.getWorkspacePath(user);
try {
Node workspaceNode = session.getNode(workspacePath.toPath());
Node homeNode = session.getNode(homePath.toPath());
List<Item> workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null);
trashHandler.removeOnlyNodesContent(session, workspaceItems);
homeNode.remove();
} catch (PathNotFoundException e) {
log.warn("{} home dir was already deleted", user);
}
Authorizable authorizable = usrManager.getAuthorizable(new PrincipalImpl(user));
if (authorizable!=null && !authorizable.isGroup()) {
log.info("removing user {}", user);
authorizable.remove();
} else log.warn("the user {} was already deleted", user);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
}
return userId;
}
}