Skip to content

Commit 3fcf8b3

Browse files
committed
disabling buttons when user does not permission
1 parent aecee92 commit 3fcf8b3

File tree

3 files changed

+122
-28
lines changed

3 files changed

+122
-28
lines changed

x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,19 @@
66
import React from 'react';
77
import { EuiButton } from '@elastic/eui';
88
import { i18n } from '@kbn/i18n';
9+
import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context';
910

1011
export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) {
12+
const { core } = useApmPluginContext();
13+
const canSave = core.application.capabilities.apm.save;
1114
return (
12-
<EuiButton color="primary" fill iconType="plusInCircle" onClick={onClick}>
15+
<EuiButton
16+
color="primary"
17+
fill
18+
iconType="plusInCircle"
19+
onClick={onClick}
20+
isDisabled={!canSave}
21+
>
1322
{i18n.translate(
1423
'xpack.apm.settings.customizeUI.customLink.createCustomLink',
1524
{ defaultMessage: 'Create custom link' }

x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkTable.tsx

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
EuiSpacer,
1414
} from '@elastic/eui';
1515
import { isEmpty } from 'lodash';
16+
import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context';
1617
import { CustomLink } from '../../../../../../common/custom_link/custom_link_types';
1718
import { units, px } from '../../../../../style/variables';
1819
import { ManagedTable } from '../../../../shared/ManagedTable';
@@ -26,6 +27,8 @@ interface Props {
2627

2728
export function CustomLinkTable({ items = [], onCustomLinkSelected }: Props) {
2829
const [searchTerm, setSearchTerm] = useState('');
30+
const { core } = useApmPluginContext();
31+
const canSave = core.application.capabilities.apm.save;
2932

3033
const columns = [
3134
{
@@ -61,22 +64,26 @@ export function CustomLinkTable({ items = [], onCustomLinkSelected }: Props) {
6164
width: px(units.triple),
6265
name: '',
6366
actions: [
64-
{
65-
name: i18n.translate(
66-
'xpack.apm.settings.customizeUI.customLink.table.editButtonLabel',
67-
{ defaultMessage: 'Edit' }
68-
),
69-
description: i18n.translate(
70-
'xpack.apm.settings.customizeUI.customLink.table.editButtonDescription',
71-
{ defaultMessage: 'Edit this custom link' }
72-
),
73-
icon: 'pencil',
74-
color: 'primary',
75-
type: 'icon',
76-
onClick: (customLink: CustomLink) => {
77-
onCustomLinkSelected(customLink);
78-
},
79-
},
67+
...(canSave
68+
? [
69+
{
70+
name: i18n.translate(
71+
'xpack.apm.settings.customizeUI.customLink.table.editButtonLabel',
72+
{ defaultMessage: 'Edit' }
73+
),
74+
description: i18n.translate(
75+
'xpack.apm.settings.customizeUI.customLink.table.editButtonDescription',
76+
{ defaultMessage: 'Edit this custom link' }
77+
),
78+
icon: 'pencil',
79+
color: 'primary',
80+
type: 'icon',
81+
onClick: (customLink: CustomLink) => {
82+
onCustomLinkSelected(customLink);
83+
},
84+
},
85+
]
86+
: []),
8087
],
8188
},
8289
];

x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@
77
import {
88
fireEvent,
99
render,
10-
waitFor,
1110
RenderResult,
11+
waitFor,
1212
} from '@testing-library/react';
1313
import React from 'react';
1414
import { act } from 'react-dom/test-utils';
15-
import * as apmApi from '../../../../../services/rest/createCallApmApi';
15+
import { CustomLinkOverview } from '.';
1616
import { License } from '../../../../../../../licensing/common/license';
17-
import * as hooks from '../../../../../hooks/use_fetcher';
17+
import { ApmPluginContextValue } from '../../../../../context/apm_plugin/apm_plugin_context';
18+
import {
19+
mockApmPluginContextValue,
20+
MockApmPluginContextWrapper,
21+
} from '../../../../../context/apm_plugin/mock_apm_plugin_context';
1822
import { LicenseContext } from '../../../../../context/license/license_context';
19-
import { CustomLinkOverview } from '.';
23+
import * as hooks from '../../../../../hooks/use_fetcher';
24+
import * as apmApi from '../../../../../services/rest/createCallApmApi';
2025
import {
2126
expectTextsInDocument,
2227
expectTextsNotInDocument,
2328
} from '../../../../../utils/testHelpers';
2429
import * as saveCustomLink from './CreateEditCustomLinkFlyout/saveCustomLink';
25-
import { MockApmPluginContextWrapper } from '../../../../../context/apm_plugin/mock_apm_plugin_context';
2630

2731
const data = [
2832
{
@@ -39,6 +43,16 @@ const data = [
3943
},
4044
];
4145

46+
function getMockAPMContext({ canSave }: { canSave: boolean }) {
47+
return ({
48+
...mockApmPluginContextValue,
49+
core: {
50+
...mockApmPluginContextValue.core,
51+
application: { capabilities: { apm: { save: canSave }, ml: {} } },
52+
},
53+
} as unknown) as ApmPluginContextValue;
54+
}
55+
4256
describe('CustomLink', () => {
4357
beforeAll(() => {
4458
jest.spyOn(apmApi, 'callApmApi').mockResolvedValue({});
@@ -70,9 +84,11 @@ describe('CustomLink', () => {
7084
});
7185
it('shows when no link is available', () => {
7286
const component = render(
73-
<LicenseContext.Provider value={goldLicense}>
74-
<CustomLinkOverview />
75-
</LicenseContext.Provider>
87+
<MockApmPluginContextWrapper>
88+
<LicenseContext.Provider value={goldLicense}>
89+
<CustomLinkOverview />
90+
</LicenseContext.Provider>
91+
</MockApmPluginContextWrapper>
7692
);
7793
expectTextsInDocument(component, ['No links found.']);
7894
});
@@ -91,6 +107,34 @@ describe('CustomLink', () => {
91107
jest.clearAllMocks();
92108
});
93109

110+
it('enables create button when user has writte privileges', () => {
111+
const mockContext = getMockAPMContext({ canSave: true });
112+
113+
const { getByTestId } = render(
114+
<LicenseContext.Provider value={goldLicense}>
115+
<MockApmPluginContextWrapper value={mockContext}>
116+
<CustomLinkOverview />
117+
</MockApmPluginContextWrapper>
118+
</LicenseContext.Provider>
119+
);
120+
const createButton = getByTestId('createButton') as HTMLButtonElement;
121+
expect(createButton.disabled).toBeFalsy();
122+
});
123+
124+
it('enables edit button on custom link table when user has writte privileges', () => {
125+
const mockContext = getMockAPMContext({ canSave: true });
126+
127+
const { getAllByText } = render(
128+
<LicenseContext.Provider value={goldLicense}>
129+
<MockApmPluginContextWrapper value={mockContext}>
130+
<CustomLinkOverview />
131+
</MockApmPluginContextWrapper>
132+
</LicenseContext.Provider>
133+
);
134+
135+
expect(getAllByText('Edit').length).toEqual(2);
136+
});
137+
94138
it('shows a table with all custom link', () => {
95139
const component = render(
96140
<LicenseContext.Provider value={goldLicense}>
@@ -108,9 +152,11 @@ describe('CustomLink', () => {
108152
});
109153

110154
it('checks if create custom link button is available and working', () => {
155+
const mockContext = getMockAPMContext({ canSave: true });
156+
111157
const { queryByText, getByText } = render(
112158
<LicenseContext.Provider value={goldLicense}>
113-
<MockApmPluginContextWrapper>
159+
<MockApmPluginContextWrapper value={mockContext}>
114160
<CustomLinkOverview />
115161
</MockApmPluginContextWrapper>
116162
</LicenseContext.Provider>
@@ -137,9 +183,10 @@ describe('CustomLink', () => {
137183
});
138184

139185
const openFlyout = () => {
186+
const mockContext = getMockAPMContext({ canSave: true });
140187
const component = render(
141188
<LicenseContext.Provider value={goldLicense}>
142-
<MockApmPluginContextWrapper>
189+
<MockApmPluginContextWrapper value={mockContext}>
143190
<CustomLinkOverview />
144191
</MockApmPluginContextWrapper>
145192
</LicenseContext.Provider>
@@ -173,9 +220,10 @@ describe('CustomLink', () => {
173220
});
174221

175222
it('deletes a custom link', async () => {
223+
const mockContext = getMockAPMContext({ canSave: true });
176224
const component = render(
177225
<LicenseContext.Provider value={goldLicense}>
178-
<MockApmPluginContextWrapper>
226+
<MockApmPluginContextWrapper value={mockContext}>
179227
<CustomLinkOverview />
180228
</MockApmPluginContextWrapper>
181229
</LicenseContext.Provider>
@@ -356,4 +404,34 @@ describe('CustomLink', () => {
356404
expectTextsNotInDocument(component, ['Start free 30-day trial']);
357405
});
358406
});
407+
408+
describe('with read-only user', () => {
409+
it('disables create custom link button', () => {
410+
const mockContext = getMockAPMContext({ canSave: false });
411+
412+
const { getByTestId } = render(
413+
<LicenseContext.Provider value={goldLicense}>
414+
<MockApmPluginContextWrapper value={mockContext}>
415+
<CustomLinkOverview />
416+
</MockApmPluginContextWrapper>
417+
</LicenseContext.Provider>
418+
);
419+
const createButton = getByTestId('createButton') as HTMLButtonElement;
420+
expect(createButton.disabled).toBeTruthy();
421+
});
422+
423+
it('removes edit button on custom link table', () => {
424+
const mockContext = getMockAPMContext({ canSave: false });
425+
426+
const { queryAllByText } = render(
427+
<LicenseContext.Provider value={goldLicense}>
428+
<MockApmPluginContextWrapper value={mockContext}>
429+
<CustomLinkOverview />
430+
</MockApmPluginContextWrapper>
431+
</LicenseContext.Provider>
432+
);
433+
434+
expect(queryAllByText('Edit').length).toEqual(0);
435+
});
436+
});
359437
});

0 commit comments

Comments
 (0)