Commit 7544ad98 authored by Alexandru Croitor's avatar Alexandru Croitor Committed by Nick Thomas

Add parsers for users, groups, projects references

Add separate parsers for mentions of users, groups, projects
in markdown content
parent ac942e3e
---
title: Adds separate parsers for mentions of users, groups, projects in markdown content
merge_request: 18318
author:
type: added
# frozen_string_literal: true
module Banzai
module ReferenceParser
class MentionedUserParser < BaseParser
self.reference_type = :user
def references_relation
User
end
# any user can be mentioned by username
def can_read_reference?(user, ref_attr, node)
true
end
end
end
end
# frozen_string_literal: true
module Banzai
module ReferenceParser
class MentionedUsersByGroupParser < BaseParser
GROUP_ATTR = 'data-group'
self.reference_type = :user
def self.data_attribute
@data_attribute ||= GROUP_ATTR
end
def references_relation
Group
end
def nodes_visible_to_user(user, nodes)
groups = lazy { grouped_objects_for_nodes(nodes, Group, GROUP_ATTR) }
nodes.select do |node|
node.has_attribute?(GROUP_ATTR) && can_read_group_reference?(node, user, groups)
end
end
def can_read_group_reference?(node, user, groups)
node_group = groups[node]
node_group && can?(user, :read_group, node_group)
end
end
end
end
# frozen_string_literal: true
module Banzai
module ReferenceParser
class MentionedUsersByProjectParser < ProjectParser
PROJECT_ATTR = 'data-project'
self.reference_type = :user
def self.data_attribute
@data_attribute ||= PROJECT_ATTR
end
def references_relation
Project
end
end
end
end
......@@ -3,7 +3,8 @@
module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor < Banzai::ReferenceExtractor
REFERABLES = %i(user issue label milestone merge_request snippet commit commit_range directly_addressed_user epic).freeze
REFERABLES = %i(user issue label milestone
merge_request snippet commit commit_range directly_addressed_user epic).freeze
attr_accessor :project, :current_user, :author
def initialize(project, current_user = nil)
......@@ -54,9 +55,9 @@ module Gitlab
def self.references_pattern
return @pattern if @pattern
patterns = REFERABLES.map do |ref|
ref.to_s.classify.constantize.try(:reference_pattern)
end
patterns = REFERABLES.map do |type|
Banzai::ReferenceParser[type].reference_type.to_s.classify.constantize.try(:reference_pattern)
end.uniq
@pattern = Regexp.union(patterns.compact)
end
......
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::ReferenceParser::MentionedUserParser do
include ReferenceParserHelpers
let(:group) { create(:group, :private) }
let(:user) { create(:user) }
let(:new_user) { create(:user) }
let(:project) { create(:project, group: group, creator: user) }
let(:link) { empty_html_link }
subject { described_class.new(Banzai::RenderContext.new(project, new_user)) }
describe '#gather_references' do
context 'when the link has a data-group attribute' do
context 'using an existing group ID' do
before do
link['data-group'] = project.group.id.to_s
group.add_developer(new_user)
end
it 'returns empty list of users' do
expect(subject.gather_references([link])).to eq([])
end
end
end
context 'when the link has a data-project attribute' do
context 'using an existing project ID' do
before do
link['data-project'] = project.id.to_s
project.add_developer(new_user)
end
it 'returns empty list of users' do
expect(subject.gather_references([link])).to eq([])
end
end
end
context 'when the link has a data-user attribute' do
it 'returns an Array of users' do
link['data-user'] = user.id.to_s
expect(subject.referenced_by([link])).to eq([user])
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::ReferenceParser::MentionedUsersByGroupParser do
include ReferenceParserHelpers
let(:group) { create(:group, :private) }
let(:user) { create(:user) }
let(:new_user) { create(:user) }
let(:project) { create(:project, group: group, creator: user) }
let(:link) { empty_html_link }
subject { described_class.new(Banzai::RenderContext.new(project, new_user)) }
describe '#gather_references' do
context 'when the link has a data-group attribute' do
context 'using an existing group ID where user does not have access' do
it 'returns empty array' do
link['data-group'] = project.group.id.to_s
expect(subject.gather_references([link])).to eq([])
end
end
context 'using an existing group ID' do
before do
link['data-group'] = project.group.id.to_s
group.add_developer(new_user)
end
it 'returns groups' do
expect(subject.gather_references([link])).to eq([group])
end
end
context 'using a non-existing group ID' do
it 'returns an empty Array' do
link['data-group'] = 'test-non-existing'
expect(subject.gather_references([link])).to eq([])
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::ReferenceParser::MentionedUsersByProjectParser do
include ReferenceParserHelpers
let(:group) { create(:group, :private) }
let(:user) { create(:user) }
let(:new_user) { create(:user) }
let(:project) { create(:project, group: group, creator: user) }
let(:link) { empty_html_link }
subject { described_class.new(Banzai::RenderContext.new(project, new_user)) }
describe '#gather_references' do
context 'when the link has a data-project attribute' do
context 'using an existing project ID where user does not have access' do
it 'returns empty Array' do
link['data-project'] = project.id.to_s
expect(subject.gather_references([link])).to eq([])
end
end
context 'using an existing project ID' do
before do
link['data-project'] = project.id.to_s
project.add_developer(new_user)
end
it 'returns an Array of referenced projects' do
expect(subject.gather_references([link])).to eq([project])
end
end
context 'using a non-existing project ID' do
it 'returns an empty Array' do
link['data-project'] = 'inexisting-project-id'
expect(subject.gather_references([link])).to eq([])
end
end
end
end
end
......@@ -265,7 +265,8 @@ describe Gitlab::ReferenceExtractor do
describe 'referables prefixes' do
def prefixes
described_class::REFERABLES.each_with_object({}) do |referable, result|
klass = referable.to_s.camelize.constantize
class_name = referable.to_s.camelize
klass = class_name.constantize if Object.const_defined?(class_name)
next unless klass.respond_to?(:reference_prefix)
......
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