Skip to content

Commit a28d980

Browse files
feat: [UIE-9722] - IAM: disable cards for linode create (#13142)
* feat: [UIE-9722] - IAM: disable cards * Added changeset: IAM: disable/enable fields based on create_linode permission
1 parent 5050b3a commit a28d980

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Fixed
3+
---
4+
5+
IAM: disable/enable fields based on create_linode permission ([#13142](https://github.com/linode/manager/pull/13142))

packages/manager/src/features/Linodes/LinodeCreate/Tabs/Marketplace/AppSelect.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import React, { useState } from 'react';
1111
import { useFormContext } from 'react-hook-form';
1212

1313
import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField';
14+
import { usePermissions } from 'src/features/IAM/hooks/usePermissions';
1415

1516
import { AppsList } from './AppsList';
1617
import { categoryOptions } from './utilities';
@@ -37,6 +38,8 @@ export const AppSelect = (props: Props) => {
3738
const [query, setQuery] = useState('');
3839
const [category, setCategory] = useState<AppCategory>();
3940

41+
const { data: permissions } = usePermissions('account', ['create_linode']);
42+
4043
return (
4144
<Paper>
4245
<Stack spacing={2}>
@@ -47,7 +50,7 @@ export const AppSelect = (props: Props) => {
4750
<Stack direction="row" flexWrap="wrap" gap={1}>
4851
<DebouncedSearchTextField
4952
containerProps={{ flexGrow: 1 }}
50-
disabled={isLoading}
53+
disabled={isLoading || !permissions?.create_linode}
5154
fullWidth
5255
hideLabel
5356
inputSlotProps={{ sx: { maxWidth: 'unset !important' } }}
@@ -59,7 +62,7 @@ export const AppSelect = (props: Props) => {
5962
value={query}
6063
/>
6164
<Autocomplete
62-
disabled={isLoading}
65+
disabled={isLoading || !permissions?.create_linode}
6366
label="Select category"
6467
onChange={(e, value) => setCategory(value?.label)}
6568
options={categoryOptions}

packages/manager/src/features/Linodes/LinodeCreate/Tabs/Marketplace/AppSelectionCard.test.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ import { renderWithTheme } from 'src/utilities/testHelpers';
55

66
import { AppSelectionCard } from './AppSelectionCard';
77

8+
const queryMocks = vi.hoisted(() => ({
9+
userPermissions: vi.fn(() => ({
10+
data: {
11+
create_linode: true,
12+
},
13+
})),
14+
}));
15+
vi.mock('src/features/IAM/hooks/usePermissions', () => ({
16+
usePermissions: queryMocks.userPermissions,
17+
}));
18+
819
describe('AppSelectionCard', () => {
920
it('Should render an a label', () => {
1021
const { getByText } = renderWithTheme(
@@ -56,4 +67,38 @@ describe('AppSelectionCard', () => {
5667
expect(onOpenDetailsDrawer).toHaveBeenCalled();
5768
expect(onSelect).not.toHaveBeenCalled();
5869
});
70+
71+
it('should enable the card when user has create_linode permission', async () => {
72+
const { getByTestId } = renderWithTheme(
73+
<AppSelectionCard
74+
checked={false}
75+
iconUrl={''}
76+
label="MySQL"
77+
onOpenDetailsDrawer={vi.fn()}
78+
onSelect={vi.fn()}
79+
/>
80+
);
81+
82+
expect(getByTestId('selection-card')).toBeEnabled();
83+
});
84+
85+
it('should disable the card when user does not have create_linode permission', async () => {
86+
queryMocks.userPermissions.mockReturnValue({
87+
data: {
88+
create_linode: false,
89+
},
90+
});
91+
92+
const { getByTestId } = renderWithTheme(
93+
<AppSelectionCard
94+
checked={false}
95+
iconUrl={''}
96+
label="MySQL"
97+
onOpenDetailsDrawer={vi.fn()}
98+
onSelect={vi.fn()}
99+
/>
100+
);
101+
102+
expect(getByTestId('selection-card')).toBeDisabled();
103+
});
59104
});

packages/manager/src/features/Linodes/LinodeCreate/Tabs/Marketplace/AppSelectionCard.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as React from 'react';
44

55
import Info from 'src/assets/icons/info.svg';
66
import { SelectionCard } from 'src/components/SelectionCard/SelectionCard';
7+
import { usePermissions } from 'src/features/IAM/hooks/usePermissions';
78

89
import { getMarketplaceAppLabel } from './utilities';
910

@@ -34,6 +35,8 @@ interface Props {
3435
export const AppSelectionCard = (props: Props) => {
3536
const { checked, iconUrl, label, onOpenDetailsDrawer, onSelect } = props;
3637

38+
const { data: permissions } = usePermissions('account', ['create_linode']);
39+
3740
const handleInfoClick = (e: React.MouseEvent) => {
3841
e.stopPropagation();
3942
e.preventDefault();
@@ -73,6 +76,7 @@ export const AppSelectionCard = (props: Props) => {
7376
return (
7477
<SelectionCard
7578
checked={checked}
79+
disabled={!permissions?.create_linode}
7680
heading={displayLabel}
7781
headingDecoration={headingDecoration}
7882
onClick={onSelect}

0 commit comments

Comments
 (0)