Skip to content

Commit 43d5a2d

Browse files
committed
Add support for filtering ACLs using subqueries
Rename EE2CAclQueryUtils to AclDenormalizedTableQueryUtils since it's also being used for other denormalized tables. Make the mask column and requested authority configurable when querying denormalized tables.
1 parent d548c17 commit 43d5a2d

13 files changed

Lines changed: 256 additions & 134 deletions

File tree

gemma-core/src/main/java/ubic/gemma/core/loader/util/mapper/EntityMapper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010

1111
/**
1212
* Map external identifiers to Gemma entities.
13+
* <p>
14+
* Mapping works by defining a set of candidates {@link Identifiable} and a set of external identifiers (e.g. gene
15+
* symbols, accession numbers, etc.) to map against. For efficiency, the mapping process creates a "state" for the
16+
* candidates that enables fast lookups that one can obtain with {@link #forCandidates(Collection)}.
17+
* <p>
18+
* It is then possible to tell if an identifier has a match among the candidates, to obtain a single match, to obtain
19+
* all matches or to obtain mapping statistics. Mapping statistics are useful for debugging, but also comparing
20+
* different mapping strategies. For example, one could want to compare whether mapping by official gene symbols or
21+
* Ensembl identifiers yields better results.
22+
*
1323
* @param <T> the type of entity being mapped
1424
* @author poirigui
1525
*/

gemma-core/src/main/java/ubic/gemma/persistence/service/common/description/BibliographicReferenceDaoImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public long countDistinctWithRelatedExperiments() {
7575
.createQuery( "select count(" + ( AclQueryUtils.requiresCountDistinct() ? "distinct " : "" ) + " b)" + " "
7676
+ "from ExpressionExperiment e join e.primaryPublication b "
7777
+ AclQueryUtils.formAclRestrictionClause( "e.id" ) );
78-
AclQueryUtils.addAclParameters( q, ExpressionExperiment.class );
78+
AclQueryUtils.setAclParameters( q, ExpressionExperiment.class );
7979
return ( Long ) q.uniqueResult();
8080
}
8181

@@ -87,7 +87,7 @@ public long countWithRelatedExperiments() {
8787
.createQuery( "select count(" + ( AclQueryUtils.requiresCountDistinct() ? "distinct " : "" ) + " e)" + " "
8888
+ "from ExpressionExperiment e join e.primaryPublication b"
8989
+ AclQueryUtils.formAclRestrictionClause( "e.id" ) );
90-
AclQueryUtils.addAclParameters( q, ExpressionExperiment.class );
90+
AclQueryUtils.setAclParameters( q, ExpressionExperiment.class );
9191
return ( Long ) q.uniqueResult();
9292
}
9393

@@ -99,7 +99,7 @@ public LinkedHashMap<BibliographicReference, Set<ExpressionExperimentIdAndShortN
9999
+ ( AclQueryUtils.requiresGroupBy() ? "group by b, e " : "" )
100100
+ "order by b.authorList nulls last, b.title nulls last"
101101
);
102-
AclQueryUtils.addAclParameters( q, ExpressionExperiment.class );
102+
AclQueryUtils.setAclParameters( q, ExpressionExperiment.class );
103103
//noinspection unchecked
104104
List<Object[]> os = q
105105
.setFirstResult( offset )
@@ -126,7 +126,7 @@ public LinkedHashMap<BibliographicReference, Collection<ExpressionExperiment>> g
126126
+ "and b in (:recs) "
127127
+ ( AclQueryUtils.requiresGroupBy() ? "group by b, e " : "" )
128128
+ "order by b.authorList nulls last, b.title nulls last" );
129-
AclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
129+
AclQueryUtils.setAclParameters( query, ExpressionExperiment.class );
130130
List<Object[]> os = QueryUtils.listByIdentifiableBatch( query, "recs", records, eeBatchSize );
131131
LinkedHashMap<BibliographicReference, Collection<ExpressionExperiment>> result = new LinkedHashMap<>();
132132
for ( Object[] o : os ) {

gemma-core/src/main/java/ubic/gemma/persistence/service/common/description/CharacteristicDaoImpl.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.hibernate.engine.spi.SessionFactoryImplementor;
3030
import org.hibernate.type.StandardBasicTypes;
3131
import org.springframework.beans.factory.annotation.Autowired;
32+
import org.springframework.security.acls.domain.BasePermission;
3233
import org.springframework.stereotype.Repository;
3334
import org.springframework.util.Assert;
3435
import ubic.gemma.core.ontology.OntologyUtils;
@@ -45,7 +46,7 @@
4546
import ubic.gemma.model.genome.Taxon;
4647
import ubic.gemma.model.genome.gene.GeneSet;
4748
import ubic.gemma.persistence.service.AbstractNoopFilteringVoEnabledDao;
48-
import ubic.gemma.persistence.util.EE2CAclQueryUtils;
49+
import ubic.gemma.persistence.util.AclDenormalizedTableQueryUtils;
4950
import ubic.gemma.persistence.util.IdentifiableUtils;
5051
import ubic.gemma.persistence.util.QueryUtils;
5152

@@ -56,6 +57,7 @@
5657

5758
import static org.hibernate.criterion.Restrictions.like;
5859
import static org.hibernate.criterion.Restrictions.not;
60+
import static ubic.gemma.persistence.service.maintenance.TableMaintenanceUtil.EE2C_IS_AUTHENTICATED_ANONYMOUSLY_MASK_COLUMN;
5961
import static ubic.gemma.persistence.service.maintenance.TableMaintenanceUtil.EE2C_QUERY_SPACE;
6062
import static ubic.gemma.persistence.util.IdentifiableUtils.toIdentifiableSet;
6163
import static ubic.gemma.persistence.util.QueryUtils.*;
@@ -242,11 +244,13 @@ public Map<Class<? extends Identifiable>, Map<String, Set<ExpressionExperiment>>
242244
private Map<Class<? extends Identifiable>, Map<String, Set<Long>>> findExperimentsByUrisInternal( Collection<String> uris, boolean includeSubjects, boolean includePredicates, boolean includeObjects, @Nullable Taxon taxon, boolean rankByLevel, int limit ) {
243245
String qs = "select T.`LEVEL`, T.VALUE_URI, T.PREDICATE_URI, T.OBJECT_URI, T.SECOND_PREDICATE_URI, T.SECOND_OBJECT_URI, T.EXPRESSION_EXPERIMENT_FK from EXPRESSION_EXPERIMENT2CHARACTERISTIC T"
244246
+ ( taxon != null ? " join INVESTIGATION I on T.EXPRESSION_EXPERIMENT_FK = I.ID " : "" )
245-
+ EE2CAclQueryUtils.formNativeAclJoinClause( "T.EXPRESSION_EXPERIMENT_FK" ) + " "
247+
+ AclDenormalizedTableQueryUtils.formNativeAclJoinClause( "T.EXPRESSION_EXPERIMENT_FK", "IS_AUTHENTICATED_ANONYMOUSLY" ) + " "
246248
+ "where "
247249
+ createPredicates( "T", "uris", includeSubjects, includePredicates, includeObjects )
248250
+ ( taxon != null ? " and I.TAXON_FK = :taxonId" : "" )
249-
+ EE2CAclQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(), "T.ACL_IS_AUTHENTICATED_ANONYMOUSLY_MASK" )
251+
+ AclDenormalizedTableQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(),
252+
"IS_AUTHENTICATED_ANONYMOUSLY", "T." + EE2C_IS_AUTHENTICATED_ANONYMOUSLY_MASK_COLUMN,
253+
BasePermission.READ )
250254
+ ( rankByLevel ? " order by FIELD(T.LEVEL, :eeClass, :edClass, :bmClass)" : "" );
251255

252256
Query query = getSessionFactory().getCurrentSession().createSQLQuery( qs )
@@ -274,7 +278,7 @@ private Map<Class<? extends Identifiable>, Map<String, Set<Long>>> findExperimen
274278
query.setParameter( "taxonId", taxon.getId() );
275279
}
276280

277-
EE2CAclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
281+
AclDenormalizedTableQueryUtils.setAclParameters( query, "IS_AUTHENTICATED_ANONYMOUSLY", ExpressionExperiment.class );
278282

279283
query.setCacheable( true );
280284

gemma-core/src/main/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignDaoImpl.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.hibernate.engine.spi.SessionFactoryImplementor;
2626
import org.hibernate.type.StandardBasicTypes;
2727
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.security.acls.domain.BasePermission;
2829
import org.springframework.stereotype.Repository;
2930
import org.springframework.util.Assert;
3031
import ubic.gemma.model.common.auditAndSecurity.AuditEvent;
@@ -43,6 +44,7 @@
4344
import ubic.gemma.model.genome.sequenceAnalysis.BlatAssociation;
4445
import ubic.gemma.model.genome.sequenceAnalysis.BlatResult;
4546
import ubic.gemma.persistence.service.common.auditAndSecurity.curation.AbstractCuratableDao;
47+
import ubic.gemma.persistence.service.maintenance.TableMaintenanceUtil;
4648
import ubic.gemma.persistence.util.*;
4749
import ubic.gemma.persistence.util.Filter;
4850

@@ -492,7 +494,7 @@ public long countExpressionExperiments( ArrayDesign arrayDesign ) {
492494
+ AclQueryUtils.formAclRestrictionClause( "ee.id" ) + " "
493495
+ "and ad = :ad" )
494496
.setParameter( "ad", arrayDesign );
495-
AclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
497+
AclQueryUtils.setAclParameters( query, ExpressionExperiment.class );
496498
return ( Long ) query.uniqueResult();
497499
}
498500

@@ -503,7 +505,7 @@ public Map<Taxon, Long> getPerTaxonCount() {
503505
+ "join ad.primaryTaxon t "
504506
+ AclQueryUtils.formAclRestrictionClause( "ad.id" ) + " "
505507
+ "group by t" );
506-
AclQueryUtils.addAclParameters( query, ArrayDesign.class );
508+
AclQueryUtils.setAclParameters( query, ArrayDesign.class );
507509
//noinspection unchecked
508510
List<Object[]> csList = query.setCacheable( true ).list();
509511
return csList.stream().collect( Collectors.toMap( row -> ( Taxon ) row[0], row -> ( Long ) row[1] ) );
@@ -536,7 +538,7 @@ public long countSwitchedExpressionExperiments( ArrayDesign arrayDesign ) {
536538
+ AclQueryUtils.formAclRestrictionClause( "e.id" ) + " "
537539
+ "and b.originalPlatform = :arrayDesign" )
538540
.setParameter( "arrayDesign", arrayDesign );
539-
AclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
541+
AclQueryUtils.setAclParameters( query, ExpressionExperiment.class );
540542
return ( Long ) query
541543
.setCacheable( true )
542544
.uniqueResult();
@@ -1059,7 +1061,7 @@ private Query finishFilteringQuery( String queryString, @Nullable Filters filter
10591061

10601062
Query query = this.getSessionFactory().getCurrentSession().createQuery( queryString );
10611063

1062-
AclQueryUtils.addAclParameters( query, ArrayDesign.class );
1064+
AclQueryUtils.setAclParameters( query, ArrayDesign.class );
10631065
FilterQueryUtils.addRestrictionParameters( query, filters );
10641066

10651067
return query;
@@ -1136,10 +1138,12 @@ private void populateBlacklisted( Collection<ArrayDesignValueObject> vos ) {
11361138
private void populateExpressionExperimentCount( Collection<ArrayDesignValueObject> entities ) {
11371139
Query query = this.getSessionFactory().getCurrentSession()
11381140
.createSQLQuery( "select ee2ad.ARRAY_DESIGN_FK as ID, count(distinct ee2ad.EXPRESSION_EXPERIMENT_FK) as EE_COUNT from EXPRESSION_EXPERIMENT2ARRAY_DESIGN ee2ad "
1139-
+ EE2CAclQueryUtils.formNativeAclJoinClause( "ee2ad.EXPRESSION_EXPERIMENT_FK" ) + " "
1141+
+ AclDenormalizedTableQueryUtils.formNativeAclJoinClause( "ee2ad.EXPRESSION_EXPERIMENT_FK", "IS_AUTHENTICATED_ANONYMOUSLY" ) + " "
11401142
+ "where ee2ad.ARRAY_DESIGN_FK in :ids "
11411143
+ "and not ee2ad.IS_ORIGINAL_PLATFORM"
1142-
+ EE2CAclQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(), "ee2ad.ACL_IS_AUTHENTICATED_ANONYMOUSLY_MASK" )
1144+
+ AclDenormalizedTableQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(),
1145+
"IS_AUTHENTICATED_ANONYMOUSLY", "ee2ad." + TableMaintenanceUtil.EE2AD_IS_AUTHENTICATED_ANONYMOUSLY_MASK_COLUMN,
1146+
BasePermission.READ )
11431147
+ formNativeNonTroubledClause( "ee2ad.EXPRESSION_EXPERIMENT_FK", ExpressionExperiment.class )
11441148
+ " group by ee2ad.ARRAY_DESIGN_FK" )
11451149
.addScalar( "ID", StandardBasicTypes.LONG )
@@ -1150,7 +1154,7 @@ private void populateExpressionExperimentCount( Collection<ArrayDesignValueObjec
11501154
.addSynchronizedEntityClass( ExpressionExperiment.class )
11511155
.addSynchronizedEntityClass( ArrayDesign.class )
11521156
.setCacheable( true );
1153-
EE2CAclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
1157+
AclDenormalizedTableQueryUtils.setAclParameters( query, "IS_AUTHENTICATED_ANONYMOUSLY", ExpressionExperiment.class );
11541158
Map<Long, Long> countById = QueryUtils.<Long, Object[]>streamByBatch( query, "ids", IdentifiableUtils.getIds( entities ), 2048 )
11551159
.collect( Collectors.toMap( o -> ( Long ) o[0], o -> ( Long ) o[1] ) );
11561160
for ( ArrayDesignValueObject vo : entities ) {
@@ -1162,12 +1166,14 @@ private void populateExpressionExperimentCount( Collection<ArrayDesignValueObjec
11621166
private void populateSwitchedExpressionExperimentCount( Collection<ArrayDesignValueObject> entities ) {
11631167
Query query = this.getSessionFactory().getCurrentSession()
11641168
.createSQLQuery( "select ee2ad.ARRAY_DESIGN_FK as ID, count(distinct ee2ad.EXPRESSION_EXPERIMENT_FK) as EE_COUNT from EXPRESSION_EXPERIMENT2ARRAY_DESIGN ee2ad "
1165-
+ EE2CAclQueryUtils.formNativeAclJoinClause( "ee2ad.EXPRESSION_EXPERIMENT_FK" ) + " "
1169+
+ AclDenormalizedTableQueryUtils.formNativeAclJoinClause( "ee2ad.EXPRESSION_EXPERIMENT_FK", "IS_AUTHENTICATED_ANONYMOUSLY" ) + " "
11661170
+ "where ee2ad.ARRAY_DESIGN_FK in :ids "
11671171
+ "and ee2ad.IS_ORIGINAL_PLATFORM "
11681172
// ignore noop switches
11691173
+ "and ee2ad.ARRAY_DESIGN_FK not in (select ARRAY_DESIGN_FK from EXPRESSION_EXPERIMENT2ARRAY_DESIGN where EXPRESSION_EXPERIMENT_FK = ee2ad.EXPRESSION_EXPERIMENT_FK and ARRAY_DESIGN_FK = ee2ad.ARRAY_DESIGN_FK and not IS_ORIGINAL_PLATFORM)"
1170-
+ EE2CAclQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(), "ee2ad.ACL_IS_AUTHENTICATED_ANONYMOUSLY_MASK" )
1174+
+ AclDenormalizedTableQueryUtils.formNativeAclRestrictionClause( ( SessionFactoryImplementor ) getSessionFactory(),
1175+
"IS_AUTHENTICATED_ANONYMOUSLY", "ee2ad." + TableMaintenanceUtil.EE2AD_IS_AUTHENTICATED_ANONYMOUSLY_MASK_COLUMN,
1176+
BasePermission.READ )
11711177
+ formNativeNonTroubledClause( "ee2ad.EXPRESSION_EXPERIMENT_FK", ExpressionExperiment.class )
11721178
+ " group by ee2ad.ARRAY_DESIGN_FK" )
11731179
.addScalar( "ID", StandardBasicTypes.LONG )
@@ -1178,7 +1184,7 @@ private void populateSwitchedExpressionExperimentCount( Collection<ArrayDesignVa
11781184
.addSynchronizedEntityClass( ExpressionExperiment.class )
11791185
.addSynchronizedEntityClass( ArrayDesign.class )
11801186
.setCacheable( true );
1181-
EE2CAclQueryUtils.addAclParameters( query, ExpressionExperiment.class );
1187+
AclDenormalizedTableQueryUtils.setAclParameters( query, "IS_AUTHENTICATED_ANONYMOUSLY", ExpressionExperiment.class );
11821188
Map<Long, Long> switchedCountById = QueryUtils.<Long, Object[]>streamByBatch( query, "ids", IdentifiableUtils.getIds( entities ), 2048 )
11831189
.collect( Collectors.toMap( row -> ( Long ) row[0], row -> ( Long ) row[1] ) );
11841190
for ( ArrayDesignValueObject vo : entities ) {

gemma-core/src/main/java/ubic/gemma/persistence/service/expression/designElement/CompositeSequenceDaoImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ protected Query getFilteringQuery( @Nullable Filters filters, @Nullable Sort sor
9999
+ ( !SecurityUtil.isUserAdmin() ? " and ad.curationDetails.troubled = false" : "" )
100100
+ FilterQueryUtils.formRestrictionClause( filters )
101101
+ FilterQueryUtils.formOrderByClause( sort ) );
102-
AclQueryUtils.addAclParameters( query, ArrayDesign.class );
102+
AclQueryUtils.setAclParameters( query, ArrayDesign.class );
103103
FilterQueryUtils.addRestrictionParameters( query, filters );
104104
return query;
105105
}
@@ -119,7 +119,7 @@ protected Query getFilteringIdQuery( @Nullable Filters filters, @Nullable Sort s
119119
+ ( !SecurityUtil.isUserAdmin() ? " and ad.curationDetails.troubled = false" : "" )
120120
+ FilterQueryUtils.formRestrictionClause( filters )
121121
+ FilterQueryUtils.formOrderByClause( sort ) );
122-
AclQueryUtils.addAclParameters( query, ArrayDesign.class );
122+
AclQueryUtils.setAclParameters( query, ArrayDesign.class );
123123
FilterQueryUtils.addRestrictionParameters( query, filters );
124124
return query;
125125
}
@@ -132,7 +132,7 @@ protected Query getFilteringCountQuery( @Nullable Filters filters ) {
132132
+ AclQueryUtils.formAclRestrictionClause( "ad.id" )
133133
+ ( !SecurityUtil.isUserAdmin() ? " and ad.curationDetails.troubled = false" : "" )
134134
+ FilterQueryUtils.formRestrictionClause( filters ) );
135-
AclQueryUtils.addAclParameters( query, ArrayDesign.class );
135+
AclQueryUtils.setAclParameters( query, ArrayDesign.class );
136136
FilterQueryUtils.addRestrictionParameters( query, filters );
137137
return query;
138138
}

0 commit comments

Comments
 (0)