From fbf2955cfc9ffc319d57960a0b0df1ee1b5fd05f Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 14 Mar 2022 18:07:46 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- app/models/concerns/bulk_member_access_load.rb | 52 +++----------------------- app/models/group.rb | 4 +- app/models/project.rb | 9 +++-- app/models/project_authorization.rb | 2 +- app/models/project_team.rb | 4 +- app/models/projects/triggered_hooks.rb | 25 +++++++++++++ app/models/user.rb | 8 +++- 7 files changed, 49 insertions(+), 55 deletions(-) create mode 100644 app/models/projects/triggered_hooks.rb (limited to 'app/models') diff --git a/app/models/concerns/bulk_member_access_load.rb b/app/models/concerns/bulk_member_access_load.rb index 927d6ccb28f..efc65e55e40 100644 --- a/app/models/concerns/bulk_member_access_load.rb +++ b/app/models/concerns/bulk_member_access_load.rb @@ -1,61 +1,19 @@ # frozen_string_literal: true -# Returns and caches in thread max member access for a resource -# module BulkMemberAccessLoad extend ActiveSupport::Concern included do - # Determine the maximum access level for a group of resources in bulk. - # - # Returns a Hash mapping resource ID -> maximum access level. - def max_member_access_for_resource_ids(resource_klass, resource_ids, &block) - raise 'Block is mandatory' unless block_given? - - memoization_index = self.id - memoization_class = self.class - - resource_ids = resource_ids.uniq - memo_id = "#{memoization_class}:#{memoization_index}" - access = load_access_hash(resource_klass, memo_id) - - # Look up only the IDs we need - resource_ids -= access.keys - - return access if resource_ids.empty? - - resource_access = yield(resource_ids) - - access.merge!(resource_access) - - missing_resource_ids = resource_ids - resource_access.keys - - missing_resource_ids.each do |resource_id| - access[resource_id] = Gitlab::Access::NO_ACCESS - end - - access - end - def merge_value_to_request_store(resource_klass, resource_id, value) - max_member_access_for_resource_ids(resource_klass, [resource_id]) do + Gitlab::SafeRequestLoader.execute(resource_key: max_member_access_for_resource_key(resource_klass), + resource_ids: [resource_id], + default_value: Gitlab::Access::NO_ACCESS) do { resource_id => value } end end - private - - def max_member_access_for_resource_key(klass, memoization_index) - "max_member_access_for_#{klass.name.underscore.pluralize}:#{memoization_index}" - end - - def load_access_hash(resource_klass, memo_id) - return {} unless Gitlab::SafeRequestStore.active? - - key = max_member_access_for_resource_key(resource_klass, memo_id) - Gitlab::SafeRequestStore[key] ||= {} - - Gitlab::SafeRequestStore[key] + def max_member_access_for_resource_key(klass) + "max_member_access_for_#{klass.name.underscore.pluralize}:#{self.class}:#{self.id}" end end end diff --git a/app/models/group.rb b/app/models/group.rb index e9fb4c36ba6..14d088dd38b 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -816,7 +816,9 @@ class Group < Namespace private def max_member_access(user_ids) - max_member_access_for_resource_ids(User, user_ids) do |user_ids| + Gitlab::SafeRequestLoader.execute(resource_key: max_member_access_for_resource_key(User), + resource_ids: user_ids, + default_value: Gitlab::Access::NO_ACCESS) do |user_ids| members_with_parents.where(user_id: user_ids).group(:user_id).maximum(:access_level) end end diff --git a/app/models/project.rb b/app/models/project.rb index 6457cce9364..e55395b32e7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1567,14 +1567,17 @@ class Project < ApplicationRecord # rubocop: disable CodeReuse/ServiceClass def execute_hooks(data, hooks_scope = :push_hooks) run_after_commit_or_now do - hooks.hooks_for(hooks_scope).select_active(hooks_scope, data).each do |hook| - hook.async_execute(data, hooks_scope.to_s) - end + triggered_hooks(hooks_scope, data).execute SystemHooksService.new.execute_hooks(data, hooks_scope) end end # rubocop: enable CodeReuse/ServiceClass + def triggered_hooks(hooks_scope, data) + triggered = ::Projects::TriggeredHooks.new(hooks_scope, data) + triggered.add_hooks(hooks) + end + def execute_integrations(data, hooks_scope = :push_hooks) # Call only service hooks that are active for this scope run_after_commit_or_now do diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb index c76332b21cd..5c6fdec16ca 100644 --- a/app/models/project_authorization.rb +++ b/app/models/project_authorization.rb @@ -9,7 +9,7 @@ class ProjectAuthorization < ApplicationRecord validates :project, presence: true validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true - validates :user, uniqueness: { scope: [:project, :access_level] }, presence: true + validates :user, uniqueness: { scope: :project }, presence: true def self.select_from_union(relations) from_union(relations) diff --git a/app/models/project_team.rb b/app/models/project_team.rb index ee5ecc2dd3c..d5e0d112aeb 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -179,7 +179,9 @@ class ProjectTeam # # Returns a Hash mapping user ID -> maximum access level. def max_member_access_for_user_ids(user_ids) - project.max_member_access_for_resource_ids(User, user_ids) do |user_ids| + Gitlab::SafeRequestLoader.execute(resource_key: project.max_member_access_for_resource_key(User), + resource_ids: user_ids, + default_value: Gitlab::Access::NO_ACCESS) do |user_ids| project.project_authorizations .where(user: user_ids) .group(:user_id) diff --git a/app/models/projects/triggered_hooks.rb b/app/models/projects/triggered_hooks.rb new file mode 100644 index 00000000000..e3aa3d106b7 --- /dev/null +++ b/app/models/projects/triggered_hooks.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Projects + class TriggeredHooks + def initialize(scope, data) + @scope = scope + @data = data + @relations = [] + end + + def add_hooks(relation) + @relations << relation + self + end + + def execute + # Assumes that the relations implement TriggerableHooks + @relations.each do |hooks| + hooks.hooks_for(@scope).select_active(@scope, @data).each do |hook| + hook.async_execute(@data, @scope.to_s) + end + end + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index fa58455ad35..4c375fe5230 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1862,7 +1862,9 @@ class User < ApplicationRecord # # Returns a Hash mapping project ID -> maximum access level. def max_member_access_for_project_ids(project_ids) - max_member_access_for_resource_ids(Project, project_ids) do |project_ids| + Gitlab::SafeRequestLoader.execute(resource_key: max_member_access_for_resource_key(Project), + resource_ids: project_ids, + default_value: Gitlab::Access::NO_ACCESS) do |project_ids| project_authorizations.where(project: project_ids) .group(:project_id) .maximum(:access_level) @@ -1877,7 +1879,9 @@ class User < ApplicationRecord # # Returns a Hash mapping project ID -> maximum access level. def max_member_access_for_group_ids(group_ids) - max_member_access_for_resource_ids(Group, group_ids) do |group_ids| + Gitlab::SafeRequestLoader.execute(resource_key: max_member_access_for_resource_key(Group), + resource_ids: group_ids, + default_value: Gitlab::Access::NO_ACCESS) do |group_ids| group_members.where(source: group_ids).group(:source_id).maximum(:access_level) end end -- cgit v1.2.1