debian-mirror-gitlab/app/services/groups/transfer_service.rb

135 lines
4.3 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2018-03-17 18:26:18 +05:30
module Groups
class TransferService < Groups::BaseService
TransferError = Class.new(StandardError)
2019-12-26 22:10:19 +05:30
attr_reader :error, :new_parent_group
2018-03-17 18:26:18 +05:30
def initialize(group, user, params = {})
super
@error = nil
end
def execute(new_parent_group)
@new_parent_group = new_parent_group
ensure_allowed_transfer
proceed_to_transfer
rescue TransferError, ActiveRecord::RecordInvalid, Gitlab::UpdatePathError => e
@group.errors.clear
2019-07-31 22:56:46 +05:30
@error = s_("TransferGroup|Transfer failed: %{error_message}") % { error_message: e.message }
2018-03-17 18:26:18 +05:30
false
end
private
def proceed_to_transfer
Group.transaction do
update_group_attributes
2019-07-07 11:18:12 +05:30
ensure_ownership
2018-03-17 18:26:18 +05:30
end
2019-07-07 11:18:12 +05:30
2019-12-20 00:11:08 +05:30
post_update_hooks(@updated_project_ids)
2019-07-07 11:18:12 +05:30
true
2018-03-17 18:26:18 +05:30
end
2019-12-20 00:11:08 +05:30
# Overridden in EE
def post_update_hooks(updated_project_ids)
end
2018-03-17 18:26:18 +05:30
def ensure_allowed_transfer
raise_transfer_error(:group_is_already_root) if group_is_already_root?
raise_transfer_error(:same_parent_as_current) if same_parent?
raise_transfer_error(:invalid_policies) unless valid_policies?
raise_transfer_error(:namespace_with_same_path) if namespace_with_same_path?
2019-12-21 20:55:43 +05:30
raise_transfer_error(:group_contains_images) if group_projects_contain_registry_images?
2018-03-17 18:26:18 +05:30
end
def group_is_already_root?
!@new_parent_group && !@group.has_parent?
end
def same_parent?
@new_parent_group && @new_parent_group.id == @group.parent_id
end
def valid_policies?
return false unless can?(current_user, :admin_group, @group)
if @new_parent_group
can?(current_user, :create_subgroup, @new_parent_group)
else
can?(current_user, :create_group)
end
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
def namespace_with_same_path?
Namespace.exists?(path: @group.path, parent: @new_parent_group)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
2019-12-21 20:55:43 +05:30
def group_projects_contain_registry_images?
2019-12-26 22:10:19 +05:30
@group.has_container_repository_including_subgroups?
2019-12-21 20:55:43 +05:30
end
2018-03-17 18:26:18 +05:30
def update_group_attributes
if @new_parent_group && @new_parent_group.visibility_level < @group.visibility_level
update_children_and_projects_visibility
@group.visibility_level = @new_parent_group.visibility_level
end
@group.parent = @new_parent_group
@group.save!
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
def update_children_and_projects_visibility
descendants = @group.descendants.where("visibility_level > ?", @new_parent_group.visibility_level)
Group
.where(id: descendants.select(:id))
.update_all(visibility_level: @new_parent_group.visibility_level)
2019-12-20 00:11:08 +05:30
projects_to_update = @group
2018-03-17 18:26:18 +05:30
.all_projects
.where("visibility_level > ?", @new_parent_group.visibility_level)
2019-12-20 00:11:08 +05:30
# Used in post_update_hooks in EE. Must use pluck (and not select)
# here as after we perform the update below we won't be able to find
# these records again.
@updated_project_ids = projects_to_update.pluck(:id)
projects_to_update
2018-03-17 18:26:18 +05:30
.update_all(visibility_level: @new_parent_group.visibility_level)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
2019-07-07 11:18:12 +05:30
def ensure_ownership
return if @new_parent_group
return unless @group.owners.empty?
@group.add_owner(current_user)
end
2018-03-17 18:26:18 +05:30
def raise_transfer_error(message)
2020-04-22 19:07:51 +05:30
raise TransferError, localized_error_messages[message]
end
def localized_error_messages
{
database_not_supported: s_('TransferGroup|Database is not supported.'),
namespace_with_same_path: s_('TransferGroup|The parent group already has a subgroup with the same path.'),
group_is_already_root: s_('TransferGroup|Group is already a root group.'),
same_parent_as_current: s_('TransferGroup|Group is already associated to the parent group.'),
invalid_policies: s_("TransferGroup|You don't have enough permissions."),
group_contains_images: s_('TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again.')
}.freeze
2018-03-17 18:26:18 +05:30
end
end
end
2019-12-20 00:11:08 +05:30
Groups::TransferService.prepend_if_ee('EE::Groups::TransferService')