From 3d894119d1e1d6fc8bc5c7342fbfeaf00e08ecd6 Mon Sep 17 00:00:00 2001 From: wesleybl Date: Mon, 16 Sep 2024 16:48:22 -0300 Subject: [PATCH 1/4] Fetch user before pass it to the restricted function It may not be in the Redux store yet when we try to pass it in. So we dispatch if it's not in the store. --- packages/volto-slate/news/6293.bugfix | 1 + .../volto-slate/src/blocks/Text/SlashMenu.jsx | 4 ++-- packages/volto/news/6293.bugfix | 1 + .../manage/BlockChooser/BlockChooser.jsx | 4 ++-- .../manage/BlockChooser/BlockChooser.test.jsx | 4 ++++ packages/volto/src/hooks/index.js | 1 + packages/volto/src/hooks/user/useFetchUser.js | 22 +++++++++++++++++++ 7 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 packages/volto-slate/news/6293.bugfix create mode 100644 packages/volto/news/6293.bugfix create mode 100644 packages/volto/src/hooks/user/useFetchUser.js diff --git a/packages/volto-slate/news/6293.bugfix b/packages/volto-slate/news/6293.bugfix new file mode 100644 index 0000000000..ea8503c548 --- /dev/null +++ b/packages/volto-slate/news/6293.bugfix @@ -0,0 +1 @@ +Fetch `user` before pass it 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 2a26c39cfe..8e00979caf 100644 --- a/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +++ b/packages/volto-slate/src/blocks/Text/SlashMenu.jsx @@ -4,7 +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 { useSelector } from 'react-redux'; +import { useFetchUser } from '@plone/volto/hooks'; const emptySlateBlock = () => ({ value: [ @@ -111,7 +111,7 @@ const PersistentSlashMenu = ({ editor }) => { } = props; const disableNewBlocks = data?.disableNewBlocks || detached; - const user = useSelector((state) => state.users?.user); + const user = useFetchUser(); const [slashMenuSelected, setSlashMenuSelected] = React.useState(0); diff --git a/packages/volto/news/6293.bugfix b/packages/volto/news/6293.bugfix new file mode 100644 index 0000000000..ea8503c548 --- /dev/null +++ b/packages/volto/news/6293.bugfix @@ -0,0 +1 @@ +Fetch `user` before pass it to the `restricted` function of the block settings. @wesleybl diff --git a/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx b/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx index 80c5142e81..b47514c027 100644 --- a/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx +++ b/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector } from 'react-redux'; +import { useFetchUser } from '@plone/volto/hooks'; import PropTypes from 'prop-types'; import { filter, map, groupBy, isEmpty } from 'lodash'; import { Accordion, Button } from 'semantic-ui-react'; @@ -36,7 +36,7 @@ const BlockChooser = ({ contentType, }) => { const intl = useIntl(); - const user = useSelector((state) => state.users?.user); + const user = useFetchUser(); const hasAllowedBlocks = !isEmpty(allowedBlocks); const filteredBlocksConfig = filter(blocksConfig, (item) => { diff --git a/packages/volto/src/components/manage/BlockChooser/BlockChooser.test.jsx b/packages/volto/src/components/manage/BlockChooser/BlockChooser.test.jsx index 447c20f61d..d2bd1bbe5a 100644 --- a/packages/volto/src/components/manage/BlockChooser/BlockChooser.test.jsx +++ b/packages/volto/src/components/manage/BlockChooser/BlockChooser.test.jsx @@ -4,6 +4,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 = {}; @@ -121,6 +122,9 @@ const store = mockStore({ locale: 'en', messages: {}, }, + userSession: { + token: jwt.sign({ fullname: 'John Doe' }, 'secret'), + }, }); describe('BlocksChooser', () => { diff --git a/packages/volto/src/hooks/index.js b/packages/volto/src/hooks/index.js index a955aa8285..0a55ce5670 100644 --- a/packages/volto/src/hooks/index.js +++ b/packages/volto/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 useFetchUser } from '@plone/volto/hooks/user/useFetchUser'; diff --git a/packages/volto/src/hooks/user/useFetchUser.js b/packages/volto/src/hooks/user/useFetchUser.js new file mode 100644 index 0000000000..36c94638f6 --- /dev/null +++ b/packages/volto/src/hooks/user/useFetchUser.js @@ -0,0 +1,22 @@ +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import jwtDecode from 'jwt-decode'; +import { getUser } from '@plone/volto/actions'; + +const useFetchUser = () => { + const user = useSelector((state) => state.users?.user); + const userId = useSelector((state) => + state.userSession.token ? jwtDecode(state.userSession.token).sub : '', + ); + const dispatch = useDispatch(); + + useEffect(() => { + if (!user?.id) { + dispatch(getUser(userId)); + } + }, [dispatch, userId, user]); + + return user; +}; + +export default useFetchUser; From c6406b4b5f8d5108b319ffa0e05e7af8f3333ccf Mon Sep 17 00:00:00 2001 From: wesleybl Date: Mon, 23 Sep 2024 09:49:30 -0300 Subject: [PATCH 2/4] Rename useFetchUser to useUser --- packages/volto-slate/src/blocks/Text/SlashMenu.jsx | 4 ++-- .../volto/src/components/manage/BlockChooser/BlockChooser.jsx | 4 ++-- packages/volto/src/hooks/index.js | 2 +- packages/volto/src/hooks/user/{useFetchUser.js => useUser.js} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename packages/volto/src/hooks/user/{useFetchUser.js => useUser.js} (100%) diff --git a/packages/volto-slate/src/blocks/Text/SlashMenu.jsx b/packages/volto-slate/src/blocks/Text/SlashMenu.jsx index 8e00979caf..9ec1612304 100644 --- a/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +++ b/packages/volto-slate/src/blocks/Text/SlashMenu.jsx @@ -4,7 +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 { useFetchUser } from '@plone/volto/hooks'; +import { useUser } from '@plone/volto/hooks'; const emptySlateBlock = () => ({ value: [ @@ -111,7 +111,7 @@ const PersistentSlashMenu = ({ editor }) => { } = props; const disableNewBlocks = data?.disableNewBlocks || detached; - const user = useFetchUser(); + const user = useUser(); const [slashMenuSelected, setSlashMenuSelected] = React.useState(0); diff --git a/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx b/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx index b47514c027..2ae878e5ba 100644 --- a/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx +++ b/packages/volto/src/components/manage/BlockChooser/BlockChooser.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useFetchUser } from '@plone/volto/hooks'; +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'; @@ -36,7 +36,7 @@ const BlockChooser = ({ contentType, }) => { const intl = useIntl(); - const user = useFetchUser(); + const user = useUser(); const hasAllowedBlocks = !isEmpty(allowedBlocks); const filteredBlocksConfig = filter(blocksConfig, (item) => { diff --git a/packages/volto/src/hooks/index.js b/packages/volto/src/hooks/index.js index 0a55ce5670..f8e327c0e6 100644 --- a/packages/volto/src/hooks/index.js +++ b/packages/volto/src/hooks/index.js @@ -1,3 +1,3 @@ export { default as useClipboard } from '@plone/volto/hooks/clipboard/useClipboard'; export { useClient } from '@plone/volto/hooks/client/useClient'; -export { default as useFetchUser } from '@plone/volto/hooks/user/useFetchUser'; +export { default as useUser } from '@plone/volto/hooks/user/useUser'; diff --git a/packages/volto/src/hooks/user/useFetchUser.js b/packages/volto/src/hooks/user/useUser.js similarity index 100% rename from packages/volto/src/hooks/user/useFetchUser.js rename to packages/volto/src/hooks/user/useUser.js From 59723367456e5a4f43c763fdde49a49c0a7b835d Mon Sep 17 00:00:00 2001 From: wesleybl Date: Mon, 23 Sep 2024 10:58:08 -0300 Subject: [PATCH 3/4] Get user and place their data in the Redux store after login --- packages/volto/src/components/theme/Login/Login.jsx | 4 ++++ packages/volto/src/hooks/user/useUser.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/volto/src/components/theme/Login/Login.jsx b/packages/volto/src/components/theme/Login/Login.jsx index efdc409e21..993efeb86a 100644 --- a/packages/volto/src/components/theme/Login/Login.jsx +++ b/packages/volto/src/components/theme/Login/Login.jsx @@ -25,6 +25,7 @@ import { toast } from 'react-toastify'; import { Toast } from '@plone/volto/components'; import aheadSVG from '@plone/volto/icons/ahead.svg'; import clearSVG from '@plone/volto/icons/clear.svg'; +import { useUser } from '@plone/volto/hooks'; const messages = defineMessages({ login: { @@ -85,6 +86,9 @@ const Login = (props) => { const previousToken = usePrevious(token); + // Get user and place their data in the Redux store + useUser(); + useEffect(() => { if (location?.state?.isLogout) { // Execute a true Logout action diff --git a/packages/volto/src/hooks/user/useUser.js b/packages/volto/src/hooks/user/useUser.js index 36c94638f6..484385e02c 100644 --- a/packages/volto/src/hooks/user/useUser.js +++ b/packages/volto/src/hooks/user/useUser.js @@ -11,7 +11,7 @@ const useFetchUser = () => { const dispatch = useDispatch(); useEffect(() => { - if (!user?.id) { + if (!user?.id && userId) { dispatch(getUser(userId)); } }, [dispatch, userId, user]); From bd5c4cc1299f6b2dd2eeccfbadf9361febf9bc7d Mon Sep 17 00:00:00 2001 From: wesleybl Date: Wed, 25 Sep 2024 15:45:41 -0300 Subject: [PATCH 4/4] Avoid dispatching getUser multiple times --- packages/volto/src/components/theme/Login/Login.jsx | 4 ---- packages/volto/src/hooks/user/useUser.js | 11 ++++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/volto/src/components/theme/Login/Login.jsx b/packages/volto/src/components/theme/Login/Login.jsx index 993efeb86a..efdc409e21 100644 --- a/packages/volto/src/components/theme/Login/Login.jsx +++ b/packages/volto/src/components/theme/Login/Login.jsx @@ -25,7 +25,6 @@ import { toast } from 'react-toastify'; import { Toast } from '@plone/volto/components'; import aheadSVG from '@plone/volto/icons/ahead.svg'; import clearSVG from '@plone/volto/icons/clear.svg'; -import { useUser } from '@plone/volto/hooks'; const messages = defineMessages({ login: { @@ -86,9 +85,6 @@ const Login = (props) => { const previousToken = usePrevious(token); - // Get user and place their data in the Redux store - useUser(); - useEffect(() => { if (location?.state?.isLogout) { // Execute a true Logout action diff --git a/packages/volto/src/hooks/user/useUser.js b/packages/volto/src/hooks/user/useUser.js index 484385e02c..3232ed0a8e 100644 --- a/packages/volto/src/hooks/user/useUser.js +++ b/packages/volto/src/hooks/user/useUser.js @@ -3,20 +3,21 @@ import { useDispatch, useSelector } from 'react-redux'; import jwtDecode from 'jwt-decode'; import { getUser } from '@plone/volto/actions'; -const useFetchUser = () => { - const user = useSelector((state) => state.users?.user); +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 && userId) { + if (!user?.id && users?.get.loading === false) { dispatch(getUser(userId)); } - }, [dispatch, userId, user]); + }, [dispatch, userId, user, users?.get.loading]); return user; }; -export default useFetchUser; +export default useUser;