From 2f3e7fc1be5073378336476740e8cf8475a80c48 Mon Sep 17 00:00:00 2001 From: kobelb Date: Fri, 7 Jun 2019 14:14:03 -0700 Subject: [PATCH 1/8] Changing the Spaces management section to behave like the other FC controlled sections --- .../server/capabilities/merge_capabilities.ts | 19 ++----------------- .../authorization/privileges/privileges.ts | 1 + x-pack/plugins/spaces/index.ts | 5 +++++ .../spaces/public/views/management/index.tsx | 2 +- .../public/views/management/page_routes.tsx | 3 +++ 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/legacy/server/capabilities/merge_capabilities.ts b/src/legacy/server/capabilities/merge_capabilities.ts index e0f2d22ab34adc..d6ab406dc251c2 100644 --- a/src/legacy/server/capabilities/merge_capabilities.ts +++ b/src/legacy/server/capabilities/merge_capabilities.ts @@ -17,23 +17,8 @@ * under the License. */ +import { merge } from 'lodash'; import { Capabilities } from '../../../core/public'; export const mergeCapabilities = (...sources: Array>): Capabilities => - sources.reduce( - (capabilities: Capabilities, source) => { - Object.entries(source).forEach(([key, value = {}]) => { - capabilities[key] = { - ...value, - ...capabilities[key], - }; - }); - - return capabilities; - }, - { - navLinks: {}, - management: {}, - catalogue: {}, - } as Capabilities - ); + merge({}, ...sources); diff --git a/x-pack/plugins/security/server/lib/authorization/privileges/privileges.ts b/x-pack/plugins/security/server/lib/authorization/privileges/privileges.ts index c858bc61393f55..60c929854aed4c 100644 --- a/x-pack/plugins/security/server/lib/authorization/privileges/privileges.ts +++ b/x-pack/plugins/security/server/lib/authorization/privileges/privileges.ts @@ -65,6 +65,7 @@ export function privilegesFactory(actions: Actions, xpackMainPlugin: XPackMainPl actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), ...allActions, actions.allHack, ], diff --git a/x-pack/plugins/spaces/index.ts b/x-pack/plugins/spaces/index.ts index 13309a800e8b49..443243581434d9 100644 --- a/x-pack/plugins/spaces/index.ts +++ b/x-pack/plugins/spaces/index.ts @@ -49,6 +49,11 @@ export const spaces = (kibana: Record) => spaces: { manage: true, }, + management: { + kibana: { + spaces: true, + }, + }, }; }, diff --git a/x-pack/plugins/spaces/public/views/management/index.tsx b/x-pack/plugins/spaces/public/views/management/index.tsx index 2d8d1c7feb2db0..656193b417aa78 100644 --- a/x-pack/plugins/spaces/public/views/management/index.tsx +++ b/x-pack/plugins/spaces/public/views/management/index.tsx @@ -18,7 +18,7 @@ import routes from 'ui/routes'; import { AdvancedSettingsSubtitle } from './components/advanced_settings_subtitle'; import { AdvancedSettingsTitle } from './components/advanced_settings_title'; -const MANAGE_SPACES_KEY = 'manage_spaces'; +const MANAGE_SPACES_KEY = 'spaces'; routes.defaults(/\/management/, { resolve: { diff --git a/x-pack/plugins/spaces/public/views/management/page_routes.tsx b/x-pack/plugins/spaces/public/views/management/page_routes.tsx index 7ef313ce5927d7..732e8c8213f1ac 100644 --- a/x-pack/plugins/spaces/public/views/management/page_routes.tsx +++ b/x-pack/plugins/spaces/public/views/management/page_routes.tsx @@ -21,6 +21,7 @@ const reactRootNodeId = 'manageSpacesReactRoot'; routes.when('/management/spaces/list', { template, k7Breadcrumbs: getListBreadcrumbs, + requireUICapability: 'manage.spaces', controller( $scope: any, $http: any, @@ -53,6 +54,7 @@ routes.when('/management/spaces/list', { routes.when('/management/spaces/create', { template, k7Breadcrumbs: getCreateBreadcrumbs, + requireUICapability: 'manage.spaces', controller( $scope: any, $http: any, @@ -89,6 +91,7 @@ routes.when('/management/spaces/edit', { routes.when('/management/spaces/edit/:spaceId', { template, k7Breadcrumbs: () => getEditBreadcrumbs(), + requireUICapability: 'manage.spaces', controller( $scope: any, $http: any, From 131cfc2027b129df643238407f9891de030da666 Mon Sep 17 00:00:00 2001 From: kobelb Date: Fri, 7 Jun 2019 14:51:37 -0700 Subject: [PATCH 2/8] Adding those glorious tests and fixing a bug --- .../edit_space/manage_space_page.tsx | 4 +- .../public/views/management/page_routes.tsx | 6 +- .../spaces_grid/spaces_grid_page.tsx | 2 +- .../feature_controls/spaces_security.ts | 175 ++++++++++++++++++ x-pack/test/functional/apps/spaces/index.ts | 1 + 5 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts diff --git a/x-pack/plugins/spaces/public/views/management/edit_space/manage_space_page.tsx b/x-pack/plugins/spaces/public/views/management/edit_space/manage_space_page.tsx index 9ea3ecdaa5739a..fa0ebfa11201b4 100644 --- a/x-pack/plugins/spaces/public/views/management/edit_space/manage_space_page.tsx +++ b/x-pack/plugins/spaces/public/views/management/edit_space/manage_space_page.tsx @@ -144,7 +144,7 @@ class ManageSpacePageUI extends Component { const { showAlteringActiveSpaceDialog } = this.state; return ( - +
{this.getFormHeading()} @@ -188,7 +188,7 @@ class ManageSpacePageUI extends Component { }} /> )} - +
); }; diff --git a/x-pack/plugins/spaces/public/views/management/page_routes.tsx b/x-pack/plugins/spaces/public/views/management/page_routes.tsx index 732e8c8213f1ac..cbbe9234293b0e 100644 --- a/x-pack/plugins/spaces/public/views/management/page_routes.tsx +++ b/x-pack/plugins/spaces/public/views/management/page_routes.tsx @@ -21,7 +21,7 @@ const reactRootNodeId = 'manageSpacesReactRoot'; routes.when('/management/spaces/list', { template, k7Breadcrumbs: getListBreadcrumbs, - requireUICapability: 'manage.spaces', + requireUICapability: 'spaces.manage', controller( $scope: any, $http: any, @@ -54,7 +54,7 @@ routes.when('/management/spaces/list', { routes.when('/management/spaces/create', { template, k7Breadcrumbs: getCreateBreadcrumbs, - requireUICapability: 'manage.spaces', + requireUICapability: 'spaces.manage', controller( $scope: any, $http: any, @@ -91,7 +91,7 @@ routes.when('/management/spaces/edit', { routes.when('/management/spaces/edit/:spaceId', { template, k7Breadcrumbs: () => getEditBreadcrumbs(), - requireUICapability: 'manage.spaces', + requireUICapability: 'spaces.manage', controller( $scope: any, $http: any, diff --git a/x-pack/plugins/spaces/public/views/management/spaces_grid/spaces_grid_page.tsx b/x-pack/plugins/spaces/public/views/management/spaces_grid/spaces_grid_page.tsx index bfdc0768b655e5..803b786b2a5b68 100644 --- a/x-pack/plugins/spaces/public/views/management/spaces_grid/spaces_grid_page.tsx +++ b/x-pack/plugins/spaces/public/views/management/spaces_grid/spaces_grid_page.tsx @@ -72,7 +72,7 @@ class SpacesGridPageUI extends Component { public render() { return ( -
+
{this.getPageContent()} {this.getConfirmDeleteModal()} diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts new file mode 100644 index 00000000000000..808b88b596302b --- /dev/null +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers'; + +// eslint-disable-next-line import/no-default-export +export default function({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) { + const esArchiver = getService('esArchiver'); + const security = getService('security'); + const PageObjects = getPageObjects(['common', 'settings', 'security']); + const appsMenu = getService('appsMenu'); + const testSubjects = getService('testSubjects'); + + describe('security feature controls', () => { + before(async () => { + await esArchiver.load('empty_kibana'); + }); + + after(async () => { + await esArchiver.unload('empty_kibana'); + }); + + describe('global all base privilege', () => { + before(async () => { + await security.role.create('global_all_role', { + kibana: [ + { + base: ['all'], + spaces: ['*'], + }, + ], + }); + + await security.user.create('global_all_user', { + password: 'global_all_user-password', + roles: ['global_all_role'], + full_name: 'test user', + }); + + await PageObjects.security.logout(); + + await PageObjects.security.login('global_all_user', 'global_all_user-password', { + expectSpaceSelector: false, + }); + }); + + after(async () => { + await Promise.all([ + security.role.delete('global_all_role'), + security.user.delete('global_all_user'), + PageObjects.security.logout(), + ]); + }); + + it('shows management navlink', async () => { + const navLinks = (await appsMenu.readLinks()).map( + (link: Record) => link.text + ); + expect(navLinks).to.contain('Management'); + }); + + it(`displays Spaces management section`, async () => { + await PageObjects.settings.navigateTo(); + await testSubjects.existOrFail('spaces'); + }); + + it(`can navigate to spaces grid page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/list', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('spaces-grid-page'); + }); + + it(`can navigate to create new space page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/create', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('spaces-edit-page'); + }); + + it(`can navigate to edit space page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/edit/default', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('spaces-edit-page'); + }); + }); + + describe('default space all base privilege', () => { + before(async () => { + await security.role.create('default_space_all_role', { + kibana: [ + { + base: ['all'], + spaces: ['default'], + }, + ], + }); + + await security.user.create('default_space_all_user', { + password: 'default_space_all_user-password', + roles: ['default_space_all_role'], + full_name: 'test user', + }); + + await PageObjects.security.logout(); + + await PageObjects.security.login( + 'default_space_all_user', + 'default_space_all_user-password', + { + expectSpaceSelector: false, + } + ); + }); + + after(async () => { + await Promise.all([ + security.role.delete('default_space_all_role'), + security.user.delete('default_space_all_user'), + PageObjects.security.logout(), + ]); + }); + + it('shows management navlink', async () => { + const navLinks = (await appsMenu.readLinks()).map( + (link: Record) => link.text + ); + expect(navLinks).to.contain('Management'); + }); + + it(`doesn't display Spaces management section`, async () => { + await PageObjects.settings.navigateTo(); + await testSubjects.existOrFail('objects'); // this ensures we've gotten to the management page + await testSubjects.missingOrFail('spaces'); + }); + + it(`can't navigate to spaces grid page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/list', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('homeApp'); + }); + + it(`can navigate to create new space page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/create', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('homeApp'); + }); + + it(`can navigate to edit space page`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/edit/default', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + }); + + await testSubjects.existOrFail('homeApp'); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/spaces/index.ts b/x-pack/test/functional/apps/spaces/index.ts index b8b4e71b141fea..ccb7d28ae51b6b 100644 --- a/x-pack/test/functional/apps/spaces/index.ts +++ b/x-pack/test/functional/apps/spaces/index.ts @@ -10,6 +10,7 @@ export default function spacesApp({ loadTestFile }: KibanaFunctionalTestDefaultP describe('Spaces app', function spacesAppTestSuite() { this.tags('ciGroup4'); + loadTestFile(require.resolve('./feature_controls/spaces_security')); loadTestFile(require.resolve('./spaces_selection')); }); } From 6250324a213b622729c462f4e09ce1d864991fad Mon Sep 17 00:00:00 2001 From: kobelb Date: Fri, 7 Jun 2019 14:59:38 -0700 Subject: [PATCH 3/8] Fixing some test descriptions --- .../apps/spaces/feature_controls/spaces_security.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts index 808b88b596302b..7ac616ce08962b 100644 --- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -153,7 +153,7 @@ export default function({ getPageObjects, getService }: KibanaFunctionalTestDefa await testSubjects.existOrFail('homeApp'); }); - it(`can navigate to create new space page`, async () => { + it(`can't navigate to create new space page`, async () => { await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/create', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, @@ -162,7 +162,7 @@ export default function({ getPageObjects, getService }: KibanaFunctionalTestDefa await testSubjects.existOrFail('homeApp'); }); - it(`can navigate to edit space page`, async () => { + it(`can't navigate to edit space page`, async () => { await PageObjects.common.navigateToActualUrl('kibana', 'management/spaces/edit/default', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, From 00fb4f3149789ad40ad752fc7f08c85728ada3fd Mon Sep 17 00:00:00 2001 From: kobelb Date: Mon, 10 Jun 2019 07:39:36 -0700 Subject: [PATCH 4/8] Making the mergeCapabilities operation emulate the old behavior --- src/legacy/server/capabilities/merge_capabilities.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/legacy/server/capabilities/merge_capabilities.ts b/src/legacy/server/capabilities/merge_capabilities.ts index d6ab406dc251c2..b0b62f89748063 100644 --- a/src/legacy/server/capabilities/merge_capabilities.ts +++ b/src/legacy/server/capabilities/merge_capabilities.ts @@ -21,4 +21,11 @@ import { merge } from 'lodash'; import { Capabilities } from '../../../core/public'; export const mergeCapabilities = (...sources: Array>): Capabilities => - merge({}, ...sources); + merge( + { + navLinks: {}, + management: {}, + catalogue: {}, + }, + ...sources + ); From 84f8acfe673e3bdd89c8eb4236c5c8c4ee0fa4fc Mon Sep 17 00:00:00 2001 From: kobelb Date: Mon, 10 Jun 2019 07:43:07 -0700 Subject: [PATCH 5/8] Fixing privileges test with the addition of the new action --- .../privileges/privileges.test.ts | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security/server/lib/authorization/privileges/privileges.test.ts b/x-pack/plugins/security/server/lib/authorization/privileges/privileges.test.ts index e18b9ecdf6fe3c..f8c6edcef2d822 100644 --- a/x-pack/plugins/security/server/lib/authorization/privileges/privileges.test.ts +++ b/x-pack/plugins/security/server/lib/authorization/privileges/privileges.test.ts @@ -318,7 +318,13 @@ describe('features', () => { actions.login, actions.version, ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + ] + : []), actions.app.get('app-1'), actions.app.get('app-2'), actions.ui.get('catalogue', 'catalogue-1'), @@ -403,7 +409,13 @@ describe('features', () => { actions.login, actions.version, ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + ] + : []), actions.ui.get('catalogue', 'bar-catalogue-1'), actions.ui.get('catalogue', 'bar-catalogue-2'), actions.ui.get('management', 'bar-management', 'bar-management-1'), @@ -614,7 +626,13 @@ describe('features', () => { actions.login, actions.version, ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + ] + : []), actions.allHack, ]); expect(actual).toHaveProperty(`${group}.read`, [actions.login, actions.version]); From 49e078ff823a95ec78b0ec564a6b1503d00c48fc Mon Sep 17 00:00:00 2001 From: kobelb Date: Mon, 10 Jun 2019 12:49:59 -0700 Subject: [PATCH 6/8] Updating jest snapshot --- .../spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/spaces/public/views/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap b/x-pack/plugins/spaces/public/views/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap index 0766bc768b120f..cfe14ea07b0109 100644 --- a/x-pack/plugins/spaces/public/views/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap +++ b/x-pack/plugins/spaces/public/views/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap @@ -3,6 +3,7 @@ exports[`SpacesGridPage renders as expected 1`] = `
Date: Tue, 11 Jun 2019 08:51:47 -0700 Subject: [PATCH 7/8] Adding tests, preventing additional clobbering --- .../capabilities/merge_capabilities.test.ts | 84 +++++++++++++++++++ .../server/capabilities/merge_capabilities.ts | 15 +++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/legacy/server/capabilities/merge_capabilities.test.ts diff --git a/src/legacy/server/capabilities/merge_capabilities.test.ts b/src/legacy/server/capabilities/merge_capabilities.test.ts new file mode 100644 index 00000000000000..a73b81bdaf0a32 --- /dev/null +++ b/src/legacy/server/capabilities/merge_capabilities.test.ts @@ -0,0 +1,84 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 { mergeCapabilities } from './merge_capabilities'; + +const defaultProps = { + catalogue: {}, + management: {}, + navLinks: {}, +}; + +test(`"{ foo: {} }" doesn't clobber "{ foo: { bar: true } }"`, () => { + const output1 = mergeCapabilities({ foo: { bar: true } }, { foo: {} }); + expect(output1).toEqual({ ...defaultProps, foo: { bar: true } }); + + const output2 = mergeCapabilities({ foo: { bar: true } }, { foo: {} }); + expect(output2).toEqual({ ...defaultProps, foo: { bar: true } }); +}); + +test(`"{ foo: { bar: true } }" doesn't clobber "{ baz: { quz: true } }"`, () => { + const output1 = mergeCapabilities({ foo: { bar: true } }, { baz: { quz: true } }); + expect(output1).toEqual({ ...defaultProps, foo: { bar: true }, baz: { quz: true } }); + + const output2 = mergeCapabilities({ baz: { quz: true } }, { foo: { bar: true } }); + expect(output2).toEqual({ ...defaultProps, foo: { bar: true }, baz: { quz: true } }); +}); + +test(`"{ foo: { bar: { baz: true } } }" doesn't clobber "{ foo: { bar: { quz: true } } }"`, () => { + const output1 = mergeCapabilities( + { foo: { bar: { baz: true } } }, + { foo: { bar: { quz: true } } } + ); + expect(output1).toEqual({ ...defaultProps, foo: { bar: { baz: true, quz: true } } }); + + const output2 = mergeCapabilities( + { foo: { bar: { quz: true } } }, + { foo: { bar: { baz: true } } } + ); + expect(output2).toEqual({ ...defaultProps, foo: { bar: { baz: true, quz: true } } }); +}); + +test(`error is thrown if boolean and object clash`, () => { + expect(() => { + mergeCapabilities({ foo: { bar: { baz: true } } }, { foo: { bar: true } }); + }).toThrowErrorMatchingInlineSnapshot(`"a boolean and an object can't be merged"`); + + expect(() => { + mergeCapabilities({ foo: { bar: true } }, { foo: { bar: { baz: true } } }); + }).toThrowErrorMatchingInlineSnapshot(`"a boolean and an object can't be merged"`); +}); + +test(`supports duplicates as long as the booleans are the same`, () => { + const output1 = mergeCapabilities({ foo: { bar: true } }, { foo: { bar: true } }); + expect(output1).toEqual({ ...defaultProps, foo: { bar: true } }); + + const output2 = mergeCapabilities({ foo: { bar: false } }, { foo: { bar: false } }); + expect(output2).toEqual({ ...defaultProps, foo: { bar: false } }); +}); + +test(`error is thrown if merging "true" and "false"`, () => { + expect(() => { + mergeCapabilities({ foo: { bar: false } }, { foo: { bar: true } }); + }).toThrowErrorMatchingInlineSnapshot(`"\\"true\\" and \\"false\\" can't be merged"`); + + expect(() => { + mergeCapabilities({ foo: { bar: true } }, { foo: { bar: false } }); + }).toThrowErrorMatchingInlineSnapshot(`"\\"true\\" and \\"false\\" can't be merged"`); +}); diff --git a/src/legacy/server/capabilities/merge_capabilities.ts b/src/legacy/server/capabilities/merge_capabilities.ts index b0b62f89748063..5fe31775ba32d8 100644 --- a/src/legacy/server/capabilities/merge_capabilities.ts +++ b/src/legacy/server/capabilities/merge_capabilities.ts @@ -17,6 +17,7 @@ * under the License. */ +import typeDetect from 'type-detect'; import { merge } from 'lodash'; import { Capabilities } from '../../../core/public'; @@ -27,5 +28,17 @@ export const mergeCapabilities = (...sources: Array>): Cap management: {}, catalogue: {}, }, - ...sources + ...sources, + (a: any, b: any) => { + if ( + (typeDetect(a) === 'boolean' && typeDetect(b) === 'Object') || + (typeDetect(b) === 'boolean' && typeDetect(a) === 'Object') + ) { + throw new Error(`a boolean and an object can't be merged`); + } + + if (typeDetect(a) === 'boolean' && typeDetect(b) === 'boolean' && a !== b) { + throw new Error(`"true" and "false" can't be merged`); + } + } ); From 84644c87b92c962bb6b079195e74a508629bd8de Mon Sep 17 00:00:00 2001 From: kobelb Date: Tue, 11 Jun 2019 09:58:43 -0700 Subject: [PATCH 8/8] Changing requireUICapability to use management.kibana.spaces --- .../plugins/spaces/public/views/management/page_routes.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/spaces/public/views/management/page_routes.tsx b/x-pack/plugins/spaces/public/views/management/page_routes.tsx index cbbe9234293b0e..34ca4acc53efe0 100644 --- a/x-pack/plugins/spaces/public/views/management/page_routes.tsx +++ b/x-pack/plugins/spaces/public/views/management/page_routes.tsx @@ -21,7 +21,7 @@ const reactRootNodeId = 'manageSpacesReactRoot'; routes.when('/management/spaces/list', { template, k7Breadcrumbs: getListBreadcrumbs, - requireUICapability: 'spaces.manage', + requireUICapability: 'management.kibana.spaces', controller( $scope: any, $http: any, @@ -54,7 +54,7 @@ routes.when('/management/spaces/list', { routes.when('/management/spaces/create', { template, k7Breadcrumbs: getCreateBreadcrumbs, - requireUICapability: 'spaces.manage', + requireUICapability: 'management.kibana.spaces', controller( $scope: any, $http: any, @@ -91,7 +91,7 @@ routes.when('/management/spaces/edit', { routes.when('/management/spaces/edit/:spaceId', { template, k7Breadcrumbs: () => getEditBreadcrumbs(), - requireUICapability: 'spaces.manage', + requireUICapability: 'management.kibana.spaces', controller( $scope: any, $http: any,