2018-11-30 17:49:35 +01:00
package org.gcube.data.access.storagehub.services ;
import java.util.ArrayList ;
2018-12-17 14:55:43 +01:00
import java.util.Collections ;
2021-03-15 11:57:46 +01:00
import java.util.HashSet ;
2018-11-30 17:49:35 +01:00
import java.util.Iterator ;
import java.util.List ;
2021-01-11 18:07:57 +01:00
import java.util.Set ;
2021-03-12 10:24:45 +01:00
import java.util.function.Predicate ;
2021-03-16 00:04:54 +01:00
import java.util.stream.Collectors ;
2018-11-30 17:49:35 +01:00
import javax.inject.Inject ;
import javax.jcr.Node ;
2020-01-22 16:41:12 +01:00
import javax.jcr.PathNotFoundException ;
import javax.jcr.RepositoryException ;
2018-11-30 17:49:35 +01:00
import javax.servlet.ServletContext ;
2019-04-11 18:30:43 +02:00
import javax.ws.rs.Consumes ;
2018-11-30 17:49:35 +01:00
import javax.ws.rs.DELETE ;
2019-04-11 18:30:43 +02:00
import javax.ws.rs.FormParam ;
2018-11-30 17:49:35 +01:00
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 ;
2020-01-22 16:41:12 +01:00
import javax.ws.rs.core.Response ;
2018-11-30 17:49:35 +01:00
import org.apache.jackrabbit.api.JackrabbitSession ;
import org.apache.jackrabbit.api.security.user.Authorizable ;
2021-03-16 00:04:54 +01:00
import org.apache.jackrabbit.api.security.user.Group ;
2018-11-30 17:49:35 +01:00
import org.apache.jackrabbit.api.security.user.Query ;
import org.apache.jackrabbit.api.security.user.QueryBuilder ;
import org.apache.jackrabbit.api.security.user.User ;
2018-12-17 14:55:43 +01:00
import org.apache.jackrabbit.core.security.principal.PrincipalImpl ;
2019-10-09 11:52:48 +02:00
import org.gcube.common.authorization.control.annotations.AuthorizationControl ;
2018-11-30 17:49:35 +01:00
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse ;
2020-03-05 15:39:34 +01:00
import org.gcube.common.storagehub.model.Excludes ;
2018-11-30 17:49:35 +01:00
import org.gcube.common.storagehub.model.exceptions.BackendGenericError ;
2021-02-08 12:30:58 +01:00
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException ;
2020-01-22 16:41:12 +01:00
import org.gcube.common.storagehub.model.exceptions.StorageHubException ;
2021-03-12 10:24:45 +01:00
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException ;
2020-03-05 15:39:34 +01:00
import org.gcube.common.storagehub.model.items.Item ;
2021-03-12 10:24:45 +01:00
import org.gcube.common.storagehub.model.items.SharedFolder ;
import org.gcube.data.access.storagehub.AuthorizationChecker ;
2018-11-30 17:49:35 +01:00
import org.gcube.data.access.storagehub.Constants ;
2021-03-31 14:49:47 +02:00
import org.gcube.data.access.storagehub.PathUtil ;
2020-03-16 16:55:26 +01:00
import org.gcube.data.access.storagehub.StorageHubAppllicationManager ;
2018-11-30 17:49:35 +01:00
import org.gcube.data.access.storagehub.Utils ;
2019-10-09 11:52:48 +02:00
import org.gcube.data.access.storagehub.exception.MyAuthException ;
2018-11-30 17:49:35 +01:00
import org.gcube.data.access.storagehub.handlers.CredentialHandler ;
2021-03-16 00:04:54 +01:00
import org.gcube.data.access.storagehub.handlers.GroupHandler ;
2020-03-05 15:39:34 +01:00
import org.gcube.data.access.storagehub.handlers.TrashHandler ;
2018-12-17 14:55:43 +01:00
import org.gcube.data.access.storagehub.handlers.UnshareHandler ;
2021-04-07 12:38:18 +02:00
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters ;
2020-03-16 16:55:26 +01:00
import org.gcube.smartgears.annotations.ManagedBy ;
2020-01-22 16:41:12 +01:00
import org.gcube.smartgears.utils.InnerMethodName ;
2018-11-30 17:49:35 +01:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@Path ( " users " )
2020-03-16 16:55:26 +01:00
@ManagedBy ( StorageHubAppllicationManager . class )
2018-11-30 17:49:35 +01:00
public class UserManager {
2020-01-22 16:41:12 +01:00
private static final String INFRASTRUCTURE_MANAGER_ROLE = " Infrastructure-Manager " ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
@Context ServletContext context ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
private static final Logger log = LoggerFactory . getLogger ( UserManager . class ) ;
2020-03-16 16:55:26 +01:00
RepositoryInitializer repository = StorageHubAppllicationManager . repository ;
2018-11-30 17:49:35 +01:00
2018-12-17 14:55:43 +01:00
@Inject
UnshareHandler unshareHandler ;
2021-03-12 10:24:45 +01:00
2021-04-07 12:38:18 +02:00
@Inject
AuthorizationChecker authChecker ;
2020-03-05 15:39:34 +01:00
@Inject
TrashHandler trashHandler ;
2021-03-16 00:04:54 +01:00
@Inject
GroupHandler groupHandler ;
2021-03-31 14:49:47 +02:00
2021-03-12 10:24:45 +01:00
@Inject
2021-03-31 14:49:47 +02:00
PathUtil pathUtil ;
2018-11-30 17:49:35 +01:00
@GET
@Path ( " " )
@Produces ( MediaType . APPLICATION_JSON )
public List < String > getUsers ( ) {
2021-03-12 10:24:45 +01:00
2020-01-22 16:41:12 +01:00
InnerMethodName . instance . set ( " getUsers " ) ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
JackrabbitSession session = null ;
2021-03-15 11:57:46 +01:00
List < String > users = null ;
2018-11-30 17:49:35 +01:00
try {
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
2021-03-15 11:57:46 +01:00
2018-11-30 17:49:35 +01:00
Iterator < Authorizable > result = session . getUserManager ( ) . findAuthorizables ( new Query ( ) {
@Override
public < T > void build ( QueryBuilder < T > builder ) {
builder . setSelector ( User . class ) ;
}
} ) ;
2021-03-15 11:57:46 +01:00
Set < String > usersSet = new HashSet < > ( ) ;
String adminUser = context . getInitParameter ( Constants . ADMIN_PARAM_NAME ) ;
2018-11-30 17:49:35 +01:00
while ( result . hasNext ( ) ) {
Authorizable user = result . next ( ) ;
2018-12-17 14:55:43 +01:00
log . debug ( " user {} found " , user . getPrincipal ( ) . getName ( ) ) ;
2021-03-15 11:57:46 +01:00
if ( user . getPrincipal ( ) . getName ( ) . equals ( adminUser ) ) continue ;
usersSet . add ( user . getPrincipal ( ) . getName ( ) ) ;
2018-11-30 17:49:35 +01:00
}
2021-03-15 11:57:46 +01:00
users = new ArrayList < > ( usersSet ) ;
Collections . sort ( users ) ;
2018-11-30 17:49:35 +01:00
} catch ( Exception e ) {
log . error ( " jcr error getting users " , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
return users ;
}
2021-02-08 12:30:58 +01:00
@GET
@Path ( " {user} " )
public String getUser ( @PathParam ( " user " ) String user ) {
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
InnerMethodName . instance . set ( " getUser " ) ;
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
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 ) ;
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
if ( authorizable ! = null & & ! authorizable . isGroup ( ) )
return authorizable . getPrincipal ( ) . getName ( ) ;
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
log . debug ( " user {} not found " , user ) ;
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
} catch ( Exception e ) {
log . error ( " jcr error getting user " , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
GXOutboundErrorResponse . throwException ( new IdNotFoundException ( user ) ) ;
2021-03-12 10:24:45 +01:00
2021-02-08 12:30:58 +01:00
return null ;
}
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
@POST
@Path ( " " )
2019-04-11 18:30:43 +02:00
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
2020-01-22 16:41:12 +01:00
@AuthorizationControl ( allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2019-04-11 18:30:43 +02:00
public String createUser ( @FormParam ( " user " ) String user , @FormParam ( " password " ) String password ) {
2021-03-12 10:24:45 +01:00
2020-01-22 16:41:12 +01:00
InnerMethodName . instance . set ( " createUser " ) ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
JackrabbitSession session = null ;
String userId = null ;
try {
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
User createdUser = usrManager . createUser ( user , password ) ;
2021-03-15 11:57:46 +01:00
2018-11-30 17:49:35 +01:00
userId = createdUser . getID ( ) ;
2019-03-26 17:09:26 +01:00
2018-11-30 17:49:35 +01:00
Node homeNode = session . getNode ( " /Home " ) ;
Node userHome = homeNode . addNode ( user , " nthl:home " ) ;
2021-04-07 12:38:18 +02:00
userHome . setProperty ( Constants . HOME_VERSION_PROP , 1l ) ;
2021-03-31 14:49:47 +02:00
2018-12-17 14:55:43 +01:00
//creating workspace folder
2021-04-07 12:38:18 +02:00
FolderCreationParameters wsFolderParameters = FolderCreationParameters . builder ( ) . name ( Constants . WORKSPACE_ROOT_FOLDER_NAME ) . description ( " workspace of " + user ) . author ( user ) . on ( userHome . getIdentifier ( ) ) . with ( session ) . build ( ) ;
Utils . createFolderInternally ( wsFolderParameters , null ) ;
2018-12-17 14:55:43 +01:00
//creating thrash folder
2021-04-07 12:38:18 +02:00
FolderCreationParameters trashFolderParameters = FolderCreationParameters . builder ( ) . name ( Constants . TRASH_ROOT_FOLDER_NAME ) . description ( " trash of " + user ) . author ( user ) . on ( userHome . getIdentifier ( ) ) . with ( session ) . build ( ) ;
Utils . createFolderInternally ( trashFolderParameters , null ) ;
2018-12-17 14:55:43 +01:00
//creating Vre container folder
2021-04-07 12:38:18 +02:00
FolderCreationParameters vreFolderParameters = FolderCreationParameters . builder ( ) . name ( Constants . PERSONAL_VRES_FOLDER_PARENT_NAME ) . description ( " vre folder container of " + user ) . author ( user ) . on ( userHome . getIdentifier ( ) ) . with ( session ) . build ( ) ;
Utils . createFolderInternally ( vreFolderParameters , null ) ;
2021-05-04 11:42:02 +02:00
//creating inbox folder
FolderCreationParameters inboxFolderParameters = FolderCreationParameters . builder ( ) . name ( Constants . INBOX_FOLDER_NAME ) . description ( " inbox of " + user ) . author ( user ) . on ( userHome . getIdentifier ( ) ) . with ( session ) . build ( ) ;
Utils . createFolderInternally ( inboxFolderParameters , null ) ;
//creating outbox folder
FolderCreationParameters outboxFolderParameters = FolderCreationParameters . builder ( ) . name ( Constants . OUTBOX_FOLDER_NAME ) . description ( " outbox of " + user ) . author ( user ) . on ( userHome . getIdentifier ( ) ) . with ( session ) . build ( ) ;
Utils . createFolderInternally ( outboxFolderParameters , null ) ;
2018-11-30 17:49:35 +01:00
session . save ( ) ;
2020-01-22 16:41:12 +01:00
} 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 ) ) ;
2018-11-30 17:49:35 +01:00
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-03-26 17:09:26 +01:00
2018-11-30 17:49:35 +01:00
return userId ;
}
2019-03-26 17:09:26 +01:00
2018-11-30 17:49:35 +01:00
@DELETE
2020-01-22 16:41:12 +01:00
@Path ( " {user} " )
@AuthorizationControl ( allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2021-03-12 10:24:45 +01:00
public String deleteUser ( @PathParam ( " user " ) final String user ) {
2020-01-22 16:41:12 +01:00
InnerMethodName . instance . set ( " deleteUser " ) ;
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
JackrabbitSession session = null ;
try {
2021-03-12 10:24:45 +01:00
2018-11-30 17:49:35 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
2019-03-26 17:09:26 +01:00
2021-03-16 00:04:54 +01:00
User authorizable = ( User ) usrManager . getAuthorizable ( new PrincipalImpl ( user ) ) ;
if ( authorizable ! = null )
removeUserFromBelongingGroup ( session , authorizable , usrManager ) ;
else log . warn ( " user was already deleted from jackrabbit, trying to delete folders " ) ;
unshareUsersFolders ( session , user ) ;
2018-11-30 17:49:35 +01:00
2021-03-16 00:04:54 +01:00
removeUserHomeAndDeleteFiles ( session , user ) ;
2021-03-15 16:01:14 +01:00
2021-03-16 00:04:54 +01:00
//FINALIZE user removal
2021-03-15 16:01:14 +01:00
if ( authorizable ! = null & & ! authorizable . isGroup ( ) ) {
log . info ( " removing user {} " , user ) ;
authorizable . remove ( ) ;
2021-03-16 00:04:54 +01:00
} else log . warn ( " the user {} was already deleted, it should never happen " , user ) ;
2021-03-15 16:01:14 +01:00
2018-11-30 17:49:35 +01:00
session . save ( ) ;
2020-01-22 16:41:12 +01:00
} 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 ) ) ;
2018-11-30 17:49:35 +01:00
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-03-26 17:09:26 +01:00
2021-03-16 00:04:54 +01:00
return user ;
}
private void removeUserFromBelongingGroup ( JackrabbitSession session , User authorizable , org . apache . jackrabbit . api . security . user . UserManager usrManager ) throws RepositoryException , StorageHubException {
Iterator < Authorizable > groups = session . getUserManager ( ) . findAuthorizables ( new Query ( ) {
@Override
public < T > void build ( QueryBuilder < T > builder ) {
builder . setSelector ( Group . class ) ;
}
} ) ;
String user = authorizable . getPrincipal ( ) . getName ( ) ;
while ( groups . hasNext ( ) ) {
Authorizable group = groups . next ( ) ;
log . info ( " group found {} " , group . getPrincipal ( ) . getName ( ) ) ;
if ( group . isGroup ( ) & & ( ( Group ) group ) . isMember ( authorizable ) ) {
boolean success = groupHandler . removeUserFromGroup ( group . getPrincipal ( ) . getName ( ) , user , session ) ;
log . warn ( " user {} {} removed from vre {} " , user , success ? " " : " not " , group . getPrincipal ( ) . getName ( ) ) ;
}
}
}
private void unshareUsersFolders ( JackrabbitSession session , String user ) {
try {
Node sharedFolderNode = session . getNode ( Constants . SHARED_FOLDER_PATH ) ;
Predicate < Node > sharedWithUserChecker = new Predicate < Node > ( ) {
@Override
public boolean test ( Node t ) {
try {
2021-04-07 12:38:18 +02:00
authChecker . checkReadAuthorizationControl ( t . getSession ( ) , user , t . getIdentifier ( ) ) ;
2021-03-16 00:04:54 +01:00
return true ;
} catch ( UserNotAuthorizedException | BackendGenericError | RepositoryException e ) {
return false ;
}
}
} ;
List < SharedFolder > items = Utils . getItemList ( sharedWithUserChecker , sharedFolderNode , Excludes . ALL , null , false , SharedFolder . class ) ;
log . debug ( " Shared folder to unshare found are {} " , items . size ( ) ) ;
for ( SharedFolder item : items ) {
String title = item . getTitle ( ) ;
log . debug ( " in list folder name {} with title {} and path {} " , item . getName ( ) , title , item . getPath ( ) ) ;
if ( item . isPublicItem ( ) & & ! item . getUsers ( ) . getMap ( ) . containsKey ( user ) ) continue ;
if ( item . isVreFolder ( ) ) continue ;
log . info ( " 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 . unshareForRemoval ( 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 {} " , user , t ) ;
}
2018-11-30 17:49:35 +01:00
}
2021-03-16 00:04:54 +01:00
private void removeUserHomeAndDeleteFiles ( JackrabbitSession session , String user ) throws RepositoryException , StorageHubException {
2021-03-31 14:49:47 +02:00
org . gcube . common . storagehub . model . Path homePath = pathUtil . getHome ( user ) ;
org . gcube . common . storagehub . model . Path workspacePath = pathUtil . getWorkspacePath ( user ) ;
2021-04-07 12:38:18 +02:00
org . gcube . common . storagehub . model . Path trashPath = pathUtil . getTrashPath ( user , session ) ;
2021-03-16 00:04:54 +01:00
try {
Node workspaceNode = session . getNode ( workspacePath . toPath ( ) ) ;
List < Item > workspaceItems = Utils . getItemList ( workspaceNode , Excludes . GET_ONLY_CONTENT , null , true , null ) . stream ( ) . filter ( i - > ! i . isShared ( ) ) . collect ( Collectors . toList ( ) ) ;
trashHandler . removeOnlyNodesContent ( session , workspaceItems ) ;
2021-03-16 13:03:27 +01:00
} catch ( PathNotFoundException e ) {
log . warn ( " {} workspace dir {} was already deleted " , user , homePath . toPath ( ) ) ;
}
try {
Node trashNode = session . getNode ( trashPath . toPath ( ) ) ;
List < Item > trashItems = Utils . getItemList ( trashNode , Excludes . ALL , null , true , null ) ;
trashHandler . removeOnlyNodesContent ( session , trashItems ) ;
} catch ( PathNotFoundException e ) {
log . warn ( " {} trash dir {} was already deleted " , user , homePath . toPath ( ) ) ;
}
try {
Node homeNode = session . getNode ( homePath . toPath ( ) ) ;
2021-03-16 00:04:54 +01:00
homeNode . remove ( ) ;
} catch ( PathNotFoundException e ) {
2021-03-16 13:03:27 +01:00
log . warn ( " {} home dir {} was already deleted " , user , homePath . toPath ( ) ) ;
2021-03-16 00:04:54 +01:00
}
}
2018-11-30 17:49:35 +01:00
}