diff --git a/app/models/account/data_transfer/manifest.rb b/app/models/account/data_transfer/manifest.rb index 2159926d5..9de76f9bf 100644 --- a/app/models/account/data_transfer/manifest.rb +++ b/app/models/account/data_transfer/manifest.rb @@ -26,20 +26,42 @@ class Account::DataTransfer::Manifest [ Account::DataTransfer::AccountRecordSet.new(account), Account::DataTransfer::UserRecordSet.new(account), - *build_record_sets(::User::Settings, ::Tag, ::Board, ::Column), + *build_record_sets( + ::User::Settings, + ::Tag, + ::Board, + ::Column + ), Account::DataTransfer::EntropyRecordSet.new(account), *build_record_sets( - ::Board::Publication, ::Webhook, ::Access, ::Card, ::Comment, ::Step, - ::Assignment, ::Tagging, ::Closure, ::Card::Goldness, ::Card::NotNow, - ::Card::ActivitySpike, ::Watch, ::Pin, ::Reaction, ::Mention, - ::Filter, ::Webhook::DelinquencyTracker, ::Event, - ::Notification, ::Notification::Bundle, ::Webhook::Delivery + ::Board::Publication, + ::Webhook, + ::Access, + ::Card, + ::Comment, + ::Step, + ::Assignment, + ::Tagging, + ::Closure, + ::Card::Goldness, + ::Card::NotNow, + ::Card::ActivitySpike, + ::Watch, + ::Pin, + ::Reaction, + ::Mention, + ::Filter, + ::Webhook::DelinquencyTracker, + ::Event, + ::Notification, + ::Notification::Bundle, + ::Webhook::Delivery ), Account::DataTransfer::ActiveStorage::BlobRecordSet.new(account), *build_record_sets(::ActiveStorage::Attachment), Account::DataTransfer::ActionText::RichTextRecordSet.new(account), Account::DataTransfer::ActiveStorage::FileRecordSet.new(account) - ] + ].then { set_importable_model_names(it) } end def build_record_sets(*models) @@ -47,4 +69,10 @@ class Account::DataTransfer::Manifest Account::DataTransfer::RecordSet.new(account: account, model: model) end end + + def set_importable_model_names(record_sets) + model_names = record_sets.filter_map { |record_set| record_set.model&.name } + record_sets.each { |record_set| record_set.importable_model_names = model_names } + record_sets + end end diff --git a/app/models/account/data_transfer/record_set.rb b/app/models/account/data_transfer/record_set.rb index 2d64d2e1c..2fba9402d 100644 --- a/app/models/account/data_transfer/record_set.rb +++ b/app/models/account/data_transfer/record_set.rb @@ -4,47 +4,14 @@ class Account::DataTransfer::RecordSet IMPORT_BATCH_SIZE = 100 - IMPORTABLE_MODEL_NAMES = %w[ - Access - Account - ActionText::RichText - ActiveStorage::Attachment - ActiveStorage::Blob - Assignment - Board - Board::Publication - Card - Card::ActivitySpike - Card::Goldness - Card::NotNow - Closure - Column - Comment - Entropy - Event - Filter - Mention - Notification - Notification::Bundle - Pin - Reaction - Step - Tag - Tagging - User - User::Settings - Watch - Webhook - Webhook::DelinquencyTracker - Webhook::Delivery - ].freeze - + attr_accessor :importable_model_names attr_reader :account, :model, :attributes - def initialize(account:, model:, attributes: nil) + def initialize(account:, model:, attributes: nil, importable_model_names: nil) @account = account @model = model @attributes = (attributes || model.column_names).map(&:to_s) + @importable_model_names = importable_model_names || [ model.name ] end def export(to:, start: nil) @@ -159,7 +126,7 @@ class Account::DataTransfer::RecordSet end def verify_model_type(type_name) - if IMPORTABLE_MODEL_NAMES.include?(type_name) + if importable_model_names.include?(type_name) type_name.constantize else raise IntegrityError, "Unrecognized model type: #{type_name}" diff --git a/test/models/account/data_transfer/action_text/rich_text_record_set_test.rb b/test/models/account/data_transfer/action_text/rich_text_record_set_test.rb index a28935a3e..2fe2c4b93 100644 --- a/test/models/account/data_transfer/action_text/rich_text_record_set_test.rb +++ b/test/models/account/data_transfer/action_text/rich_text_record_set_test.rb @@ -30,6 +30,7 @@ class Account::DataTransfer::ActionText::RichTextRecordSetTest < ActiveSupport:: reader = ZipFile::Reader.new(tempfile) record_set = Account::DataTransfer::ActionText::RichTextRecordSet.new(importing_account) + record_set.importable_model_names = %w[ ActionText::RichText Card ] error = assert_raises(Account::DataTransfer::RecordSet::IntegrityError) do record_set.check(from: reader) diff --git a/test/models/account/data_transfer/record_set_test.rb b/test/models/account/data_transfer/record_set_test.rb index 74b457edf..8c8d75e5e 100644 --- a/test/models/account/data_transfer/record_set_test.rb +++ b/test/models/account/data_transfer/record_set_test.rb @@ -1,10 +1,14 @@ require "test_helper" class Account::DataTransfer::RecordSetTest < ActiveSupport::TestCase + setup do + @importable_model_names = %w[ Card Board Event ] + end + test "check rejects polymorphic type not in the importable models allowlist" do event_data = build_event_data(eventable_type: "Identity") - record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event) + record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event, importable_model_names: @importable_model_names) error = assert_raises(Account::DataTransfer::RecordSet::IntegrityError) do record_set.check(from: build_reader(dir: "events", data: event_data)) @@ -16,7 +20,7 @@ class Account::DataTransfer::RecordSetTest < ActiveSupport::TestCase test "check rejects nonexistent polymorphic type" do event_data = build_event_data(eventable_type: "Nonexistent::ClassName") - record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event) + record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event, importable_model_names: @importable_model_names) error = assert_raises(Account::DataTransfer::RecordSet::IntegrityError) do record_set.check(from: build_reader(dir: "events", data: event_data)) @@ -28,7 +32,7 @@ class Account::DataTransfer::RecordSetTest < ActiveSupport::TestCase test "check rejects non-ActiveRecord class used as polymorphic type" do event_data = build_event_data(eventable_type: "ActiveSupport::BroadcastLogger") - record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event) + record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event, importable_model_names: @importable_model_names) error = assert_raises(Account::DataTransfer::RecordSet::IntegrityError) do record_set.check(from: build_reader(dir: "events", data: event_data)) @@ -40,7 +44,7 @@ class Account::DataTransfer::RecordSetTest < ActiveSupport::TestCase test "check accepts polymorphic type in the importable models allowlist" do event_data = build_event_data(eventable_type: "Card") - record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event) + record_set = Account::DataTransfer::RecordSet.new(account: importing_account, model: Event, importable_model_names: @importable_model_names) assert_nothing_raised do record_set.check(from: build_reader(dir: "events", data: event_data))