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

Account Management: Create API keys #82005

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bbea19f
Account Management: Create API keys
thomheymann Oct 28, 2020
fc4dce5
Apply suggestions from code review
thomheymann Oct 30, 2020
19e0380
Added suggestions from code review
thomheymann Nov 2, 2020
1fc64ab
Apply suggestions from code review
thomheymann Nov 2, 2020
cbdb663
Merge remote-tracking branch 'origin/security/create-api-key' into se…
thomheymann Nov 2, 2020
ad3907e
Updated lock file and create route handler
thomheymann Nov 2, 2020
d1906c1
Fixed test failures
thomheymann Nov 2, 2020
e5e2d76
Fixed unit test and prettier errors
thomheymann Nov 2, 2020
8a7705e
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 2, 2020
5bb6813
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 4, 2020
325a21c
Added suggestions from code review
thomheymann Nov 5, 2020
ef4b6e4
Fixed types in tests
thomheymann Nov 6, 2020
37c5f8c
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 6, 2020
6dd9fa1
Fix test failure
thomheymann Nov 6, 2020
4f50010
Added e2e tests
thomheymann Nov 9, 2020
d6d3c0c
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 9, 2020
dad4664
Fix linting errors
thomheymann Nov 9, 2020
aeb0662
Added link to account management
thomheymann Nov 10, 2020
fe64fd9
Fixed translations
thomheymann Nov 10, 2020
9f36566
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 10, 2020
eec51bf
Merge remote-tracking branch 'origin/master' into security/create-api…
thomheymann Nov 11, 2020
16848fb
Remove unused eslint disable
thomheymann Nov 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@
"react-resizable": "^1.7.5",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-use": "^13.27.0",
"react-use": "^15.3.4",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@streamich any concerns with updating react-use from 13.27 to 15.3?

"recompose": "^0.26.0",
"redux": "^4.0.5",
"redux-actions": "^2.6.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,12 @@ test('can display string element as title', () => {
expect(notifications.toasts.add).toHaveBeenCalledTimes(1);
expect(notifications.toasts.add.mock.calls[0][0]).toMatchInlineSnapshot(`
Object {
"color": undefined,
"iconType": undefined,
"onClose": undefined,
"text": MountPoint {
"reactNode": <React.Fragment />,
},
"title": MountPoint {
"reactNode": "foo",
},
"toastLifeTimeMs": undefined,
}
`);
});
Expand Down Expand Up @@ -120,7 +116,6 @@ test('can set toast properties', () => {
Object {
"color": "danger",
"iconType": "foo",
"onClose": undefined,
"text": MountPoint {
"reactNode": <React.Fragment>
1
Expand All @@ -147,42 +142,36 @@ test('can display success, warning and danger toasts', () => {
Object {
"color": "success",
"iconType": "check",
"onClose": undefined,
"text": MountPoint {
"reactNode": <React.Fragment />,
},
"title": MountPoint {
"reactNode": "1",
},
"toastLifeTimeMs": undefined,
}
`);
expect(notifications.toasts.add.mock.calls[1][0]).toMatchInlineSnapshot(`
Object {
"color": "warning",
"iconType": "help",
"onClose": undefined,
"text": MountPoint {
"reactNode": <React.Fragment />,
},
"title": MountPoint {
"reactNode": "2",
},
"toastLifeTimeMs": undefined,
}
`);
expect(notifications.toasts.add.mock.calls[2][0]).toMatchInlineSnapshot(`
Object {
"color": "danger",
"iconType": "alert",
"onClose": undefined,
"text": MountPoint {
"reactNode": <React.Fragment />,
},
"title": MountPoint {
"reactNode": "3",
},
"toastLifeTimeMs": undefined,
}
`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,14 @@ import { KibanaReactNotifications } from './types';
import { toMountPoint } from '../util';

export const createNotifications = (services: KibanaServices): KibanaReactNotifications => {
const show: KibanaReactNotifications['toasts']['show'] = ({
title,
body,
color,
iconType,
toastLifeTimeMs,
onClose,
}) => {
const show: KibanaReactNotifications['toasts']['show'] = ({ title, body, ...rest }) => {
if (!services.notifications) {
throw new TypeError('Could not show notification as notifications service is not available.');
}
services.notifications!.toasts.add({
title: toMountPoint(title),
text: toMountPoint(<>{body || null}</>),
color,
iconType,
toastLifeTimeMs,
onClose,
...rest,
});
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FunctionComponent } from 'react';
import { ChangePassword } from './change_password';
import { PersonalInfo } from './personal_info';
import { AuthenticatedUser } from '../../../common/model';
import { UserAPIClient } from '../../management';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { NotificationsSetup } from '../../../../../../src/core/public';

export interface AccountDetailsPageProps {
user: AuthenticatedUser;
notifications: NotificationsSetup;
}

export const AccountDetailsPage: FunctionComponent<AccountDetailsPageProps> = ({
user,
notifications,
}) => {
const { services } = useKibana();
const userAPIClient = new UserAPIClient(services.http!);

return (
<>
<PersonalInfo user={user} />
<ChangePassword user={user} userAPIClient={userAPIClient} notifications={notifications} />
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

export { AccountDetailsPage as default } from './account_details_page'; // eslint-disable-line import/no-default-export
export { ChangePassword } from './change_password';
export { PersonalInfo } from './personal_info';
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { EuiDescribedFormGroup, EuiFormRow, EuiText } from '@elastic/eui';
import {
EuiDescribedFormGroup,
EuiDescriptionList,
EuiDescriptionListTitle,
EuiDescriptionListDescription,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { AuthenticatedUser } from '../../../common/model';

Expand All @@ -31,23 +36,19 @@ export const PersonalInfo = (props: Props) => {
/>
}
>
<EuiFormRow fullWidth>
<EuiText size="s">
<dl>
<dt title="username" data-test-subj="username">
{props.user.username}
</dt>
<dd title="email" data-test-subj="email">
{props.user.email || (
<FormattedMessage
id="xpack.security.account.noEmailMessage"
defaultMessage="no email address"
/>
)}
</dd>
</dl>
</EuiText>
</EuiFormRow>
<EuiDescriptionList>
<EuiDescriptionListTitle title="username" data-test-subj="username">
{props.user.username}
</EuiDescriptionListTitle>
<EuiDescriptionListDescription title="email" data-test-subj="email">
{props.user.email || (
<FormattedMessage
id="xpack.security.account.noEmailMessage"
defaultMessage="No email address"
/>
)}
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiDescribedFormGroup>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import ReactDOM from 'react-dom';
import { act, screen, fireEvent } from '@testing-library/react';
import { AppMount, AppNavLinkStatus, ScopedHistory } from '../../../../../src/core/public';
import { coreMock } from '../../../../../src/core/public/mocks';
import { mockAuthenticatedUser } from '../../common/model/authenticated_user.mock';
import { securityMock } from '../mocks';
import { accountManagementApp } from './account_management_app';
import { createMemoryHistory } from 'history';

describe('accountManagementApp', () => {
it('registers application', () => {
const { application, getStartServices } = coreMock.createSetup();
const { authc } = securityMock.createSetup();
accountManagementApp.create({ application, getStartServices, authc });
expect(application.register).toHaveBeenLastCalledWith({
id: 'security_account',
appRoute: '/security/account',
navLinkStatus: AppNavLinkStatus.hidden,
title: 'Account Management',
mount: expect.any(Function),
});
});

it('renders application and sets breadcrumbs', async () => {
const { application, getStartServices } = coreMock.createSetup();
const coreStartMock = coreMock.createStart();
getStartServices.mockResolvedValue([coreStartMock, {}, {}]);
const { authc } = securityMock.createSetup();
authc.getCurrentUser.mockResolvedValue(
mockAuthenticatedUser({ username: 'some-user', full_name: undefined })
);
accountManagementApp.create({ application, getStartServices, authc });
const [[{ mount }]] = application.register.mock.calls;
const element = document.body.appendChild(document.createElement('div'));

await act(async () => {
await (mount as AppMount)({
element,
appBasePath: '',
onAppLeave: jest.fn(),
setHeaderActionMenu: jest.fn(),
history: (createMemoryHistory() as unknown) as ScopedHistory,
});
});
expect(coreStartMock.chrome.setBreadcrumbs).toHaveBeenLastCalledWith([
expect.objectContaining({ text: 'Account Management' }),
]);

fireEvent.click(screen.getByRole('tab', { name: 'API Keys' }));
expect(coreStartMock.chrome.setBreadcrumbs).toHaveBeenLastCalledWith([
expect.objectContaining({ text: 'Account Management' }),
expect.objectContaining({ text: 'API Keys' }),
]);

// Need to cleanup manually since `mount` renders the app straight to the DOM
ReactDOM.unmountComponentAtNode(element);
document.body.removeChild(element);
});
});

This file was deleted.

Loading