From 6fe7b4a202b987c4ac7d71f36e9e190b3e3b3820 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Wed, 21 Oct 2020 15:07:27 -0700 Subject: [PATCH] feat: adding feature flags to escape/hide html in markdown (#11340) * utilizing feature flag for html escapement * use src alias * Feature flag to allow hiding of HTML tags * strips js attr * better feature flag naming * simplifying * Adding comments to new feature flags * shorter comment, because pylint, * pedantic change to get black to format a file --- .../components/gridComponents/Markdown.jsx | 28 +++++++++++++------ superset-frontend/src/featureFlags.ts | 2 ++ superset/config.py | 4 +++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx b/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx index 18ab67306b..ab507a68fe 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx @@ -19,23 +19,26 @@ import React from 'react'; import PropTypes from 'prop-types'; import ReactMarkdown from 'react-markdown'; +import htmlParser from 'react-markdown/plugins/html-parser'; + import cx from 'classnames'; import { t } from '@superset-ui/core'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; import { MarkdownEditor } from 'src/components/AsyncAceEditor'; +import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; -import DeleteComponentButton from '../DeleteComponentButton'; -import DragDroppable from '../dnd/DragDroppable'; -import ResizableContainer from '../resizable/ResizableContainer'; -import MarkdownModeDropdown from '../menu/MarkdownModeDropdown'; -import WithPopoverMenu from '../menu/WithPopoverMenu'; -import { componentShape } from '../../util/propShapes'; -import { ROW_TYPE, COLUMN_TYPE } from '../../util/componentTypes'; +import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton'; +import DragDroppable from 'src/dashboard/components/dnd/DragDroppable'; +import ResizableContainer from 'src/dashboard/components/resizable/ResizableContainer'; +import MarkdownModeDropdown from 'src/dashboard/components/menu/MarkdownModeDropdown'; +import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu'; +import { componentShape } from 'src/dashboard/util/propShapes'; +import { ROW_TYPE, COLUMN_TYPE } from 'src/dashboard/util/componentTypes'; import { GRID_MIN_COLUMN_COUNT, GRID_MIN_ROW_UNITS, GRID_BASE_UNIT, -} from '../../util/constants'; +} from 'src/dashboard/util/constants'; const propTypes = { id: PropTypes.string.isRequired, @@ -84,6 +87,7 @@ function isSafeMarkup(node) { return true; } + class Markdown extends React.PureComponent { constructor(props) { super(props); @@ -260,8 +264,14 @@ class Markdown extends React.PureComponent { ? MARKDOWN_ERROR_MESSAGE : this.state.markdownSource || MARKDOWN_PLACE_HOLDER } - escapeHtml={false} + escapeHtml={isFeatureEnabled(FeatureFlag.ESCAPE_MARKDOWN_HTML)} + skipHtml={!isFeatureEnabled(FeatureFlag.DISPLAY_MARKDOWN_HTML)} allowNode={isSafeMarkup} + astPlugins={[ + htmlParser({ + isValidNode: node => node.type !== 'script', + }), + ]} /> ); } diff --git a/superset-frontend/src/featureFlags.ts b/superset-frontend/src/featureFlags.ts index 46a3455c3e..85001be0ba 100644 --- a/superset-frontend/src/featureFlags.ts +++ b/superset-frontend/src/featureFlags.ts @@ -28,6 +28,8 @@ export enum FeatureFlag { SQLLAB_BACKEND_PERSISTENCE = 'SQLLAB_BACKEND_PERSISTENCE', THUMBNAILS = 'THUMBNAILS', LISTVIEWS_DEFAULT_CARD_VIEW = 'LISTVIEWS_DEFAULT_CARD_VIEW', + DISPLAY_MARKDOWN_HTML = 'DISPLAY_MARKDOWN_HTML', + ESCAPE_MARKDOWN_HTML = 'ESCAPE_MARKDOWN_HTML', } export type FeatureFlagMap = { diff --git a/superset/config.py b/superset/config.py index 30bd13fec9..ebc00134c9 100644 --- a/superset/config.py +++ b/superset/config.py @@ -313,6 +313,10 @@ DEFAULT_FEATURE_FLAGS: Dict[str, bool] = { "TAGGING_SYSTEM": False, "SQLLAB_BACKEND_PERSISTENCE": False, "LISTVIEWS_DEFAULT_CARD_VIEW": False, + # When True, this flag allows display of HTML tags in Markdown components + "DISPLAY_MARKDOWN_HTML": True, + # When True, this escapes HTML (rather than rendering it) in Markdown components + "ESCAPE_MARKDOWN_HTML": False, } # Set the default view to card/grid view if thumbnail support is enabled.