diff options
Diffstat (limited to 'app/services/authorized_project_update/project_group_link_create_service.rb')
-rw-r--r-- | app/services/authorized_project_update/project_group_link_create_service.rb | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/app/services/authorized_project_update/project_group_link_create_service.rb b/app/services/authorized_project_update/project_group_link_create_service.rb new file mode 100644 index 00000000000..db2db091374 --- /dev/null +++ b/app/services/authorized_project_update/project_group_link_create_service.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module AuthorizedProjectUpdate + class ProjectGroupLinkCreateService < BaseService + include Gitlab::Utils::StrongMemoize + + BATCH_SIZE = 1000 + + def initialize(project, group) + @project = project + @group = group + end + + def execute + group.members_from_self_and_ancestors_with_effective_access_level + .each_batch(of: BATCH_SIZE, column: :user_id) do |members| + existing_authorizations = existing_project_authorizations(members) + authorizations_to_create = [] + user_ids_to_delete = [] + + members.each do |member| + existing_access_level = existing_authorizations[member.user_id] + + if existing_access_level + # User might already have access to the project unrelated to the + # current project share + next if existing_access_level >= member.access_level + + user_ids_to_delete << member.user_id + end + + authorizations_to_create << { user_id: member.user_id, + project_id: project.id, + access_level: member.access_level } + end + + update_authorizations(user_ids_to_delete, authorizations_to_create) + end + + ServiceResponse.success + end + + private + + attr_reader :project, :group + + def existing_project_authorizations(members) + user_ids = members.map(&:user_id) + + ProjectAuthorization.where(project_id: project.id, user_id: user_ids) # rubocop: disable CodeReuse/ActiveRecord + .select(:user_id, :access_level) + .each_with_object({}) do |authorization, hash| + hash[authorization.user_id] = authorization.access_level + end + end + + def update_authorizations(user_ids_to_delete, authorizations_to_create) + ProjectAuthorization.transaction do + if user_ids_to_delete.any? + ProjectAuthorization.where(project_id: project.id, user_id: user_ids_to_delete) # rubocop: disable CodeReuse/ActiveRecord + .delete_all + end + + if authorizations_to_create.any? + ProjectAuthorization.insert_all(authorizations_to_create) + end + end + end + end +end |