mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
Init permissions check for the general links
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
30d8d08cc4
commit
372951327d
@ -19,9 +19,11 @@ import {
|
||||
GlobalContextProvider,
|
||||
LoadingIndicatorPage,
|
||||
OverlayBlocker,
|
||||
UserProvider,
|
||||
} from 'strapi-helper-plugin';
|
||||
import TestEE from 'ee_else_ce/containers/TestEE';
|
||||
import { SETTINGS_BASE_URL, SHOW_TUTORIALS } from '../../config';
|
||||
import { fakePermissionsData } from '../../utils';
|
||||
|
||||
import Header from '../../components/Header/index';
|
||||
import NavTopRightWrapper from '../../components/NavTopRightWrapper';
|
||||
@ -176,52 +178,54 @@ export class Admin extends React.Component {
|
||||
settingsBaseURL={SETTINGS_BASE_URL || '/settings'}
|
||||
updatePlugin={updatePlugin}
|
||||
>
|
||||
<Wrapper>
|
||||
<LeftMenu version={strapiVersion} plugins={plugins} />
|
||||
<NavTopRightWrapper>
|
||||
{/* Injection zone not ready yet */}
|
||||
<Logout />
|
||||
<LocaleToggle isLogged />
|
||||
</NavTopRightWrapper>
|
||||
<div className="adminPageRightWrapper">
|
||||
<Header />
|
||||
<Content>
|
||||
<Switch>
|
||||
<Route path="/" render={props => this.renderRoute(props, HomePage)} exact />
|
||||
<Route path="/me" component={ProfilePage} />
|
||||
{/* TODO remove this Route it is just made for the test */}
|
||||
<Route path="/test" component={TestEE} />
|
||||
<Route path="/plugins/:pluginId" render={this.renderPluginDispatcher} />
|
||||
<Route
|
||||
path="/list-plugins"
|
||||
render={props => this.renderRoute(props, InstalledPluginsPage)}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path="/marketplace"
|
||||
render={props => this.renderRoute(props, MarketplacePage)}
|
||||
/>
|
||||
<Route
|
||||
path={`${SETTINGS_BASE_URL || '/settings'}/:settingId`}
|
||||
render={props => this.renderRoute(props, SettingsPage)}
|
||||
/>
|
||||
<Route
|
||||
path={SETTINGS_BASE_URL || '/settings'}
|
||||
render={props => this.renderRoute(props, SettingsPage)}
|
||||
exact
|
||||
/>
|
||||
<Route key="7" path="" component={NotFoundPage} />
|
||||
<Route key="8" path="404" component={NotFoundPage} />
|
||||
</Switch>
|
||||
</Content>
|
||||
</div>
|
||||
<OverlayBlocker
|
||||
key="overlayBlocker"
|
||||
isOpen={blockApp && showGlobalAppBlocker}
|
||||
{...overlayBlockerData}
|
||||
/>
|
||||
{SHOW_TUTORIALS && <OnboardingVideos />}
|
||||
</Wrapper>
|
||||
<UserProvider value={fakePermissionsData.user2}>
|
||||
<Wrapper>
|
||||
<LeftMenu version={strapiVersion} plugins={plugins} />
|
||||
<NavTopRightWrapper>
|
||||
{/* Injection zone not ready yet */}
|
||||
<Logout />
|
||||
<LocaleToggle isLogged />
|
||||
</NavTopRightWrapper>
|
||||
<div className="adminPageRightWrapper">
|
||||
<Header />
|
||||
<Content>
|
||||
<Switch>
|
||||
<Route path="/" render={props => this.renderRoute(props, HomePage)} exact />
|
||||
<Route path="/me" component={ProfilePage} />
|
||||
{/* TODO remove this Route it is just made for the test */}
|
||||
<Route path="/test" component={TestEE} />
|
||||
<Route path="/plugins/:pluginId" render={this.renderPluginDispatcher} />
|
||||
<Route
|
||||
path="/list-plugins"
|
||||
render={props => this.renderRoute(props, InstalledPluginsPage)}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path="/marketplace"
|
||||
render={props => this.renderRoute(props, MarketplacePage)}
|
||||
/>
|
||||
<Route
|
||||
path={`${SETTINGS_BASE_URL || '/settings'}/:settingId`}
|
||||
render={props => this.renderRoute(props, SettingsPage)}
|
||||
/>
|
||||
<Route
|
||||
path={SETTINGS_BASE_URL || '/settings'}
|
||||
render={props => this.renderRoute(props, SettingsPage)}
|
||||
exact
|
||||
/>
|
||||
<Route key="7" path="" component={NotFoundPage} />
|
||||
<Route key="8" path="404" component={NotFoundPage} />
|
||||
</Switch>
|
||||
</Content>
|
||||
</div>
|
||||
<OverlayBlocker
|
||||
key="overlayBlocker"
|
||||
isOpen={blockApp && showGlobalAppBlocker}
|
||||
{...overlayBlockerData}
|
||||
/>
|
||||
{SHOW_TUTORIALS && <OnboardingVideos />}
|
||||
</Wrapper>
|
||||
</UserProvider>
|
||||
</GlobalContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,9 +4,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useContext, useEffect, useReducer } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { UserContext } from 'strapi-helper-plugin';
|
||||
import {
|
||||
LeftMenuLinksSection,
|
||||
LeftMenuFooter,
|
||||
@ -14,40 +15,48 @@ import {
|
||||
LeftMenuLinkContainer,
|
||||
LinksContainer,
|
||||
} from '../../components/LeftMenu';
|
||||
import { SETTINGS_BASE_URL } from '../../config';
|
||||
import { hasPermissions } from '../../utils';
|
||||
import reducer, { initialState } from './reducer';
|
||||
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const LeftMenu = ({ version, plugins }) => {
|
||||
const location = useLocation();
|
||||
const general = {
|
||||
searchable: false,
|
||||
name: 'general',
|
||||
links: [
|
||||
{
|
||||
icon: 'list',
|
||||
label: 'app.components.LeftMenuLinkContainer.listPlugins',
|
||||
destination: '/list-plugins',
|
||||
},
|
||||
{
|
||||
icon: 'shopping-basket',
|
||||
label: 'app.components.LeftMenuLinkContainer.installNewPlugin',
|
||||
destination: '/marketplace',
|
||||
},
|
||||
{
|
||||
icon: 'cog',
|
||||
label: 'app.components.LeftMenuLinkContainer.settings',
|
||||
destination: SETTINGS_BASE_URL,
|
||||
},
|
||||
],
|
||||
};
|
||||
const permissions = useContext(UserContext);
|
||||
const [{ generalSectionLinks }, dispatch] = useReducer(reducer, initialState);
|
||||
const filteredLinks = generalSectionLinks.filter(link => link.isDisplayed);
|
||||
|
||||
useEffect(() => {
|
||||
const getLinksPermissions = async () => {
|
||||
generalSectionLinks.forEach(async (_, i) => {
|
||||
const hasPermission = await hasPermissions(permissions, generalSectionLinks[i].permissions);
|
||||
|
||||
dispatch({
|
||||
type: 'SET_LINK_PERMISSION',
|
||||
index: i,
|
||||
hasPermission,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
getLinksPermissions();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<LeftMenuHeader />
|
||||
<LinksContainer>
|
||||
<LeftMenuLinkContainer plugins={plugins} />
|
||||
<LeftMenuLinksSection section="general" {...general} location={location} />
|
||||
{filteredLinks.length && (
|
||||
<LeftMenuLinksSection
|
||||
section="general"
|
||||
name="general"
|
||||
links={filteredLinks}
|
||||
location={location}
|
||||
searchable={false}
|
||||
/>
|
||||
)}
|
||||
</LinksContainer>
|
||||
<LeftMenuFooter key="footer" version={version} />
|
||||
</Wrapper>
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
/* eslint-disable consistent-return */
|
||||
import produce from 'immer';
|
||||
import { set } from 'lodash';
|
||||
import { SETTINGS_BASE_URL } from '../../config';
|
||||
|
||||
const initialState = {
|
||||
generalSectionLinks: [
|
||||
{
|
||||
icon: 'list',
|
||||
label: 'app.components.LeftMenuLinkContainer.listPlugins',
|
||||
destination: '/list-plugins',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.uninstall', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'shopping-basket',
|
||||
label: 'app.components.LeftMenuLinkContainer.installNewPlugin',
|
||||
destination: '/marketplace',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.install', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'cog',
|
||||
label: 'app.components.LeftMenuLinkContainer.settings',
|
||||
isDisplayed: false,
|
||||
destination: SETTINGS_BASE_URL,
|
||||
permissions: [
|
||||
// webhooks
|
||||
{ action: 'admin::webhook.create', subject: null },
|
||||
{ action: 'admin::webhook.read', subject: null },
|
||||
{ action: 'admin::webhook.update', subject: null },
|
||||
{ action: 'admin::webhook.delete', subject: null },
|
||||
// users
|
||||
{ action: 'admin::users.create', subject: null },
|
||||
{ action: 'admin::users.read', subject: null },
|
||||
{ action: 'admin::users.update', subject: null },
|
||||
{ action: 'admin::users.delete', subject: null },
|
||||
// roles
|
||||
{ action: 'admin::roles.create', subject: null },
|
||||
{ action: 'admin::roles.update', subject: null },
|
||||
{ action: 'admin::roles.read', subject: null },
|
||||
{ action: 'admin::roles.delete', subject: null },
|
||||
// media library
|
||||
{ action: 'plugins::upload.read', subject: null },
|
||||
{ action: 'plugins::upload.assets.create', subject: null },
|
||||
{ action: 'plugins::upload.assets.update', subject: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const reducer = (state, action) =>
|
||||
produce(state, draftState => {
|
||||
switch (action.type) {
|
||||
case 'SET_LINK_PERMISSION': {
|
||||
set(draftState, ['generalSectionLinks', action.index, 'isDisplayed'], action.hasPermission);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return draftState;
|
||||
}
|
||||
});
|
||||
|
||||
export default reducer;
|
||||
export { initialState };
|
||||
@ -17,7 +17,7 @@ const data = {
|
||||
action: 'admin::marketplace.plugins.uninstall',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: [],
|
||||
conditions: ['customCondition'],
|
||||
},
|
||||
|
||||
// Admin webhooks
|
||||
@ -222,24 +222,24 @@ const data = {
|
||||
],
|
||||
user2: [
|
||||
// Admin marketplace
|
||||
{
|
||||
action: 'admin::marketplace.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: [],
|
||||
},
|
||||
// {
|
||||
// action: 'admin::marketplace.read',
|
||||
// subject: null,
|
||||
// fields: null,
|
||||
// conditions: [],
|
||||
// },
|
||||
{
|
||||
action: 'admin::marketplace.plugins.install',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'admin::marketplace.plugins.uninstall',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: [],
|
||||
conditions: ['some condition'],
|
||||
},
|
||||
// {
|
||||
// action: 'admin::marketplace.plugins.uninstall',
|
||||
// subject: null,
|
||||
// fields: null,
|
||||
// conditions: [],
|
||||
// },
|
||||
|
||||
// Admin webhooks
|
||||
{
|
||||
@ -324,7 +324,7 @@ const data = {
|
||||
action: 'plugins::content-type-builder.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
|
||||
// Documentation plugin
|
||||
@ -332,19 +332,19 @@ const data = {
|
||||
// action: 'plugins::documentation.read',
|
||||
// subject: null,
|
||||
// fields: null,
|
||||
// conditions: null,
|
||||
// conditions:[],
|
||||
// },
|
||||
// {
|
||||
// action: 'plugins::documentation.settings.update',
|
||||
// subject: null,
|
||||
// fields: null,
|
||||
// conditions: null,
|
||||
// conditions:[],
|
||||
// },
|
||||
// {
|
||||
// action: 'plugins::documentation.settings.regenerate',
|
||||
// subject: null,
|
||||
// fields: null,
|
||||
// conditions: null,
|
||||
// conditions:[],
|
||||
// },
|
||||
|
||||
// Upload plugin
|
||||
@ -352,31 +352,31 @@ const data = {
|
||||
action: 'plugins::upload.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::upload.assets.create',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::upload.assets.update',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::upload.assets.dowload',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::upload.assets.copy-link',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
|
||||
// Users-permissions
|
||||
@ -384,61 +384,61 @@ const data = {
|
||||
action: 'plugins::users-permissions.roles.create',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.roles.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.roles.update',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.roles.delete',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.email-templates.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.email-templates.update',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.providers.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.providers.update',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.advanced-settings.read',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
{
|
||||
action: 'plugins::users-permissions.advanced-settings.update',
|
||||
subject: null,
|
||||
fields: null,
|
||||
conditions: null,
|
||||
conditions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
36
packages/strapi-admin/admin/src/utils/hasPermissions.js
Normal file
36
packages/strapi-admin/admin/src/utils/hasPermissions.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { transform } from 'lodash';
|
||||
|
||||
const hasPermissions = async (userPermissions, permissions) => {
|
||||
const matchingPermissions = transform(
|
||||
userPermissions,
|
||||
(result, value) => {
|
||||
const associatedPermission = permissions.find(
|
||||
perm => perm.action === value.action && perm.subject === value.subject
|
||||
);
|
||||
|
||||
if (associatedPermission) {
|
||||
result.push(value);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
if (!permissions.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchingPermissions.some(perm => perm.conditions && perm.conditions.length)) {
|
||||
console.log('should do something');
|
||||
const hasPermission = await new Promise(resolve =>
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, 2000)
|
||||
);
|
||||
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
return matchingPermissions.length > 0;
|
||||
};
|
||||
|
||||
export default hasPermissions;
|
||||
@ -1,3 +1,5 @@
|
||||
export { default as checkFormValidity } from './checkFormValidity';
|
||||
export { default as formatAPIErrors } from './formatAPIErrors';
|
||||
export { default as roleTabsLabel } from './roleTabsLabel';
|
||||
export { default as fakePermissionsData } from './fakePermissionsData';
|
||||
export { default as hasPermissions } from './hasPermissions';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user