From 71a4c4718116b707c393af55f2f532f3852ffeb8 Mon Sep 17 00:00:00 2001 From: Daniel Uber Date: Wed, 23 Feb 2022 14:14:14 -0600 Subject: [PATCH] Update identities where the auth data dump is a plain hash (#16676) * Update identities where the auth data dump is a plain hash All but 3 records in DEV have OmniAuth::AuthHash objects serialized as auth data dump. Normalize the remaining ones so they don't cause no method errors when we treat the auth_data_dump as an object (sending `#info` instead of asking for `['info']`). should address https://app.honeybadger.io/projects/66984/faults/84183659 Add null safety check in a second example (that null values should not cause an error, and should not be coerced to auth hashes). * Ignore rubocop suggestion to create list Because the factory for identities doesn't automatically create the required user object, this is impractical. While I'm here, move the identity hash update into the creation block rather than doing this in two passes. Co-authored-by: Jamie Gaskins --- ...160059_coerce_identity_auth_data_format.rb | 12 +++++ .../coerce_identity_auth_data_format_spec.rb | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 lib/data_update_scripts/20220223160059_coerce_identity_auth_data_format.rb create mode 100644 spec/lib/data_update_scripts/coerce_identity_auth_data_format_spec.rb 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