summaryrefslogtreecommitdiff
path: root/lib/banzai
diff options
context:
space:
mode:
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/html_entity_filter.rb2
-rw-r--r--lib/banzai/filter/issuable_state_filter.rb6
-rw-r--r--lib/banzai/filter/milestone_reference_filter.rb2
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb34
-rw-r--r--lib/banzai/redactor.rb21
-rw-r--r--lib/banzai/reference_parser/issuable_parser.rb2
-rw-r--r--lib/banzai/reference_parser/issue_parser.rb25
7 files changed, 73 insertions, 19 deletions
diff --git a/lib/banzai/filter/html_entity_filter.rb b/lib/banzai/filter/html_entity_filter.rb
index f3bd587c28b..e008fd428b0 100644
--- a/lib/banzai/filter/html_entity_filter.rb
+++ b/lib/banzai/filter/html_entity_filter.rb
@@ -5,7 +5,7 @@ module Banzai
# Text filter that escapes these HTML entities: & " < >
class HtmlEntityFilter < HTML::Pipeline::TextFilter
def call
- ERB::Util.html_escape_once(text)
+ ERB::Util.html_escape(text)
end
end
end
diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb
index 327ea9449a1..77299abe324 100644
--- a/lib/banzai/filter/issuable_state_filter.rb
+++ b/lib/banzai/filter/issuable_state_filter.rb
@@ -15,6 +15,8 @@ module Banzai
issuables = extractor.extract([doc])
issuables.each do |node, issuable|
+ next if !can_read_cross_project? && issuable.project != project
+
if VISIBLE_STATES.include?(issuable.state) && node.inner_html == issuable.reference_link_text(project)
node.content += " (#{issuable.state})"
end
@@ -25,6 +27,10 @@ module Banzai
private
+ def can_read_cross_project?
+ Ability.allowed?(current_user, :read_cross_project)
+ end
+
def current_user
context[:current_user]
end
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
index 2a6b0964ac5..8ec696ce5fc 100644
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ b/lib/banzai/filter/milestone_reference_filter.rb
@@ -64,7 +64,7 @@ module Banzai
finder_params[:group_ids] = [project.group.id]
end
- MilestonesFinder.new(finder_params).execute.find_by(params)
+ MilestonesFinder.new(finder_params).find_by(params)
end
def url_for_object(milestone, project)
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index a79a0154846..0ac7e231b5b 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -14,23 +14,33 @@ module Banzai
end
def highlight_node(node)
- code = node.text
css_classes = 'code highlight js-syntax-highlight'
- language = node.attr('lang')
+ lang = node.attr('lang')
+ retried = false
- if use_rouge?(language)
- lexer = lexer_for(language)
+ if use_rouge?(lang)
+ lexer = lexer_for(lang)
language = lexer.tag
+ else
+ lexer = Rouge::Lexers::PlainText.new
+ language = lang
+ end
+
+ begin
+ code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, node.text), tag: language)
+ css_classes << " #{language}" if language
+ rescue
+ # Gracefully handle syntax highlighter bugs/errors to ensure users can
+ # still access an issue/comment/etc. First, retry with the plain text
+ # filter. If that fails, then just skip this entirely, but that would
+ # be a pretty bad upstream bug.
+ return if retried
- begin
- code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, code), tag: language)
- css_classes << " #{language}"
- rescue
- # Gracefully handle syntax highlighter bugs/errors to ensure
- # users can still access an issue/comment/etc.
+ language = nil
+ lexer = Rouge::Lexers::PlainText.new
+ retried = true
- language = nil
- end
+ retry
end
highlighted = %(<pre class="#{css_classes}" lang="#{language}" v-pre="true"><code>#{code}</code></pre>)
diff --git a/lib/banzai/redactor.rb b/lib/banzai/redactor.rb
index de3ebe72720..827df7c08ae 100644
--- a/lib/banzai/redactor.rb
+++ b/lib/banzai/redactor.rb
@@ -19,8 +19,9 @@ module Banzai
#
# Returns the documents passed as the first argument.
def redact(documents)
- all_document_nodes = document_nodes(documents)
+ redact_cross_project_references(documents) unless can_read_cross_project?
+ all_document_nodes = document_nodes(documents)
redact_document_nodes(all_document_nodes)
end
@@ -51,6 +52,18 @@ module Banzai
metadata
end
+ def redact_cross_project_references(documents)
+ extractor = Banzai::IssuableExtractor.new(project, user)
+ issuables = extractor.extract(documents)
+
+ issuables.each do |node, issuable|
+ next if issuable.project == project
+
+ node['class'] = node['class'].gsub('has-tooltip', '')
+ node['title'] = nil
+ end
+ end
+
# Returns the nodes visible to the current user.
#
# nodes - The input nodes to check.
@@ -78,5 +91,11 @@ module Banzai
{ document: document, nodes: Querying.css(document, 'a.gfm[data-reference-type]') }
end
end
+
+ private
+
+ def can_read_cross_project?
+ Ability.allowed?(user, :read_cross_project)
+ end
end
end
diff --git a/lib/banzai/reference_parser/issuable_parser.rb b/lib/banzai/reference_parser/issuable_parser.rb
index 3953867eb83..fad127d7e5b 100644
--- a/lib/banzai/reference_parser/issuable_parser.rb
+++ b/lib/banzai/reference_parser/issuable_parser.rb
@@ -18,7 +18,7 @@ module Banzai
end
def can_read_reference?(user, issuable)
- can?(user, "read_#{issuable.class.to_s.underscore}".to_sym, issuable)
+ can?(user, "read_#{issuable.class.to_s.underscore}_iid".to_sym, issuable)
end
end
end
diff --git a/lib/banzai/reference_parser/issue_parser.rb b/lib/banzai/reference_parser/issue_parser.rb
index 38d4e3f3e44..230827129b6 100644
--- a/lib/banzai/reference_parser/issue_parser.rb
+++ b/lib/banzai/reference_parser/issue_parser.rb
@@ -5,12 +5,31 @@ module Banzai
def nodes_visible_to_user(user, nodes)
issues = records_for_nodes(nodes)
+ issues_to_check = issues.values
- readable_issues = Ability
- .issues_readable_by_user(issues.values, user).to_set
+ unless can?(user, :read_cross_project)
+ issues_to_check, cross_project_issues = issues_to_check.partition do |issue|
+ issue.project == project
+ end
+ end
+
+ readable_issues = Ability.issues_readable_by_user(issues_to_check, user).to_set
nodes.select do |node|
- readable_issues.include?(issues[node])
+ issue_in_node = issues[node]
+
+ # We check the inclusion of readable issues first because it's faster.
+ #
+ # But we need to fall back to `read_issue_iid` if the user cannot read
+ # cross project, since it might be possible the user can see the IID
+ # but not the issue.
+ if readable_issues.include?(issue_in_node)
+ true
+ elsif cross_project_issues&.include?(issue_in_node)
+ can_read_reference?(user, issue_in_node)
+ else
+ false
+ end
end
end