From ebea8e4c3e300fb3c53e1dec458e081c0a3ad3f7 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:01:11 -0400 Subject: [PATCH] Changes for additional PR review feedback --- x-pack/plugins/security/common/constants.ts | 10 ++++ .../check_saved_objects_privileges.test.ts | 47 +++++++++++++++++++ .../check_saved_objects_privileges.ts | 41 +++++++++------- ...ecure_saved_objects_client_wrapper.test.ts | 2 +- .../secure_saved_objects_client_wrapper.ts | 20 +++++--- x-pack/plugins/spaces/common/constants.ts | 10 ++++ .../public/lib/documentation_links.test.ts | 25 ++++++++++ .../spaces/public/lib/documentation_links.ts | 19 ++++++++ x-pack/plugins/spaces/public/lib/index.ts | 9 ++++ .../components/no_spaces_available.tsx | 2 +- .../components/selectable_spaces_control.tsx | 10 ++-- .../components/share_mode_control.tsx | 3 +- .../components/share_to_space_flyout.test.tsx | 6 +++ .../components/share_to_space_flyout.tsx | 6 +-- .../share_saved_objects_to_space_column.tsx | 3 +- .../spaces_manager/spaces_manager.test.ts | 2 +- .../public/spaces_manager/spaces_manager.ts | 2 +- .../routes/api/external/share_to_space.ts | 2 +- .../common/lib/saved_object_test_utils.ts | 2 +- 19 files changed, 181 insertions(+), 40 deletions(-) create mode 100644 x-pack/plugins/spaces/public/lib/documentation_links.test.ts create mode 100644 x-pack/plugins/spaces/public/lib/documentation_links.ts create mode 100644 x-pack/plugins/spaces/public/lib/index.ts diff --git a/x-pack/plugins/security/common/constants.ts b/x-pack/plugins/security/common/constants.ts index 44b6601daa7ff9..a0d63c0a9dd6f3 100644 --- a/x-pack/plugins/security/common/constants.ts +++ b/x-pack/plugins/security/common/constants.ts @@ -4,6 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +/** + * The identifier in a saved object's `namespaces` array when it is shared globally to all spaces. + */ +export const ALL_SPACES_ID = '*'; + +/** + * The identifier in a saved object's `namespaces` array when it is shared to an unknown space (e.g., one that the end user is not authorized to see). + */ +export const UNKNOWN_SPACE = '?'; + export const GLOBAL_RESOURCE = '*'; export const APPLICATION_PREFIX = 'kibana-'; export const RESERVED_PRIVILEGES_APPLICATION_WILDCARD = 'kibana-*'; diff --git a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts index f287cc04280ac9..4a2426a9e8a40f 100644 --- a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts @@ -95,6 +95,38 @@ describe('#checkSavedObjectsPrivileges', () => { ]; expect(mockCheckPrivileges.atSpaces).toHaveBeenCalledWith(spaceIds, { kibana: actions }); }); + + test(`uses checkPrivileges.globally when checking for "all spaces" (*)`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.globally.mockReturnValue(expectedResult as any); + mockSpacesService = undefined; + const checkSavedObjectsPrivileges = createFactory(); + + const namespaces = [undefined, 'default', namespace1, namespace1, '*']; + const result = await checkSavedObjectsPrivileges(actions, namespaces); + + expect(result).toBe(expectedResult); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.globally).toHaveBeenCalledTimes(1); + expect(mockCheckPrivileges.globally).toHaveBeenCalledWith({ kibana: actions }); + }); + + test(`uses checkPrivileges.globally when Spaces is disabled`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.globally.mockReturnValue(expectedResult as any); + mockSpacesService = undefined; + const checkSavedObjectsPrivileges = createFactory(); + + const namespaces = [undefined, 'default', namespace1, namespace1, '*']; + const result = await checkSavedObjectsPrivileges(actions, namespaces); + + expect(result).toBe(expectedResult); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.globally).toHaveBeenCalledTimes(1); + expect(mockCheckPrivileges.globally).toHaveBeenCalledWith({ kibana: actions }); + }); }); describe('when checking a single namespace', () => { @@ -115,6 +147,21 @@ describe('#checkSavedObjectsPrivileges', () => { expect(mockCheckPrivileges.atSpace).toHaveBeenCalledWith(spaceId, { kibana: actions }); }); + test(`uses checkPrivileges.globally when checking for "all spaces" (*)`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.globally.mockReturnValue(expectedResult as any); + mockSpacesService = undefined; + const checkSavedObjectsPrivileges = createFactory(); + + const result = await checkSavedObjectsPrivileges(actions, '*'); + + expect(result).toBe(expectedResult); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.globally).toHaveBeenCalledTimes(1); + expect(mockCheckPrivileges.globally).toHaveBeenCalledWith({ kibana: actions }); + }); + test(`uses checkPrivileges.globally when Spaces is disabled`, async () => { const expectedResult = Symbol(); mockCheckPrivileges.globally.mockReturnValue(expectedResult as any); diff --git a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts index 7c0ca7dcaa3922..6b70e25eb448d3 100644 --- a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts +++ b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts @@ -5,6 +5,7 @@ */ import { KibanaRequest } from '../../../../../src/core/server'; +import { ALL_SPACES_ID } from '../../common/constants'; import { SpacesService } from '../plugin'; import { CheckPrivilegesWithRequest, CheckPrivilegesResponse } from './types'; @@ -33,24 +34,32 @@ export const checkSavedObjectsPrivilegesWithRequestFactory = ( namespaceOrNamespaces?: string | Array ) { const spacesService = getSpacesService(); - if (!spacesService) { - // Spaces disabled, authorizing globally - return await checkPrivilegesWithRequest(request).globally({ kibana: actions }); - } else if (Array.isArray(namespaceOrNamespaces)) { - // Spaces enabled, authorizing against multiple spaces - if (!namespaceOrNamespaces.length) { - throw new Error(`Can't check saved object privileges for 0 namespaces`); + const privileges = { kibana: actions }; + + if (spacesService) { + if (Array.isArray(namespaceOrNamespaces)) { + // Spaces enabled, authorizing against multiple spaces + if (!namespaceOrNamespaces.length) { + throw new Error(`Can't check saved object privileges for 0 namespaces`); + } + const spaceIds = uniq( + namespaceOrNamespaces.map((x) => spacesService.namespaceToSpaceId(x)) + ); + + if (!spaceIds.includes(ALL_SPACES_ID)) { + return await checkPrivilegesWithRequest(request).atSpaces(spaceIds, privileges); + } + } else { + // Spaces enabled, authorizing against a single space + const spaceId = spacesService.namespaceToSpaceId(namespaceOrNamespaces); + if (spaceId !== ALL_SPACES_ID) { + return await checkPrivilegesWithRequest(request).atSpace(spaceId, privileges); + } } - const spaceIds = uniq( - namespaceOrNamespaces.map((x) => spacesService.namespaceToSpaceId(x)) - ); - - return await checkPrivilegesWithRequest(request).atSpaces(spaceIds, { kibana: actions }); - } else { - // Spaces enabled, authorizing against a single space - const spaceId = spacesService.namespaceToSpaceId(namespaceOrNamespaces); - return await checkPrivilegesWithRequest(request).atSpace(spaceId, { kibana: actions }); } + + // Spaces plugin is disabled OR we are checking privileges for "all spaces", authorizing globally + return await checkPrivilegesWithRequest(request).globally(privileges); }; }; }; diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts index d58413ec5c2717..ecf95a142a769f 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts @@ -172,7 +172,7 @@ const expectObjectNamespaceFiltering = async ( ); expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenLastCalledWith( 'login:', - namespaces + namespaces.filter((x) => x !== '*') // when we check what namespaces to redact, we don't check privileges for '*', only actual space IDs ); }; diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts index 95da13a7228d69..34c8a9d2df7836 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts @@ -18,6 +18,7 @@ import { SavedObjectsDeleteFromNamespacesOptions, SavedObjectsUtils, } from '../../../../../src/core/server'; +import { ALL_SPACES_ID, UNKNOWN_SPACE } from '../../common/constants'; import { SecurityAuditLogger } from '../audit'; import { Actions, CheckSavedObjectsPrivileges } from '../authorization'; import { CheckPrivilegesResponse } from '../authorization/types'; @@ -55,8 +56,6 @@ interface EnsureAuthorizedTypeResult { isGloballyAuthorized?: boolean; } -const ALL_SPACES_ID = '*'; - export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContract { private readonly actions: Actions; private readonly auditLogger: PublicMethodsOf; @@ -391,7 +390,7 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra private redactAndSortNamespaces(spaceIds: string[], privilegeMap: Record) { return spaceIds - .map((x) => (x === ALL_SPACES_ID || privilegeMap[x] ? x : '?')) + .map((x) => (x === ALL_SPACES_ID || privilegeMap[x] ? x : UNKNOWN_SPACE)) .sort(namespaceComparator); } @@ -406,7 +405,12 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra return savedObject; } - const privilegeMap = await this.getNamespacesPrivilegeMap(savedObject.namespaces); + const namespaces = savedObject.namespaces.filter((x) => x !== ALL_SPACES_ID); // all users can see the "all spaces" ID + if (namespaces.length === 0) { + return savedObject; + } + + const privilegeMap = await this.getNamespacesPrivilegeMap(namespaces); return { ...savedObject, @@ -421,7 +425,9 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra return response; } const { saved_objects: savedObjects } = response; - const namespaces = uniq(savedObjects.flatMap((savedObject) => savedObject.namespaces || [])); + const namespaces = uniq( + savedObjects.flatMap((savedObject) => savedObject.namespaces || []) + ).filter((x) => x !== ALL_SPACES_ID); // all users can see the "all spaces" ID if (namespaces.length === 0) { return response; } @@ -454,9 +460,9 @@ function uniq(arr: T[]): T[] { function namespaceComparator(a: string, b: string) { const A = a.toUpperCase(); const B = b.toUpperCase(); - if (A === '?' && B !== '?') { + if (A === UNKNOWN_SPACE && B !== UNKNOWN_SPACE) { return 1; - } else if (A !== '?' && B === '?') { + } else if (A !== UNKNOWN_SPACE && B === UNKNOWN_SPACE) { return -1; } return A > B ? 1 : A < B ? -1 : 0; diff --git a/x-pack/plugins/spaces/common/constants.ts b/x-pack/plugins/spaces/common/constants.ts index 33f1aae70ea009..bd47fe7b8b8777 100644 --- a/x-pack/plugins/spaces/common/constants.ts +++ b/x-pack/plugins/spaces/common/constants.ts @@ -6,6 +6,16 @@ export const DEFAULT_SPACE_ID = `default`; +/** + * The identifier in a saved object's `namespaces` array when it is shared globally to all spaces. + */ +export const ALL_SPACES_ID = '*'; + +/** + * The identifier in a saved object's `namespaces` array when it is shared to an unknown space (e.g., one that the end user is not authorized to see). + */ +export const UNKNOWN_SPACE = '?'; + /** * The minimum number of spaces required to show a search control. */ diff --git a/x-pack/plugins/spaces/public/lib/documentation_links.test.ts b/x-pack/plugins/spaces/public/lib/documentation_links.test.ts new file mode 100644 index 00000000000000..55319530304050 --- /dev/null +++ b/x-pack/plugins/spaces/public/lib/documentation_links.test.ts @@ -0,0 +1,25 @@ +/* + * 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 { docLinksServiceMock } from '../../../../../src/core/public/mocks'; +import { DocumentationLinksService } from './documentation_links'; + +describe('DocumentationLinksService', () => { + const setup = () => { + const docLinks = docLinksServiceMock.createStartContract(); + const service = new DocumentationLinksService(docLinks); + return { docLinks, service }; + }; + + describe('#getKibanaPrivilegesDocUrl', () => { + it('returns expected value', () => { + const { service } = setup(); + expect(service.getKibanaPrivilegesDocUrl()).toMatchInlineSnapshot( + `"https://www.elastic.co/guide/en/kibana/mocked-test-branch/kibana-privileges.html"` + ); + }); + }); +}); diff --git a/x-pack/plugins/spaces/public/lib/documentation_links.ts b/x-pack/plugins/spaces/public/lib/documentation_links.ts new file mode 100644 index 00000000000000..71ba89d5b87e29 --- /dev/null +++ b/x-pack/plugins/spaces/public/lib/documentation_links.ts @@ -0,0 +1,19 @@ +/* + * 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 { DocLinksStart } from 'src/core/public'; + +export class DocumentationLinksService { + private readonly kbn: string; + + constructor(docLinks: DocLinksStart) { + this.kbn = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/`; + } + + public getKibanaPrivilegesDocUrl() { + return `${this.kbn}kibana-privileges.html`; + } +} diff --git a/x-pack/plugins/spaces/public/lib/index.ts b/x-pack/plugins/spaces/public/lib/index.ts new file mode 100644 index 00000000000000..6dce93b81c7fc6 --- /dev/null +++ b/x-pack/plugins/spaces/public/lib/index.ts @@ -0,0 +1,9 @@ +/* + * 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 { DocumentationLinksService } from './documentation_links'; + +export { DocumentationLinksService }; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/no_spaces_available.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/no_spaces_available.tsx index f4fcda0d451e74..afa65cc7ad7dfa 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/no_spaces_available.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/no_spaces_available.tsx @@ -15,7 +15,7 @@ interface Props { export const NoSpacesAvailable = (props: Props) => { const { capabilities, getUrlForApp } = props.application; - const canCreateNewSpaces = capabilities.spaces?.manage; + const canCreateNewSpaces = capabilities.spaces.manage; if (!canCreateNewSpaces) { return null; } diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/selectable_spaces_control.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/selectable_spaces_control.tsx index a8e20f81359797..3cd7093b0bb209 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/selectable_spaces_control.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/selectable_spaces_control.tsx @@ -21,6 +21,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { CoreStart } from 'src/core/public'; import { NoSpacesAvailable } from './no_spaces_available'; +import { ALL_SPACES_ID, UNKNOWN_SPACE } from '../../../common/constants'; +import { DocumentationLinksService } from '../../lib'; import { SpaceAvatar } from '../../space_avatar'; import { SpaceTarget } from '../types'; @@ -33,8 +35,6 @@ interface Props { type SpaceOption = EuiSelectableOption & { ['data-space-id']: string }; -const ALL_SPACES_ID = '*'; -const UNKNOWN_SPACE = '?'; const ROW_HEIGHT = 40; const activeSpaceProps = { append: Current, @@ -77,7 +77,9 @@ export const SelectableSpacesControl = (props: Props) => { return null; } - const kibanaPrivilegesUrl = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/kibana-privileges.html`; + const kibanaPrivilegesUrl = new DocumentationLinksService( + docLinks! + ).getKibanaPrivilegesDocUrl(); return ( <> @@ -102,7 +104,7 @@ export const SelectableSpacesControl = (props: Props) => { }; const getNoSpacesAvailable = () => { if (spaces.length < 2) { - return ; + return ; } return null; }; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx index 4ad37094b18af1..2f1a3e0d459eeb 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx @@ -20,6 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { CoreStart } from 'src/core/public'; import { SelectableSpacesControl } from './selectable_spaces_control'; +import { ALL_SPACES_ID } from '../../../common/constants'; import { SpaceTarget } from '../types'; interface Props { @@ -31,8 +32,6 @@ interface Props { disabled?: boolean; } -const ALL_SPACES_ID = '*'; - function createLabel({ title, text, diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_to_space_flyout.test.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_to_space_flyout.test.tsx index 13826a519b1e84..ad49161ddd7053 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_to_space_flyout.test.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_to_space_flyout.test.tsx @@ -86,6 +86,12 @@ const setup = async (opts: SetupOpts = {}) => { } as SavedObjectsManagementRecord; const { getStartServices } = coreMock.createSetup(); + const startServices = coreMock.createStart(); + startServices.application.capabilities = { + ...startServices.application.capabilities, + spaces: { manage: true }, + }; + getStartServices.mockResolvedValue([startServices, , ,]); const wrapper = mountWithIntl( ; } -const ALL_SPACES_ID = '*'; const arraysAreEqual = (a: unknown[], b: unknown[]) => a.every((x) => b.includes(x)) && b.every((x) => a.includes(x)); @@ -98,10 +98,10 @@ export const ShareSavedObjectsToSpaceFlyout = (props: Props) => { return { isSelectionChanged: false, spacesToAdd: [], spacesToRemove: [] }; } const initialSelection = currentNamespaces.filter( - (spaceId) => spaceId !== activeSpace.id && spaceId !== '?' + (spaceId) => spaceId !== activeSpace.id && spaceId !== UNKNOWN_SPACE ); const { selectedSpaceIds } = shareOptions; - const filteredSelection = selectedSpaceIds.filter((x) => x !== '?'); + const filteredSelection = selectedSpaceIds.filter((x) => x !== UNKNOWN_SPACE); const isSharedToAllSpaces = !initialSelection.includes(ALL_SPACES_ID) && filteredSelection.includes(ALL_SPACES_ID); const isUnsharedFromAllSpaces = diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/share_saved_objects_to_space_column.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/share_saved_objects_to_space_column.tsx index b34287a3c5c449..0f988cf5a152db 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/share_saved_objects_to_space_column.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/share_saved_objects_to_space_column.tsx @@ -13,11 +13,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { SavedObjectsManagementColumn } from '../../../../../src/plugins/saved_objects_management/public'; import { SpaceTarget } from './types'; import { SpacesManager } from '../spaces_manager'; +import { ALL_SPACES_ID, UNKNOWN_SPACE } from '../../common/constants'; import { getSpaceColor } from '..'; const SPACES_DISPLAY_COUNT = 5; -const ALL_SPACES_ID = '*'; -const UNKNOWN_SPACE = '?'; type SpaceMap = Map; interface ColumnDataProps { diff --git a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts index 06cf3ef17dc820..7f005e37d96e90 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts @@ -116,7 +116,7 @@ describe('SpacesManager', () => { const result = await spacesManager.getShareSavedObjectPermissions('foo'); expect(coreStart.http.get).toHaveBeenCalledTimes(2); expect(coreStart.http.get).toHaveBeenLastCalledWith( - '/api/spaces/_share_saved_object_permissions', + '/internal/spaces/_share_saved_object_permissions', { query: { type: 'foo' }, } diff --git a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts index 98b00c58bf27d4..c81f7c17b7770d 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts @@ -109,7 +109,7 @@ export class SpacesManager { public async getShareSavedObjectPermissions( type: string ): Promise<{ shareToAllSpaces: boolean }> { - return this.http.get('/api/spaces/_share_saved_object_permissions', { query: { type } }); + return this.http.get('/internal/spaces/_share_saved_object_permissions', { query: { type } }); } public async shareSavedObjectAdd(object: SavedObject, spaces: string[]): Promise { diff --git a/x-pack/plugins/spaces/server/routes/api/external/share_to_space.ts b/x-pack/plugins/spaces/server/routes/api/external/share_to_space.ts index cc3573896ca8ff..5bf3b2779ba2a2 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/share_to_space.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/share_to_space.ts @@ -39,7 +39,7 @@ export function initShareToSpacesApi(deps: ExternalRouteDeps) { externalRouter.get( { - path: '/api/spaces/_share_saved_object_permissions', + path: '/internal/spaces/_share_saved_object_permissions', validate: { query: schema.object({ type: schema.string() }) }, }, createLicensedRouteHandler(async (_context, request, response) => { diff --git a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts index 395a343a2af1ee..511d183145a305 100644 --- a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts +++ b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts @@ -74,7 +74,7 @@ export const getTestTitle = ( export const isUserAuthorizedAtSpace = (user: TestUser | undefined, namespace: string) => !user || - namespace === ALL_SPACES_ID || + (user.authorizedAtSpaces.length > 0 && namespace === ALL_SPACES_ID) || user.authorizedAtSpaces.includes('*') || user.authorizedAtSpaces.includes(namespace);