mirror of
https://github.com/strapi/strapi.git
synced 2025-11-03 19:36:20 +00:00
fix(content-releases):disable edit and delete buttons in the Details page when you don't have permissions (#19099)
* add the disable permissions and style to the edit and delete buttons * fix review comments and add unit test * fix type errors * remove useless Icon * add satisfies to define Permissions type
This commit is contained in:
parent
1832540151
commit
28dd017262
@ -1,57 +1,74 @@
|
||||
import { Permission as StrapiPermission } from '@strapi/helper-plugin';
|
||||
|
||||
type Permission = Pick<StrapiPermission, 'action' | 'subject'>;
|
||||
interface PermissionMap {
|
||||
main: Permission[];
|
||||
create: Permission[];
|
||||
update: Permission[];
|
||||
delete: Permission[];
|
||||
createAction: Permission[];
|
||||
deleteAction: Permission[];
|
||||
publish: Permission[];
|
||||
}
|
||||
|
||||
export const PERMISSIONS: PermissionMap = {
|
||||
export const PERMISSIONS = {
|
||||
main: [
|
||||
{
|
||||
action: 'plugin::content-releases.read',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
create: [
|
||||
{
|
||||
action: 'plugin::content-releases.create',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
update: [
|
||||
{
|
||||
action: 'plugin::content-releases.update',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
delete: [
|
||||
{
|
||||
action: 'plugin::content-releases.delete',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
createAction: [
|
||||
{
|
||||
action: 'plugin::content-releases.create-action',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
deleteAction: [
|
||||
{
|
||||
action: 'plugin::content-releases.delete-action',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
publish: [
|
||||
{
|
||||
action: 'plugin::content-releases.publish',
|
||||
subject: null,
|
||||
id: '',
|
||||
actionParameters: {},
|
||||
properties: {},
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
} satisfies Record<string, StrapiPermission[]>;
|
||||
|
||||
@ -26,6 +26,7 @@ import {
|
||||
useNotification,
|
||||
useQueryParams,
|
||||
ConfirmDialog,
|
||||
useRBAC,
|
||||
} from '@strapi/helper-plugin';
|
||||
import { ArrowLeft, EmptyDocuments, More, Pencil, Trash } from '@strapi/icons';
|
||||
import { useIntl } from 'react-intl';
|
||||
@ -58,8 +59,16 @@ const ReleaseInfoWrapper = styled(Flex)`
|
||||
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
||||
`;
|
||||
|
||||
const StyledFlex = styled(Flex)`
|
||||
const StyledFlex = styled(Flex)<{ disabled?: boolean }>`
|
||||
align-self: stretch;
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
|
||||
svg path {
|
||||
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
||||
}
|
||||
span {
|
||||
color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
||||
}
|
||||
`;
|
||||
|
||||
const PencilIcon = styled(Pencil)`
|
||||
@ -80,10 +89,11 @@ const TrashIcon = styled(Trash)`
|
||||
|
||||
interface PopoverButtonProps {
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
disabled?: boolean;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const PopoverButton = ({ onClick, children }: PopoverButtonProps) => {
|
||||
const PopoverButton = ({ onClick, disabled, children }: PopoverButtonProps) => {
|
||||
return (
|
||||
<StyledFlex
|
||||
paddingTop={2}
|
||||
@ -95,6 +105,7 @@ const PopoverButton = ({ onClick, children }: PopoverButtonProps) => {
|
||||
as="button"
|
||||
hasRadius
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
</StyledFlex>
|
||||
@ -120,6 +131,9 @@ export const ReleaseDetailsLayout = ({
|
||||
const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
|
||||
const toggleNotification = useNotification();
|
||||
const { formatAPIError } = useAPIErrorHandler();
|
||||
const {
|
||||
allowedActions: { canUpdate, canDelete },
|
||||
} = useRBAC(PERMISSIONS);
|
||||
|
||||
const release = data?.data;
|
||||
|
||||
@ -224,28 +238,24 @@ export const ReleaseDetailsLayout = ({
|
||||
minWidth="242px"
|
||||
>
|
||||
<Flex alignItems="center" justifyContent="center" direction="column" padding={1}>
|
||||
<CheckPermissions permissions={PERMISSIONS.update}>
|
||||
<PopoverButton onClick={openReleaseModal}>
|
||||
<PencilIcon />
|
||||
<Typography ellipsis>
|
||||
{formatMessage({
|
||||
id: 'content-releases.header.actions.edit',
|
||||
defaultMessage: 'Edit',
|
||||
})}
|
||||
</Typography>
|
||||
</PopoverButton>
|
||||
</CheckPermissions>
|
||||
<CheckPermissions permissions={PERMISSIONS.delete}>
|
||||
<PopoverButton onClick={openWarningConfirmDialog}>
|
||||
<TrashIcon />
|
||||
<Typography ellipsis textColor="danger600">
|
||||
{formatMessage({
|
||||
id: 'content-releases.header.actions.delete',
|
||||
defaultMessage: 'Delete',
|
||||
})}
|
||||
</Typography>
|
||||
</PopoverButton>
|
||||
</CheckPermissions>
|
||||
<PopoverButton disabled={!canUpdate} onClick={openReleaseModal}>
|
||||
<PencilIcon />
|
||||
<Typography ellipsis>
|
||||
{formatMessage({
|
||||
id: 'content-releases.header.actions.edit',
|
||||
defaultMessage: 'Edit',
|
||||
})}
|
||||
</Typography>
|
||||
</PopoverButton>
|
||||
<PopoverButton disabled={!canDelete} onClick={openWarningConfirmDialog}>
|
||||
<TrashIcon />
|
||||
<Typography ellipsis textColor="danger600">
|
||||
{formatMessage({
|
||||
id: 'content-releases.header.actions.delete',
|
||||
defaultMessage: 'Delete',
|
||||
})}
|
||||
</Typography>
|
||||
</PopoverButton>
|
||||
</Flex>
|
||||
<ReleaseInfoWrapper
|
||||
direction="column"
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { useRBAC } from '@strapi/helper-plugin';
|
||||
import { render, server, screen } from '@tests/utils';
|
||||
import { rest } from 'msw';
|
||||
|
||||
@ -9,6 +10,10 @@ jest.mock('@strapi/helper-plugin', () => ({
|
||||
...jest.requireActual('@strapi/helper-plugin'),
|
||||
// eslint-disable-next-line
|
||||
CheckPermissions: ({ children }: { children: JSX.Element }) => <div>{children}</div>,
|
||||
useRBAC: jest.fn(() => ({
|
||||
isLoading: false,
|
||||
allowedActions: { canUpdate: true, canDelete: true },
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('Releases details page', () => {
|
||||
@ -141,4 +146,42 @@ describe('Releases details page', () => {
|
||||
const container = screen.getByText(/This entry was/);
|
||||
expect(container.querySelector('span')).toHaveTextContent('published');
|
||||
});
|
||||
|
||||
it('renders the details page with the delete and edit buttons disabled', async () => {
|
||||
// @ts-expect-error – mocking
|
||||
useRBAC.mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
allowedActions: { canUpdate: false, canDelete: false },
|
||||
}));
|
||||
|
||||
server.use(
|
||||
rest.get('/content-releases/:releaseId', (req, res, ctx) =>
|
||||
res(ctx.json(mockReleaseDetailsPageData.noActionsHeaderData))
|
||||
)
|
||||
);
|
||||
|
||||
server.use(
|
||||
rest.get('/content-releases/:releaseId/actions', (req, res, ctx) =>
|
||||
res(ctx.json(mockReleaseDetailsPageData.noActionsBodyData))
|
||||
)
|
||||
);
|
||||
|
||||
const { user } = render(<ReleaseDetailsPage />, {
|
||||
initialEntries: [{ pathname: `/content-releases/1` }],
|
||||
});
|
||||
|
||||
await screen.findByText(mockReleaseDetailsPageData.noActionsHeaderData.data.name);
|
||||
|
||||
const moreButton = screen.getByRole('button', { name: 'Release actions' });
|
||||
expect(moreButton).toBeInTheDocument();
|
||||
|
||||
await user.click(moreButton);
|
||||
|
||||
// shows the popover actions
|
||||
const editButton = screen.getByRole('button', { name: 'Edit' });
|
||||
expect(editButton).toBeDisabled();
|
||||
|
||||
const deleteButton = screen.getByRole('button', { name: 'Delete' });
|
||||
expect(deleteButton).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user