2020-06-17 15:08:36 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module AuthorizedProjectUpdate
|
|
|
|
class ProjectGroupLinkCreateService < BaseService
|
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
|
|
|
|
BATCH_SIZE = 1000
|
|
|
|
|
2020-08-05 21:09:40 +00:00
|
|
|
def initialize(project, group, group_access = nil)
|
2020-06-17 15:08:36 +00:00
|
|
|
@project = project
|
|
|
|
@group = group
|
2020-08-05 21:09:40 +00:00
|
|
|
@group_access = group_access
|
2020-06-17 15:08:36 +00:00
|
|
|
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|
|
2020-08-05 21:09:40 +00:00
|
|
|
new_access_level = access_level(member.access_level)
|
2020-06-17 15:08:36 +00:00
|
|
|
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
|
2020-08-05 21:09:40 +00:00
|
|
|
next if existing_access_level >= new_access_level
|
2020-06-17 15:08:36 +00:00
|
|
|
|
|
|
|
user_ids_to_delete << member.user_id
|
|
|
|
end
|
|
|
|
|
|
|
|
authorizations_to_create << { user_id: member.user_id,
|
|
|
|
project_id: project.id,
|
2020-08-05 21:09:40 +00:00
|
|
|
access_level: new_access_level }
|
2020-06-17 15:08:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
update_authorizations(user_ids_to_delete, authorizations_to_create)
|
|
|
|
end
|
|
|
|
|
|
|
|
ServiceResponse.success
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2020-08-05 21:09:40 +00:00
|
|
|
attr_reader :project, :group, :group_access
|
|
|
|
|
|
|
|
def access_level(membership_access_level)
|
|
|
|
return membership_access_level unless group_access
|
|
|
|
|
2021-06-11 09:09:58 +00:00
|
|
|
# access level (role) must not be higher than the max access level (role) set when
|
2020-08-05 21:09:40 +00:00
|
|
|
# creating the project share
|
|
|
|
[membership_access_level, group_access].min
|
|
|
|
end
|
2020-06-17 15:08:36 +00:00
|
|
|
|
|
|
|
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)
|
2021-11-30 15:14:19 +00:00
|
|
|
project.remove_project_authorizations(user_ids_to_delete) if user_ids_to_delete.any?
|
|
|
|
ProjectAuthorization.insert_all_in_batches(authorizations_to_create) if authorizations_to_create.any?
|
2020-06-17 15:08:36 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|