2018-12-17 14:55:43 +01:00
package org.gcube.data.access.storagehub.services ;
import java.util.ArrayList ;
import java.util.Iterator ;
import java.util.List ;
import javax.inject.Inject ;
2018-12-28 17:58:08 +01:00
import javax.jcr.Node ;
2019-04-12 16:47:39 +02:00
import javax.jcr.NodeIterator ;
2019-10-09 10:35:23 +02:00
import javax.jcr.PathNotFoundException ;
2018-12-28 17:58:08 +01:00
import javax.jcr.security.AccessControlManager ;
import javax.jcr.security.Privilege ;
2018-12-17 14:55:43 +01:00
import javax.servlet.ServletContext ;
2019-04-11 18:30:43 +02:00
import javax.ws.rs.Consumes ;
2018-12-17 14:55:43 +01:00
import javax.ws.rs.DELETE ;
2019-04-11 18:30:43 +02:00
import javax.ws.rs.FormParam ;
2018-12-17 14:55:43 +01:00
import javax.ws.rs.GET ;
import javax.ws.rs.POST ;
import javax.ws.rs.PUT ;
import javax.ws.rs.Path ;
import javax.ws.rs.PathParam ;
2019-04-11 16:38:41 +02:00
import javax.ws.rs.Produces ;
2018-12-17 14:55:43 +01:00
import javax.ws.rs.core.Context ;
2019-04-11 16:38:41 +02:00
import javax.ws.rs.core.MediaType ;
2018-12-17 14:55:43 +01:00
import org.apache.jackrabbit.api.JackrabbitSession ;
2018-12-28 17:58:08 +01:00
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList ;
2018-12-17 14:55:43 +01:00
import org.apache.jackrabbit.api.security.user.Authorizable ;
import org.apache.jackrabbit.api.security.user.Group ;
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-28 17:58:08 +01:00
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils ;
2019-10-09 10:35:23 +02:00
import org.gcube.common.authorization.control.annotations.AuthorizationControl ;
2018-12-28 17:58:08 +01:00
import org.gcube.common.authorization.library.provider.AuthorizationProvider ;
2018-12-17 14:55:43 +01:00
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse ;
2019-10-10 18:15:38 +02:00
import org.gcube.common.scope.api.ScopeProvider ;
2018-12-28 17:58:08 +01:00
import org.gcube.common.storagehub.model.acls.AccessType ;
2018-12-17 14:55:43 +01:00
import org.gcube.common.storagehub.model.exceptions.BackendGenericError ;
2019-10-10 19:09:30 +02:00
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters ;
2019-10-09 10:35:23 +02:00
import org.gcube.common.storagehub.model.exceptions.InvalidItemException ;
2019-10-10 18:15:38 +02:00
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException ;
2018-12-28 17:58:08 +01:00
import org.gcube.common.storagehub.model.types.NodeProperty ;
import org.gcube.common.storagehub.model.types.PrimaryNodeType ;
import org.gcube.data.access.storagehub.Constants ;
import org.gcube.data.access.storagehub.Utils ;
2019-10-09 10:35:23 +02:00
import org.gcube.data.access.storagehub.exception.MyAuthException ;
2018-12-17 14:55:43 +01:00
import org.gcube.data.access.storagehub.handlers.CredentialHandler ;
2019-10-10 19:09:30 +02:00
import org.gcube.smartgears.utils.InnerMethodName ;
2018-12-17 14:55:43 +01:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@Path ( " groups " )
public class GroupManager {
@Context ServletContext context ;
2019-10-10 18:15:38 +02:00
private static final String VREMANAGER_ROLE = " VRE-Manager " ;
2019-10-25 14:58:09 +02:00
private static final String INFRASTRUCTURE_MANAGER_ROLE = " Infrastructure-Manager " ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
private static final Logger log = LoggerFactory . getLogger ( GroupManager . class ) ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
@Inject
RepositoryInitializer repository ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
@GET
@Path ( " " )
2019-05-06 18:56:22 +02:00
@Produces ( MediaType . APPLICATION_JSON )
2018-12-17 14:55:43 +01:00
public List < String > getGroups ( ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " getGroups " ) ;
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
List < String > groups = new ArrayList < > ( ) ;
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 ( Group . class ) ;
}
} ) ;
while ( result . hasNext ( ) ) {
Authorizable group = result . next ( ) ;
log . info ( " group {} found " , group . getPrincipal ( ) . getName ( ) ) ;
groups . add ( group . getPrincipal ( ) . getName ( ) ) ;
}
} catch ( Exception e ) {
2018-12-28 17:58:08 +01:00
log . error ( " jcr error getting groups " , e ) ;
2018-12-17 14:55:43 +01:00
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
return groups ;
}
@POST
@Path ( " " )
2019-04-11 18:30:43 +02:00
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
2019-10-25 14:58:09 +02:00
@AuthorizationControl ( allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2019-04-12 16:47:39 +02:00
public String createGroup ( @FormParam ( " group " ) String group , @FormParam ( " accessType " ) AccessType accessType ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " createGroup " ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
String groupId = null ;
try {
2019-10-10 18:15:38 +02:00
2019-10-25 14:58:09 +02:00
if ( ! isValidGroupForContext ( groupId ) )
throw new UserNotAuthorizedException ( " only VREManager can execute this operation " ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
Group createdGroup = usrManager . createGroup ( group ) ;
groupId = createdGroup . getID ( ) ;
2019-04-11 16:38:41 +02:00
2019-04-12 17:41:21 +02:00
createVreFolder ( groupId , session , accessType ! = null ? accessType : AccessType . WRITE_OWNER ) ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
session . save ( ) ;
} catch ( Exception e ) {
log . error ( " jcr error creating group {} " , group , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
return groupId ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
@DELETE
2019-04-11 16:38:41 +02:00
@Path ( " {group} " )
2019-10-25 14:58:09 +02:00
@AuthorizationControl ( allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2019-04-11 16:38:41 +02:00
public String deleteGroup ( @PathParam ( " group " ) String group ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " deleteGroup " ) ;
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
try {
2019-10-10 18:15:38 +02:00
2019-10-25 14:58:09 +02:00
if ( ! isValidGroupForContext ( group ) )
throw new UserNotAuthorizedException ( " only VREManager of the selected VRE can execute this operation " ) ;
2018-12-17 14:55:43 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
2019-04-11 16:38:41 +02:00
try {
2019-10-09 10:35:23 +02:00
getVreFolderNode ( session , group ) . removeSharedSet ( ) ;
2019-04-11 16:38:41 +02:00
} catch ( Exception e ) {
log . warn ( " vreFolder {} not found, removing only the group " , group ) ;
}
Authorizable authorizable = usrManager . getAuthorizable ( group ) ;
2018-12-17 14:55:43 +01:00
if ( authorizable . isGroup ( ) )
authorizable . remove ( ) ;
session . save ( ) ;
} catch ( Exception e ) {
log . error ( " jcr error getting users " , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-04-11 16:38:41 +02:00
return group ;
2018-12-17 14:55:43 +01:00
}
2019-04-11 16:38:41 +02:00
2019-10-25 14:58:09 +02:00
public boolean isAdmin ( ) { return AuthorizationProvider . instance . get ( ) . getClient ( ) . getRoles ( ) . contains ( INFRASTRUCTURE_MANAGER_ROLE ) ; }
2018-12-17 14:55:43 +01:00
@PUT
@Path ( " {id} " )
2019-04-11 18:30:43 +02:00
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
2019-10-25 14:58:09 +02:00
@AuthorizationControl ( allowedRoles = { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2019-04-11 18:30:43 +02:00
public boolean addUserToGroup ( @PathParam ( " id " ) String groupId , @FormParam ( " userId " ) String userId ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " addUserToGroup " ) ;
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
boolean success = false ;
try {
2019-10-10 18:15:38 +02:00
2019-10-25 14:58:09 +02:00
if ( ! isValidGroupForContext ( groupId ) & & ! isAdmin ( ) )
throw new UserNotAuthorizedException ( " only VREManager of the selected VRE can execute this operation " ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
User user = ( User ) usrManager . getAuthorizable ( userId ) ;
2019-10-10 19:09:30 +02:00
if ( group . isMember ( user ) )
throw new InvalidCallParameters ( " user " + userId + " is already member of group " + groupId ) ;
2018-12-17 14:55:43 +01:00
success = group . addMember ( user ) ;
2019-04-11 16:38:41 +02:00
String folderName = group . getPrincipal ( ) . getName ( ) ;
2019-10-09 10:35:23 +02:00
Node folder = getVreFolderNode ( session , folderName ) ;
2019-04-12 16:47:39 +02:00
2019-04-11 16:38:41 +02:00
String userPath = String . format ( " %s%s/%s " , Utils . getWorkspacePath ( user . getPrincipal ( ) . getName ( ) ) . toPath ( ) , Constants . VRE_FOLDER_PARENT_NAME , folderName ) ;
log . debug ( " creating folder in user path {} " , userPath ) ;
session . getWorkspace ( ) . clone ( session . getWorkspace ( ) . getName ( ) , folder . getPath ( ) , userPath , false ) ;
2018-12-17 14:55:43 +01:00
session . save ( ) ;
} catch ( Exception e ) {
log . error ( " jcr error adding user {} to group {} " , userId , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
return success ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
@DELETE
@Path ( " {groupId}/users/{userId} " )
2019-10-25 14:58:09 +02:00
@AuthorizationControl ( allowedRoles = { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
2018-12-17 14:55:43 +01:00
public boolean removeUserFromGroup ( @PathParam ( " groupId " ) String groupId , @PathParam ( " userId " ) String userId ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " removeUserFromGroup " ) ;
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
boolean success = false ;
try {
2019-10-10 18:15:38 +02:00
2019-10-25 14:58:09 +02:00
if ( ! isValidGroupForContext ( groupId ) & & ! isAdmin ( ) )
throw new UserNotAuthorizedException ( " only VREManager of the selected VRE can execute this operation " ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
User user = ( User ) usrManager . getAuthorizable ( userId ) ;
2019-10-10 19:09:30 +02:00
if ( ! group . isMember ( user ) )
throw new InvalidCallParameters ( " user " + userId + " is not member of group " + groupId ) ;
2019-04-12 16:47:39 +02:00
//delete folder on user
String folderName = group . getPrincipal ( ) . getName ( ) ;
2019-10-09 10:35:23 +02:00
Node folder = getVreFolderNode ( session , folderName ) ;
2019-04-12 16:47:39 +02:00
NodeIterator ni = folder . getSharedSet ( ) ;
while ( ni . hasNext ( ) ) {
Node node = ni . nextNode ( ) ;
if ( node . getPath ( ) . startsWith ( Utils . getWorkspacePath ( user . getPrincipal ( ) . getName ( ) ) . toPath ( ) ) ) {
node . removeShare ( ) ;
break ;
}
}
2018-12-17 14:55:43 +01:00
success = group . removeMember ( user ) ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
session . save ( ) ;
} catch ( Exception e ) {
log . error ( " jcr error adding user {} to group {} " , userId , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
return success ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
@GET
@Path ( " {groupId}/users " )
2019-04-11 16:38:41 +02:00
@Produces ( MediaType . APPLICATION_JSON )
2019-10-10 18:15:38 +02:00
@AuthorizationControl ( allowedRoles = { VREMANAGER_ROLE } , exception = MyAuthException . class )
2018-12-17 14:55:43 +01:00
public List < String > getUsersOfGroup ( @PathParam ( " groupId " ) String groupId ) {
2019-10-10 19:09:30 +02:00
InnerMethodName . instance . set ( " getUsersOfGroup " ) ;
2018-12-17 14:55:43 +01:00
JackrabbitSession session = null ;
List < String > users = new ArrayList < > ( ) ;
try {
2019-10-10 18:15:38 +02:00
2019-10-25 14:58:09 +02:00
if ( ! isValidGroupForContext ( groupId ) )
throw new UserNotAuthorizedException ( " only VREManager of the selected VRE can execute this operation " ) ;
2019-10-10 18:15:38 +02:00
2018-12-17 14:55:43 +01:00
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
Iterator < Authorizable > it = group . getMembers ( ) ;
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
while ( it . hasNext ( ) ) {
Authorizable user = it . next ( ) ;
users . add ( user . getPrincipal ( ) . getName ( ) ) ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
} catch ( Exception e ) {
log . error ( " jcr error getting users of group {} " , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
2019-04-11 16:38:41 +02:00
2018-12-17 14:55:43 +01:00
return users ;
}
2018-12-28 17:58:08 +01:00
2019-04-12 16:47:39 +02:00
private void createVreFolder ( String groupId , JackrabbitSession session , AccessType defaultAccessType ) throws Exception {
2018-12-28 17:58:08 +01:00
2019-04-11 16:38:41 +02:00
Node sharedRootNode = session . getNode ( Constants . SHARED_FOLDER_PATH ) ;
String name = groupId ;
String title = groupId . substring ( groupId . lastIndexOf ( " - " ) + 1 ) ;
Node folder = Utils . createFolderInternally ( session , sharedRootNode , name , " VREFolder for " + groupId , false , AuthorizationProvider . instance . get ( ) . getClient ( ) . getId ( ) , null ) ;
folder . setPrimaryType ( PrimaryNodeType . NT_WORKSPACE_SHARED_FOLDER ) ;
folder . setProperty ( NodeProperty . IS_VRE_FOLDER . toString ( ) , true ) ;
folder . setProperty ( NodeProperty . TITLE . toString ( ) , name ) ;
folder . setProperty ( NodeProperty . DISPLAY_NAME . toString ( ) , title ) ;
session . save ( ) ;
AccessControlManager acm = session . getAccessControlManager ( ) ;
JackrabbitAccessControlList acls = AccessControlUtils . getAccessControlList ( acm , folder . getPath ( ) ) ;
Privilege [ ] adminPrivileges = new Privilege [ ] { acm . privilegeFromName ( AccessType . ADMINISTRATOR . getValue ( ) ) } ;
acls . addAccessControlEntry ( AccessControlUtils . getPrincipal ( session , AuthorizationProvider . instance . get ( ) . getClient ( ) . getId ( ) ) , adminPrivileges ) ;
2018-12-28 17:58:08 +01:00
2019-04-12 16:47:39 +02:00
Privilege [ ] usersPrivileges = new Privilege [ ] { acm . privilegeFromName ( defaultAccessType . getValue ( ) ) } ;
acls . addAccessControlEntry ( AccessControlUtils . getPrincipal ( session , groupId ) , usersPrivileges ) ;
acm . setPolicy ( folder . getPath ( ) , acls ) ;
2018-12-28 17:58:08 +01:00
}
2019-10-09 10:35:23 +02:00
private Node getVreFolderNode ( JackrabbitSession session , String name ) throws InvalidItemException , Exception {
Node sharedRootNode = session . getNode ( Constants . SHARED_FOLDER_PATH ) ;
Node vreFolder = null ;
try {
vreFolder = sharedRootNode . getNode ( name ) ;
} catch ( PathNotFoundException e ) {
log . debug ( " is an old HL VRE " ) ;
}
NodeIterator nodes = sharedRootNode . getNodes ( ) ;
while ( nodes . hasNext ( ) ) {
Node node = nodes . nextNode ( ) ;
if ( node . getProperty ( NodeProperty . TITLE . toString ( ) ) . getString ( ) . equals ( name ) ) {
vreFolder = node ;
break ;
}
}
if ( vreFolder = = null ) throw new InvalidItemException ( " vre folder not found " ) ;
return vreFolder ;
}
2019-04-11 16:38:41 +02:00
2019-10-25 14:58:09 +02:00
private boolean isValidGroupForContext ( String group ) {
2019-10-10 18:15:38 +02:00
String currentContext = ScopeProvider . instance . get ( ) ;
String expectedGroupId = currentContext . replace ( " / " , " - " ) . substring ( 1 ) ;
2019-10-25 14:58:09 +02:00
return group . equals ( expectedGroupId ) ;
2019-10-10 18:15:38 +02:00
}
2018-12-17 14:55:43 +01:00
}