Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Controls] - Secure Features API #35841

Merged
merged 13 commits into from
May 3, 2019
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,17 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
return [];
},
privileges() {
return kfetch({ method: 'get', pathname: '/api/security/privileges', query: { includeActions: true } });
return kfetch({ method: 'get', pathname: '/api/security/privileges', query: { includeActions: true } });
},
features() {
return kfetch({ method: 'get', pathname: '/api/features/v1' });
return kfetch({ method: 'get', pathname: '/api/features/v1' }).catch(e => {
// TODO: This check can be removed once all of these `resolve` entries are moved out of Angular and into the React app.
const unauthorizedForFeatures = _.get(e, 'body.statusCode') === 404;
if (unauthorizedForFeatures) {
return [];
}
throw e;
});
}
},
controllerAs: 'editRole',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,14 @@ describe('features', () => {
{
group: 'global',
expectManageSpaces: true,
expectGetFeatures: true,
},
{
group: 'space',
expectManageSpaces: false,
expectGetFeatures: false,
},
].forEach(({ group, expectManageSpaces }) => {
].forEach(({ group, expectManageSpaces, expectGetFeatures }) => {
describe(group, () => {
test('actions defined only at the feature are included in `all` and `read`', () => {
const features: Feature[] = [
Expand Down Expand Up @@ -331,6 +333,7 @@ describe('features', () => {
all: [
actions.login,
actions.version,
...(expectGetFeatures ? [actions.api.get('features')] : []),
...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []),
actions.app.get('app-1'),
actions.app.get('app-2'),
Expand Down Expand Up @@ -415,6 +418,7 @@ describe('features', () => {
expect(actual).toHaveProperty(`${group}.all`, [
actions.login,
actions.version,
...(expectGetFeatures ? [actions.api.get('features')] : []),
...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []),
actions.ui.get('catalogue', 'bar-catalogue-1'),
actions.ui.get('catalogue', 'bar-catalogue-2'),
Expand Down Expand Up @@ -745,6 +749,7 @@ describe('features', () => {
expect(actual).toHaveProperty(`${group}.all`, [
actions.login,
actions.version,
...(expectGetFeatures ? [actions.api.get('features')] : []),
...(expectManageSpaces ? [actions.space.manage, actions.ui.get('spaces', 'manage')] : []),
actions.allHack,
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export function privilegesFactory(actions: Actions, xpackMainPlugin: XPackMainPl
all: [
actions.login,
actions.version,
actions.api.get('features'),
actions.space.manage,
actions.ui.get('spaces', 'manage'),
...allActions,
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/spaces/public/lib/spaces_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ export class SpacesManager extends EventEmitter {
}

public async getSpace(id: string): Promise<Space> {
return await this.httpAgent.get(`${this.baseUrl}/space/${id}`);
return await this.httpAgent
.get(`${this.baseUrl}/space/${id}`)
.then((response: IHttpResponse<Space[]>) => response.data);
}

public async createSpace(space: Space) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ test('renders without crashing', () => {
},
editable: true,
onChange: jest.fn(),
validator: new SpaceValidator({ features: [] }),
validator: new SpaceValidator(),
};
const wrapper = shallowWithIntl(
<SpaceIdentifier.WrappedComponent {...props} intl={null as any} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

jest.mock('ui/kfetch', () => ({
kfetch: () => Promise.resolve([{ id: 'foo', name: 'foo', app: [], privileges: {} }]),
}));
import { EuiButton, EuiLink, EuiSwitch } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
import React from 'react';
Expand All @@ -19,11 +21,9 @@ const space = {
name: 'My Space',
disabledFeatures: [],
};
const buildMockChrome = () => {
return {
addBasePath: (path: string) => path,
};
};
const buildMockChrome = () => ({
addBasePath: (path: string) => path,
});

describe('ManageSpacePage', () => {
it('allows a space to be created', async () => {
Expand All @@ -44,10 +44,12 @@ describe('ManageSpacePage', () => {
<ManageSpacePage.WrappedComponent
spacesManager={spacesManager}
spacesNavState={spacesNavState}
features={[{ id: 'foo', name: 'foo', app: [], privileges: {} }]}
intl={null as any}
/>
);

await waitForDataLoad(wrapper);

const nameInput = wrapper.find('input[name="name"]');
const descriptionInput = wrapper.find('textarea[name="description"]');

Expand All @@ -70,8 +72,8 @@ describe('ManageSpacePage', () => {

it('allows a space to be updated', async () => {
const mockHttp = {
get: jest.fn(async () => {
return Promise.resolve({
get: jest.fn(async () =>
Promise.resolve({
data: {
id: 'existing-space',
name: 'Existing Space',
Expand All @@ -80,8 +82,8 @@ describe('ManageSpacePage', () => {
initials: 'AB',
disabledFeatures: [],
},
});
}),
})
),
delete: jest.fn(() => Promise.resolve()),
};
const mockChrome = buildMockChrome();
Expand All @@ -99,12 +101,11 @@ describe('ManageSpacePage', () => {
spaceId={'existing-space'}
spacesManager={spacesManager}
spacesNavState={spacesNavState}
features={[{ id: 'foo', name: 'foo', app: [], privileges: {} }]}
intl={null as any}
/>
);

await Promise.resolve();
await waitForDataLoad(wrapper);

expect(mockHttp.get).toHaveBeenCalledWith('/api/spaces/space/existing-space');

Expand All @@ -128,8 +129,8 @@ describe('ManageSpacePage', () => {

it('warns when updating features in the active space', async () => {
const mockHttp = {
get: jest.fn(async () => {
return Promise.resolve({
get: jest.fn(async () =>
Promise.resolve({
data: {
id: 'my-space',
name: 'Existing Space',
Expand All @@ -138,8 +139,8 @@ describe('ManageSpacePage', () => {
initials: 'AB',
disabledFeatures: [],
},
});
}),
})
),
delete: jest.fn(() => Promise.resolve()),
};
const mockChrome = buildMockChrome();
Expand All @@ -157,12 +158,11 @@ describe('ManageSpacePage', () => {
spaceId={'my-space'}
spacesManager={spacesManager}
spacesNavState={spacesNavState}
features={[{ id: 'foo', name: 'foo', app: [], privileges: {} }]}
intl={null as any}
/>
);

await Promise.resolve();
await waitForDataLoad(wrapper);

expect(mockHttp.get).toHaveBeenCalledWith('/api/spaces/space/my-space');

Expand Down Expand Up @@ -195,8 +195,8 @@ describe('ManageSpacePage', () => {

it('does not warn when features are left alone in the active space', async () => {
const mockHttp = {
get: jest.fn(async () => {
return Promise.resolve({
get: jest.fn(async () =>
Promise.resolve({
data: {
id: 'my-space',
name: 'Existing Space',
Expand All @@ -205,8 +205,8 @@ describe('ManageSpacePage', () => {
initials: 'AB',
disabledFeatures: [],
},
});
}),
})
),
delete: jest.fn(() => Promise.resolve()),
};
const mockChrome = buildMockChrome();
Expand All @@ -224,12 +224,11 @@ describe('ManageSpacePage', () => {
spaceId={'my-space'}
spacesManager={spacesManager}
spacesNavState={spacesNavState}
features={[{ id: 'foo', name: 'foo', app: [], privileges: {} }]}
intl={null as any}
/>
);

await Promise.resolve();
await waitForDataLoad(wrapper);

expect(mockHttp.get).toHaveBeenCalledWith('/api/spaces/space/my-space');

Expand Down Expand Up @@ -286,3 +285,9 @@ async function clickSaveButton(wrapper: ReactWrapper<any, any>) {

wrapper.update();
}

async function waitForDataLoad(wrapper: ReactWrapper<any, any>) {
await Promise.resolve();
await Promise.resolve();
wrapper.update();
}
Loading