Class: Banzai::ReferenceRedactor

Inherits:
Object
  • Object
show all
Defined in:
lib/banzai/reference_redactor.rb

Overview

Class for removing Markdown references a certain user is not allowed to view.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context) ⇒ ReferenceRedactor

context - An instance of ‘Banzai::RenderContext`.



10
11
12
# File 'lib/banzai/reference_redactor.rb', line 10

def initialize(context)
  @context = context
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



7
8
9
# File 'lib/banzai/reference_redactor.rb', line 7

def context
  @context
end

Instance Method Details

#document_nodes(documents) ⇒ Object



119
120
121
122
123
# File 'lib/banzai/reference_redactor.rb', line 119

def document_nodes(documents)
  documents.map do |document|
    { document: document, nodes: Querying.css(document, 'a.gfm[data-reference-type]') }
  end
end

#nodes_visible_to_user(nodes) ⇒ Object

Returns the nodes visible to the current user.

nodes - The input nodes to check.

Returns a new Array containing the visible nodes.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/banzai/reference_redactor.rb', line 101

def nodes_visible_to_user(nodes)
  per_type = Hash.new { |h, k| h[k] = [] }
  visible = Set.new

  nodes.each do |node|
    per_type[node.attr('data-reference-type')] << node
  end

  per_type.each do |type, nodes|
    parser = Banzai::ReferenceParser[type].new(context)

    visible.merge(parser.nodes_visible_to_user(user, nodes))
  rescue Banzai::ReferenceParser::InvalidReferenceType
  end

  visible
end

#redact(documents) ⇒ Object

Redacts the references in the given Array of documents.

This method modifies the given documents in-place.

documents - A list of HTML documents containing references to redact.

Returns the documents passed as the first argument.



25
26
27
28
29
30
# File 'lib/banzai/reference_redactor.rb', line 25

def redact(documents)
  redact_cross_project_references(documents) unless can_read_cross_project?

  all_document_nodes = document_nodes(documents)
  redact_document_nodes(all_document_nodes)
end

#redact_cross_project_references(documents) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/banzai/reference_redactor.rb', line 84

def redact_cross_project_references(documents)
  extractor = Banzai::IssuableExtractor.new(context)
  issuables = extractor.extract(documents)

  issuables.each do |node, issuable|
    next if issuable.project == context.project_for_node(node)

    node['class'] = node['class'].gsub('has-tooltip', '')
    node['title'] = nil
  end
end

#redact_document_nodes(all_document_nodes) ⇒ Object

Redacts the given node documents

data - An Array of a Hashes mapping an HTML document to nodes to redact.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/banzai/reference_redactor.rb', line 35

def redact_document_nodes(all_document_nodes)
  all_nodes = all_document_nodes.flat_map { |x| x[:nodes] }
  visible = nodes_visible_to_user(all_nodes)
   = []

  all_document_nodes.each do |entry|
    nodes_for_document = entry[:nodes]

    doc_data = {
      document: entry[:document],
      total_reference_count: nodes_for_document.count,
      visible_reference_count: nodes_for_document.count
    }

     << doc_data

    nodes_for_document.each do |node|
      next if visible.include?(node)

      doc_data[:visible_reference_count] -= 1
      redacted_content = redacted_node_content(node)
      node.replace(redacted_content)
    end
  end

  
end

#redacted_node_content(node) ⇒ Object

Return redacted content of given node as either the original link (<a> tag), the original content (text), or the inner HTML of the node.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/banzai/reference_redactor.rb', line 66

def redacted_node_content(node)
  original_content = node.attr('data-original')
  original_content = CGI.escape_html(original_content) if original_content

  # Build the raw <a> tag just with a link as href and content if
  # it's originally a link pattern. We shouldn't return a plain text href.
  original_link =
    if node.attr('data-link-reference') == 'true'
      href = node.attr('href')

      %(<a href="#{href}">#{original_content}</a>)
    end

  # The reference should be replaced by the original link's content,
  # which is not always the same as the rendered one.
  original_link || original_content || node.inner_html
end

#userObject



14
15
16
# File 'lib/banzai/reference_redactor.rb', line 14

def user
  context.current_user
end