From 7e3465f37a008ebb2f12d2689aff2d70431f6deb Mon Sep 17 00:00:00 2001
From: wesleybl <wesleybl@gmail.com>
Date: Fri, 4 Oct 2024 14:46:19 -0300
Subject: [PATCH 1/3] Pass the `user`, `navRoot` and `contentType` objects to
 the `restricted` function of the block settings

---
 docs/source/recipes/how-to-restrict-blocks.md |  8 +++++--
 news/6264.feature                             |  1 +
 .../volto-slate/src/blocks/Text/SlashMenu.jsx | 16 ++++++++++++-
 .../manage/BlockChooser/BlockChooser.jsx      | 10 +++++++-
 .../manage/BlockChooser/BlockChooser.test.jsx |  4 ++++
 src/hooks/index.js                            |  1 +
 src/hooks/user/useUser.js                     | 23 +++++++++++++++++++
 7 files changed, 59 insertions(+), 4 deletions(-)
 create mode 100644 news/6264.feature
 create mode 100644 src/hooks/user/useUser.js

diff --git a/docs/source/recipes/how-to-restrict-blocks.md b/docs/source/recipes/how-to-restrict-blocks.md
index b757215766..179323ef2c 100644
--- a/docs/source/recipes/how-to-restrict-blocks.md
+++ b/docs/source/recipes/how-to-restrict-blocks.md
@@ -22,12 +22,16 @@ 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` is the current object data.
+`block` is the block being evaluated in `BlockChooser`.
+`navRoot` is the nearest navigation root object.
+`contentType` is the current content type.
+`user` is 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`):
 
diff --git a/news/6264.feature b/news/6264.feature
new file mode 100644
index 0000000000..e8a31aaf20
--- /dev/null
+++ b/news/6264.feature
@@ -0,0 +1 @@
+Pass the `user`, `navRoot` and `contentType` objects to the `restricted` function of the block settings. @wesleybl
diff --git a/packages/volto-slate/src/blocks/Text/SlashMenu.jsx b/packages/volto-slate/src/blocks/Text/SlashMenu.jsx
index de312e3d89..947a1f3cda 100644
--- a/packages/volto-slate/src/blocks/Text/SlashMenu.jsx
+++ b/packages/volto-slate/src/blocks/Text/SlashMenu.jsx
@@ -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: [
@@ -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);
@@ -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))
@@ -152,6 +163,9 @@ const PersistentSlashMenu = ({ editor }) => {
       properties,
       slashCommand,
       hasAllowedBlocks,
+      navRoot,
+      contentType,
+      user,
     ],
   );
 
diff --git a/src/components/manage/BlockChooser/BlockChooser.jsx b/src/components/manage/BlockChooser/BlockChooser.jsx
index 69b3d87c38..2ae878e5ba 100644
--- a/src/components/manage/BlockChooser/BlockChooser.jsx
+++ b/src/components/manage/BlockChooser/BlockChooser.jsx
@@ -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';
@@ -35,6 +36,7 @@ const BlockChooser = ({
   contentType,
 }) => {
   const intl = useIntl();
+  const user = useUser();
   const hasAllowedBlocks = !isEmpty(allowedBlocks);
 
   const filteredBlocksConfig = filter(blocksConfig, (item) => {
@@ -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;
       }
     }
diff --git a/src/components/manage/BlockChooser/BlockChooser.test.jsx b/src/components/manage/BlockChooser/BlockChooser.test.jsx
index 22fd5b5f48..bb9dd2b4e7 100644
--- a/src/components/manage/BlockChooser/BlockChooser.test.jsx
+++ b/src/components/manage/BlockChooser/BlockChooser.test.jsx
@@ -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 = {};
 
@@ -122,6 +123,9 @@ const store = mockStore({
     locale: 'en',
     messages: {},
   },
+  userSession: {
+    token: jwt.sign({ fullname: 'John Doe' }, 'secret'),
+  },
 });
 
 describe('BlocksChooser', () => {
diff --git a/src/hooks/index.js b/src/hooks/index.js
index a955aa8285..f8e327c0e6 100644
--- a/src/hooks/index.js
+++ b/src/hooks/index.js
@@ -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';
diff --git a/src/hooks/user/useUser.js b/src/hooks/user/useUser.js
new file mode 100644
index 0000000000..3232ed0a8e
--- /dev/null
+++ b/src/hooks/user/useUser.js
@@ -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;

From 3d0a09845772e806e4c97dc2e837c312725525c0 Mon Sep 17 00:00:00 2001
From: Steve Piercy <web@stevepiercy.com>
Date: Fri, 4 Oct 2024 14:35:46 -0700
Subject: [PATCH 2/3] Convert wall of text to a definition list to improve
 readability

---
 docs/source/recipes/how-to-restrict-blocks.md | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/docs/source/recipes/how-to-restrict-blocks.md b/docs/source/recipes/how-to-restrict-blocks.md
index 179323ef2c..16ef380c10 100644
--- a/docs/source/recipes/how-to-restrict-blocks.md
+++ b/docs/source/recipes/how-to-restrict-blocks.md
@@ -27,11 +27,20 @@ The function has this signature:
 }
 ```
 
-`properties` is the current object data.
-`block` is the block being evaluated in `BlockChooser`.
-`navRoot` is the nearest navigation root object.
-`contentType` is the current content type.
-`user` is an object that represents the currently authenticated user.
+`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`):
 

From c4d4cd06af530df6e5466ab6b37b509d59757e61 Mon Sep 17 00:00:00 2001
From: Steve Piercy <web@stevepiercy.com>
Date: Fri, 4 Oct 2024 14:36:19 -0700
Subject: [PATCH 3/3] Update news/6264.feature

Oxford comma
---
 news/6264.feature | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/news/6264.feature b/news/6264.feature
index e8a31aaf20..505e64c3b6 100644
--- a/news/6264.feature
+++ b/news/6264.feature
@@ -1 +1 @@
-Pass the `user`, `navRoot` and `contentType` objects to the `restricted` function of the block settings. @wesleybl
+Pass the `user`, `navRoot`, and `contentType` objects to the `restricted` function of the block settings. @wesleybl