From a57a1d433a62dcfb9407dd06bfe15d676e1fac96 Mon Sep 17 00:00:00 2001 From: Robert Olson Date: Thu, 5 Mar 2026 14:39:00 -0600 Subject: [PATCH] Add filtering for private data to protein_structure lookups. --- middleware/DecorateQuery.js | 23 ++++++++++++++++++----- middleware/PublicDataTypes.js | 2 +- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/middleware/DecorateQuery.js b/middleware/DecorateQuery.js index aa084a0a..2f7e1d1c 100644 --- a/middleware/DecorateQuery.js +++ b/middleware/DecorateQuery.js @@ -1,13 +1,26 @@ +// Collections that need join-based access control (they reference genomes but don't have their own permission fields) +const joinAccessControlCollections = { + protein_structure: { fromIndex: 'genome', from: 'genome_id', to: 'genome_id' } +} + module.exports = function (req, res, next) { if (req.call_method !== 'query') { return next() } req.call_params[0] = req.call_params[0] || '&q=*:*' - if (!req.user) { - if (!req.publicFree || (req.publicFree && (req.publicFree.indexOf(req.call_collection) < 0))) { - req.call_params[0] = req.call_params[0] + '&fq=public:true' + + // Check if this collection needs join-based access control + const joinConfig = joinAccessControlCollections[req.call_collection] + if (joinConfig) { + // Use a Solr cross-collection join to filter by the referenced collection's access control + if (!req.user) { + req.call_params[0] = req.call_params[0] + `&fq={!join method=crossCollection from=${joinConfig.from} to=${joinConfig.to} fromIndex=${joinConfig.fromIndex}}public:true` + } else { + req.call_params[0] = req.call_params[0] + `&fq={!join method=crossCollection from=${joinConfig.from} to=${joinConfig.to} fromIndex=${joinConfig.fromIndex}}(public:true OR owner:${req.user} OR user_read:${req.user})` } - } else { - if (!req.publicFree || (req.publicFree && (req.publicFree.indexOf(req.call_collection) < 0))) { + } else if (!req.publicFree || (req.publicFree && (req.publicFree.indexOf(req.call_collection) < 0))) { + if (!req.user) { + req.call_params[0] = req.call_params[0] + '&fq=public:true' + } else { req.call_params[0] = req.call_params[0] + ('&fq=(public:true OR owner:' + req.user + ' OR user_read:' + req.user + ')') } } diff --git a/middleware/PublicDataTypes.js b/middleware/PublicDataTypes.js index 0f2e985f..d43d5877 100644 --- a/middleware/PublicDataTypes.js +++ b/middleware/PublicDataTypes.js @@ -1,5 +1,5 @@ -const publicFree = ['antibiotics', 'enzyme_class_ref', 'epitope', 'epitope_assay', 'experiment', 'bioset', 'bioset_result', 'gene_ontology_ref', 'id_ref', 'misc_niaid_sgc', 'pathway_ref', 'ppi', 'pig', 'protein_family_ref', 'sp_gene_evidence', 'sp_gene_ref', 'spike_lineage', 'spike_variant', 'subsystem_ref', 'taxonomy', 'transcriptomics_experiment', 'transcriptomics_gene', 'transcriptomics_sample', 'model_reaction', 'model_complex_role', 'model_compound', 'model_template_biomass', 'model_template_reaction', 'feature_sequence', 'protein_structure', 'protein_feature', 'surveillance', 'serology', 'sequence_feature', 'sequence_feature_vt'] +const publicFree = ['antibiotics', 'enzyme_class_ref', 'epitope', 'epitope_assay', 'experiment', 'bioset', 'bioset_result', 'gene_ontology_ref', 'id_ref', 'misc_niaid_sgc', 'pathway_ref', 'ppi', 'pig', 'protein_family_ref', 'sp_gene_evidence', 'sp_gene_ref', 'spike_lineage', 'spike_variant', 'subsystem_ref', 'taxonomy', 'transcriptomics_experiment', 'transcriptomics_gene', 'transcriptomics_sample', 'model_reaction', 'model_complex_role', 'model_compound', 'model_template_biomass', 'model_template_reaction', 'feature_sequence', 'protein_feature', 'surveillance', 'serology', 'sequence_feature', 'sequence_feature_vt'] module.exports = function (req, res, next) { req.publicFree = publicFree