Class: Organizations::Users::TransferService

Inherits:
Object
  • Object
show all
Includes:
Gitlab::Utils::StrongMemoize, Concerns::OrganizationUpdater
Defined in:
app/services/organizations/users/transfer_service.rb

Constant Summary collapse

BATCH_SIZE =
50

Constants included from Concerns::OrganizationUpdater

Concerns::OrganizationUpdater::ORGANIZATION_ID_UPDATE_BATCH_SIZE

Instance Method Summary collapse

Methods included from Concerns::OrganizationUpdater

#update_organization_id_for

Constructor Details

#initialize(users:, new_organization:) ⇒ TransferService

Returns a new instance of TransferService.



11
12
13
14
# File 'app/services/organizations/users/transfer_service.rb', line 11

def initialize(users:, new_organization:)
  @users = users
  @new_organization = new_organization
end

Instance Method Details

#can_transfer_users?Boolean

Returns:

  • (Boolean)


47
48
49
50
51
52
# File 'app/services/organizations/users/transfer_service.rb', line 47

def can_transfer_users?
  return false unless users_belong_to_single_organization?
  return false unless old_organization.present?

  true
end

#executeObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'app/services/organizations/users/transfer_service.rb', line 16

def execute
  return ServiceResponse.error(message: transfer_error) unless can_transfer_users?

  # Only create a transaction if we're not already in one
  # This allows the related organization group transfer
  # service to manage the outer transaction
  in_outer_transaction = User.connection.transaction_open?

  if in_outer_transaction
    perform_transfer
  else
    User.transaction do
      perform_transfer
    end
  end

  ServiceResponse.success
rescue StandardError => e
  # When in outer transaction: re-raise to propagate and trigger rollback
  # When managing own transaction: return error (transaction already rolled back)
  raise e if in_outer_transaction

  ServiceResponse.error(message: e.message)
end

#prepare_botsObject

Pre-create bot users before the transaction to avoid exclusive lease errors This is called by the group transfer service before starting the transaction



43
44
45
# File 'app/services/organizations/users/transfer_service.rb', line 43

def prepare_bots
  new_organization_bots
end

#transfer_errorObject



54
55
56
57
58
# File 'app/services/organizations/users/transfer_service.rb', line 54

def transfer_error
  return organization_not_found_error unless old_organization.present?

  users_different_organizations_error unless users_belong_to_single_organization?
end

#users_belong_to_single_organization?Boolean

rubocop:disable CodeReuse/ActiveRecord – Query specific to this service rubocop:disable Database/AvoidUsingPluckWithoutLimit – Using batches of 50

Returns:

  • (Boolean)


62
63
64
65
66
67
# File 'app/services/organizations/users/transfer_service.rb', line 62

def users_belong_to_single_organization?
  organization_ids = users.distinct.pluck(:organization_id).compact

  # All users must belong to exactly one organization
  organization_ids.size == 1
end