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 1ab06b7912d1f..0d7156bbe998d 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -311,7 +311,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;
}