diff --git a/lib/data_update_scripts/20220223160059_coerce_identity_auth_data_format.rb b/lib/data_update_scripts/20220223160059_coerce_identity_auth_data_format.rb new file mode 100644 index 000000000..a5bcb9f2c --- /dev/null +++ b/lib/data_update_scripts/20220223160059_coerce_identity_auth_data_format.rb @@ -0,0 +1,12 @@ +module DataUpdateScripts + class CoerceIdentityAuthDataFormat + def run + Identity.with_statement_timeout(5.minutes) do + Identity.where("auth_data_dump ~ '^---\n'").find_each do |identity| + auth_hash = OmniAuth::AuthHash.new(**identity.auth_data_dump) + identity.update_columns(auth_data_dump: auth_hash) + end + end + end + end +end diff --git a/spec/lib/data_update_scripts/coerce_identity_auth_data_format_spec.rb b/spec/lib/data_update_scripts/coerce_identity_auth_data_format_spec.rb new file mode 100644 index 000000000..b3bef98f8 --- /dev/null +++ b/spec/lib/data_update_scripts/coerce_identity_auth_data_format_spec.rb @@ -0,0 +1,45 @@ +require "rails_helper" +require Rails.root.join( + "lib/data_update_scripts/20220223160059_coerce_identity_auth_data_format.rb", +) + +describe DataUpdateScripts::CoerceIdentityAuthDataFormat do + # make malformed identities + before do + # make two we do want to change + omniauth_mock_twitter_payload + + # rubocop:disable RSpec/FactoryBot/CreateList + 2.times do + create(:identity, provider: :twitter, user: create(:user)) do |identity| + hash = { "info" => { "email" => Faker::Internet.email } } + identity.update(auth_data_dump: hash) + end + end + # rubocop:enable RSpec/FactoryBot/CreateList + + # and one we don't want changed + create(:identity, provider: :twitter, user: create(:user)) + end + + it "changes hash auth data dumps to AuthHash" do + # we have two malformed identities (with plain hashes for auth_data_dump) + expect(Identity.where("auth_data_dump ~ '^---\n'").count).to equal(2) + + described_class.new.run + + # all three should be OmniAuth::AuthHash now + expect(Identity.all.map { |i| i.auth_data_dump.class }.uniq).to eq([OmniAuth::AuthHash]) + end + + it "handles null values safely" do + id = create(:identity, provider: :twitter, user: create(:user)) + id.update_column(:auth_data_dump, nil) + + described_class.new.run + + auth_data_classes = Identity.all.map { |i| i.auth_data_dump.class }.uniq + expect(auth_data_classes).to include(OmniAuth::AuthHash, NilClass) + expect(auth_data_classes).not_to include(Hash) + end +end