This is an automated email from the ASF dual-hosted git repository.

yjc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 6755083  fix(dashboard): incorrect perm for users with multiple roles 
(#14148)
6755083 is described below

commit 6755083e3adddcb72c7124db5fa2f3100ab13d72
Author: Jesse Yang <[email protected]>
AuthorDate: Wed Apr 14 16:04:09 2021 -0700

    fix(dashboard): incorrect perm for users with multiple roles (#14148)
---
 superset-frontend/package-lock.json                | 40 ++++++++++-----
 superset-frontend/src/dashboard/actions/hydrate.js | 18 +++----
 .../src/dashboard/util/findPermission.test.ts      | 59 ++++++++++++++++++++++
 .../util/{getPermissions.ts => findPermission.ts}  | 25 +++------
 4 files changed, 102 insertions(+), 40 deletions(-)

diff --git a/superset-frontend/package-lock.json 
b/superset-frontend/package-lock.json
index 035e48f..d1b1d0d 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -122,7 +122,7 @@
         "regenerator-runtime": "^0.13.5",
         "rison": "^0.1.1",
         "shortid": "^2.2.6",
-        "urijs": "^1.19.4",
+        "urijs": "^1.19.6",
         "use-immer": "^0.4.2",
         "use-query-params": "^1.1.9"
       },
@@ -54461,9 +54461,9 @@
       }
     },
     "node_modules/urijs": {
-      "version": "1.19.4",
-      "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.4.tgz";,
-      "integrity": 
"sha512-2YF/wdFu02Gsly/wyx+S/f5w/oCF0ihVSgK/Sn8fcY/ZYMYtqxgi03Vi3V7HqyQP8mj8xHMuNFTBIPufmPRdoA=="
+      "version": "1.19.6",
+      "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.6.tgz";,
+      "integrity": 
"sha512-eSXsXZ2jLvGWeLYlQA3Gh36BcjF+0amo92+wHPyN1mdR8Nxf75fuEuYTd9c0a+m/vhCjRK0ESlE9YNLW+E1VEw=="
     },
     "node_modules/urix": {
       "version": "0.1.0",
@@ -78681,6 +78681,12 @@
           "requires": {
             "glob": "^7.1.3"
           }
+        },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz";,
+          "integrity": 
"sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+          "dev": true
         }
       }
     },
@@ -78844,7 +78850,7 @@
     },
     "chalk": {
       "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz";,
+      "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz";,
       "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
       "dev": true,
       "requires": {
@@ -82030,7 +82036,7 @@
       "dependencies": {
         "domelementtype": {
           "version": "1.1.3",
-          "resolved": 
"https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz";,
+          "resolved": 
"http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz";,
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
         }
       }
@@ -92097,7 +92103,7 @@
     },
     "json5": {
       "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz";,
+      "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz";,
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
     },
     "jsonfile": {
@@ -94586,7 +94592,7 @@
     },
     "pify": {
       "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz";,
+      "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz";,
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
       "dev": true
     },
@@ -100253,7 +100259,7 @@
     },
     "regexpu-core": {
       "version": "1.0.0",
-      "resolved": 
"https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz";,
+      "resolved": 
"http://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz";,
       "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
       "dev": true,
       "requires": {
@@ -100264,13 +100270,13 @@
     },
     "regjsgen": {
       "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz";,
+      "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz";,
       "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
       "dev": true
     },
     "regjsparser": {
       "version": "0.1.5",
-      "resolved": 
"https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz";,
+      "resolved": 
"http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz";,
       "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
       "dev": true,
       "requires": {
@@ -106039,6 +106045,12 @@
             "strip-ansi": "^5.0.0"
           }
         },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz";,
+          "integrity": 
"sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+          "dev": true
+        },
         "yargs": {
           "version": "13.2.4",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz";,
@@ -107142,9 +107154,9 @@
       "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
     },
     "y18n": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz";,
-      "integrity": 
"sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz";,
+      "integrity": 
"sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
       "dev": true
     },
     "yallist": {
diff --git a/superset-frontend/src/dashboard/actions/hydrate.js 
b/superset-frontend/src/dashboard/actions/hydrate.js
index 8065bf6..7b87d5c 100644
--- a/superset-frontend/src/dashboard/actions/hydrate.js
+++ b/superset-frontend/src/dashboard/actions/hydrate.js
@@ -28,7 +28,7 @@ import { getInitialState as getInitialNativeFilterState } 
from 'src/dashboard/re
 import { getParam } from 'src/modules/utils';
 import { applyDefaultFormData } from 'src/explore/store';
 import { buildActiveFilters } from 'src/dashboard/util/activeDashboardFilters';
-import getPermissions from 'src/dashboard/util/getPermissions';
+import findPermission from 'src/dashboard/util/findPermission';
 import {
   DASHBOARD_FILTER_SCOPE_GLOBAL,
   dashboardFilter,
@@ -311,21 +311,21 @@ export const hydrateDashboard = (dashboardData, 
chartData, datasourcesData) => (
       dashboardInfo: {
         ...dashboardData,
         userId: String(user.userId), // legacy, please use state.user instead
-        dash_edit_perm: getPermissions('can_write', 'Dashboard', roles),
-        dash_save_perm: getPermissions('can_save_dash', 'Superset', roles),
-        dash_share_perm: getPermissions(
+        dash_edit_perm: findPermission('can_write', 'Dashboard', roles),
+        dash_save_perm: findPermission('can_save_dash', 'Superset', roles),
+        dash_share_perm: findPermission(
           'can_share_dashboard',
           'Superset',
           roles,
         ),
-        superset_can_explore: getPermissions('can_explore', 'Superset', roles),
-        superset_can_share: getPermissions(
+        superset_can_explore: findPermission('can_explore', 'Superset', roles),
+        superset_can_share: findPermission(
           'can_share_chart',
           'Superset',
           roles,
         ),
-        superset_can_csv: getPermissions('can_csv', 'Superset', roles),
-        slice_can_edit: getPermissions('can_slice', 'Superset', roles),
+        superset_can_csv: findPermission('can_csv', 'Superset', roles),
+        slice_can_edit: findPermission('can_slice', 'Superset', roles),
         common: {
           // legacy, please use state.common instead
           flash_messages: common.flash_messages,
@@ -347,7 +347,7 @@ export const hydrateDashboard = (dashboardData, chartData, 
datasourcesData) => (
         css: dashboardData.css || '',
         colorNamespace: metadata?.color_namespace || null,
         colorScheme: metadata?.color_scheme || null,
-        editMode: getPermissions('can_write', 'Dashboard', roles) && editMode,
+        editMode: findPermission('can_write', 'Dashboard', roles) && editMode,
         isPublished: dashboardData.published,
         hasUnsavedChanges: false,
         maxUndoHistoryExceeded: false,
diff --git a/superset-frontend/src/dashboard/util/findPermission.test.ts 
b/superset-frontend/src/dashboard/util/findPermission.test.ts
new file mode 100644
index 0000000..0dda552
--- /dev/null
+++ b/superset-frontend/src/dashboard/util/findPermission.test.ts
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import findPermission from './findPermission';
+
+test('findPermission for single role', () => {
+  expect(findPermission('abc', 'def', { role: [['abc', 'def']] })).toEqual(
+    true,
+  );
+
+  expect(findPermission('abc', 'def', { role: [['abc', 'de']] })).toEqual(
+    false,
+  );
+
+  expect(findPermission('abc', 'def', { role: [] })).toEqual(false);
+});
+
+test('findPermission for multiple roles', () => {
+  expect(
+    findPermission('abc', 'def', {
+      role1: [
+        ['ccc', 'aaa'],
+        ['abc', 'def'],
+      ],
+      role2: [['abc', 'def']],
+    }),
+  ).toEqual(true);
+
+  expect(
+    findPermission('abc', 'def', {
+      role1: [['abc', 'def']],
+      role2: [['abc', 'dd']],
+    }),
+  ).toEqual(true);
+
+  expect(
+    findPermission('abc', 'def', {
+      role1: [['ccc', 'aaa']],
+      role2: [['aaa', 'ddd']],
+    }),
+  ).toEqual(false);
+
+  expect(findPermission('abc', 'def', { role1: [], role2: [] 
})).toEqual(false);
+});
diff --git a/superset-frontend/src/dashboard/util/getPermissions.ts 
b/superset-frontend/src/dashboard/util/findPermission.ts
similarity index 63%
rename from superset-frontend/src/dashboard/util/getPermissions.ts
rename to superset-frontend/src/dashboard/util/findPermission.ts
index 0208fd6..613d189 100644
--- a/superset-frontend/src/dashboard/util/getPermissions.ts
+++ b/superset-frontend/src/dashboard/util/findPermission.ts
@@ -18,22 +18,13 @@
  */
 import memoizeOne from 'memoize-one';
 
-const findPermissions = (perm: string, view: string, roles: object) => {
-  const roleList = Object.entries(roles);
-  if (roleList.length === 0) return false;
-  let bool;
+type UserRoles = Record<string, [string, string][]>;
 
-  roleList.forEach(([role, permissions]) => {
-    bool = Boolean(
-      permissions.find(
-        (permission: Array<string>) =>
-          permission[0] === perm && permission[1] === view,
-      ),
-    );
-  });
-  return bool;
-};
+const findPermission = memoizeOne(
+  (perm: string, view: string, roles: UserRoles) =>
+    Object.values(roles).some(permissions =>
+      permissions.some(([perm_, view_]) => perm_ === perm && view_ === view),
+    ),
+);
 
-const getPermissions = memoizeOne(findPermissions);
-
-export default getPermissions;
+export default findPermission;

Reply via email to