Commit 5f8f8461 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'fix-spec' into 'master'

Spec fix

See merge request gitlab-org/gitlab!41893
parents 7a6911ba bbeeeda8
......@@ -68,14 +68,14 @@ RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMent
let(:user_mentions) { epic_user_mentions }
let(:resource) { epic }
it_behaves_like 'resource mentions migration', MigrateEpicMentionsToDb, Epic
it_behaves_like 'resource mentions migration', MigrateEpicMentionsToDb, 'Epic'
context 'when FF disabled' do
before do
stub_feature_flags(migrate_user_mentions: false)
end
it_behaves_like 'resource migration not run', MigrateEpicMentionsToDb, Epic
it_behaves_like 'resource migration not run', MigrateEpicMentionsToDb, 'Epic'
end
context 'mentions in epic notes' do
......@@ -87,14 +87,14 @@ RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMent
# this not points to an innexistent noteable record in desigs table
let!(:note5) { notes.create!(noteable_id: non_existing_record_id, noteable_type: 'Epic', author_id: author.id, note: description_mentions, project_id: project.id) }
it_behaves_like 'resource notes mentions migration', MigrateEpicNotesMentionsToDb, Epic
it_behaves_like 'resource notes mentions migration', MigrateEpicNotesMentionsToDb, 'Epic'
context 'when FF disabled' do
before do
stub_feature_flags(migrate_user_mentions: false)
end
it_behaves_like 'resource notes migration not run', MigrateEpicNotesMentionsToDb, Epic
it_behaves_like 'resource notes migration not run', MigrateEpicNotesMentionsToDb, 'Epic'
end
end
end
......@@ -119,14 +119,14 @@ RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMent
let(:user_mentions) { design_user_mentions }
let(:resource) { design }
it_behaves_like 'resource notes mentions migration', MigrateDesignNotesMentionsToDb, DesignManagement::Design
it_behaves_like 'resource notes mentions migration', MigrateDesignNotesMentionsToDb, 'DesignManagement::Design'
context 'when FF disabled' do
before do
stub_feature_flags(migrate_user_mentions: false)
end
it_behaves_like 'resource notes migration not run', MigrateDesignNotesMentionsToDb, DesignManagement::Design
it_behaves_like 'resource notes migration not run', MigrateDesignNotesMentionsToDb, 'DesignManagement::Design'
end
end
end
......
......@@ -16,7 +16,7 @@ module Banzai
end
def nodes_visible_to_user(user, nodes)
groups = lazy { grouped_objects_for_nodes(nodes, Group, GROUP_ATTR) }
groups = lazy { grouped_objects_for_nodes(nodes, references_relation, GROUP_ATTR) }
nodes.select do |node|
node.has_attribute?(GROUP_ATTR) && can_read_group_reference?(node, user, groups)
......
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Lib
module Banzai
# isolated Banzai::ReferenceParser
module ReferenceParser
# Returns the reference parser class for the given type
#
# Example:
#
# Banzai::ReferenceParser['isolated_mentioned_group']
#
# This would return the `::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser::IsolatedMentionedGroupParser` class.
def self.[](name)
const_get("::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser::#{name.to_s.camelize}Parser", false)
end
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Lib
module Banzai
module ReferenceParser
# isolated Banzai::ReferenceParser::MentionedGroupParser
class IsolatedMentionedGroupParser < ::Banzai::ReferenceParser::MentionedGroupParser
extend ::Gitlab::Utils::Override
self.reference_type = :user
override :references_relation
def references_relation
::Gitlab::BackgroundMigration::UserMentions::Models::Group
end
end
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Lib
module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class IsolatedReferenceExtractor < ::Gitlab::ReferenceExtractor
REFERABLES = %i(isolated_mentioned_group).freeze
REFERABLES.each do |type|
define_method("#{type}s") do
@references[type] ||= isolated_references(type)
end
end
def isolated_references(type)
context = ::Banzai::RenderContext.new(project, current_user)
processor = ::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser[type].new(context)
refs = processor.process(html_documents)
refs[:visible]
end
end
end
end
end
end
end
......@@ -36,7 +36,8 @@ module Gitlab
if extractor
extractors[current_user] = extractor
else
extractor = extractors[current_user] ||= ::Gitlab::ReferenceExtractor.new(project, current_user)
extractor = extractors[current_user] ||=
Gitlab::BackgroundMigration::UserMentions::Lib::Gitlab::IsolatedReferenceExtractor.new(project, current_user)
extractor.reset_memoized_values
end
......@@ -71,7 +72,7 @@ module Gitlab
mentioned_users_ids = array_to_sql(refs.mentioned_users.pluck(:id))
mentioned_projects_ids = array_to_sql(refs.mentioned_projects.pluck(:id))
mentioned_groups_ids = array_to_sql(refs.mentioned_groups.pluck(:id))
mentioned_groups_ids = array_to_sql(refs.isolated_mentioned_groups.pluck(:id))
return if mentioned_users_ids.blank? && mentioned_projects_ids.blank? && mentioned_groups_ids.blank?
......
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Models
module Concerns
module Namespace
# extracted methods for recursive traversing of namespace hierarchy
module RecursiveTraversal
extend ActiveSupport::Concern
def root_ancestor
return self if persisted? && parent_id.nil?
strong_memoize(:root_ancestor) do
Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.base_and_ancestors
.reorder(nil)
.find_by(parent_id: nil)
end
end
# Returns all ancestors, self, and descendants of the current namespace.
def self_and_hierarchy
Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.all_objects
end
# Returns all the ancestors of the current namespaces.
def ancestors
return self.class.none unless parent_id
Gitlab::ObjectHierarchy
.new(self.class.where(id: parent_id))
.base_and_ancestors
end
# returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
def ancestors_upto(top = nil, hierarchy_order: nil)
Gitlab::ObjectHierarchy.new(self.class.where(id: id))
.ancestors(upto: top, hierarchy_order: hierarchy_order)
end
def self_and_ancestors(hierarchy_order: nil)
return self.class.where(id: id) unless parent_id
Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.base_and_ancestors(hierarchy_order: hierarchy_order)
end
# Returns all the descendants of the current namespace.
def descendants
Gitlab::ObjectHierarchy
.new(self.class.where(parent_id: id))
.base_and_descendants
end
def self_and_descendants
Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.base_and_descendants
end
end
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Models
# isolated Group model
class Group < ::Gitlab::BackgroundMigration::UserMentions::Models::Namespace
self.store_full_sti_class = false
has_one :saml_provider
def self.declarative_policy_class
"GroupPolicy"
end
def max_member_access_for_user(user)
return GroupMember::NO_ACCESS unless user
return GroupMember::OWNER if user.admin?
max_member_access = members_with_parents.where(user_id: user)
.reorder(access_level: :desc)
.first
&.access_level
max_member_access || GroupMember::NO_ACCESS
end
def members_with_parents
# Avoids an unnecessary SELECT when the group has no parents
source_ids =
if has_parent?
self_and_ancestors.reorder(nil).select(:id)
else
id
end
group_hierarchy_members = GroupMember.active_without_invites_and_requests
.where(source_id: source_ids)
GroupMember.from_union([group_hierarchy_members,
members_from_self_and_ancestor_group_shares])
end
# rubocop: disable Metrics/AbcSize
def members_from_self_and_ancestor_group_shares
group_group_link_table = GroupGroupLink.arel_table
group_member_table = GroupMember.arel_table
source_ids =
if has_parent?
self_and_ancestors.reorder(nil).select(:id)
else
id
end
group_group_links_query = GroupGroupLink.where(shared_group_id: source_ids)
cte = Gitlab::SQL::CTE.new(:group_group_links_cte, group_group_links_query)
cte_alias = cte.table.alias(GroupGroupLink.table_name)
# Instead of members.access_level, we need to maximize that access_level at
# the respective group_group_links.group_access.
member_columns = GroupMember.attribute_names.map do |column_name|
if column_name == 'access_level'
smallest_value_arel([cte_alias[:group_access], group_member_table[:access_level]],
'access_level')
else
group_member_table[column_name]
end
end
GroupMember
.with(cte.to_arel)
.select(*member_columns)
.from([group_member_table, cte.alias_to(group_group_link_table)])
.where(group_member_table[:requested_at].eq(nil))
.where(group_member_table[:source_id].eq(group_group_link_table[:shared_with_group_id]))
.where(group_member_table[:source_type].eq('Namespace'))
end
# rubocop: enable Metrics/AbcSize
def smallest_value_arel(args, column_alias)
Arel::Nodes::As.new(
Arel::Nodes::NamedFunction.new('LEAST', args),
Arel::Nodes::SqlLiteral.new(column_alias))
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
module UserMentions
module Models
# isolated Namespace model
class Namespace < ApplicationRecord
include ::Gitlab::VisibilityLevel
include ::Gitlab::Utils::StrongMemoize
include Gitlab::BackgroundMigration::UserMentions::Models::Concerns::Namespace::RecursiveTraversal
belongs_to :parent, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Namespace"
def visibility_level_field
:visibility_level
end
def has_parent?
parent_id.present? || parent.present?
end
# Overridden in EE::Namespace
def feature_available?(_feature)
false
end
end
end
end
end
end
Namespace.prepend_if_ee('::EE::Namespace')
......@@ -74,14 +74,14 @@ RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMent
let(:user_mentions) { merge_request_user_mentions }
let(:resource) { merge_request }
it_behaves_like 'resource mentions migration', MigrateMergeRequestMentionsToDb, MergeRequest
it_behaves_like 'resource mentions migration', MigrateMergeRequestMentionsToDb, 'MergeRequest'
context 'when FF disabled' do
before do
stub_feature_flags(migrate_user_mentions: false)
end
it_behaves_like 'resource migration not run', MigrateMergeRequestMentionsToDb, MergeRequest
it_behaves_like 'resource migration not run', MigrateMergeRequestMentionsToDb, 'MergeRequest'
end
end
......@@ -103,14 +103,14 @@ RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMent
let(:user_mentions) { commit_user_mentions }
let(:resource) { commit }
it_behaves_like 'resource notes mentions migration', MigrateCommitNotesMentionsToDb, Commit
it_behaves_like 'resource notes mentions migration', MigrateCommitNotesMentionsToDb, 'Commit'
context 'when FF disabled' do
before do
stub_feature_flags(migrate_user_mentions: false)
end
it_behaves_like 'resource notes migration not run', MigrateCommitNotesMentionsToDb, Commit
it_behaves_like 'resource notes migration not run', MigrateCommitNotesMentionsToDb, 'Commit'
end
end
end
......
# frozen_string_literal: true
RSpec.shared_examples 'resource mentions migration' do |migration_class, resource_class|
RSpec.shared_examples 'resource mentions migration' do |migration_class, resource_class_name|
it 'migrates resource mentions' do
join = migration_class::JOIN
conditions = migration_class::QUERY_CONDITIONS
resource_class = "#{Gitlab::BackgroundMigration::UserMentions::Models}::#{resource_class_name}".constantize
expect do
subject.perform(resource_class.name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
end.to change { user_mentions.count }.by(1)
user_mention = user_mentions.last
......@@ -16,23 +17,23 @@ RSpec.shared_examples 'resource mentions migration' do |migration_class, resourc
# check that performing the same job twice does not fail and does not change counts
expect do
subject.perform(resource_class.name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
end.to change { user_mentions.count }.by(0)
end
end
RSpec.shared_examples 'resource notes mentions migration' do |migration_class, resource_class|
RSpec.shared_examples 'resource notes mentions migration' do |migration_class, resource_class_name|
it 'migrates mentions from note' do
join = migration_class::JOIN
conditions = migration_class::QUERY_CONDITIONS
# there are 5 notes for each noteable_type, but two do not have mentions and
# another one's noteable_id points to an inexistent resource
expect(notes.where(noteable_type: resource_class.to_s).count).to eq 5
expect(notes.where(noteable_type: resource_class_name).count).to eq 5
expect(user_mentions.count).to eq 0
expect do
subject.perform(resource_class.name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
end.to change { user_mentions.count }.by(2)
# check that the user_mention for regular note is created
......@@ -51,7 +52,7 @@ RSpec.shared_examples 'resource notes mentions migration' do |migration_class, r
# check that performing the same job twice does not fail and does not change counts
expect do
subject.perform(resource_class.name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
end.to change { user_mentions.count }.by(0)
end
end
......@@ -83,24 +84,25 @@ RSpec.shared_examples 'schedules resource mentions migration' do |resource_class
end
end
RSpec.shared_examples 'resource migration not run' do |migration_class, resource_class|
RSpec.shared_examples 'resource migration not run' do |migration_class, resource_class_name|
it 'does not migrate mentions' do
join = migration_class::JOIN
conditions = migration_class::QUERY_CONDITIONS
resource_class = "#{Gitlab::BackgroundMigration::UserMentions::Models}::#{resource_class_name}".constantize
expect do
subject.perform(resource_class.name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
end.to change { user_mentions.count }.by(0)
end
end
RSpec.shared_examples 'resource notes migration not run' do |migration_class, resource_class|
RSpec.shared_examples 'resource notes migration not run' do |migration_class, resource_class_name|
it 'does not migrate mentions' do
join = migration_class::JOIN
conditions = migration_class::QUERY_CONDITIONS
expect do
subject.perform(resource_class.name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
end.to change { user_mentions.count }.by(0)
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment