summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 00:00:32 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 00:00:32 +0000
commit1153e17b2d34c50834251038269ac11f18219bdf (patch)
tree20b80086422da0d03cb3a1af0300858570c35e7e /app/assets/javascripts
parentd111c2d301f43d0b6de98f47da39d2b107ce17a1 (diff)
downloadgitlab-ce-1153e17b2d34c50834251038269ac11f18219bdf.tar.gz
Add latest changes from gitlab-org/security/gitlab@14-9-stable-ee
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/behaviors/components/diagram_performance_warning.vue25
-rw-r--r--app/assets/javascripts/behaviors/markdown/constants.js16
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_kroki.js63
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js21
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js20
6 files changed, 110 insertions, 37 deletions
diff --git a/app/assets/javascripts/behaviors/components/diagram_performance_warning.vue b/app/assets/javascripts/behaviors/components/diagram_performance_warning.vue
new file mode 100644
index 00000000000..31b2682b546
--- /dev/null
+++ b/app/assets/javascripts/behaviors/components/diagram_performance_warning.vue
@@ -0,0 +1,25 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ i18n: {
+ bodyText: __('Warning: Displaying this diagram might cause performance issues on this page.'),
+ buttonText: __('Display'),
+ },
+ components: {
+ GlAlert,
+ },
+};
+</script>
+
+<template>
+ <gl-alert
+ :primary-button-text="$options.i18n.buttonText"
+ variant="warning"
+ @dismiss="$emit('closeAlert')"
+ @primaryAction="$emit('showImage')"
+ >
+ {{ $options.i18n.bodyText }}
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/behaviors/markdown/constants.js b/app/assets/javascripts/behaviors/markdown/constants.js
index b4545d6c6c6..13f8d9ef0cf 100644
--- a/app/assets/javascripts/behaviors/markdown/constants.js
+++ b/app/assets/javascripts/behaviors/markdown/constants.js
@@ -1,3 +1,19 @@
// https://prosemirror.net/docs/ref/#model.ParseRule.priority
export const DEFAULT_PARSE_RULE_PRIORITY = 50;
export const HIGHER_PARSE_RULE_PRIORITY = 1 + DEFAULT_PARSE_RULE_PRIORITY;
+
+export const unrestrictedPages = [
+ // Group wiki
+ 'groups:wikis:show',
+ 'groups:wikis:edit',
+ 'groups:wikis:create',
+
+ // Project wiki
+ 'projects:wikis:show',
+ 'projects:wikis:edit',
+ 'projects:wikis:create',
+
+ // Project files
+ 'projects:show',
+ 'projects:blob:show',
+];
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index c4e09efe263..6236e3bdefc 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
import initUserPopovers from '../../user_popovers';
import highlightCurrentUser from './highlight_current_user';
+import { renderKroki } from './render_kroki';
import renderMath from './render_math';
import renderMermaid from './render_mermaid';
import renderSandboxedMermaid from './render_sandboxed_mermaid';
@@ -13,6 +14,7 @@ import renderMetrics from './render_metrics';
//
$.fn.renderGFM = function renderGFM() {
syntaxHighlight(this.find('.js-syntax-highlight').get());
+ renderKroki(this.find('.js-render-kroki[hidden]').get());
renderMath(this.find('.js-render-math'));
if (gon.features?.sandboxedMermaid) {
renderSandboxedMermaid(this.find('.js-render-mermaid'));
diff --git a/app/assets/javascripts/behaviors/markdown/render_kroki.js b/app/assets/javascripts/behaviors/markdown/render_kroki.js
new file mode 100644
index 00000000000..7843df0cd8e
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/render_kroki.js
@@ -0,0 +1,63 @@
+import Vue from 'vue';
+import DiagramPerformanceWarning from '../components/diagram_performance_warning.vue';
+import { unrestrictedPages } from './constants';
+
+/**
+ * Create alert element.
+ *
+ * @param {Element} krokiImage Kroki `img` element
+ * @return {Element} Alert element
+ */
+function createAlert(krokiImage) {
+ const app = new Vue({
+ el: document.createElement('div'),
+ name: 'DiagramPerformanceWarningRoot',
+ render(createElement) {
+ return createElement(DiagramPerformanceWarning, {
+ on: {
+ closeAlert() {
+ app.$destroy();
+ app.$el.remove();
+ },
+ showImage() {
+ krokiImage.removeAttribute('hidden');
+ app.$destroy();
+ app.$el.remove();
+ },
+ },
+ });
+ },
+ });
+
+ return app.$el;
+}
+
+/**
+ * Add warning alert to hidden Kroki images,
+ * or show Kroki image if on an unrestricted page.
+ *
+ * Kroki images are given a hidden attribute by the
+ * backend when the original markdown source is large.
+ *
+ * @param {Array<Element>} krokiImages Array of hidden Kroki `img` elements
+ */
+export function renderKroki(krokiImages) {
+ const pageName = document.querySelector('body').dataset.page;
+ const isUnrestrictedPage = unrestrictedPages.includes(pageName);
+
+ krokiImages.forEach((krokiImage) => {
+ if (isUnrestrictedPage) {
+ krokiImage.removeAttribute('hidden');
+ return;
+ }
+
+ const parent = krokiImage.closest('.js-markdown-code');
+
+ // A single Kroki image is processed multiple times for some reason,
+ // so this condition ensures we only create one alert per Kroki image
+ if (!parent.hasAttribute('data-kroki-processed')) {
+ parent.setAttribute('data-kroki-processed', 'true');
+ parent.after(createAlert(krokiImage));
+ }
+ });
+}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index d78c456ed5b..f9cf3af98bb 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -3,6 +3,7 @@ import { once, countBy } from 'lodash';
import createFlash from '~/flash';
import { darkModeEnabled } from '~/lib/utils/color_utils';
import { __, sprintf } from '~/locale';
+import { unrestrictedPages } from './constants';
// Renders diagrams and flowcharts from text using Mermaid in any element with the
// `js-render-mermaid` class.
@@ -30,24 +31,6 @@ let renderedMermaidBlocks = 0;
let mermaidModule = {};
-// Whitelist pages where we won't impose any restrictions
-// on mermaid rendering
-const WHITELISTED_PAGES = [
- // Group wiki
- 'groups:wikis:show',
- 'groups:wikis:edit',
- 'groups:wikis:create',
-
- // Project wiki
- 'projects:wikis:show',
- 'projects:wikis:edit',
- 'projects:wikis:create',
-
- // Project files
- 'projects:show',
- 'projects:blob:show',
-];
-
export function initMermaid(mermaid) {
let theme = 'neutral';
@@ -163,7 +146,7 @@ function renderMermaids($els) {
* up the entire thread and causing a DoS.
*/
if (
- !WHITELISTED_PAGES.includes(pageName) &&
+ !unrestrictedPages.includes(pageName) &&
((source && source.length > MAX_CHAR_LIMIT) ||
renderedChars > MAX_CHAR_LIMIT ||
renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT ||
diff --git a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js
index 85a991a1ec9..6922ec9c5a5 100644
--- a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js
@@ -9,6 +9,7 @@ import {
} from '~/lib/utils/url_utility';
import { darkModeEnabled } from '~/lib/utils/color_utils';
import { setAttributes } from '~/lib/utils/dom_utils';
+import { unrestrictedPages } from './constants';
// Renders diagrams and flowcharts from text using Mermaid in any element with the
// `js-render-mermaid` class.
@@ -36,23 +37,6 @@ const BUFFER_IFRAME_HEIGHT = 10;
const elsProcessingMap = new WeakMap();
let renderedMermaidBlocks = 0;
-// Pages without any restrictions on mermaid rendering
-const PAGES_WITHOUT_RESTRICTIONS = [
- // Group wiki
- 'groups:wikis:show',
- 'groups:wikis:edit',
- 'groups:wikis:create',
-
- // Project wiki
- 'projects:wikis:show',
- 'projects:wikis:edit',
- 'projects:wikis:create',
-
- // Project files
- 'projects:show',
- 'projects:blob:show',
-];
-
function shouldLazyLoadMermaidBlock(source) {
/**
* If source contains `&`, which means that it might
@@ -149,7 +133,7 @@ function renderMermaids($els) {
* up the entire thread and causing a DoS.
*/
if (
- !PAGES_WITHOUT_RESTRICTIONS.includes(pageName) &&
+ !unrestrictedPages.includes(pageName) &&
((source && source.length > MAX_CHAR_LIMIT) ||
renderedChars > MAX_CHAR_LIMIT ||
renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT ||