diff --git a/app/models/authenticator/base.rb b/app/models/authenticator/base.rb index a150732ad80..716dcfe90d0 100644 --- a/app/models/authenticator/base.rb +++ b/app/models/authenticator/base.rb @@ -137,7 +137,18 @@ def authorize(taskid, username, *args) end user.lastlogon = Time.now.utc - user.save! + if user.new_record? + User.with_lock do + user.save! + rescue ActiveRecord::RecordInvalid # Try update when catching create race condition. + userid, user = find_or_initialize_user(identity, username) + update_user_attributes(user, userid, identity) + user.miq_groups = matching_groups + user.save! + end + else + user.save! + end _log.info("Authorized User: [#{user.userid}]") task.userid = user.userid diff --git a/spec/models/authenticator/httpd_spec.rb b/spec/models/authenticator/httpd_spec.rb index d83f3a54fe4..648ddace219 100644 --- a/spec/models/authenticator/httpd_spec.rb +++ b/spec/models/authenticator/httpd_spec.rb @@ -272,6 +272,18 @@ def authenticate 'X-Remote-User-Email' => 'Sally@example.com') end + context "with a race condition on create user" do + before do + authenticate + end + + it "update the exiting user" do + allow(User).to receive(:lookup_by_userid).and_return(nil) + allow(User).to receive(:in_my_region).and_return(User.none, User.all) + expect { authenticate }.not_to(change { User.where(:userid => 'sally@example.com').count }.from(1)) + end + end + context "when user record with userid in upn format already exists" do let!(:sally_username) { FactoryBot.create(:user, :userid => 'sAlly') } let!(:sally_dn) { FactoryBot.create(:user, :userid => dn) }