diff --git a/changelogs/unreleased/user-auth-bmiller-return-early-if-user-is-nil.yml b/changelogs/unreleased/user-auth-bmiller-return-early-if-user-is-nil.yml new file mode 100644 index 0000000000000000000000000000000000000000..b259fdecd5634724318753064fa6c8f701b02bb3 --- /dev/null +++ b/changelogs/unreleased/user-auth-bmiller-return-early-if-user-is-nil.yml @@ -0,0 +1,5 @@ +--- +title: Fix a crash when logging in using SAML for the first time when sign-ups are disabled +merge_request: 50216 +author: +type: other diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb index f556a7f40e95a98da2cd26b208897d2c95229c95..fe1bf730e76b9aa39e6ea13a3ae47ab843b30e40 100644 --- a/lib/gitlab/auth/o_auth/user.rb +++ b/lib/gitlab/auth/o_auth/user.rb @@ -239,8 +239,9 @@ def sync_profile_from_provider? end def update_profile - clear_user_synced_attributes_metadata + return unless gl_user + clear_user_synced_attributes_metadata return unless sync_profile_from_provider? || creating_linked_ldap_user? metadata = gl_user.build_user_synced_attributes_metadata diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb index 6c6cee9c273b88b83715c145e24eb3ff8c723010..7a8e6e77d52daf6fca771630aa6d88b3b30b15fb 100644 --- a/spec/lib/gitlab/auth/o_auth/user_spec.rb +++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb @@ -995,6 +995,23 @@ def result_identities(dn, uid) end end + context 'when gl_user is nil' do + # We can't use `allow_next_instance_of` here because the stubbed method is called inside `initialize`. + # When the class calls `gl_user` during `initialize`, the `nil` value is overwritten and we do not see expected results from the spec. + # So we use `allow_any_instance_of` to preserve the `nil` value to test the behavior when `gl_user` is nil. + + # rubocop:disable RSpec/AnyInstanceOf + before do + allow_any_instance_of(described_class).to receive(:gl_user) { nil } + allow_any_instance_of(described_class).to receive(:sync_profile_from_provider?) { true } # to make the code flow proceed until gl_user.build_user_synced_attributes_metadata is called + end + # rubocop:enable RSpec/AnyInstanceOf + + it 'does not raise NoMethodError' do + expect { oauth_user }.not_to raise_error + end + end + describe '._uid_and_provider' do let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }