11package ubic .gemma .core .security .authorization .acl ;
22
3+ import gemma .gsec .acl .ParentIdentityRetrievalStrategy ;
34import gemma .gsec .acl .domain .AclGrantedAuthoritySid ;
45import gemma .gsec .acl .domain .AclObjectIdentity ;
56import gemma .gsec .acl .domain .AclService ;
67import lombok .extern .apachecommons .CommonsLog ;
7- import org .hibernate .Hibernate ;
88import org .hibernate .Query ;
99import org .hibernate .SessionFactory ;
1010import org .hibernate .dialect .function .SQLFunction ;
3030import ubic .gemma .model .expression .bioAssayData .MeanVarianceRelation ;
3131import ubic .gemma .model .expression .biomaterial .BioMaterial ;
3232import ubic .gemma .model .expression .experiment .*;
33- import ubic .gemma .persistence .service .expression .experiment .ExpressionExperimentService ;
3433
3534import javax .annotation .Nullable ;
3635import java .lang .reflect .Modifier ;
@@ -66,8 +65,13 @@ private static void addSecuredChildToParent( Class<? extends SecuredChild<?>> cl
6665 static {
6766 // FIXME: handle sub-assays and sub-biomaterials in the child to parent query, or recursively resolve parents as
6867 // a special case
69- addSecuredChildToParent ( BioAssay .class , ExpressionExperiment .class , null );
70- addSecuredChildToParent ( BioMaterial .class , ExpressionExperiment .class , null );
68+ // this cover cases where the BioAssay is attached to a EE or a subset of an EE
69+ addSecuredChildToParent ( BioAssay .class , ExpressionExperiment .class ,
70+ //language=HQL
71+ "select coalesce(ee.id, eess.sourceExperiment.id) from ExpressionExperiment ee join ee.bioAssays ba, ExpressionExperimentSubSet eess join eess.bioAssays eessba where ba.id = aoi.identifier or eessba.id = aoi.identifier" );
72+ addSecuredChildToParent ( BioMaterial .class , ExpressionExperiment .class ,
73+ //language=HQL
74+ "select coalesce(ee.id, eess.sourceExperiment.id) from ExpressionExperiment ee join ee.bioAssays ba join ba.sampleUsed bm, ExpressionExperimentSubSet eess join eess.bioAssays eessba join eessba.sampleUsed eessbm where bm.id = aoi.identifier or eessbm.id = aoi.identifier" );
7175 addSecuredChildToParent ( ExpressionExperimentSubSet .class , ExpressionExperiment .class ,
7276 //language=HQL
7377 "select ears.analysis.id from ExpressionAnalysisResultSet ears where ears.id = aoi.identifier" );
@@ -108,7 +112,7 @@ private static void addSecuredChildToParent( Class<? extends SecuredChild<?>> cl
108112 @ Autowired
109113 private SessionFactory sessionFactory ;
110114 @ Autowired
111- private ExpressionExperimentService expressionExperimentService ;
115+ private ParentIdentityRetrievalStrategy parentIdentityRetrievalStrategy ;
112116
113117 @ Override
114118 @ Transactional
@@ -205,7 +209,6 @@ private void lintAclObjectIdentityLackingSecurable( Class<? extends Securable> c
205209 }
206210 for ( AclObjectIdentity aoi : list ) {
207211 if ( config .isApplyFixes () ) {
208- // not removing child, but we will visit it later if it's also dangling
209212 aclService .deleteAcl ( aoi , true );
210213 log .info ( "Deleted dangling " + aoi + "." );
211214 results .add ( new LintResult ( clazz , aoi .getIdentifier (), String .format ( "%s has no corresponding %s entity with ID %d." , aoi , clazz .getName (), aoi .getIdentifier () ), true ) );
@@ -225,7 +228,7 @@ private void lintSecurableLackingObjectIdentity( Class<? extends Securable> claz
225228 //noinspection unchecked
226229 List <? extends Securable > list = sessionFactory .getCurrentSession ()
227230 .createQuery ( "select e from " + clazz .getName () + " e "
228- + "where e.id not in ( " + " select aoi.identifier from AclObjectIdentity aoi where aoi.type = :type" + " )" )
231+ + "where e.id not in (select aoi.identifier from AclObjectIdentity aoi where aoi.type = :type)" )
229232 .setParameter ( "type" , clazz .getName () )
230233 .setReadOnly ( !config .isApplyFixes () )
231234 .list ();
@@ -248,7 +251,7 @@ private void lintSecurableLackingObjectIdentity( Class<? extends Securable> claz
248251 private void lintSecurableLackingObjectIdentity ( Class <? extends Securable > clazz , Long identifier , AclLinterConfig config , Collection <LintResult > results ) {
249252 Securable s = ( Securable ) sessionFactory .getCurrentSession ()
250253 .createQuery ( "select e from " + clazz .getName () + " e "
251- + "where e.id = :identifier and e.id not in ( " + " select aoi.identifier from AclObjectIdentity aoi where aoi.type = :type" + " )" )
254+ + "where e.id = :identifier and e.id not in (select aoi.identifier from AclObjectIdentity aoi where aoi.type = :type and aoi.identifier = :identifier )" )
252255 .setParameter ( "identifier" , identifier )
253256 .setParameter ( "type" , clazz .getName () )
254257 .setReadOnly ( !config .isApplyFixes () )
@@ -286,7 +289,7 @@ private void lintSecuredChildWithoutParent( Class<? extends SecuredChild<?>> cla
286289 }
287290 for ( AclObjectIdentity aoi : list ) {
288291 if ( config .isApplyFixes () ) {
289- AclObjectIdentity parentAoi = getParentAclObjectIdentity ( clazz , aoi );
292+ AclObjectIdentity parentAoi = ( AclObjectIdentity ) parentIdentityRetrievalStrategy . locateParentIdentity ( aoi );
290293 String p = aoi .getType () + " Id=" + aoi .getIdentifier () + " has no parent ACL identity, it should be " + parentAoi + "." ;
291294 if ( parentAoi != null ) {
292295 aoi .setParentObject ( parentAoi );
@@ -311,12 +314,12 @@ private void lintSecuredChildWithoutParent( Class<? extends SecuredChild<?>> cla
311314 .uniqueResult ();
312315 String s = clazz .getSimpleName () + " Id=" + identifier ;
313316 if ( aoi == null ) {
314- log .info ( s + " has a parent ACL identity." );
317+ log .warn ( s + " does not have an ACL identity." );
315318 return ;
316319 }
317320 String p = s + " has no parent ACL identity." ;
318321 if ( config .isApplyFixes () ) {
319- AclObjectIdentity parentAoi = getParentAclObjectIdentity ( clazz , aoi );
322+ AclObjectIdentity parentAoi = ( AclObjectIdentity ) parentIdentityRetrievalStrategy . locateParentIdentity ( aoi );
320323 if ( parentAoi != null ) {
321324 aoi .setParentObject ( parentAoi );
322325 results .add ( new LintResult ( clazz , aoi .getIdentifier (), p , true ) );
@@ -351,7 +354,7 @@ private void lintSecuredChildWithIncorrectParent( Class<? extends SecuredChild<?
351354 String p = String .format ( "%s Id=%d does not have a parent ACL identity of type %s: %s." , aoi .getType (),
352355 aoi .getIdentifier (), expectedParentClass .getSimpleName (), currentParentAoi );
353356 if ( config .isApplyFixes () ) {
354- AclObjectIdentity parentAoi = getParentAclObjectIdentity ( clazz , aoi );
357+ AclObjectIdentity parentAoi = ( AclObjectIdentity ) parentIdentityRetrievalStrategy . locateParentIdentity ( aoi );
355358 if ( parentAoi != null ) {
356359 aoi .setParentObject ( parentAoi );
357360 results .add ( new LintResult ( clazz , aoi .getIdentifier (), p , true ) );
@@ -380,15 +383,15 @@ private void lintSecuredChildWithIncorrectParent( Class<? extends SecuredChild<?
380383 .uniqueResult ();
381384 String s = clazz .getSimpleName () + " Id=" + identifier ;
382385 if ( row == null ) {
383- log .info ( s + " has no parent ACL identity identity ." );
386+ log .info ( s + " has no parent ACL identity." );
384387 return ;
385388 }
386389 AclObjectIdentity aoi = ( AclObjectIdentity ) row [0 ];
387390 AclObjectIdentity currentParentAoi = ( AclObjectIdentity ) row [1 ];
388391 String problem = String .format ( "%s does not have a parent ACL identity of type %s: %s." , s ,
389392 expectedParentClass .getSimpleName (), currentParentAoi );
390393 if ( config .isApplyFixes () ) {
391- AclObjectIdentity parentAoi = getParentAclObjectIdentity ( clazz , aoi );
394+ AclObjectIdentity parentAoi = ( AclObjectIdentity ) parentIdentityRetrievalStrategy . locateParentIdentity ( aoi );
392395 if ( parentAoi != null ) {
393396 aoi .setParentObject ( parentAoi );
394397 results .add ( new LintResult ( clazz , aoi .getId (), problem , true ) );
@@ -400,82 +403,6 @@ private void lintSecuredChildWithIncorrectParent( Class<? extends SecuredChild<?
400403 }
401404 }
402405
403- @ Nullable
404- private AclObjectIdentity getParentAclObjectIdentity ( Class <? extends SecuredChild <?>> clazz , AclObjectIdentity aoi ) {
405- Class <? extends Securable > parentType ;
406- Long parentIdentifier ;
407- if ( ExperimentalFactor .class .isAssignableFrom ( clazz ) ) {
408- parentType = ExpressionExperiment .class ;
409- ExperimentalFactor factor = ( ExperimentalFactor ) sessionFactory .getCurrentSession ()
410- .get ( ExperimentalFactor .class , aoi .getIdentifier () );
411- ExpressionExperiment ee = expressionExperimentService .findByFactor ( factor );
412- parentIdentifier = ee != null ? ee .getId () : null ;
413- } else if ( FactorValue .class .isAssignableFrom ( clazz ) ) {
414- parentType = ExpressionExperiment .class ;
415- FactorValue factor = ( FactorValue ) sessionFactory .getCurrentSession ()
416- .get ( FactorValue .class , aoi .getIdentifier () );
417- ExpressionExperiment ee = expressionExperimentService .findByFactorValue ( factor );
418- parentIdentifier = ee != null ? ee .getId () : null ;
419- } else if ( BioAssay .class .isAssignableFrom ( clazz ) ) {
420- parentType = ExpressionExperiment .class ;
421- BioAssay ba = ( BioAssay ) sessionFactory .getCurrentSession ()
422- .get ( BioAssay .class , aoi .getIdentifier () );
423- ExpressionExperiment ee = expressionExperimentService .findByBioAssay ( ba );
424- parentIdentifier = ee != null ? ee .getId () : null ;
425- } else if ( BioMaterial .class .isAssignableFrom ( clazz ) ) {
426- parentType = ExpressionExperiment .class ;
427- BioMaterial bm = ( BioMaterial ) sessionFactory .getCurrentSession ()
428- .get ( BioMaterial .class , aoi .getIdentifier () );
429- Collection <ExpressionExperiment > ees = expressionExperimentService .findByBioMaterial ( bm );
430- if ( ees .size () == 1 ) {
431- parentIdentifier = ees .iterator ().next ().getId ();
432- } else if ( ees .size () > 1 ) {
433- log .warn ( "More than one ExpressionExperiment refer to " + bm + ", cannot pick its parent ACL identity." );
434- parentIdentifier = null ;
435- } else {
436- parentIdentifier = null ;
437- }
438- } else if ( MeanVarianceRelation .class .isAssignableFrom ( clazz ) ) {
439- MeanVarianceRelation mvr = ( MeanVarianceRelation ) sessionFactory .getCurrentSession ()
440- .get ( MeanVarianceRelation .class , aoi .getIdentifier () );
441- ExpressionExperiment ee = expressionExperimentService .findByMeanVarianceRelation ( mvr );
442- parentType = ExpressionExperiment .class ;
443- parentIdentifier = ee != null ? ee .getId () : null ;
444- } else {
445- // try automated!
446- SecuredChild <?> sc = ( SecuredChild <?> ) sessionFactory .getCurrentSession ()
447- .get ( clazz , aoi .getIdentifier () );
448- if ( sc != null && sc .getSecurityOwner () != null ) {
449- //noinspection unchecked
450- parentType = Hibernate .getClass ( sc .getSecurityOwner () );
451- parentIdentifier = sc .getSecurityOwner ().getId ();
452- } else if ( sc == null ) {
453- log .warn ( "Cannot resolve ACL identity for " + clazz .getSimpleName () + " Id=" + aoi .getIdentifier () + "." );
454- parentType = null ;
455- parentIdentifier = null ;
456- } else {
457- log .warn ( "Cannot resolve parent ACL identity for " + aoi .getType () + "." );
458- parentType = null ;
459- parentIdentifier = null ;
460- }
461- }
462- if ( parentIdentifier != null ) {
463- AclObjectIdentity parentAoi = ( AclObjectIdentity ) sessionFactory .getCurrentSession ()
464- .createQuery ( "select aoi from AclObjectIdentity aoi where aoi.type = :type and aoi.identifier = :identifier" )
465- .setParameter ( "type" , parentType .getName () )
466- .setParameter ( "identifier" , parentIdentifier )
467- .uniqueResult ();
468- if ( parentAoi != null ) {
469- return parentAoi ;
470- } else {
471- log .warn ( "Could not resolve ACL identity for " + parentType .getSimpleName () + " Id=" + parentIdentifier + "." );
472- return null ;
473- }
474- } else {
475- return null ;
476- }
477- }
478-
479406 /**
480407 * Lint for securable entities that are explicitly not children, but have a parent object set in their ACL identity.
481408 * <p>
0 commit comments