From 965eb079d27a48f79375e3df8fea3e45c6dfcc37 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 5 Jan 2021 10:15:45 -0500 Subject: [PATCH] Introduce mechanism to request default capabilities (#86473) (#87291) --- ...rver.capabilitiessetup.registerswitcher.md | 14 +++++- ...plugin-core-server.capabilitiesswitcher.md | 2 +- .../capabilities/capabilities_service.test.ts | 27 ++++++++++- .../capabilities/capabilities_service.tsx | 2 + .../capabilities/capabilities_service.ts | 16 ++++++- .../capabilities_service.test.ts | 46 +++++++++++++++++-- .../capabilities/resolve_capabilities.test.ts | 12 ++--- .../capabilities/resolve_capabilities.ts | 19 ++++++-- .../routes/resolve_capabilities.ts | 6 ++- src/core/server/capabilities/types.ts | 3 +- src/core/server/server.api.md | 2 +- .../spaces_manager/spaces_manager.test.ts | 28 +++-------- .../public/spaces_manager/spaces_manager.ts | 21 +++++---- .../capabilities_switcher.test.ts | 35 ++++++++++---- .../capabilities/capabilities_switcher.ts | 7 +-- 15 files changed, 178 insertions(+), 62 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md b/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md index d0fd524f3234f..715f15ec812a3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md +++ b/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md @@ -31,7 +31,19 @@ How to restrict some capabilities ```ts // my-plugin/server/plugin.ts public setup(core: CoreSetup, deps: {}) { - core.capabilities.registerSwitcher((request, capabilities) => { + core.capabilities.registerSwitcher((request, capabilities, useDefaultCapabilities) => { + // useDefaultCapabilities is a special case that switchers typically don't have to concern themselves with. + // The default capabilities are typically the ones you provide in your CapabilitiesProvider, but this flag + // gives each switcher an opportunity to change the default capabilities of other plugins' capabilities. + // For example, you may decide to flip another plugin's capability to false if today is Tuesday, + // but you wouldn't want to do this when we are requesting the default set of capabilities. + if (useDefaultCapabilities) { + return { + somePlugin: { + featureEnabledByDefault: true + } + } + } if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { return { somePlugin: { diff --git a/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md b/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md index 01aa3a32c9abb..e6a0a9a096671 100644 --- a/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md +++ b/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md @@ -9,5 +9,5 @@ See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) Signature: ```typescript -export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; +export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities, useDefaultCapabilities: boolean) => Partial | Promise>; ``` diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index 286a93fdc2398..aa9c10ecfb2b2 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -41,11 +41,36 @@ describe('#start', () => { http.post.mockReturnValue(Promise.resolve(mockedCapabilities)); }); + it('requests default capabilities on anonymous paths', async () => { + http.anonymousPaths.isAnonymous.mockReturnValue(true); + const service = new CapabilitiesService(); + const appIds = ['app1', 'app2', 'legacyApp1', 'legacyApp2']; + const { capabilities } = await service.start({ + http, + appIds, + }); + + expect(http.post).toHaveBeenCalledWith('/api/core/capabilities', { + query: { + useDefaultCapabilities: true, + }, + body: JSON.stringify({ applications: appIds }), + }); + + // @ts-expect-error TypeScript knows this shouldn't be possible + expect(() => (capabilities.foo = 'foo')).toThrowError(); + }); + it('only returns capabilities for given appIds', async () => { const service = new CapabilitiesService(); + const appIds = ['app1', 'app2', 'legacyApp1', 'legacyApp2']; const { capabilities } = await service.start({ http, - appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], + appIds, + }); + + expect(http.post).toHaveBeenCalledWith('/api/core/capabilities', { + body: JSON.stringify({ applications: appIds }), }); // @ts-expect-error TypeScript knows this shouldn't be possible diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 1164164aec4c5..156b75b2d8abe 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -38,7 +38,9 @@ export interface CapabilitiesStart { */ export class CapabilitiesService { public async start({ appIds, http }: StartDeps): Promise { + const useDefaultCapabilities = http.anonymousPaths.isAnonymous(window.location.pathname); const capabilities = await http.post('/api/core/capabilities', { + query: useDefaultCapabilities ? { useDefaultCapabilities } : undefined, body: JSON.stringify({ applications: appIds }), }); diff --git a/src/core/server/capabilities/capabilities_service.ts b/src/core/server/capabilities/capabilities_service.ts index f0be9743d4d60..9af945d17b2ad 100644 --- a/src/core/server/capabilities/capabilities_service.ts +++ b/src/core/server/capabilities/capabilities_service.ts @@ -76,7 +76,19 @@ export interface CapabilitiesSetup { * ```ts * // my-plugin/server/plugin.ts * public setup(core: CoreSetup, deps: {}) { - * core.capabilities.registerSwitcher((request, capabilities) => { + * core.capabilities.registerSwitcher((request, capabilities, useDefaultCapabilities) => { + * // useDefaultCapabilities is a special case that switchers typically don't have to concern themselves with. + * // The default capabilities are typically the ones you provide in your CapabilitiesProvider, but this flag + * // gives each switcher an opportunity to change the default capabilities of other plugins' capabilities. + * // For example, you may decide to flip another plugin's capability to false if today is Tuesday, + * // but you wouldn't want to do this when we are requesting the default set of capabilities. + * if (useDefaultCapabilities) { + * return { + * somePlugin: { + * featureEnabledByDefault: true + * } + * } + * } * if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { * return { * somePlugin: { @@ -150,7 +162,7 @@ export class CapabilitiesService { public start(): CapabilitiesStart { return { - resolveCapabilities: (request) => this.resolveCapabilities(request, []), + resolveCapabilities: (request) => this.resolveCapabilities(request, [], false), }; } } diff --git a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts index 17f2c77bbf660..4217dd98ae735 100644 --- a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts +++ b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts @@ -72,17 +72,57 @@ describe('CapabilitiesService', () => { `); }); - it('uses the service capabilities providers', async () => { - serviceSetup.registerProvider(() => ({ + it('uses the service capabilities providers and switchers', async () => { + const getInitialCapabilities = () => ({ catalogue: { something: true, }, - })); + management: {}, + navLinks: {}, + }); + serviceSetup.registerProvider(() => getInitialCapabilities()); + + const switcher = jest.fn((_, capabilities) => capabilities); + serviceSetup.registerSwitcher(switcher); const result = await supertest(httpSetup.server.listener) .post('/api/core/capabilities') .send({ applications: [] }) .expect(200); + + expect(switcher).toHaveBeenCalledTimes(1); + expect(switcher).toHaveBeenCalledWith(expect.anything(), getInitialCapabilities(), false); + expect(result.body).toMatchInlineSnapshot(` + Object { + "catalogue": Object { + "something": true, + }, + "management": Object {}, + "navLinks": Object {}, + } + `); + }); + + it('passes useDefaultCapabilities to registered switchers', async () => { + const getInitialCapabilities = () => ({ + catalogue: { + something: true, + }, + management: {}, + navLinks: {}, + }); + serviceSetup.registerProvider(() => getInitialCapabilities()); + + const switcher = jest.fn((_, capabilities) => capabilities); + serviceSetup.registerSwitcher(switcher); + + const result = await supertest(httpSetup.server.listener) + .post('/api/core/capabilities?useDefaultCapabilities=true') + .send({ applications: [] }) + .expect(200); + + expect(switcher).toHaveBeenCalledTimes(1); + expect(switcher).toHaveBeenCalledWith(expect.anything(), getInitialCapabilities(), true); expect(result.body).toMatchInlineSnapshot(` Object { "catalogue": Object { diff --git a/src/core/server/capabilities/resolve_capabilities.test.ts b/src/core/server/capabilities/resolve_capabilities.test.ts index 372efeff21ae2..21c723ea1ddc3 100644 --- a/src/core/server/capabilities/resolve_capabilities.test.ts +++ b/src/core/server/capabilities/resolve_capabilities.test.ts @@ -36,7 +36,7 @@ describe('resolveCapabilities', () => { }); it('returns the initial capabilities if no switcher are used', async () => { - const result = await resolveCapabilities(defaultCaps, [], request, []); + const result = await resolveCapabilities(defaultCaps, [], request, [], true); expect(result).toEqual(defaultCaps); }); @@ -55,7 +55,7 @@ describe('resolveCapabilities', () => { A: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result).toMatchInlineSnapshot(` Object { "catalogue": Object { @@ -83,7 +83,7 @@ describe('resolveCapabilities', () => { A: false, }, }); - await resolveCapabilities(caps, [switcher], request, []); + await resolveCapabilities(caps, [switcher], request, [], true); expect(caps.catalogue).toEqual({ A: true, B: true, @@ -105,7 +105,7 @@ describe('resolveCapabilities', () => { C: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.catalogue).toEqual({ A: true, B: true, @@ -127,7 +127,7 @@ describe('resolveCapabilities', () => { .filter(([key]) => key !== 'B') .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.catalogue).toEqual({ A: true, B: true, @@ -153,7 +153,7 @@ describe('resolveCapabilities', () => { record: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.section).toEqual({ boolean: true, record: { diff --git a/src/core/server/capabilities/resolve_capabilities.ts b/src/core/server/capabilities/resolve_capabilities.ts index 1be504d4bc314..6f4eff6b882d0 100644 --- a/src/core/server/capabilities/resolve_capabilities.ts +++ b/src/core/server/capabilities/resolve_capabilities.ts @@ -23,7 +23,8 @@ import { KibanaRequest } from '../http'; export type CapabilitiesResolver = ( request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ) => Promise; export const getCapabilitiesResolver = ( @@ -31,16 +32,24 @@ export const getCapabilitiesResolver = ( switchers: () => CapabilitiesSwitcher[] ): CapabilitiesResolver => async ( request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ): Promise => { - return resolveCapabilities(capabilities(), switchers(), request, applications); + return resolveCapabilities( + capabilities(), + switchers(), + request, + applications, + useDefaultCapabilities + ); }; export const resolveCapabilities = async ( capabilities: Capabilities, switchers: CapabilitiesSwitcher[], request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ): Promise => { const mergedCaps = cloneDeep({ ...capabilities, @@ -54,7 +63,7 @@ export const resolveCapabilities = async ( }); return switchers.reduce(async (caps, switcher) => { const resolvedCaps = await caps; - const changes = await switcher(request, resolvedCaps); + const changes = await switcher(request, resolvedCaps, useDefaultCapabilities); return recursiveApplyChanges(resolvedCaps, changes); }, Promise.resolve(mergedCaps)); }; diff --git a/src/core/server/capabilities/routes/resolve_capabilities.ts b/src/core/server/capabilities/routes/resolve_capabilities.ts index 3fb1bb3d13d0b..3694c4b894684 100644 --- a/src/core/server/capabilities/routes/resolve_capabilities.ts +++ b/src/core/server/capabilities/routes/resolve_capabilities.ts @@ -29,14 +29,18 @@ export function registerCapabilitiesRoutes(router: IRouter, resolver: Capabiliti authRequired: 'optional', }, validate: { + query: schema.object({ + useDefaultCapabilities: schema.boolean({ defaultValue: false }), + }), body: schema.object({ applications: schema.arrayOf(schema.string()), }), }, }, async (ctx, req, res) => { + const { useDefaultCapabilities } = req.query; const { applications } = req.body; - const capabilities = await resolver(req, applications); + const capabilities = await resolver(req, applications, useDefaultCapabilities); return res.ok({ body: capabilities, }); diff --git a/src/core/server/capabilities/types.ts b/src/core/server/capabilities/types.ts index 105233761a437..efef31dcc8417 100644 --- a/src/core/server/capabilities/types.ts +++ b/src/core/server/capabilities/types.ts @@ -34,5 +34,6 @@ export type CapabilitiesProvider = () => Partial; */ export type CapabilitiesSwitcher = ( request: KibanaRequest, - uiCapabilities: Capabilities + uiCapabilities: Capabilities, + useDefaultCapabilities: boolean ) => Partial | Promise>; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index cef5f33726ed5..848cd3a657e9c 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -310,7 +310,7 @@ export interface CapabilitiesStart { } // @public -export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; +export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities, useDefaultCapabilities: boolean) => Partial | Promise>; // @alpha export const config: { 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 bc861964bf56d..25e1a0e071197 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 @@ -10,16 +10,9 @@ import { nextTick } from '@kbn/test/jest'; describe('SpacesManager', () => { describe('#constructor', () => { - it('attempts to retrieve the active space', () => { + it('does not attempt to retrieve the active space', () => { const coreStart = coreMock.createStart(); new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); - }); - - it('does not retrieve the active space if on an anonymous path', () => { - const coreStart = coreMock.createStart(); - coreStart.http.anonymousPaths.isAnonymous.mockReturnValue(true); - new SpacesManager(coreStart.http); expect(coreStart.http.get).not.toHaveBeenCalled(); }); }); @@ -32,6 +25,7 @@ describe('SpacesManager', () => { name: 'my space', }); const spacesManager = new SpacesManager(coreStart.http); + await spacesManager.getActiveSpace(); expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); await nextTick(); @@ -50,7 +44,7 @@ describe('SpacesManager', () => { const spacesManager = new SpacesManager(coreStart.http); expect(coreStart.http.get).not.toHaveBeenCalled(); - expect(() => spacesManager.getActiveSpace()).toThrowErrorMatchingInlineSnapshot( + expect(() => spacesManager.getActiveSpace()).rejects.toThrowErrorMatchingInlineSnapshot( `"Cannot retrieve the active space for anonymous paths"` ); }); @@ -68,9 +62,6 @@ describe('SpacesManager', () => { }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); - - await nextTick(); const activeSpace = await spacesManager.getActiveSpace(); expect(activeSpace).toEqual({ @@ -99,7 +90,7 @@ describe('SpacesManager', () => { expect(() => spacesManager.getActiveSpace({ forceRefresh: true }) - ).toThrowErrorMatchingInlineSnapshot( + ).rejects.toThrowErrorMatchingInlineSnapshot( `"Cannot retrieve the active space for anonymous paths"` ); }); @@ -111,10 +102,9 @@ describe('SpacesManager', () => { const shareToAllSpaces = Symbol(); coreStart.http.get.mockResolvedValue({ shareToAllSpaces }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space const result = await spacesManager.getShareSavedObjectPermissions('foo'); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { @@ -126,17 +116,15 @@ describe('SpacesManager', () => { it('allows the share if security is disabled', async () => { const coreStart = coreMock.createStart(); - coreStart.http.get.mockResolvedValueOnce({}); coreStart.http.get.mockRejectedValueOnce({ body: { statusCode: 404, }, }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space const result = await spacesManager.getShareSavedObjectPermissions('foo'); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { @@ -148,16 +136,14 @@ describe('SpacesManager', () => { it('throws all other errors', async () => { const coreStart = coreMock.createStart(); - coreStart.http.get.mockResolvedValueOnce({}); coreStart.http.get.mockRejectedValueOnce(new Error('Get out of here!')); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space await expect( spacesManager.getShareSavedObjectPermissions('foo') ).rejects.toThrowErrorMatchingInlineSnapshot(`"Get out of here!"`); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { 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 856899c127fd2..a7d74de603505 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts @@ -22,16 +22,21 @@ export class SpacesManager { private readonly serverBasePath: string; - public readonly onActiveSpaceChange$: Observable; + private readonly _onActiveSpaceChange$: Observable; constructor(private readonly http: HttpSetup) { this.serverBasePath = http.basePath.serverBasePath; - this.onActiveSpaceChange$ = this.activeSpace$ + this._onActiveSpaceChange$ = this.activeSpace$ .asObservable() .pipe(skipWhile((v: Space | null) => v == null)) as Observable; + } - this.refreshActiveSpace(); + public get onActiveSpaceChange$() { + if (!this.activeSpace$.value) { + this.refreshActiveSpace(); + } + return this._onActiveSpaceChange$; } public async getSpaces(options: GetAllSpacesOptions = {}): Promise { @@ -44,14 +49,14 @@ export class SpacesManager { return await this.http.get(`/api/spaces/space/${encodeURIComponent(id)}`); } - public getActiveSpace({ forceRefresh = false } = {}) { + public async getActiveSpace({ forceRefresh = false } = {}) { if (this.isAnonymousPath()) { throw new Error(`Cannot retrieve the active space for anonymous paths`); } - if (!forceRefresh && this.activeSpace$.value) { - return Promise.resolve(this.activeSpace$.value); + if (forceRefresh || !this.activeSpace$.value) { + await this.refreshActiveSpace(); } - return this.http.get('/internal/spaces/_active_space') as Promise; + return this.activeSpace$.value!; } public async createSpace(space: Space) { @@ -149,7 +154,7 @@ export class SpacesManager { if (this.isAnonymousPath()) { return; } - const activeSpace = await this.getActiveSpace({ forceRefresh: true }); + const activeSpace = await this.http.get('/internal/spaces/_active_space'); this.activeSpace$.next(activeSpace); } diff --git a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts index bfd73984811ef..770f8a16560ec 100644 --- a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts +++ b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts @@ -152,7 +152,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); }); @@ -166,12 +166,31 @@ describe('capabilitiesSwitcher', () => { const capabilities = buildCapabilities(); - const { switcher } = setup(space); + const { switcher, spacesService } = setup(space); const request = httpServerMock.createKibanaRequest({ routeAuthRequired: false }); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); + + expect(result).toEqual(buildCapabilities()); + expect(spacesService.getActiveSpace).not.toHaveBeenCalled(); + }); + + it('does not toggle capabilities when the default capabilities are requested', async () => { + const space: Space = { + id: 'space', + name: '', + disabledFeatures: ['feature_1', 'feature_2', 'feature_3'], + }; + + const capabilities = buildCapabilities(); + + const { switcher, spacesService } = setup(space); + const request = httpServerMock.createKibanaRequest(); + + const result = await switcher(request, capabilities, true); expect(result).toEqual(buildCapabilities()); + expect(spacesService.getActiveSpace).not.toHaveBeenCalled(); }); it('logs a debug message, and does not toggle capabilities if an error is encountered', async () => { @@ -188,7 +207,7 @@ describe('capabilitiesSwitcher', () => { spacesService.getActiveSpace.mockRejectedValue(new Error('Something terrible happened')); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); expect(logger.debug).toHaveBeenCalledWith( @@ -207,7 +226,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); }); @@ -223,7 +242,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); @@ -247,7 +266,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); @@ -274,7 +293,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); diff --git a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts index ee059f7b9c26e..4bf4c0683f570 100644 --- a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts +++ b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts @@ -15,10 +15,11 @@ export function setupCapabilitiesSwitcher( getSpacesService: () => SpacesServiceStart, logger: Logger ): CapabilitiesSwitcher { - return async (request, capabilities) => { - const isAnonymousRequest = !request.route.options.authRequired; + return async (request, capabilities, useDefaultCapabilities) => { + const isAuthRequiredOrOptional = !request.route.options.authRequired; + const shouldNotToggleCapabilities = isAuthRequiredOrOptional || useDefaultCapabilities; - if (isAnonymousRequest) { + if (shouldNotToggleCapabilities) { return capabilities; }