diff --git a/lib/auth/github_authenticator.rb b/lib/auth/github_authenticator.rb index aaf43fa1b2b..d12142114f2 100644 --- a/lib/auth/github_authenticator.rb +++ b/lib/auth/github_authenticator.rb @@ -86,7 +86,12 @@ class Auth::GithubAuthenticator < Auth::Authenticator if !!candidate[:verified] && (user = User.find_by_email(candidate[:email])) result.email = candidate[:email] result.email_valid = !!candidate[:verified] - GithubUserInfo.create( + + GithubUserInfo + .where('user_id = ? OR github_user_id = ?', user.id, github_user_id) + .destroy_all + + GithubUserInfo.create!( user_id: user.id, screen_name: screen_name, github_user_id: github_user_id diff --git a/spec/components/auth/github_authenticator_spec.rb b/spec/components/auth/github_authenticator_spec.rb index 4ade5665577..797221cfe22 100644 --- a/spec/components/auth/github_authenticator_spec.rb +++ b/spec/components/auth/github_authenticator_spec.rb @@ -84,6 +84,35 @@ describe Auth::GithubAuthenticator do expect(result.email).to eq("john@example.com") end + it 'should not error out if user already has a different old github account attached' do + + # There is a rare case where an end user had + # 2 different github accounts and moved emails between the 2 + + GithubUserInfo.create!(user_id: user.id, screen_name: 'bob', github_user_id: 100) + + hash = { + extra: { + all_emails: [{ + email: user.email, + primary: false, + verified: true, + }] + }, + info: { + email: "john@example.com", + nickname: "john", + name: "John Bob", + }, + uid: "1001" + } + + result = authenticator.after_authenticate(hash) + + expect(result.user.id).to eq(user.id) + expect(GithubUserInfo.where(user_id: user.id).pluck(:github_user_id)).to eq([1001]) + end + it 'will not authenticate for already existing users with an unverified email' do hash = { extra: {