Skip to content

Commit 9f5aeb9

Browse files
authored
Merge pull request #2265 from broadinstitute/jb-raw-location-classic-upload
Strip undefined attributes during StudyFile creation (SCP-5996)
2 parents 2b2f1ee + 6bd9cdf commit 9f5aeb9

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

app/controllers/api/v1/study_files_controller.rb

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -331,23 +331,22 @@ def perform_update!(study_file)
331331
end
332332
if safe_file_params[:custom_color_updates]
333333
parsed_update = JSON.parse(safe_file_params[:custom_color_updates])
334-
safe_file_params['cluster_file_info'] = {custom_colors: ClusterFileInfo.merge_color_updates(study_file, parsed_update)}
335-
safe_file_params.delete(:custom_color_updates)
334+
safe_file_params[:cluster_file_info_attributes] = {
335+
custom_colors: ClusterFileInfo.merge_color_updates(study_file, parsed_update)
336+
}
336337
end
337338

338339
# manually check first if species/assembly was supplied by name
339340
species_name = safe_file_params[:species]
340-
safe_file_params.delete(:species)
341341
assembly_name = safe_file_params[:assembly]
342-
safe_file_params.delete(:assembly)
343342
set_taxon_and_assembly_by_name({species: species_name, assembly: assembly_name})
344343
# clear the id so that it doesn't get overwritten -- this would be a security hole for existing files
345344
# and for new files the id will have been set along with creation of the StudyFile object in the `create`
346345
# method above
347346
safe_file_params.delete(:_id)
348347

349348
parse_on_upload = safe_file_params[:parse_on_upload]
350-
safe_file_params.delete(:parse_on_upload)
349+
cleaned_params = self.class.strip_undefined_params(safe_file_params)
351350

352351
# check if the name of the file has changed as we won't be able to tell after we saved
353352
name_changed = study_file.persisted? && study_file.name != safe_file_params[:name]
@@ -363,7 +362,7 @@ def perform_update!(study_file)
363362
fileSize: study_file.upload_file_size
364363
}, current_api_user)
365364

366-
study_file.update!(safe_file_params)
365+
study_file.update!(cleaned_params)
367366

368367
# invalidate caches first
369368
study_file.delay.invalidate_cache_by_file_type
@@ -388,7 +387,7 @@ def perform_update!(study_file)
388387
end
389388
end
390389

391-
if ['Expression Matrix', 'MM Coordinate Matrix'].include?(study_file.file_type) && !safe_file_params[:y_axis_label].blank?
390+
if ['Expression Matrix', 'MM Coordinate Matrix'].include?(study_file.file_type) && cleaned_params[:y_axis_label].present?
392391
# if user is supplying an expression axis label, update default options hash
393392
study.default_options[:expression_label] = safe_file_params[:y_axis_label]
394393
study.save
@@ -400,8 +399,8 @@ def perform_update!(study_file)
400399
end
401400
end
402401

403-
if safe_file_params[:upload].present? && !is_chunked ||
404-
safe_file_params[:remote_location].present? ||
402+
if cleaned_params[:upload].present? && !is_chunked ||
403+
cleaned_params[:remote_location].present? ||
405404
study_file.needs_raw_counts_extraction?
406405
complete_upload_process(study_file, parse_on_upload)
407406
end
@@ -705,6 +704,29 @@ def bundle
705704
end
706705
end
707706

707+
# remove any remaining parameters that aren't defined and can cause UnknownAttribute errors when saving
708+
def self.strip_undefined_params(parameters)
709+
safe_params = {}
710+
transform = parameters.is_a?(ActionController::Parameters) ? :to_unsafe_hash : :with_indifferent_access
711+
accessible_params = parameters.send(transform)
712+
StudyFile.nested_attributes.keys.map do |association|
713+
classname = association.to_s.chomp('_attributes').singularize.camelize
714+
next unless Object.const_defined?(classname) && accessible_params[association].present?
715+
716+
assoc_class = classname.constantize
717+
safe_params[association] = {}
718+
accessible_params[association].each do |attribute, value|
719+
safe_params[association][attribute] = value if assoc_class.fields[attribute.to_s].present?
720+
end
721+
end
722+
accessible_params.each do |param, val|
723+
next if param.to_s.ends_with?('_attributes')
724+
725+
safe_params[param] = val if StudyFile.fields[param.to_s].present?
726+
end
727+
safe_params
728+
end
729+
708730
private
709731

710732
# manual check to see if user supplied taxon/assembly by name

test/api/study_files_controller_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,30 @@ class StudyFilesControllerTest < ActionDispatch::IntegrationTest
355355
assert ann_data_file.needs_raw_counts_extraction?
356356
end
357357
end
358+
359+
test 'should remove undefined parameters' do
360+
params = {
361+
name: 'matrix.tsv',
362+
upload_file_name: 'matrix.tsv',
363+
upload_content_type: 'application/octet-stream',
364+
upload_file_size: 1.megabyte,
365+
file_type: 'Expression Matrix',
366+
this_is_not_an_attribute: 'foo',
367+
expression_file_info_attributes: {
368+
is_raw_counts: true,
369+
biosample_input_type: 'Whole cell',
370+
modality: 'Transcriptomic: unbiased',
371+
raw_counts_associations: [''],
372+
units: 'raw counts',
373+
library_preparation_protocol: "10x 5' v3",
374+
also_not_an_attribute: 'bar'
375+
}
376+
}
377+
clean_params = Api::V1::StudyFilesController.strip_undefined_params(params).with_indifferent_access
378+
assert_equal params[:name], clean_params[:name]
379+
assert_equal params[:file_type], clean_params[:file_type]
380+
assert_equal params[:expression_file_info_attributes][:units], clean_params[:expression_file_info_attributes][:units]
381+
assert_nil clean_params[:this_is_not_an_attribute]
382+
assert_nil clean_params[:expression_file_info_attributes][:also_not_an_attribute]
383+
end
358384
end

0 commit comments

Comments
 (0)