20831: Fixing tests wip
authorPeter Amstutz <peter.amstutz@curii.com>
Wed, 8 Nov 2023 22:34:40 +0000 (17:34 -0500)
committerPeter Amstutz <peter.amstutz@curii.com>
Wed, 8 Nov 2023 22:34:40 +0000 (17:34 -0500)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

services/api/app/controllers/arvados/v1/users_controller.rb
services/api/app/models/api_client_authorization.rb
services/api/app/models/user.rb

index 2353f67c1a3978d611034e28e5e900cca1bcfc40..afe2f96cca6237679c8f4cf2ecab7ad9021fe369 100644 (file)
@@ -17,41 +17,7 @@ class Arvados::V1::UsersController < ApplicationController
   def batch_update
     @objects = []
     params[:updates].andand.each do |uuid, attrs|
-      begin
-        u = User.find_or_create_by(uuid: uuid)
-      rescue ActiveRecord::RecordNotUnique
-        retry
-      end
-      needupdate = {}
-      nullify_attrs(attrs).each do |k,v|
-        if !v.nil? && u.send(k) != v
-          needupdate[k] = v
-        end
-      end
-      if needupdate.length > 0
-        begin
-          u.update!(needupdate)
-        rescue ActiveRecord::RecordInvalid
-          loginCluster = Rails.configuration.Login.LoginCluster
-          if u.uuid[0..4] == loginCluster && !needupdate[:username].nil?
-            local_user = User.find_by_username(needupdate[:username])
-            # The username of this record conflicts with an existing,
-            # different user record.  This can happen because the
-            # username changed upstream on the login cluster, or
-            # because we're federated with another cluster with a user
-            # by the same username.  The login cluster is the source
-            # of truth, so change the username on the conflicting
-            # record and retry the update operation.
-            if local_user.uuid != u.uuid
-              new_username = "#{needupdate[:username]}#{rand(99999999)}"
-              Rails.logger.warn("cached username '#{needupdate[:username]}' collision with user '#{local_user.uuid}' - renaming to '#{new_username}' before retrying")
-              local_user.update!({username: new_username})
-              retry
-            end
-          end
-          raise # Not the issue we're handling above
-        end
-      end
+      u = User.update_remote_user nullify_attrs(attrs)
       @objects << u
     end
     @offset = 0
index ef73d79c176d28961e597ef6df28536816304aa2..cc40c21aff0862c177b23e0603684c74a677ec33 100644 (file)
@@ -363,71 +363,17 @@ class ApiClientAuthorization < ArvadosModel
     if user.nil? and remote_user.nil?
       Rails.logger.warn "remote token #{token.inspect} rejected: cannot get owner #{remote_user_uuid} from database or remote cluster"
       return nil
+    end
+
     # Invariant:    remote_user_prefix == upstream_cluster_id
     # therefore:    remote_user_prefix != Rails.configuration.ClusterID
     # Add or update user and token in local database so we can
     # validate subsequent requests faster.
-    elsif user.nil?
-      # Create a new record for this user.
-      user = User.new(uuid: remote_user['uuid'],
-                      is_active: false,
-                      is_admin: false,
-                      email: remote_user['email'],
-                      owner_uuid: system_user_uuid)
-      user.set_initial_username(requested: remote_user['username'])
-    end
 
-    # Sync user record if we loaded a remote user.
     act_as_system_user do
       if remote_user
-        %w[first_name last_name email prefs].each do |attr|
-          user.send(attr+'=', remote_user[attr])
-        end
-
-        begin
-          user.save!
-        rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
-          Rails.logger.debug("remote user #{remote_user['uuid']} already exists, retrying...")
-          # Some other request won the race: retry fetching the user record.
-          user = User.uncached do
-            User.find_by_uuid(remote_user['uuid'])
-          end
-          if !user
-            Rails.logger.warn("cannot find or create remote user #{remote_user['uuid']}")
-            return nil
-          end
-        end
-
-        if user.is_invited && !remote_user['is_invited']
-          # Remote user is not "invited" state, they should be unsetup, which
-          # also makes them inactive.
-          user.unsetup
-        else
-          if !user.is_invited && remote_user['is_invited'] and
-            (remote_user_prefix == Rails.configuration.Login.LoginCluster or
-             Rails.configuration.Users.AutoSetupNewUsers or
-             Rails.configuration.Users.NewUsersAreActive or
-             Rails.configuration.RemoteClusters[remote_user_prefix].andand["ActivateUsers"])
-            user.setup
-          end
-
-          if !user.is_active && remote_user['is_active'] && user.is_invited and
-            (remote_user_prefix == Rails.configuration.Login.LoginCluster or
-             Rails.configuration.Users.NewUsersAreActive or
-             Rails.configuration.RemoteClusters[remote_user_prefix].andand["ActivateUsers"])
-            user.update!(is_active: true)
-          elsif user.is_active && !remote_user['is_active']
-            user.update!(is_active: false)
-          end
-
-          if remote_user_prefix == Rails.configuration.Login.LoginCluster and
-            user.is_active and
-            user.is_admin != remote_user['is_admin']
-            # Remote cluster controls our user database, including the
-            # admin flag.
-            user.update!(is_admin: remote_user['is_admin'])
-          end
-        end
+        # Sync user record if we loaded a remote user.
+        user = User.update_remote_user remote_user
       end
 
       # If stored_secret is set, we save stored_secret in the database
index 2ac5a78fa7db436a4d4177d04c218353794d0c2e..f183251dbff1be50f3e59e4c0acf4040c489979a 100644 (file)
@@ -599,13 +599,20 @@ SELECT target_uuid, perm_level
       retry
     end
 
-    user.lock do
+    remote_user_prefix = user.uuid[0..4]
+
+    user.with_lock do
       needupdate = {}
-      nulled_attrs = nullify_attrs(remote_user)
-      [:email, :username, :first_name, :last_name, :prefs].each |k|
-        v = nulled_attrs[k]
-      if !v.nil? && user.send(k) != v
-        needupdate[k] = v
+      [:email, :username, :first_name, :last_name, :prefs].each do |k|
+        v = remote_user[k]
+        if !v.nil? && user.send(k) != v
+          needupdate[k] = v
+        end
+      end
+
+      if user.username == ""
+        user.set_initial_username(requested: remote_user['username'])
+        needupdate.delete 'username'
       end
 
       if needupdate.length > 0
@@ -613,7 +620,7 @@ SELECT target_uuid, perm_level
           user.update!(needupdate)
         rescue ActiveRecord::RecordInvalid
           loginCluster = Rails.configuration.Login.LoginCluster
-          if user.uuid[0..4] == loginCluster && !needupdate[:username].nil?
+          if remote_user_prefix == loginCluster && !needupdate[:username].nil?
             local_user = User.find_by_username(needupdate[:username])
             # The username of this record conflicts with an existing,
             # different user record.  This can happen because the