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

Pass the user, navRoot and contentType objects to the restricted function of the block settings #6375

Merged
merged 4 commits into from
Oct 5, 2024
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
17 changes: 15 additions & 2 deletions docs/source/recipes/how-to-restrict-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,25 @@ The function has this signature:
block: BlockConfigBase;
navRoot: Content;
contentType: string;
user: Object
}) => boolean;
}
```

Where `properties` is the current object data and `block` is the block being evaluated in `BlockChooser`.
`navRoot` is the nearest navigation root object and `contentType` is the current content type.
`properties`
: The current object data.

`block`
: The block being evaluated in `BlockChooser`.

`navRoot`
: The nearest navigation root object.

`contentType`
: The current content type.

`user`
: An object that represents the currently authenticated user.

In the following configuration example, you can restrict a block so that it cannot be added unless the content type is `News Item` or the content item is in a specific path in the content tree (`/folder`):

Expand Down
1 change: 1 addition & 0 deletions news/6264.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Pass the `user`, `navRoot`, and `contentType` objects to the `restricted` function of the block settings. @wesleybl
16 changes: 15 additions & 1 deletion packages/volto-slate/src/blocks/Text/SlashMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { filter, isEmpty } from 'lodash';
import { Menu } from 'semantic-ui-react';
import { useIntl, FormattedMessage } from 'react-intl';
import { Icon } from '@plone/volto/components';
import { useUser } from '@plone/volto/hooks';

const emptySlateBlock = () => ({
value: [
Expand Down Expand Up @@ -105,9 +106,13 @@ const PersistentSlashMenu = ({ editor }) => {
selected,
allowedBlocks,
detached,
navRoot,
contentType,
} = props;
const disableNewBlocks = data?.disableNewBlocks || detached;

const user = useUser();

const [slashMenuSelected, setSlashMenuSelected] = React.useState(0);

const hasAllowedBlocks = !isEmpty(allowedBlocks);
Expand All @@ -122,7 +127,13 @@ const PersistentSlashMenu = ({ editor }) => {
hasAllowedBlocks
? allowedBlocks.includes(item.id)
: typeof item.restricted === 'function'
? !item.restricted({ properties, block: item })
? !item.restricted({
properties,
block: item,
navRoot,
contentType,
user,
})
: !item.restricted,
)
.filter((block) => Boolean(block.title && block.id))
Expand Down Expand Up @@ -152,6 +163,9 @@ const PersistentSlashMenu = ({ editor }) => {
properties,
slashCommand,
hasAllowedBlocks,
navRoot,
contentType,
user,
],
);

Expand Down
10 changes: 9 additions & 1 deletion src/components/manage/BlockChooser/BlockChooser.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { useUser } from '@plone/volto/hooks';
import PropTypes from 'prop-types';
import { filter, map, groupBy, isEmpty } from 'lodash';
import { Accordion, Button } from 'semantic-ui-react';
Expand Down Expand Up @@ -35,6 +36,7 @@ const BlockChooser = ({
contentType,
}) => {
const intl = useIntl();
const user = useUser();
const hasAllowedBlocks = !isEmpty(allowedBlocks);

const filteredBlocksConfig = filter(blocksConfig, (item) => {
Expand All @@ -57,7 +59,13 @@ const BlockChooser = ({
// depending on this function, given properties (current present blocks) and the
// block being evaluated
return typeof item.restricted === 'function'
? !item.restricted({ properties, block: item, navRoot, contentType })
? !item.restricted({
properties,
block: item,
navRoot,
contentType,
user,
})
: !item.restricted;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/manage/BlockChooser/BlockChooser.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Provider } from 'react-intl-redux';
import configureStore from 'redux-mock-store';
import BlockChooser from './BlockChooser';
import config from '@plone/volto/registry';
import jwt from 'jsonwebtoken';

const blockSVG = {};

Expand Down Expand Up @@ -122,6 +123,9 @@ const store = mockStore({
locale: 'en',
messages: {},
},
userSession: {
token: jwt.sign({ fullname: 'John Doe' }, 'secret'),
},
});

describe('BlocksChooser', () => {
Expand Down
1 change: 1 addition & 0 deletions src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as useClipboard } from '@plone/volto/hooks/clipboard/useClipboard';
export { useClient } from '@plone/volto/hooks/client/useClient';
export { default as useUser } from '@plone/volto/hooks/user/useUser';
23 changes: 23 additions & 0 deletions src/hooks/user/useUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import jwtDecode from 'jwt-decode';
import { getUser } from '@plone/volto/actions';

const useUser = () => {
const users = useSelector((state) => state.users);
const user = users?.user;
const userId = useSelector((state) =>
state.userSession.token ? jwtDecode(state.userSession.token).sub : '',
);
const dispatch = useDispatch();

useEffect(() => {
if (!user?.id && users?.get.loading === false) {
dispatch(getUser(userId));
}
}, [dispatch, userId, user, users?.get.loading]);

return user;
};

export default useUser;
Loading