mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Load Capabilities from InjectedMetadata (#36710)
This commit is contained in:
parent
1e25d1d5e5
commit
d9c34caf95
26 changed files with 251 additions and 185 deletions
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index) > [kibana-plugin-public](./kibana-plugin-public.md) > [InjectedMetadataSetup](./kibana-plugin-public.injectedmetadatasetup.md) > [getCapabilities](./kibana-plugin-public.injectedmetadatasetup.getcapabilities.md)
|
||||
|
||||
## InjectedMetadataSetup.getCapabilities property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getCapabilities: () => Capabilities;
|
||||
```
|
|
@ -17,6 +17,7 @@ export interface InjectedMetadataSetup
|
|||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [getBasePath](./kibana-plugin-public.injectedmetadatasetup.getbasepath.md) | <code>() => string</code> | |
|
||||
| [getCapabilities](./kibana-plugin-public.injectedmetadatasetup.getcapabilities.md) | <code>() => Capabilities</code> | |
|
||||
| [getCspConfig](./kibana-plugin-public.injectedmetadatasetup.getcspconfig.md) | <code>() => {`<p/>` warnLegacyBrowsers: boolean;`<p/>` }</code> | |
|
||||
| [getInjectedVar](./kibana-plugin-public.injectedmetadatasetup.getinjectedvar.md) | <code>(name: string, defaultValue?: any) => unknown</code> | |
|
||||
| [getInjectedVars](./kibana-plugin-public.injectedmetadatasetup.getinjectedvars.md) | <code>() => {`<p/>` [key: string]: unknown;`<p/>` }</code> | |
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import fetchMock from 'fetch-mock/es5/client';
|
||||
|
||||
import { InjectedMetadataService } from '../../injected_metadata';
|
||||
import { CapabilitiesService } from './capabilities_service';
|
||||
import { basePathServiceMock } from '../../base_path/base_path_service.mock';
|
||||
|
@ -29,74 +26,21 @@ describe('#start', () => {
|
|||
basePath.addToPath.mockImplementation(str => str);
|
||||
const injectedMetadata = new InjectedMetadataService({
|
||||
injectedMetadata: {
|
||||
vars: {
|
||||
uiCapabilities: {
|
||||
foo: { feature: true },
|
||||
bar: { feature: true },
|
||||
capabilities: {
|
||||
catalogue: {},
|
||||
management: {},
|
||||
navLinks: {
|
||||
app1: true,
|
||||
app2: false,
|
||||
},
|
||||
foo: { feature: true },
|
||||
bar: { feature: true },
|
||||
},
|
||||
} as any,
|
||||
}).start();
|
||||
const apps = [{ id: 'app1' }, { id: 'app2', capabilities: { app2: { feature: true } } }] as any;
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.post('/api/capabilities', (url: string, options: any) => ({
|
||||
body: options.body,
|
||||
status: 200,
|
||||
}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
it('calls backend API with merged capabilities', async () => {
|
||||
const service = new CapabilitiesService();
|
||||
await service.start({ apps, basePath, injectedMetadata });
|
||||
expect(fetchMock.calls()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
"/api/capabilities",
|
||||
Object {
|
||||
"body": "{\\"capabilities\\":{\\"navLinks\\":{\\"app2\\":true,\\"app1\\":true},\\"management\\":{},\\"catalogue\\":{},\\"app2\\":{\\"feature\\":true}}}",
|
||||
"credentials": "same-origin",
|
||||
"headers": Object {
|
||||
"kbn-xsrf": "xxx",
|
||||
},
|
||||
"method": "POST",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('returns capabilities from backend', async () => {
|
||||
const service = new CapabilitiesService();
|
||||
expect((await service.start({ apps, basePath, injectedMetadata })).capabilities)
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"app2": Object {
|
||||
"feature": true,
|
||||
},
|
||||
"catalogue": Object {},
|
||||
"management": Object {},
|
||||
"navLinks": Object {
|
||||
"app1": true,
|
||||
"app2": true,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('filters available apps based on returned navLinks', async () => {
|
||||
fetchMock.post(
|
||||
'/api/capabilities',
|
||||
(url: string, options: any) => ({
|
||||
body: JSON.stringify({ capabilities: { navLinks: { app1: true, app2: false } } }),
|
||||
status: 200,
|
||||
}),
|
||||
{ overwriteRoutes: true }
|
||||
);
|
||||
const service = new CapabilitiesService();
|
||||
expect((await service.start({ apps, basePath, injectedMetadata })).availableApps).toEqual([
|
||||
{ id: 'app1' },
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import { deepFreeze, RecursiveReadonly } from '../../utils/deep_freeze';
|
||||
import { MixedApp } from '../application_service';
|
||||
import { mergeCapabilities } from './merge_capabilities';
|
||||
import { InjectedMetadataStart } from '../../injected_metadata';
|
||||
import { BasePathStart } from '../../base_path';
|
||||
|
||||
|
@ -76,38 +75,7 @@ export interface CapabilitiesStart {
|
|||
*/
|
||||
export class CapabilitiesService {
|
||||
public async start({ apps, basePath, injectedMetadata }: StartDeps): Promise<CapabilitiesStart> {
|
||||
const mergedCapabilities = mergeCapabilities(
|
||||
// Custom capabilites for new platform apps
|
||||
...apps.filter(app => app.capabilities).map(app => app.capabilities!),
|
||||
// Generate navLink capabilities for all apps
|
||||
...apps.map(app => ({ navLinks: { [app.id]: true } }))
|
||||
);
|
||||
|
||||
// NOTE: should replace `fetch` with browser HTTP service once it exists
|
||||
const res = await fetch(basePath.addToPath('/api/capabilities'), {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ capabilities: mergedCapabilities }),
|
||||
headers: {
|
||||
'kbn-xsrf': 'xxx',
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
});
|
||||
|
||||
if (res.status === 401) {
|
||||
return {
|
||||
availableApps: [],
|
||||
capabilities: deepFreeze({
|
||||
navLinks: {},
|
||||
management: {},
|
||||
catalogue: {},
|
||||
}),
|
||||
};
|
||||
} else if (res.status !== 200) {
|
||||
throw new Error(`Capabilities check failed.`);
|
||||
}
|
||||
|
||||
const body = await res.json();
|
||||
const capabilities = deepFreeze(body.capabilities as Capabilities);
|
||||
const capabilities = deepFreeze(injectedMetadata.getCapabilities());
|
||||
const availableApps = apps.filter(app => capabilities.navLinks[app.id]);
|
||||
|
||||
return {
|
||||
|
|
|
@ -22,6 +22,7 @@ const createSetupContractMock = () => {
|
|||
const setupContract: jest.Mocked<InjectedMetadataSetup> = {
|
||||
getBasePath: jest.fn(),
|
||||
getKibanaVersion: jest.fn(),
|
||||
getCapabilities: jest.fn(),
|
||||
getCspConfig: jest.fn(),
|
||||
getLegacyMetadata: jest.fn(),
|
||||
getPlugins: jest.fn(),
|
||||
|
@ -29,6 +30,7 @@ const createSetupContractMock = () => {
|
|||
getInjectedVars: jest.fn(),
|
||||
getKibanaBuildNumber: jest.fn(),
|
||||
};
|
||||
setupContract.getCapabilities.mockReturnValue({} as any);
|
||||
setupContract.getCspConfig.mockReturnValue({ warnLegacyBrowsers: true });
|
||||
setupContract.getKibanaVersion.mockReturnValue('kibanaVersion');
|
||||
setupContract.getLegacyMetadata.mockReturnValue({
|
||||
|
|
|
@ -21,6 +21,7 @@ import { get } from 'lodash';
|
|||
import { DiscoveredPlugin, PluginName } from '../../server';
|
||||
import { UiSettingsState } from '../ui_settings';
|
||||
import { deepFreeze } from '../utils/deep_freeze';
|
||||
import { Capabilities } from '..';
|
||||
|
||||
/** @public */
|
||||
export interface LegacyNavLink {
|
||||
|
@ -48,6 +49,7 @@ export interface InjectedMetadataParams {
|
|||
id: PluginName;
|
||||
plugin: DiscoveredPlugin;
|
||||
}>;
|
||||
capabilities: Capabilities;
|
||||
legacyMetadata: {
|
||||
app: unknown;
|
||||
translations: unknown;
|
||||
|
@ -97,6 +99,10 @@ export class InjectedMetadataService {
|
|||
return this.state.version;
|
||||
},
|
||||
|
||||
getCapabilities: () => {
|
||||
return this.state.capabilities;
|
||||
},
|
||||
|
||||
getCspConfig: () => {
|
||||
return this.state.csp;
|
||||
},
|
||||
|
@ -133,6 +139,7 @@ export interface InjectedMetadataSetup {
|
|||
getBasePath: () => string;
|
||||
getKibanaBuildNumber: () => number;
|
||||
getKibanaVersion: () => string;
|
||||
getCapabilities: () => Capabilities;
|
||||
getCspConfig: () => {
|
||||
warnLegacyBrowsers: boolean;
|
||||
};
|
||||
|
|
|
@ -221,6 +221,7 @@ export interface InjectedMetadataParams {
|
|||
id: PluginName;
|
||||
plugin: DiscoveredPlugin;
|
||||
}>;
|
||||
capabilities: Capabilities;
|
||||
legacyMetadata: {
|
||||
app: unknown;
|
||||
translations: unknown;
|
||||
|
@ -246,6 +247,8 @@ export interface InjectedMetadataSetup {
|
|||
// (undocumented)
|
||||
getBasePath: () => string;
|
||||
// (undocumented)
|
||||
getCapabilities: () => Capabilities;
|
||||
// (undocumented)
|
||||
getCspConfig: () => {
|
||||
warnLegacyBrowsers: boolean;
|
||||
};
|
||||
|
@ -452,8 +455,8 @@ export interface UiSettingsState {
|
|||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/core/public/injected_metadata/injected_metadata_service.ts:48:7 - (ae-forgotten-export) The symbol "PluginName" needs to be exported by the entry point index.d.ts
|
||||
// src/core/public/injected_metadata/injected_metadata_service.ts:49:7 - (ae-forgotten-export) The symbol "DiscoveredPlugin" needs to be exported by the entry point index.d.ts
|
||||
// src/core/public/injected_metadata/injected_metadata_service.ts:49:7 - (ae-forgotten-export) The symbol "PluginName" needs to be exported by the entry point index.d.ts
|
||||
// src/core/public/injected_metadata/injected_metadata_service.ts:50:7 - (ae-forgotten-export) The symbol "DiscoveredPlugin" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ const coreSystem = new CoreSystem({
|
|||
csp: {
|
||||
warnLegacyBrowsers: false,
|
||||
},
|
||||
capabilities: uiCapabilities,
|
||||
uiPlugins: [],
|
||||
vars: {
|
||||
kbnIndex: '.kibana',
|
||||
|
|
|
@ -85,4 +85,15 @@ describe('capabilitiesMixin', () => {
|
|||
|
||||
expect(mockRegisterCapabilitiesRoute.mock.calls[0][2]).toEqual([mockModifier1, mockModifier2]);
|
||||
});
|
||||
|
||||
it('exposes request#getCapabilities for retrieving legacy capabilities', async () => {
|
||||
const kbnServer = getKbnServer();
|
||||
jest.spyOn(server, 'decorate');
|
||||
await capabilitiesMixin(kbnServer, server);
|
||||
expect(server.decorate).toHaveBeenCalledWith(
|
||||
'request',
|
||||
'getCapabilities',
|
||||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,6 +23,7 @@ import { Capabilities } from '../../../core/public';
|
|||
import KbnServer from '../kbn_server';
|
||||
import { registerCapabilitiesRoute } from './capabilities_route';
|
||||
import { mergeCapabilities } from './merge_capabilities';
|
||||
import { resolveCapabilities } from './resolve_capabilities';
|
||||
|
||||
export type CapabilitiesModifier = (
|
||||
request: Request,
|
||||
|
@ -48,6 +49,19 @@ export async function capabilitiesMixin(kbnServer: KbnServer, server: Server) {
|
|||
))
|
||||
);
|
||||
|
||||
server.decorate('request', 'getCapabilities', function() {
|
||||
// Get legacy nav links
|
||||
const navLinks = server.getUiNavLinks().reduce(
|
||||
(acc, spec) => ({
|
||||
...acc,
|
||||
[spec._id]: true,
|
||||
}),
|
||||
{} as Record<string, boolean>
|
||||
);
|
||||
|
||||
return resolveCapabilities(this, modifiers, defaultCapabilities, { navLinks });
|
||||
});
|
||||
|
||||
registerCapabilitiesRoute(server, defaultCapabilities, modifiers);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
import Joi from 'joi';
|
||||
import { Server } from 'hapi';
|
||||
|
||||
import { CapabilitiesModifier } from '.';
|
||||
import { Capabilities } from '../../../core/public';
|
||||
import { mergeCapabilities } from './merge_capabilities';
|
||||
import { CapabilitiesModifier } from './capabilities_mixin';
|
||||
import { resolveCapabilities } from './resolve_capabilities';
|
||||
|
||||
export const registerCapabilitiesRoute = (
|
||||
server: Server,
|
||||
|
@ -40,15 +40,14 @@ export const registerCapabilitiesRoute = (
|
|||
},
|
||||
},
|
||||
async handler(request) {
|
||||
let { capabilities } = request.payload as { capabilities: Capabilities };
|
||||
capabilities = mergeCapabilities({ ...defaultCapabilities }, capabilities);
|
||||
|
||||
for (const provider of modifiers) {
|
||||
capabilities = await provider(request, capabilities);
|
||||
}
|
||||
|
||||
const { capabilities } = request.payload as { capabilities: Capabilities };
|
||||
return {
|
||||
capabilities,
|
||||
capabilities: await resolveCapabilities(
|
||||
request,
|
||||
modifiers,
|
||||
defaultCapabilities,
|
||||
capabilities
|
||||
),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
|
||||
import { Capabilities } from '../../../core/public';
|
||||
|
||||
export const mergeCapabilities = (...sources: Capabilities[]): Capabilities =>
|
||||
export const mergeCapabilities = (...sources: Array<Partial<Capabilities>>): Capabilities =>
|
||||
sources.reduce(
|
||||
(capabilities, source) => {
|
||||
Object.entries(source).forEach(([key, value]) => {
|
||||
(capabilities: Capabilities, source) => {
|
||||
Object.entries(source).forEach(([key, value = {}]) => {
|
||||
capabilities[key] = {
|
||||
...value,
|
||||
...capabilities[key],
|
||||
|
|
34
src/legacy/server/capabilities/resolve_capabilities.ts
Normal file
34
src/legacy/server/capabilities/resolve_capabilities.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 { Request } from 'hapi';
|
||||
|
||||
import { Capabilities } from '../../../core/public';
|
||||
import { mergeCapabilities } from './merge_capabilities';
|
||||
import { CapabilitiesModifier } from './capabilities_mixin';
|
||||
|
||||
export const resolveCapabilities = (
|
||||
request: Request,
|
||||
modifiers: CapabilitiesModifier[],
|
||||
...capabilities: Array<Partial<Capabilities>>
|
||||
) =>
|
||||
modifiers.reduce(
|
||||
async (resolvedCaps, modifier) => modifier(request, await resolvedCaps),
|
||||
Promise.resolve(mergeCapabilities(...capabilities))
|
||||
);
|
3
src/legacy/server/kbn_server.d.ts
vendored
3
src/legacy/server/kbn_server.d.ts
vendored
|
@ -39,6 +39,7 @@ import {
|
|||
SavedObjectsSchema,
|
||||
SavedObjectsManagement,
|
||||
} from './saved_objects';
|
||||
import { Capabilities } from '../../core/public';
|
||||
|
||||
export interface KibanaConfig {
|
||||
get<T>(key: string): T;
|
||||
|
@ -71,12 +72,14 @@ declare module 'hapi' {
|
|||
scopedTutorialContextFactory: (...args: any[]) => any
|
||||
) => void;
|
||||
savedObjectsManagement(): SavedObjectsManagement;
|
||||
getUiNavLinks(): Array<{ _id: string }>;
|
||||
}
|
||||
|
||||
interface Request {
|
||||
getSavedObjectsClient(): SavedObjectsClient;
|
||||
getBasePath(): string;
|
||||
getUiSettingsService(): any;
|
||||
getCapabilities(): Promise<Capabilities>;
|
||||
}
|
||||
|
||||
interface ResponseToolkit {
|
||||
|
|
|
@ -252,6 +252,8 @@ export function uiRenderMixin(kbnServer, server, config) {
|
|||
uiPlugins,
|
||||
|
||||
legacyMetadata,
|
||||
|
||||
capabilities: await request.getCapabilities(),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
|
|||
...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
|
||||
...disabledPlugins.map(key => `--xpack.${key}.enabled=false`),
|
||||
`--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'foo_plugin')}`,
|
||||
'--optimize.enabled=false',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
import cheerio from 'cheerio';
|
||||
import { UICapabilities } from 'ui/capabilities';
|
||||
import { format as formatUrl } from 'url';
|
||||
import util from 'util';
|
||||
|
@ -42,21 +43,23 @@ export class UICapabilitiesService {
|
|||
|
||||
public async get({
|
||||
credentials,
|
||||
navLinks,
|
||||
spaceId,
|
||||
}: {
|
||||
credentials?: BasicCredentials;
|
||||
navLinks?: Record<string, boolean>;
|
||||
spaceId?: string;
|
||||
}): Promise<GetUICapabilitiesResult> {
|
||||
const spaceUrlPrefix = spaceId ? `/s/${spaceId}` : '';
|
||||
this.log.debug(`requesting ${spaceUrlPrefix}/api/capabilities to get the uiCapabilities`);
|
||||
const requestOptions = credentials ? { auth: credentials } : {};
|
||||
const response = await this.axios.post(
|
||||
`${spaceUrlPrefix}/api/capabilities`,
|
||||
{ capabilities: { navLinks } },
|
||||
requestOptions
|
||||
);
|
||||
this.log.debug(`requesting ${spaceUrlPrefix}/app/kibana to parse the uiCapabilities`);
|
||||
const requestHeaders = credentials
|
||||
? {
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${credentials.username}:${credentials.password}`
|
||||
).toString('base64')}`,
|
||||
}
|
||||
: {};
|
||||
const response = await this.axios.get(`${spaceUrlPrefix}/app/kibana`, {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
|
||||
if (response.status === 302 && response.headers.location === '/') {
|
||||
return {
|
||||
|
@ -65,6 +68,13 @@ export class UICapabilitiesService {
|
|||
};
|
||||
}
|
||||
|
||||
if (response.status === 404) {
|
||||
return {
|
||||
success: false,
|
||||
failureReason: GetUICapabilitiesFailureReason.NotFound,
|
||||
};
|
||||
}
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`Expected status code of 200, received ${response.status} ${
|
||||
|
@ -73,10 +83,25 @@ export class UICapabilitiesService {
|
|||
);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: response.data.capabilities,
|
||||
};
|
||||
const dom = cheerio.load(response.data.toString());
|
||||
const element = dom('kbn-injected-metadata');
|
||||
if (!element) {
|
||||
throw new Error('Unable to find "kbn-injected-metadata" element');
|
||||
}
|
||||
|
||||
const dataAttrJson = element.attr('data');
|
||||
|
||||
try {
|
||||
const dataAttr = JSON.parse(dataAttrJson);
|
||||
return {
|
||||
success: true,
|
||||
value: dataAttr.capabilities as UICapabilities,
|
||||
};
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Unable to parse JSON from the kbn-injected-metadata data attribute: ${dataAttrJson}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
import expect from '@kbn/expect';
|
||||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function catalogueTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
|
@ -24,12 +26,10 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
credentials: { username: user.username, password: user.password },
|
||||
spaceId: space.id,
|
||||
});
|
||||
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'superuser at everything_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything is enabled
|
||||
const expected = mapValues(uiCapabilities.value!.catalogue, () => true);
|
||||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
|
@ -41,6 +41,8 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
case 'global_read at everything_space':
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'everything_space_read at everything_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything except ml and monitoring is enabled
|
||||
const expected = mapValues(
|
||||
uiCapabilities.value!.catalogue,
|
||||
|
@ -58,13 +60,16 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
case 'dual_privileges_read at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read at nothing_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything is disabled
|
||||
const expected = mapValues(uiCapabilities.value!.catalogue, () => false);
|
||||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
break;
|
||||
}
|
||||
// if we don't have access at the space itself, all ui
|
||||
// capabilities should be false
|
||||
// if we don't have access at the space itself, we're
|
||||
// redirected to the space selector and the ui capabilities
|
||||
// are lagely irrelevant because they won't be consumed
|
||||
case 'no_kibana_privileges at everything_space':
|
||||
case 'no_kibana_privileges at nothing_space':
|
||||
case 'legacy_all at everything_space':
|
||||
|
@ -73,7 +78,10 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
assertDeeplyFalse(uiCapabilities.value!.catalogue);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
import expect from '@kbn/expect';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function fooTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
|
@ -23,14 +25,14 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
credentials: { username: user.username, password: user.password },
|
||||
spaceId: space.id,
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
switch (scenario.id) {
|
||||
// these users have a read/write view
|
||||
case 'superuser at everything_space':
|
||||
case 'global_all at everything_space':
|
||||
case 'dual_privileges_all at everything_space':
|
||||
case 'everything_space_all at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
expect(uiCapabilities.value!.foo).to.eql({
|
||||
create: true,
|
||||
edit: true,
|
||||
|
@ -42,6 +44,8 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
case 'global_read at everything_space':
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'everything_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
expect(uiCapabilities.value!.foo).to.eql({
|
||||
create: false,
|
||||
edit: false,
|
||||
|
@ -58,6 +62,8 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
case 'dual_privileges_read at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read at nothing_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
expect(uiCapabilities.value!.foo).to.eql({
|
||||
create: false,
|
||||
edit: false,
|
||||
|
@ -65,8 +71,9 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
show: false,
|
||||
});
|
||||
break;
|
||||
// if we don't have access at the space itself, all ui
|
||||
// capabilities should be false
|
||||
// if we don't have access at the space itself, we're
|
||||
// redirected to the space selector and the ui capabilities
|
||||
// are largely irrelevant because they won't be consumed
|
||||
case 'no_kibana_privileges at everything_space':
|
||||
case 'no_kibana_privileges at nothing_space':
|
||||
case 'legacy_all at everything_space':
|
||||
|
@ -75,7 +82,10 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
assertDeeplyFalse(uiCapabilities.value!.foo);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -8,7 +8,10 @@ import expect from '@kbn/expect';
|
|||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { NavLinksBuilder } from '../../common/nav_links_builder';
|
||||
import { FeaturesService } from '../../common/services';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
|
@ -29,13 +32,12 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
credentials: { username: user.username, password: user.password },
|
||||
navLinks: navLinksBuilder.all(),
|
||||
spaceId: space.id,
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
switch (scenario.id) {
|
||||
case 'superuser at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.all());
|
||||
break;
|
||||
case 'global_all at everything_space':
|
||||
|
@ -44,6 +46,8 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
case 'global_read at everything_space':
|
||||
case 'everything_space_all at everything_space':
|
||||
case 'everything_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(
|
||||
navLinksBuilder.except('ml', 'monitoring')
|
||||
);
|
||||
|
@ -55,10 +59,10 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
case 'global_read at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read at nothing_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.only('management'));
|
||||
break;
|
||||
// these users have no access to any navLinks except management
|
||||
// which is not a navLink that ever gets disabled.
|
||||
case 'no_kibana_privileges at everything_space':
|
||||
case 'no_kibana_privileges at nothing_space':
|
||||
case 'legacy_all at everything_space':
|
||||
|
@ -67,7 +71,10 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.only('management'));
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -7,9 +7,11 @@ import expect from '@kbn/expect';
|
|||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { SavedObjectsManagementBuilder } from '../../common/saved_objects_management_builder';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
UICapabilitiesService,
|
||||
GetUICapabilitiesFailureReason,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
const savedObjectsManagementBuilder = new SavedObjectsManagementBuilder(true);
|
||||
|
||||
|
@ -28,8 +30,6 @@ export default function savedObjectsManagementTests({
|
|||
credentials: { username: user.username, password: user.password },
|
||||
spaceId: space.id,
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
switch (scenario.id) {
|
||||
case 'superuser at everything_space':
|
||||
case 'global_all at everything_space':
|
||||
|
@ -76,7 +76,10 @@ export default function savedObjectsManagementTests({
|
|||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
assertDeeplyFalse(uiCapabilities.value!.savedObjectsManagement);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
import expect from '@kbn/expect';
|
||||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function catalogueTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
|
@ -24,10 +26,10 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
password: scenario.password,
|
||||
},
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
switch (scenario.username) {
|
||||
case 'superuser': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything is enabled
|
||||
const expected = mapValues(uiCapabilities.value!.catalogue, () => true);
|
||||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
|
@ -37,6 +39,8 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
case 'read':
|
||||
case 'dual_privileges_all':
|
||||
case 'dual_privileges_read': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything except ml and monitoring is enabled
|
||||
const expected = mapValues(
|
||||
uiCapabilities.value!.catalogue,
|
||||
|
@ -47,6 +51,8 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
}
|
||||
case 'foo_all':
|
||||
case 'foo_read': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// only foo is enabled
|
||||
const expected = mapValues(
|
||||
uiCapabilities.value!.catalogue,
|
||||
|
@ -55,10 +61,11 @@ export default function catalogueTests({ getService }: KibanaFunctionalTestDefau
|
|||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
break;
|
||||
}
|
||||
// these users have no access to any ui capabilities
|
||||
// these users have no access to even get the ui capabilities
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
assertDeeplyFalse(uiCapabilities.value!.catalogue);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
import expect from '@kbn/expect';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function fooTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
|
@ -23,16 +25,14 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
password: scenario.password,
|
||||
},
|
||||
});
|
||||
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
|
||||
switch (scenario.username) {
|
||||
// these users have a read/write view of Foo
|
||||
case 'superuser':
|
||||
case 'all':
|
||||
case 'dual_privileges_all':
|
||||
case 'foo_all':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
expect(uiCapabilities.value!.foo).to.eql({
|
||||
create: true,
|
||||
edit: true,
|
||||
|
@ -44,6 +44,8 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
case 'read':
|
||||
case 'dual_privileges_read':
|
||||
case 'foo_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('foo');
|
||||
expect(uiCapabilities.value!.foo).to.eql({
|
||||
create: false,
|
||||
edit: false,
|
||||
|
@ -51,10 +53,11 @@ export default function fooTests({ getService }: KibanaFunctionalTestDefaultProv
|
|||
show: true,
|
||||
});
|
||||
break;
|
||||
// these users have no access to any ui capabilities
|
||||
// these users have no access to even get the ui capabilities
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
assertDeeplyFalse(uiCapabilities.value!.foo);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
// all other users can't do anything with Foo
|
||||
default:
|
||||
|
|
|
@ -8,7 +8,10 @@ import expect from '@kbn/expect';
|
|||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { NavLinksBuilder } from '../../common/nav_links_builder';
|
||||
import { FeaturesService } from '../../common/services';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
|
@ -30,34 +33,35 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
username: scenario.username,
|
||||
password: scenario.password,
|
||||
},
|
||||
navLinks: navLinksBuilder.all(),
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
|
||||
switch (scenario.username) {
|
||||
case 'superuser':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.all());
|
||||
break;
|
||||
case 'all':
|
||||
case 'read':
|
||||
case 'dual_privileges_all':
|
||||
case 'dual_privileges_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(
|
||||
navLinksBuilder.except('ml', 'monitoring')
|
||||
);
|
||||
break;
|
||||
case 'foo_all':
|
||||
case 'foo_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(
|
||||
navLinksBuilder.only('management', 'foo')
|
||||
);
|
||||
break;
|
||||
// these users have no access to any navLinks except management
|
||||
// which is not a navLink that ever gets disabled.
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.only('management'));
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -8,9 +8,11 @@ import expect from '@kbn/expect';
|
|||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { SavedObjectsManagementBuilder } from '../../common/saved_objects_management_builder';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import {
|
||||
UICapabilitiesService,
|
||||
GetUICapabilitiesFailureReason,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
import { assertDeeplyFalse } from '../../common/lib/assert_deeply_false';
|
||||
|
||||
const savedObjectsManagementBuilder = new SavedObjectsManagementBuilder(false);
|
||||
|
||||
|
@ -29,8 +31,6 @@ export default function savedObjectsManagementTests({
|
|||
password: scenario.password,
|
||||
},
|
||||
});
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
switch (scenario.username) {
|
||||
case 'superuser':
|
||||
case 'all':
|
||||
|
@ -53,6 +53,8 @@ export default function savedObjectsManagementTests({
|
|||
break;
|
||||
case 'foo_all':
|
||||
case 'foo_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(
|
||||
savedObjectsManagementBuilder.build({
|
||||
all: [],
|
||||
|
@ -64,7 +66,8 @@ export default function savedObjectsManagementTests({
|
|||
// these users have no access to any ui capabilities
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
assertDeeplyFalse(uiCapabilities.value!.savedObjectsManagement);
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
|
|
|
@ -25,10 +25,7 @@ export default function navLinksTests({ getService }: KibanaFunctionalTestDefaul
|
|||
|
||||
SpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.name}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
navLinks: navLinksBuilder.all(),
|
||||
spaceId: scenario.id,
|
||||
});
|
||||
const uiCapabilities = await uiCapabilitiesService.get({ spaceId: scenario.id });
|
||||
switch (scenario.id) {
|
||||
case 'everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue