@ -1,5 +1,6 @@
package org.gcube.data.access.storagehub.services ;
import java.security.Principal ;
import java.util.ArrayList ;
import java.util.Iterator ;
import java.util.List ;
@ -8,6 +9,8 @@ import javax.inject.Inject;
import javax.jcr.Node ;
import javax.jcr.NodeIterator ;
import javax.jcr.PathNotFoundException ;
import javax.jcr.RepositoryException ;
import javax.jcr.security.AccessControlEntry ;
import javax.jcr.security.AccessControlManager ;
import javax.jcr.security.Privilege ;
import javax.servlet.ServletContext ;
@ -22,6 +25,7 @@ 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.JackrabbitAccessControlList ;
@ -34,15 +38,26 @@ import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils
import org.gcube.common.authorization.control.annotations.AuthorizationControl ;
import org.gcube.common.authorization.library.provider.AuthorizationProvider ;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse ;
import org.gcube.common.scope.api.ScopeProvider ;
import org.gcube.common.storagehub.model.Excludes ;
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.exceptions.UserNotAuthorizedException ;
import org.gcube.common.storagehub.model.types.NodeProperty ;
import org.gcube.common.storagehub.model.types.PrimaryNodeType ;
import org.gcube.data.access.storagehub.AuthorizationChecker ;
import org.gcube.data.access.storagehub.Constants ;
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.Node2ItemConverter ;
import org.gcube.data.access.storagehub.handlers.VRE ;
import org.gcube.data.access.storagehub.handlers.VREManager ;
import org.gcube.smartgears.utils.InnerMethodName ;
import org.glassfish.jersey.media.multipart.FormDataParam ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@ -51,17 +66,30 @@ public class GroupManager {
@Context ServletContext context ;
private static final String VREMANAGER_ROLE = "VRE-Manager" ;
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager" ;
private static final Logger log = LoggerFactory . getLogger ( GroupManager . class ) ;
@Inject
RepositoryInitializer repository ;
@Inject
VREManager vreManager ;
@Inject
Node2ItemConverter node2Item ;
@Inject
AuthorizationChecker authChecker ;
@GET
@Path ( "" )
@Produces ( MediaType . APPLICATION_JSON )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
public List < String > getGroups ( ) {
InnerMethodName . instance . set ( "getGroups" ) ;
JackrabbitSession session = null ;
List < String > groups = new ArrayList < > ( ) ;
try {
@ -80,9 +108,9 @@ public class GroupManager {
log . info ( "group {} found" , group . getPrincipal ( ) . getName ( ) ) ;
groups . add ( group . getPrincipal ( ) . getName ( ) ) ;
}
} catch ( Exception e) {
log . error ( "jcr error getting groups", e) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e) ) ;
} catch ( Repository Exception r e ) {
log . error ( "jcr error creating item", r e) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( "jcr error creating item" , r e) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
@ -92,13 +120,16 @@ public class GroupManager {
@POST
@Path ( "" )
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
public String createGroup ( @FormParam ( "group" ) String group , @FormParam ( "accessType" ) AccessType accessType ) {
@Consumes ( MediaType . MULTIPART_FORM_DATA )
@AuthorizationControl ( allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public String createGroup ( @FormDataParam ( "group" ) String group , @FormDataParam ( "accessType" ) AccessType accessType , @FormDataParam ( "folderOwner" ) String folderOwner ) {
InnerMethodName . instance . set ( "createGroup" ) ;
JackrabbitSession session = null ;
String groupId = null ;
try {
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
@ -106,7 +137,7 @@ public class GroupManager {
Group createdGroup = usrManager . createGroup ( group ) ;
groupId = createdGroup . getID ( ) ;
createVreFolder ( groupId , session , accessType ! = null ? accessType : AccessType . WRITE_OWNER );
createVreFolder ( groupId , session , accessType ! = null ? accessType : AccessType . WRITE_OWNER , folderOwner );
session . save ( ) ;
} catch ( Exception e ) {
@ -122,11 +153,14 @@ public class GroupManager {
@DELETE
@Path ( "{group}" )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
@AuthorizationControl ( allowed Roles= { INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public String deleteGroup ( @PathParam ( "group" ) String group ) {
InnerMethodName . instance . set ( "deleteGroup" ) ;
JackrabbitSession session = null ;
try {
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
@ -140,26 +174,169 @@ public class GroupManager {
if ( authorizable . isGroup ( ) )
authorizable . remove ( ) ;
session . save ( ) ;
} catch ( Exception e) {
log . error ( "jcr error getting users", e) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e) ) ;
} catch ( Repository Exception r e ) {
log . error ( "jcr error creating item", r e) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( "jcr error creating item" , r e) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
return group ;
}
public boolean isInfraManager ( ) { return AuthorizationProvider . instance . get ( ) . getClient ( ) . getRoles ( ) . contains ( INFRASTRUCTURE_MANAGER_ROLE ) ; }
@PUT
@Path ( "{id}/admins" )
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
@AuthorizationControl ( allowedRoles = { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public void addAdmin ( @PathParam ( "id" ) String groupId , @FormParam ( "userId" ) String userId ) {
InnerMethodName . instance . set ( "addAddmin" ) ;
JackrabbitSession session = null ;
try {
if ( ! isInfraManager ( ) & & ! isValidGroupForContext ( groupId ) )
throw new UserNotAuthorizedException ( "only VREManager of the selected VRE can execute this operation" ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = ( ( JackrabbitSession ) session ) . getUserManager ( ) ;
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
User authUser = ( User ) usrManager . getAuthorizable ( userId ) ;
if ( ! group . isMember ( authUser ) )
throw new InvalidCallParameters ( "user " + userId + " is not in the group " + groupId ) ;
Node vreFolder = getVreFolderNode ( session , groupId ) ;
AccessControlManager acm = session . getAccessControlManager ( ) ;
JackrabbitAccessControlList acls = AccessControlUtils . getAccessControlList ( acm , vreFolder . getPath ( ) ) ;
Privilege [ ] userPrivileges = new Privilege [ ] { acm . privilegeFromName ( AccessType . ADMINISTRATOR . getValue ( ) ) } ;
Principal principal = AccessControlUtils . getPrincipal ( session , userId ) ;
acls . addAccessControlEntry ( principal , userPrivileges ) ;
acm . setPolicy ( vreFolder . getPath ( ) , acls ) ;
session . save ( ) ;
} catch ( StorageHubException she ) {
log . error ( she . getErrorMessage ( ) , she ) ;
GXOutboundErrorResponse . throwException ( she , Response . Status . fromStatusCode ( she . getStatus ( ) ) ) ;
} catch ( RepositoryException re ) {
log . error ( "adding admin to VREFolder" , re ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( "jcr error adding admin to VREFolder" , re ) ) ;
} finally {
if ( session ! = null )
session . logout ( ) ;
}
}
@DELETE
@Path ( "{id}/admins/{userId}" )
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
@AuthorizationControl ( allowedRoles = { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public void removeAdmin ( @PathParam ( "id" ) String groupId , @PathParam ( "userId" ) String userId ) {
InnerMethodName . instance . set ( "removeAdmin" ) ;
JackrabbitSession session = null ;
try {
if ( ! isValidGroupForContext ( groupId ) & & ! isInfraManager ( ) )
throw new UserNotAuthorizedException ( "only VREManager of the selected VRE can execute this operation" ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
Node vreFolder = getVreFolderNode ( session , groupId ) ;
AccessControlManager acm = session . getAccessControlManager ( ) ;
JackrabbitAccessControlList acls = AccessControlUtils . getAccessControlList ( acm , vreFolder . getPath ( ) ) ;
AccessControlEntry toRemove = null ;
for ( AccessControlEntry acl : acls . getAccessControlEntries ( ) )
if ( acl . getPrincipal ( ) . getName ( ) . equals ( userId ) ) {
toRemove = acl ;
break ;
}
acls . removeAccessControlEntry ( toRemove ) ;
acm . setPolicy ( vreFolder . getPath ( ) , acls ) ;
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 ( ) ;
}
}
@GET
@Path ( "{groupId}/admins" )
@Produces ( MediaType . APPLICATION_JSON )
public List < String > getAdmins ( @PathParam ( "groupId" ) String groupId ) {
InnerMethodName . instance . set ( "getAdmins" ) ;
JackrabbitSession session = null ;
List < String > users = new ArrayList < > ( ) ;
try {
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
VRE vreFolder = Utils . getVreFolderItemByGroupNameAndUser ( session , groupId , AuthorizationProvider . instance . get ( ) . getClient ( ) . getId ( ) , node2Item , vreManager , Excludes . ALL ) ;
AccessControlManager acm = session . getAccessControlManager ( ) ;
//authChecker.checkAdministratorControl(session, (VreFolder)vreFolder.getVreFolder());
Node node = session . getNodeByIdentifier ( vreFolder . getVreFolder ( ) . getId ( ) ) ;
JackrabbitAccessControlList acls = AccessControlUtils . getAccessControlList ( acm , node . getPath ( ) ) ;
for ( AccessControlEntry acl : acls . getAccessControlEntries ( ) )
for ( Privilege pr : acl . getPrivileges ( ) ) {
if ( pr . getName ( ) . equals ( AccessType . ADMINISTRATOR . getValue ( ) ) ) {
users . add ( acl . getPrincipal ( ) . getName ( ) ) ;
}
}
} 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 users ;
}
@PUT
@Path ( "{id}" )
@Path ( "{id} /users ")
@Consumes ( MediaType . APPLICATION_FORM_URLENCODED )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
@AuthorizationControl ( allowed Roles= { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public boolean addUserToGroup ( @PathParam ( "id" ) String groupId , @FormParam ( "userId" ) String userId ) {
InnerMethodName . instance . set ( "addUserToGroup" ) ;
JackrabbitSession session = null ;
boolean success = false ;
try {
if ( ! isValidGroupForContext ( groupId ) & & ! isInfraManager ( ) )
throw new UserNotAuthorizedException ( "only VREManager of the selected VRE can execute this operation" ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
@ -167,6 +344,9 @@ public class GroupManager {
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
User user = ( User ) usrManager . getAuthorizable ( userId ) ;
if ( group . isMember ( user ) )
throw new InvalidCallParameters ( "user " + userId + " is already member of group " + groupId ) ;
success = group . addMember ( user ) ;
String folderName = group . getPrincipal ( ) . getName ( ) ;
@ -177,10 +357,13 @@ public class GroupManager {
session . getWorkspace ( ) . clone ( session . getWorkspace ( ) . getName ( ) , folder . getPath ( ) , userPath , false ) ;
session . save ( ) ;
} catch ( Exception e ) {
log . error ( "jcr error adding user {} to group {}" , userId , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
} 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 ( ) ;
}
@ -190,12 +373,18 @@ public class GroupManager {
@DELETE
@Path ( "{groupId}/users/{userId}" )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
@AuthorizationControl ( allowed Roles= { VREMANAGER_ROLE , INFRASTRUCTURE_MANAGER_ROLE } , exception = MyAuthException . class )
public boolean removeUserFromGroup ( @PathParam ( "groupId" ) String groupId , @PathParam ( "userId" ) String userId ) {
InnerMethodName . instance . set ( "removeUserFromGroup" ) ;
JackrabbitSession session = null ;
boolean success = false ;
try {
if ( ! isValidGroupForContext ( groupId ) & & ! isInfraManager ( ) )
throw new UserNotAuthorizedException ( "only VREManager of the selected VRE can execute this operation" ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
@ -203,6 +392,9 @@ public class GroupManager {
Group group = ( Group ) usrManager . getAuthorizable ( groupId ) ;
User user = ( User ) usrManager . getAuthorizable ( userId ) ;
if ( ! group . isMember ( user ) )
throw new InvalidCallParameters ( "user " + userId + " is not member of group " + groupId ) ;
//delete folder on user
String folderName = group . getPrincipal ( ) . getName ( ) ;
Node folder = getVreFolderNode ( session , folderName ) ;
@ -219,9 +411,12 @@ public class GroupManager {
success = group . removeMember ( user ) ;
session . save ( ) ;
} catch ( Exception e ) {
log . error ( "jcr error adding user {} to group {}" , userId , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} 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 ( ) ;
@ -233,12 +428,18 @@ public class GroupManager {
@GET
@Path ( "{groupId}/users" )
@Produces ( MediaType . APPLICATION_JSON )
@AuthorizationControl ( allowed = { "lucio.lelii" } , exception = MyAuthException . class )
@AuthorizationControl ( allowed Roles= { VREMANAGER_ROLE } , exception = MyAuthException . class )
public List < String > getUsersOfGroup ( @PathParam ( "groupId" ) String groupId ) {
InnerMethodName . instance . set ( "getUsersOfGroup" ) ;
JackrabbitSession session = null ;
List < String > users = new ArrayList < > ( ) ;
try {
if ( ! isValidGroupForContext ( groupId ) )
throw new UserNotAuthorizedException ( "only VREManager of the selected VRE can execute this operation" ) ;
session = ( JackrabbitSession ) repository . getRepository ( ) . login ( CredentialHandler . getAdminCredentials ( context ) ) ;
org . apache . jackrabbit . api . security . user . UserManager usrManager = session . getUserManager ( ) ;
@ -253,10 +454,13 @@ public class GroupManager {
}
} catch ( Exception e ) {
log . error ( "jcr error getting users of group {}" , groupId , e ) ;
GXOutboundErrorResponse . throwException ( new BackendGenericError ( e ) ) ;
} finally {
} 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 ( ) ;
}
@ -264,7 +468,7 @@ public class GroupManager {
return users ;
}
private void createVreFolder ( String groupId , JackrabbitSession session , AccessType defaultAccessType ) throws Exception {
private void createVreFolder ( String groupId , JackrabbitSession session , AccessType defaultAccessType , String owner ) throws Exception {
Node sharedRootNode = session . getNode ( Constants . SHARED_FOLDER_PATH ) ;
@ -272,7 +476,7 @@ public class GroupManager {
String title = groupId . substring ( groupId . lastIndexOf ( "-" ) + 1 ) ;
Node folder = Utils . createFolderInternally ( session , sharedRootNode , name , "VREFolder for " + groupId , false , AuthorizationProvider. instance . get ( ) . getClient ( ) . getId ( ) , null ) ;
Node folder = Utils . createFolderInternally ( session , sharedRootNode , name , "VREFolder for " + groupId , false , owner , null ) ;
folder . setPrimaryType ( PrimaryNodeType . NT_WORKSPACE_SHARED_FOLDER ) ;
folder . setProperty ( NodeProperty . IS_VRE_FOLDER . toString ( ) , true ) ;
folder . setProperty ( NodeProperty . TITLE . toString ( ) , name ) ;
@ -281,25 +485,29 @@ public class GroupManager {
AccessControlManager acm = session . getAccessControlManager ( ) ;
JackrabbitAccessControlList acls = AccessControlUtils . getAccessControlList ( acm , folder . getPath ( ) ) ;
Privilege [ ] adminPrivileges = new Privilege [ ] { acm . privilegeFromName ( AccessType . ADMINISTRATOR . getValue ( ) ) } ;
/ * Privilege [ ] adminPrivileges = new Privilege [ ] { acm . privilegeFromName ( AccessType . ADMINISTRATOR . getValue ( ) ) } ;
acls . addAccessControlEntry ( AccessControlUtils . getPrincipal ( session , AuthorizationProvider . instance . get ( ) . getClient ( ) . getId ( ) ) , adminPrivileges ) ;
* /
Privilege [ ] usersPrivileges = new Privilege [ ] { acm . privilegeFromName ( defaultAccessType . getValue ( ) ) } ;
acls . addAccessControlEntry ( AccessControlUtils . getPrincipal ( session , groupId ) , usersPrivileges ) ;
acm . setPolicy ( folder . getPath ( ) , acls ) ;
}
private Node getVreFolderNode ( JackrabbitSession session , String name ) throws InvalidItemException , Exception {
private Node getVreFolderNode ( JackrabbitSession session , String name ) throws InvalidItemException , Repository 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 ( ) ;
@ -313,4 +521,10 @@ public class GroupManager {
return vreFolder ;
}
private boolean isValidGroupForContext ( String group ) {
String currentContext = ScopeProvider . instance . get ( ) ;
String expectedGroupId = currentContext . replace ( "/" , "-" ) . substring ( 1 ) ;
return group . equals ( expectedGroupId ) ;
}
}