mirror of
https://github.com/strapi/strapi.git
synced 2025-12-06 12:01:52 +00:00
Add permissions to ctb main compo
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
e73101b664
commit
7d9041ecc3
@ -331,6 +331,11 @@ const data = {
|
|||||||
subject: 'application::address.address',
|
subject: 'application::address.address',
|
||||||
conditions: [],
|
conditions: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
action: 'plugins::content-manager.explorer.create',
|
||||||
|
subject: 'application::restaurant.restaurant',
|
||||||
|
conditions: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
action: 'plugins::content-manager.explorer.create',
|
action: 'plugins::content-manager.explorer.create',
|
||||||
subject: 'application::homepage.homepage',
|
subject: 'application::homepage.homepage',
|
||||||
@ -338,12 +343,12 @@ const data = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Content type builder
|
// Content type builder
|
||||||
{
|
// {
|
||||||
action: 'plugins::content-type-builder.read',
|
// action: 'plugins::content-type-builder.read',
|
||||||
subject: null,
|
// subject: null,
|
||||||
fields: null,
|
// fields: null,
|
||||||
conditions: [],
|
// conditions: [],
|
||||||
},
|
// },
|
||||||
|
|
||||||
// Documentation plugin
|
// Documentation plugin
|
||||||
// {
|
// {
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Redirect } from 'react-router-dom';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import useUser from '../../hooks/useUser';
|
||||||
|
import hasPermissions from '../../utils/hasPermissions';
|
||||||
|
import LoadingIndicatorPage from '../LoadingIndicatorPage';
|
||||||
|
|
||||||
|
const WithPagePermissions = ({ permissions, children }) => {
|
||||||
|
const userPermissions = useUser();
|
||||||
|
const [state, setState] = useState({ isLoading: true, canAccess: false });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkPermission = async () => {
|
||||||
|
try {
|
||||||
|
const canAccess = await hasPermissions(userPermissions, permissions);
|
||||||
|
|
||||||
|
setState({ isLoading: false, canAccess });
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
strapi.notification.error('notification.error');
|
||||||
|
|
||||||
|
setState({ isLoading: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkPermission();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (state.isLoading) {
|
||||||
|
return <LoadingIndicatorPage />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.canAccess) {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
|
||||||
|
WithPagePermissions.defaultProps = {
|
||||||
|
permissions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
WithPagePermissions.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
permissions: PropTypes.array,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WithPagePermissions;
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import useUser from '../../hooks/useUser';
|
||||||
|
import hasPermissions from '../../utils/hasPermissions';
|
||||||
|
|
||||||
|
// NOTE: this component is very similar to the WithPagePermissions
|
||||||
|
// except that it does not handle redirections nor loading state
|
||||||
|
|
||||||
|
const WithPermissions = ({ permissions, children }) => {
|
||||||
|
const userPermissions = useUser();
|
||||||
|
const [state, setState] = useState({ isLoading: true, canAccess: false });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkPermission = async () => {
|
||||||
|
try {
|
||||||
|
const canAccess = await hasPermissions(userPermissions, permissions);
|
||||||
|
|
||||||
|
setState({ isLoading: false, canAccess });
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
strapi.notification.error('notification.error');
|
||||||
|
|
||||||
|
setState({ isLoading: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkPermission();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (state.isLoading) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.canAccess) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
|
||||||
|
WithPermissions.defaultProps = {
|
||||||
|
permissions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
WithPermissions.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
permissions: PropTypes.array,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WithPermissions;
|
||||||
12
packages/strapi-helper-plugin/lib/src/hooks/useUser.js
Normal file
12
packages/strapi-helper-plugin/lib/src/hooks/useUser.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* useUser
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import UserContext from '../contexts/UserContext';
|
||||||
|
|
||||||
|
const useUser = () => useContext(UserContext);
|
||||||
|
|
||||||
|
export default useUser;
|
||||||
@ -79,6 +79,8 @@ export { default as SelectNav } from './components/SelectNav';
|
|||||||
export { default as SelectWrapper } from './components/SelectWrapper';
|
export { default as SelectWrapper } from './components/SelectWrapper';
|
||||||
export { default as UserProvider } from './components/UserProvider';
|
export { default as UserProvider } from './components/UserProvider';
|
||||||
export { default as ViewContainer } from './components/ViewContainer';
|
export { default as ViewContainer } from './components/ViewContainer';
|
||||||
|
export { default as WithPagePermissions } from './components/WithPagePermissions';
|
||||||
|
export { default as WithPermissions } from './components/WithPermissions';
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
export { GlobalContext, GlobalContextProvider, useGlobalContext } from './contexts/GlobalContext';
|
export { GlobalContext, GlobalContextProvider, useGlobalContext } from './contexts/GlobalContext';
|
||||||
@ -87,6 +89,7 @@ export { default as UserContext } from './contexts/UserContext';
|
|||||||
// Hooks
|
// Hooks
|
||||||
export { default as useQuery } from './hooks/useQuery';
|
export { default as useQuery } from './hooks/useQuery';
|
||||||
export { default as useStrapi } from './hooks/useStrapi';
|
export { default as useStrapi } from './hooks/useStrapi';
|
||||||
|
export { default as useUser } from './hooks/useUser';
|
||||||
|
|
||||||
// Providers
|
// Providers
|
||||||
export { default as StrapiProvider } from './providers/StrapiProvider';
|
export { default as StrapiProvider } from './providers/StrapiProvider';
|
||||||
|
|||||||
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useGlobalContext } from 'strapi-helper-plugin';
|
import { useGlobalContext, WithPermissions } from 'strapi-helper-plugin';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { Button } from '@buffetjs/core';
|
import { Button } from '@buffetjs/core';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import getTrad from '../../utils/getTrad';
|
import getTrad from '../../utils/getTrad';
|
||||||
|
import pluginPermissions from '../../utils/permissions';
|
||||||
|
|
||||||
// Create link from content-type-builder to content-manager
|
// Create link from content-type-builder to content-manager
|
||||||
function EditViewButton(props) {
|
function EditViewButton(props) {
|
||||||
@ -31,9 +32,7 @@ function EditViewButton(props) {
|
|||||||
const category = get(modifiedData, 'category', '');
|
const category = get(modifiedData, 'category', '');
|
||||||
|
|
||||||
const suffixUrl =
|
const suffixUrl =
|
||||||
type === 'content-types'
|
type === 'content-types' ? props.getModelName() : `${category}/${componentSlug}`;
|
||||||
? props.getModelName()
|
|
||||||
: `${category}/${componentSlug}`;
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
emitEvent('willEditEditLayout');
|
emitEvent('willEditEditLayout');
|
||||||
@ -49,14 +48,13 @@ function EditViewButton(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<WithPermissions permissions={pluginPermissions.main}>
|
||||||
<Button
|
<Button
|
||||||
{...props}
|
{...props}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
icon={<FontAwesomeIcon icon="cog" style={{ fontSize: 13 }} />}
|
icon={<FontAwesomeIcon icon="cog" style={{ fontSize: 13 }} />}
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: getTrad(
|
id: getTrad(`injected-components.content-manager.edit-settings-view.link.${type}`),
|
||||||
`injected-components.content-manager.edit-settings-view.link.${type}`
|
|
||||||
),
|
|
||||||
})}
|
})}
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: 15,
|
paddingLeft: 15,
|
||||||
@ -65,6 +63,7 @@ function EditViewButton(props) {
|
|||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</WithPermissions>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { LiLink, useGlobalContext } from 'strapi-helper-plugin';
|
import { LiLink, useGlobalContext, WithPermissions } from 'strapi-helper-plugin';
|
||||||
|
import pluginPermissions from '../../utils/permissions';
|
||||||
|
|
||||||
// Create link from content-type-builder to content-manager
|
// Create link from content-type-builder to content-manager
|
||||||
function EditViewLink(props) {
|
function EditViewLink(props) {
|
||||||
@ -23,6 +24,7 @@ function EditViewLink(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<WithPermissions permissions={pluginPermissions.main}>
|
||||||
<LiLink
|
<LiLink
|
||||||
{...props}
|
{...props}
|
||||||
url={url}
|
url={url}
|
||||||
@ -30,6 +32,7 @@ function EditViewLink(props) {
|
|||||||
emitEvent('willEditEditLayout');
|
emitEvent('willEditEditLayout');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</WithPermissions>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
import React, { Suspense, lazy } from 'react';
|
import React, { Suspense, lazy } from 'react';
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route } from 'react-router-dom';
|
||||||
import { LoadingIndicatorPage } from 'strapi-helper-plugin';
|
import { LoadingIndicatorPage, WithPagePermissions } from 'strapi-helper-plugin';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
|
import pluginPermissions from '../../utils/permissions';
|
||||||
import DataManagerProvider from '../DataManagerProvider';
|
import DataManagerProvider from '../DataManagerProvider';
|
||||||
import RecursivePath from '../RecursivePath';
|
import RecursivePath from '../RecursivePath';
|
||||||
import icons from './utils/icons.json';
|
import icons from './utils/icons.json';
|
||||||
@ -17,14 +18,12 @@ const ListView = lazy(() => import('../ListView'));
|
|||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
|
<WithPagePermissions permissions={pluginPermissions.main}>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<DataManagerProvider allIcons={icons}>
|
<DataManagerProvider allIcons={icons}>
|
||||||
<Suspense fallback={<LoadingIndicatorPage />}>
|
<Suspense fallback={<LoadingIndicatorPage />}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route path={`/plugins/${pluginId}/content-types/:uid`} component={ListView} />
|
||||||
path={`/plugins/${pluginId}/content-types/:uid`}
|
|
||||||
component={ListView}
|
|
||||||
/>
|
|
||||||
<Route
|
<Route
|
||||||
path={`/plugins/${pluginId}/component-categories/:categoryUid`}
|
path={`/plugins/${pluginId}/component-categories/:categoryUid`}
|
||||||
component={RecursivePath}
|
component={RecursivePath}
|
||||||
@ -33,6 +32,7 @@ const App = () => {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
</DataManagerProvider>
|
</DataManagerProvider>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
</WithPagePermissions>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import App from './containers/App';
|
|||||||
import Initializer from './containers/Initializer';
|
import Initializer from './containers/Initializer';
|
||||||
import Link from './InjectedComponents/ContentManager/EditViewLink';
|
import Link from './InjectedComponents/ContentManager/EditViewLink';
|
||||||
import Button from './InjectedComponents/ContentManager/EditSettingViewButton';
|
import Button from './InjectedComponents/ContentManager/EditSettingViewButton';
|
||||||
|
import pluginPermissions from './utils/permissions';
|
||||||
import lifecycles from './lifecycles';
|
import lifecycles from './lifecycles';
|
||||||
import trads from './translations';
|
import trads from './translations';
|
||||||
import pluginId from './pluginId';
|
import pluginId from './pluginId';
|
||||||
@ -64,7 +65,7 @@ export default strapi => {
|
|||||||
defaultMessage: 'Content-Types Builder',
|
defaultMessage: 'Content-Types Builder',
|
||||||
},
|
},
|
||||||
name,
|
name,
|
||||||
permissions: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
permissions: pluginPermissions.main,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
const pluginPermissions = {
|
||||||
|
// This permission regards the main component (App) and is used to tell
|
||||||
|
// If the plugin link should be displayed in the menu
|
||||||
|
// And also if the plugin is accessible. This use case is found when a user types the url of the
|
||||||
|
// plugin directly in the browser
|
||||||
|
main: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginPermissions;
|
||||||
Loading…
x
Reference in New Issue
Block a user