fix(dashboard): incorrect perm for users with multiple roles (#14148)

This commit is contained in:
Jesse Yang 2021-04-14 16:04:09 -07:00 committed by GitHub
parent 36bd6d8303
commit 6755083e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 40 deletions

View File

@ -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": {

View File

@ -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,

View File

@ -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);
});

View File

@ -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;