Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ exports[`it renders without blowing up 1`] = `
onClick={[Function]}
type="button"
>
hide
<FormattedMessage
defaultMessage="hide"
id="xpack.security.management.editRole.collapsiblePanel.hideLinkText"
values={Object {}}
/>
</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
*/

import { EuiLink } from '@elastic/eui';
import { mount, shallow } from 'enzyme';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
import { CollapsiblePanel } from './collapsible_panel';

test('it renders without blowing up', () => {
const wrapper = shallow(
const wrapper = shallowWithIntl(
<CollapsiblePanel iconType="logoElasticsearch" title="Elasticsearch">
<p>child</p>
</CollapsiblePanel>
Expand All @@ -20,7 +20,7 @@ test('it renders without blowing up', () => {
});

test('it renders children by default', () => {
const wrapper = mount(
const wrapper = mountWithIntl(
<CollapsiblePanel iconType="logoElasticsearch" title="Elasticsearch">
<p className="child">child 1</p>
<p className="child">child 2</p>
Expand All @@ -32,7 +32,7 @@ test('it renders children by default', () => {
});

test('it hides children when the "hide" link is clicked', () => {
const wrapper = mount(
const wrapper = mountWithIntl(
<CollapsiblePanel iconType="logoElasticsearch" title="Elasticsearch">
<p className="child">child 1</p>
<p className="child">child 2</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EuiSpacer,
EuiTitle,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';

interface Props {
Expand Down Expand Up @@ -55,7 +56,19 @@ export class CollapsiblePanel extends Component<Props, State> {
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiLink onClick={this.toggleCollapsed}>{this.state.collapsed ? 'show' : 'hide'}</EuiLink>
<EuiLink onClick={this.toggleCollapsed}>
{this.state.collapsed ? (
<FormattedMessage
id="xpack.security.management.editRole.collapsiblePanel.showLinkText"
defaultMessage="show"
/>
) : (
<FormattedMessage
id="xpack.security.management.editRole.collapsiblePanel.hideLinkText"
defaultMessage="hide"
/>
)}
</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import {
// @ts-ignore
EuiConfirmModal,
} from '@elastic/eui';
import { mount, shallow } from 'enzyme';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
import { DeleteRoleButton } from './delete_role_button';

test('it renders without crashing', () => {
const deleteHandler = jest.fn();
const wrapper = shallow(<DeleteRoleButton canDelete={true} onDelete={deleteHandler} />);
const wrapper = shallowWithIntl(<DeleteRoleButton canDelete={true} onDelete={deleteHandler} />);
expect(wrapper.find(EuiButtonEmpty)).toHaveLength(1);
expect(deleteHandler).toHaveBeenCalledTimes(0);
});

test('it shows a confirmation dialog when clicked', () => {
const deleteHandler = jest.fn();
const wrapper = mount(<DeleteRoleButton canDelete={true} onDelete={deleteHandler} />);
const wrapper = mountWithIntl(<DeleteRoleButton canDelete={true} onDelete={deleteHandler} />);

wrapper.find(EuiButtonEmpty).simulate('click');

Expand All @@ -33,7 +33,7 @@ test('it shows a confirmation dialog when clicked', () => {

test('it renders nothing when canDelete is false', () => {
const deleteHandler = jest.fn();
const wrapper = shallow(<DeleteRoleButton canDelete={false} onDelete={deleteHandler} />);
const wrapper = shallowWithIntl(<DeleteRoleButton canDelete={false} onDelete={deleteHandler} />);
expect(wrapper.find('*')).toHaveLength(0);
expect(deleteHandler).toHaveBeenCalledTimes(0);
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
// @ts-ignore
EuiOverlayMask,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';

interface Props {
Expand All @@ -35,7 +36,10 @@ export class DeleteRoleButton extends Component<Props, State> {
return (
<Fragment>
<EuiButtonEmpty color={'danger'} onClick={this.showModal}>
Delete role
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.deleteRoleButtonLabel"
defaultMessage="Delete role"
/>
</EuiButtonEmpty>
{this.maybeShowModal()}
</Fragment>
Expand All @@ -49,15 +53,40 @@ export class DeleteRoleButton extends Component<Props, State> {
return (
<EuiOverlayMask>
<EuiConfirmModal
title={'Delete Role'}
title={
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.deleteRoleTitle"
defaultMessage="Delete Role"
/>
}
onCancel={this.closeModal}
onConfirm={this.onConfirmDelete}
cancelButtonText={"No, don't delete"}
confirmButtonText={'Yes, delete role'}
cancelButtonText={
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.cancelButtonLabel"
defaultMessage="No, don't delete"
/>
}
confirmButtonText={
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.confirmButtonLabel"
defaultMessage="Yes, delete role"
/>
}
buttonColor={'danger'}
>
<p>Are you sure you want to delete this role?</p>
<p>This action cannot be undone!</p>
<p>
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.deletingRoleConfirmationText"
defaultMessage="Are you sure you want to delete this role?"
/>
</p>
<p>
<FormattedMessage
id="xpack.security.management.editRoles.deleteRoleButton.deletingRoleWarningText"
defaultMessage="This action cannot be undone!"
/>
</p>
</EuiConfirmModal>
</EuiOverlayMask>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import {
EuiButton,
EuiButtonEmpty,
Expand All @@ -19,6 +20,7 @@ import {
EuiText,
EuiTitle,
} from '@elastic/eui';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import { get } from 'lodash';
import React, { ChangeEvent, Component, Fragment, HTMLProps } from 'react';
import { toastNotifications } from 'ui/notify';
Expand Down Expand Up @@ -47,14 +49,15 @@ interface Props {
spaces?: Space[];
spacesEnabled: boolean;
userProfile: UserProfile;
intl: InjectedIntl;
}

interface State {
role: Role;
formError: RoleValidationResult | null;
}

export class EditRolePage extends Component<Props, State> {
class EditRolePageUI extends Component<Props, State> {
private validator: RoleValidator;

constructor(props: Props) {
Expand All @@ -67,9 +70,17 @@ export class EditRolePage extends Component<Props, State> {
}

public render() {
const description = this.props.spacesEnabled
? `Set privileges on your Elasticsearch data and control access to your Kibana spaces.`
: `Set privileges on your Elasticsearch data and control access to Kibana.`;
const description = this.props.spacesEnabled ? (
<FormattedMessage
id="xpack.security.management.editRole.setPrivilegesToKibanaSpacesDescription"
defaultMessage="Set privileges on your Elasticsearch data and control access to your Kibana spaces."
/>
) : (
<FormattedMessage
id="xpack.security.management.editRole.setPrivilegesToKibanaDescription"
defaultMessage="Set privileges on your Elasticsearch data and control access to Kibana."
/>
);

return (
<EuiPage className="editRolePage" restrictWidth>
Expand All @@ -86,7 +97,10 @@ export class EditRolePage extends Component<Props, State> {
<EuiSpacer size="s" />
<EuiText size="s" color="subdued">
<p id="reservedRoleDescription" tabIndex={1}>
Reserved roles are built-in and cannot be removed or modified.
<FormattedMessage
id="xpack.security.management.editRole.modifyingReversedRolesDescription"
defaultMessage="Reserved roles are built-in and cannot be removed or modified."
/>
</p>
</EuiText>
</Fragment>
Expand Down Expand Up @@ -115,12 +129,27 @@ export class EditRolePage extends Component<Props, State> {
tabIndex: 0,
};
if (isReservedRole(this.props.role)) {
titleText = 'Viewing role';
titleText = (
<FormattedMessage
id="xpack.security.management.editRole.viewingRoleTitle"
defaultMessage="Viewing role"
/>
);
props['aria-describedby'] = 'reservedRoleDescription';
} else if (this.editingExistingRole()) {
titleText = 'Edit role';
titleText = (
<FormattedMessage
id="xpack.security.management.editRole.editRoleTitle"
defaultMessage="Edit role"
/>
);
} else {
titleText = 'Create role';
titleText = (
<FormattedMessage
id="xpack.security.management.editRole.createRoleTitle"
defaultMessage="Create role"
/>
);
}

return (
Expand Down Expand Up @@ -148,11 +177,21 @@ export class EditRolePage extends Component<Props, State> {
return (
<EuiPanel>
<EuiFormRow
label={'Role name'}
label={
<FormattedMessage
id="xpack.security.management.editRole.roleNameFormRowTitle"
defaultMessage="Role name"
/>
}
helpText={
!isReservedRole(this.props.role) && this.editingExistingRole()
? "A role's name cannot be changed once it has been created."
: undefined
!isReservedRole(this.props.role) && this.editingExistingRole() ? (
<FormattedMessage
id="xpack.security.management.editRole.roleNameFormRowHelpText"
defaultMessage="A role's name cannot be changed once it has been created."
/>
) : (
undefined
)
}
{...this.validator.validateRoleName(this.state.role)}
>
Expand Down Expand Up @@ -225,10 +264,27 @@ export class EditRolePage extends Component<Props, State> {

public getFormButtons = () => {
if (isReservedRole(this.props.role)) {
return <EuiButton onClick={this.backToRoleList}>Return to role list</EuiButton>;
return (
<EuiButton onClick={this.backToRoleList}>
<FormattedMessage
id="xpack.security.management.editRole.returnToRoleListButtonLabel"
defaultMessage="Return to role list"
/>
</EuiButton>
);
}

const saveText = this.editingExistingRole() ? 'Update role' : 'Create role';
const saveText = this.editingExistingRole() ? (
<FormattedMessage
id="xpack.security.management.editRole.updateRoleText"
defaultMessage="Update role"
/>
) : (
<FormattedMessage
id="xpack.security.management.editRole.createRoleText"
defaultMessage="Create role"
/>
);

return (
<EuiFlexGroup responsive={false}>
Expand All @@ -244,7 +300,10 @@ export class EditRolePage extends Component<Props, State> {
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty data-test-subj={`roleFormCancelButton`} onClick={this.backToRoleList}>
Cancel
<FormattedMessage
id="xpack.security.management.editRole.cancelButtonLabel"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={true} />
Expand Down Expand Up @@ -274,7 +333,7 @@ export class EditRolePage extends Component<Props, State> {
formError: null,
});

const { httpClient } = this.props;
const { httpClient, intl } = this.props;

const role = {
...this.state.role,
Expand All @@ -287,7 +346,12 @@ export class EditRolePage extends Component<Props, State> {

saveRole(httpClient, role)
.then(() => {
toastNotifications.addSuccess('Saved role');
toastNotifications.addSuccess(
intl.formatMessage({
id: 'xpack.security.management.editRole.roleSuccessfullySavedNotificationMessage',
defaultMessage: 'Saved role',
})
);
this.backToRoleList();
})
.catch((error: any) => {
Expand All @@ -297,11 +361,16 @@ export class EditRolePage extends Component<Props, State> {
};

public handleDeleteRole = () => {
const { httpClient, role } = this.props;
const { httpClient, role, intl } = this.props;

deleteRole(httpClient, role.name)
.then(() => {
toastNotifications.addSuccess('Deleted role');
toastNotifications.addSuccess(
intl.formatMessage({
id: 'xpack.security.management.editRole.roleSuccessfullyDeletedNotificationMessage',
defaultMessage: 'Deleted role',
})
);
this.backToRoleList();
})
.catch((error: any) => {
Expand All @@ -313,3 +382,5 @@ export class EditRolePage extends Component<Props, State> {
window.location.hash = ROLES_PATH;
};
}

export const EditRolePage = injectI18n(EditRolePageUI);
Loading