summaryrefslogtreecommitdiff
path: root/lib/banzai
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-19 22:11:55 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-19 22:11:55 +0000
commit5a8431feceba47fd8e1804d9aa1b1730606b71d5 (patch)
treee5df8e0ceee60f4af8093f5c4c2f934b8abced05 /lib/banzai
parent4d477238500c347c6553d335d920bedfc5a46869 (diff)
downloadgitlab-ce-5a8431feceba47fd8e1804d9aa1b1730606b71d5.tar.gz
Add latest changes from gitlab-org/gitlab@12-5-stable-ee
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/inline_grafana_metrics_filter.rb76
-rw-r--r--lib/banzai/filter/inline_metrics_redactor_filter.rb89
-rw-r--r--lib/banzai/filter/video_link_filter.rb2
-rw-r--r--lib/banzai/pipeline/ascii_doc_pipeline.rb3
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb1
5 files changed, 139 insertions, 32 deletions
diff --git a/lib/banzai/filter/inline_grafana_metrics_filter.rb b/lib/banzai/filter/inline_grafana_metrics_filter.rb
new file mode 100644
index 00000000000..321580b532f
--- /dev/null
+++ b/lib/banzai/filter/inline_grafana_metrics_filter.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # HTML filter that inserts a placeholder element for each
+ # reference to a grafana dashboard.
+ class InlineGrafanaMetricsFilter < Banzai::Filter::InlineEmbedsFilter
+ # Placeholder element for the frontend to use as an
+ # injection point for charts.
+ def create_element(params)
+ begin_loading_dashboard(params[:url])
+
+ doc.document.create_element(
+ 'div',
+ class: 'js-render-metrics',
+ 'data-dashboard-url': metrics_dashboard_url(params)
+ )
+ end
+
+ def embed_params(node)
+ query_params = Gitlab::Metrics::Dashboard::Url.parse_query(node['href'])
+ return unless [:panelId, :from, :to].all? do |param|
+ query_params.include?(param)
+ end
+
+ { url: node['href'], start: query_params[:from], end: query_params[:to] }
+ end
+
+ # Selects any links with an href contains the configured
+ # grafana domain for the project
+ def xpath_search
+ return unless grafana_url.present?
+
+ %(descendant-or-self::a[starts-with(@href, '#{grafana_url}')])
+ end
+
+ private
+
+ def project
+ context[:project]
+ end
+
+ def grafana_url
+ project&.grafana_integration&.grafana_url
+ end
+
+ def metrics_dashboard_url(params)
+ Gitlab::Routing.url_helpers.project_grafana_api_metrics_dashboard_url(
+ project,
+ embedded: true,
+ grafana_url: params[:url],
+ start: format_time(params[:start]),
+ end: format_time(params[:end])
+ )
+ end
+
+ # Formats a timestamp from Grafana for compatibility with
+ # parsing in JS via `new Date(timestamp)`
+ #
+ # @param time [String] Represents miliseconds since epoch
+ def format_time(time)
+ Time.at(time.to_i / 1000).utc.strftime('%FT%TZ')
+ end
+
+ # Fetches a dashboard and caches the result for the
+ # FE to fetch quickly while rendering charts
+ def begin_loading_dashboard(url)
+ ::Gitlab::Metrics::Dashboard::Finder.find(
+ project,
+ embedded: true,
+ grafana_url: url
+ )
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/inline_metrics_redactor_filter.rb b/lib/banzai/filter/inline_metrics_redactor_filter.rb
index 4d8a5028898..e84ba83e03e 100644
--- a/lib/banzai/filter/inline_metrics_redactor_filter.rb
+++ b/lib/banzai/filter/inline_metrics_redactor_filter.rb
@@ -8,14 +8,17 @@ module Banzai
include Gitlab::Utils::StrongMemoize
METRICS_CSS_CLASS = '.js-render-metrics'
+ URL = Gitlab::Metrics::Dashboard::Url
+
+ Embed = Struct.new(:project_path, :permission)
# Finds all embeds based on the css class the FE
# uses to identify the embedded content, removing
# only unnecessary nodes.
def call
nodes.each do |node|
- path = paths_by_node[node]
- user_has_access = user_access_by_path[path]
+ embed = embeds_by_node[node]
+ user_has_access = user_access_by_embed[embed]
node.remove unless user_has_access
end
@@ -30,40 +33,69 @@ module Banzai
end
# Returns all nodes which the FE will identify as
- # a metrics dashboard placeholder element
+ # a metrics embed placeholder element
#
# @return [Nokogiri::XML::NodeSet]
def nodes
@nodes ||= doc.css(METRICS_CSS_CLASS)
end
- # Maps a node to the full path of a project.
+ # Maps a node to key properties of an embed.
# Memoized so we only need to run the regex to get
# the project full path from the url once per node.
#
- # @return [Hash<Nokogiri::XML::Node, String>]
- def paths_by_node
- strong_memoize(:paths_by_node) do
- nodes.each_with_object({}) do |node, paths|
- paths[node] = path_for_node(node)
+ # @return [Hash<Nokogiri::XML::Node, Embed>]
+ def embeds_by_node
+ strong_memoize(:embeds_by_node) do
+ nodes.each_with_object({}) do |node, embeds|
+ embed = Embed.new
+ url = node.attribute('data-dashboard-url').to_s
+
+ set_path_and_permission(embed, url, URL.regex, :read_environment)
+ set_path_and_permission(embed, url, URL.grafana_regex, :read_project) unless embed.permission
+
+ embeds[node] = embed if embed.permission
end
end
end
- # Gets a project's full_path from the dashboard url
- # in the placeholder node. The FE will use the attr
- # `data-dashboard-url`, so we want to check against that
- # attribute directly in case a user has manually
- # created a metrics element (rather than supporting
- # an alternate attr in InlineMetricsFilter).
+ # Attempts to determine the path and permission attributes
+ # of a url based on expected dashboard url formats and
+ # sets the attributes on an Embed object
#
- # @return [String]
- def path_for_node(node)
- url = node.attribute('data-dashboard-url').to_s
-
- Gitlab::Metrics::Dashboard::Url.regex.match(url) do |m|
+ # @param embed [Embed]
+ # @param url [String]
+ # @param regex [RegExp]
+ # @param permission [Symbol]
+ def set_path_and_permission(embed, url, regex, permission)
+ return unless path = regex.match(url) do |m|
"#{$~[:namespace]}/#{$~[:project]}"
end
+
+ embed.project_path = path
+ embed.permission = permission
+ end
+
+ # Returns a mapping representing whether the current user
+ # has permission to view the embed for the project.
+ # Determined in a batch
+ #
+ # @return [Hash<Embed, Boolean>]
+ def user_access_by_embed
+ strong_memoize(:user_access_by_embed) do
+ unique_embeds.each_with_object({}) do |embed, access|
+ project = projects_by_path[embed.project_path]
+
+ access[embed] = Ability.allowed?(user, embed.permission, project)
+ end
+ end
+ end
+
+ # Returns a unique list of embeds
+ #
+ # @return [Array<Embed>]
+ def unique_embeds
+ embeds_by_node.values.uniq
end
# Maps a project's full path to a Project object.
@@ -74,22 +106,17 @@ module Banzai
def projects_by_path
strong_memoize(:projects_by_path) do
Project.eager_load(:route, namespace: [:route])
- .where_full_path_in(paths_by_node.values.uniq)
+ .where_full_path_in(unique_project_paths)
.index_by(&:full_path)
end
end
- # Returns a mapping representing whether the current user
- # has permission to view the metrics for the project.
- # Determined in a batch
+ # Returns a list of the full_paths of every project which
+ # has an embed in the doc
#
- # @return [Hash<Project, Boolean>]
- def user_access_by_path
- strong_memoize(:user_access_by_path) do
- projects_by_path.each_with_object({}) do |(path, project), access|
- access[path] = Ability.allowed?(user, :read_environment, project)
- end
- end
+ # @return [Array<String>]
+ def unique_project_paths
+ embeds_by_node.values.map(&:project_path).uniq
end
end
end
diff --git a/lib/banzai/filter/video_link_filter.rb b/lib/banzai/filter/video_link_filter.rb
index ed82fbc1f94..98987ee2019 100644
--- a/lib/banzai/filter/video_link_filter.rb
+++ b/lib/banzai/filter/video_link_filter.rb
@@ -15,7 +15,7 @@ module Banzai
end
def extra_element_attrs
- { width: "100%" }
+ { width: "400" }
end
end
end
diff --git a/lib/banzai/pipeline/ascii_doc_pipeline.rb b/lib/banzai/pipeline/ascii_doc_pipeline.rb
index 82b99d3de4a..90edc7010f4 100644
--- a/lib/banzai/pipeline/ascii_doc_pipeline.rb
+++ b/lib/banzai/pipeline/ascii_doc_pipeline.rb
@@ -10,6 +10,9 @@ module Banzai
Filter::SyntaxHighlightFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
+ Filter::ColorFilter,
+ Filter::ImageLazyLoadFilter,
+ Filter::ImageLinkFilter,
Filter::AsciiDocPostProcessingFilter
]
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 08e27257fdf..f6c12cdb53b 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -30,6 +30,7 @@ module Banzai
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
Filter::InlineMetricsFilter,
+ Filter::InlineGrafanaMetricsFilter,
Filter::TableOfContentsFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,