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
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
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
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