From 8d38675cbc98b600b3edc6d9e77033917f52b435 Mon Sep 17 00:00:00 2001 From: Phillip Kelley-Dotson Date: Thu, 24 Feb 2022 17:42:55 -0800 Subject: [PATCH] chore: add intersect method from backend to fontend for upload extensions (#18811) * chore: add intersect method from be to font end * fix lint * add suggestion * fix python test * run precommit * fix pytlint * update changes from masters --- .../src/views/CRUD/utils.test.tsx | 17 +++++++++++++++++ superset-frontend/src/views/CRUD/utils.tsx | 12 ++++++++++++ .../src/views/components/Menu.tsx | 2 +- .../src/views/components/MenuRight.tsx | 6 +++++- .../src/views/components/types.ts | 7 ++++--- superset/views/base.py | 18 ++++++++---------- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/superset-frontend/src/views/CRUD/utils.test.tsx b/superset-frontend/src/views/CRUD/utils.test.tsx index ce7139e82a99a..68d377e3102cf 100644 --- a/superset-frontend/src/views/CRUD/utils.test.tsx +++ b/superset-frontend/src/views/CRUD/utils.test.tsx @@ -23,6 +23,7 @@ import { getPasswordsNeeded, getAlreadyExists, hasTerminalValidation, + checkUploadExtensions, } from 'src/views/CRUD/utils'; const terminalErrors = { @@ -186,3 +187,19 @@ test('successfully modified rison to encode correctly', () => { expect(rison.decode(actualEncoding)).toEqual(testObject); }); }); + +test('checkUploadExtenssions should return valid upload extensions', () => { + const uploadExtensionTest = ['a', 'b', 'c']; + const randomExtension = ['a', 'c']; + const randomExtensionTwo = ['c']; + const randomExtensionThree: Array = []; + expect( + checkUploadExtensions(randomExtension, uploadExtensionTest), + ).toBeTruthy(); + expect( + checkUploadExtensions(randomExtensionTwo, uploadExtensionTest), + ).toBeTruthy(); + expect( + checkUploadExtensions(randomExtensionThree, uploadExtensionTest), + ).toBeFalsy(); +}); diff --git a/superset-frontend/src/views/CRUD/utils.tsx b/superset-frontend/src/views/CRUD/utils.tsx index 174e1aa493108..d9d21c8565d17 100644 --- a/superset-frontend/src/views/CRUD/utils.tsx +++ b/superset-frontend/src/views/CRUD/utils.tsx @@ -27,6 +27,7 @@ import { css, } from '@superset-ui/core'; import Chart from 'src/types/Chart'; +import { intersection } from 'lodash'; import rison from 'rison'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import { FetchDataConfig } from 'src/components/ListView'; @@ -409,3 +410,14 @@ export const hasTerminalValidation = (errors: Record[]) => isNeedsPassword(payload) || isAlreadyExists(payload), ), ); + +export const checkUploadExtensions = ( + perm: Array | string | undefined | boolean, + cons: Array, +) => { + if (perm !== undefined) { + if (typeof perm === 'boolean') return perm; + return intersection(perm, cons).length; + } + return false; +}; diff --git a/superset-frontend/src/views/components/Menu.tsx b/superset-frontend/src/views/components/Menu.tsx index 5231d27f21256..313c4b5cac071 100644 --- a/superset-frontend/src/views/components/Menu.tsx +++ b/superset-frontend/src/views/components/Menu.tsx @@ -79,7 +79,7 @@ interface MenuObjectChildProps { index?: number; url?: string; isFrontendRoute?: boolean; - perm?: string | boolean; + perm?: string | Array | boolean; view?: string; } diff --git a/superset-frontend/src/views/components/MenuRight.tsx b/superset-frontend/src/views/components/MenuRight.tsx index 8222a978c008b..fe55e832b7338 100644 --- a/superset-frontend/src/views/components/MenuRight.tsx +++ b/superset-frontend/src/views/components/MenuRight.tsx @@ -26,6 +26,7 @@ import { useSelector } from 'react-redux'; import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; import LanguagePicker from './LanguagePicker'; import DatabaseModal from '../CRUD/data/database/DatabaseModal'; +import { checkUploadExtensions } from '../CRUD/utils'; import { ExtentionConfigs, GlobalMenuDataOptions, @@ -75,6 +76,7 @@ const RightMenu = ({ CSV_EXTENSIONS, COLUMNAR_EXTENSIONS, EXCEL_EXTENSIONS, + ALLOWED_EXTENSIONS, HAS_GSHEETS_INSTALLED, } = useSelector(state => state.common.conf); @@ -188,7 +190,9 @@ const RightMenu = ({ title={menuIconAndLabel(menu)} > {menu.childs.map((item, idx) => - typeof item !== 'string' && item.name && item.perm ? ( + typeof item !== 'string' && + item.name && + checkUploadExtensions(item.perm, ALLOWED_EXTENSIONS) ? ( <> {idx === 2 && } diff --git a/superset-frontend/src/views/components/types.ts b/superset-frontend/src/views/components/types.ts index 0eff33390a727..d46c2e1619132 100644 --- a/superset-frontend/src/views/components/types.ts +++ b/superset-frontend/src/views/components/types.ts @@ -20,9 +20,10 @@ import { NavBarProps, MenuObjectProps } from './Menu'; export interface ExtentionConfigs { - CSV_EXTENSIONS: boolean; - COLUMNAR_EXTENSIONS: boolean; - EXCEL_EXTENSIONS: boolean; + ALLOWED_EXTENSIONS: Array; + CSV_EXTENSIONS: Array; + COLUMNAR_EXTENSIONS: Array; + EXCEL_EXTENSIONS: Array; HAS_GSHEETS_INSTALLED: boolean; } export interface RightMenuProps { diff --git a/superset/views/base.py b/superset/views/base.py index 067e8d74a727a..1249bc43cc4fb 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -104,6 +104,10 @@ "GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL", "DASHBOARD_AUTO_REFRESH_MODE", "SCHEDULED_QUERIES", + "EXCEL_EXTENSIONS", + "CSV_EXTENSIONS", + "COLUMNAR_EXTENSIONS", + "ALLOWED_EXTENSIONS", ) logger = logging.getLogger(__name__) @@ -347,16 +351,10 @@ def common_bootstrap_payload() -> Dict[str, Any]: locale = str(get_locale()) # should not expose API TOKEN to frontend - frontend_config = {k: conf.get(k) for k in FRONTEND_CONF_KEYS} - frontend_config["EXCEL_EXTENSIONS"] = bool( - bool(conf["EXCEL_EXTENSIONS"].intersection(conf["ALLOWED_EXTENSIONS"])), - ) - frontend_config["CSV_EXTENSIONS"] = bool( - bool(conf["CSV_EXTENSIONS"].intersection(conf["ALLOWED_EXTENSIONS"])), - ) - frontend_config["COLUMNAR_EXTENSIONS"] = bool( - bool(conf["COLUMNAR_EXTENSIONS"].intersection(conf["ALLOWED_EXTENSIONS"])), - ) + frontend_config = { + k: (list(conf.get(k)) if isinstance(conf.get(k), set) else conf.get(k)) + for k in FRONTEND_CONF_KEYS + } if conf.get("SLACK_API_TOKEN"): frontend_config["ALERT_REPORTS_NOTIFICATION_METHODS"] = [