Add permissions to homepage

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2020-06-12 12:39:34 +02:00 committed by Alexandre Bodin
parent d674b1f7e6
commit 51722ca3a1
8 changed files with 180 additions and 94 deletions

View File

@ -425,7 +425,7 @@ const data = {
// Users-permissions
{
action: 'plugins::users-permissions.roles.create',
action: 'plugins::users-permissions.roles.createe',
subject: null,
fields: null,
conditions: [],
@ -466,12 +466,12 @@ const data = {
fields: null,
conditions: [],
},
{
action: 'plugins::users-permissions.providers.update',
subject: null,
fields: null,
conditions: [],
},
// {
// action: 'plugins::users-permissions.providers.update',
// subject: null,
// fields: null,
// conditions: [],
// },
{
action: 'plugins::users-permissions.advanced-settings.read',
subject: null,
@ -479,7 +479,7 @@ const data = {
conditions: [],
},
{
action: 'plugins::users-permissions.advanced-settings.update',
action: 'plugins::users-permissions.advanced-settings.eupdate',
subject: null,
fields: null,
conditions: [],

View File

@ -12,7 +12,7 @@ import { InputsIndex as Input, LoadingIndicator } from 'strapi-helper-plugin';
import { Wrapper } from './Components';
function EditForm({ onChange, showLoaders, values }) {
function EditForm({ disabled, onChange, showLoaders, values }) {
const { roles, settings } = values;
const generateSelectOptions = () =>
@ -44,6 +44,7 @@ function EditForm({ onChange, showLoaders, values }) {
selectOptions={generateSelectOptions()}
type="select"
value={get(settings, 'default_role')}
disabled={disabled}
/>
<div className="col-6"></div>
<Input
@ -56,16 +57,17 @@ function EditForm({ onChange, showLoaders, values }) {
name="advanced.settings.unique_email"
onChange={onChange}
type="toggle"
disabled={disabled}
value={get(settings, 'unique_email')}
/>
<div className="col-6"></div>
<Input
disabled={disabled}
label={{
id: 'users-permissions.EditForm.inputToggle.label.sign-up',
}}
inputDescription={{
id:
'users-permissions.EditForm.inputToggle.description.sign-up',
id: 'users-permissions.EditForm.inputToggle.description.sign-up',
}}
name="advanced.settings.allow_register"
onChange={onChange}
@ -74,13 +76,12 @@ function EditForm({ onChange, showLoaders, values }) {
/>
<div className="col-6"></div>
<Input
disabled={disabled}
label={{
id:
'users-permissions.EditForm.inputToggle.label.email-reset-password',
id: 'users-permissions.EditForm.inputToggle.label.email-reset-password',
}}
inputDescription={{
id:
'users-permissions.EditForm.inputToggle.description.email-reset-password',
id: 'users-permissions.EditForm.inputToggle.description.email-reset-password',
}}
name="advanced.settings.email_reset_password"
onChange={onChange}
@ -89,13 +90,12 @@ function EditForm({ onChange, showLoaders, values }) {
/>
<div className="col-6"></div>
<Input
disabled={disabled}
label={{
id:
'users-permissions.EditForm.inputToggle.label.email-confirmation',
id: 'users-permissions.EditForm.inputToggle.label.email-confirmation',
}}
inputDescription={{
id:
'users-permissions.EditForm.inputToggle.description.email-confirmation',
id: 'users-permissions.EditForm.inputToggle.description.email-confirmation',
}}
name="advanced.settings.email_confirmation"
onChange={onChange}
@ -104,9 +104,9 @@ function EditForm({ onChange, showLoaders, values }) {
/>
<div className="col-6"></div>
<Input
disabled={disabled}
label={{
id:
'users-permissions.EditForm.inputToggle.label.email-confirmation-redirection',
id: 'users-permissions.EditForm.inputToggle.label.email-confirmation-redirection',
}}
inputDescription={{
id:
@ -125,6 +125,7 @@ function EditForm({ onChange, showLoaders, values }) {
}
EditForm.propTypes = {
disabled: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired,
showLoaders: PropTypes.bool.isRequired,
values: PropTypes.object.isRequired,

View File

@ -8,7 +8,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { map, omitBy, size } from 'lodash';
import { Button, LoadingBar, LoadingIndicator } from 'strapi-helper-plugin';
import { Button, LoadingBar, LoadingIndicator, CheckPermissions } from 'strapi-helper-plugin';
import pluginPermissions from '../../permissions';
import ListRow from '../ListRow';
import { Flex, ListWrapper, Title, Wrapper } from './Components';
@ -86,6 +87,7 @@ const generateListTitle = (data, settingType) => {
};
function List({
allowedActions,
data,
deleteData,
noButton,
@ -95,6 +97,14 @@ function List({
values,
}) {
const object = omitBy(data, v => v.name === 'server'); // Remove the server key when displaying providers
const button = allowedActions.canCreateRole ? (
<Button onClick={onButtonClick} secondaryHotlineAdd>
<FormattedMessage id={`users-permissions.List.button.${settingType}`} />
</Button>
) : (
// Align the list
<div style={{ height: 26 }} />
);
return (
<Wrapper>
@ -106,17 +116,7 @@ function List({
generateListTitle(data, settingType)
)}
</Title>
<div>
{noButton ? (
''
) : (
<Button onClick={onButtonClick} secondaryHotlineAdd>
<FormattedMessage
id={`users-permissions.List.button.${settingType}`}
/>
</Button>
)}
</div>
<div>{noButton ? '' : button}</div>
</Flex>
<ListWrapper
@ -130,6 +130,7 @@ function List({
<ul className={noButton ? 'padded-list' : ''}>
{map(object, item => (
<ListRow
allowedActions={allowedActions}
deleteData={deleteData}
item={item}
key={item.name}

View File

@ -10,8 +10,10 @@ import { FormattedMessage } from 'react-intl';
import { capitalize, get, includes } from 'lodash';
import { IconLinks } from '@buffetjs/core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { CheckPermissions, PopUpWarning } from 'strapi-helper-plugin';
import getTrad from '../../utils/getTrad';
import { PopUpWarning } from 'strapi-helper-plugin';
import pluginPermissions from '../../permissions';
import en from '../../translations/en.json';
import { HomePageContext } from '../../contexts/HomePage';
import { Container, Flex, Row, Wrapper } from './Components';
@ -30,30 +32,38 @@ class ListRow extends React.Component {
undeletableIDs = ['public', 'authenticated'];
generateContent = () => {
let links = [
{
icon: <FontAwesomeIcon icon="pencil-alt" />,
onClick: this.handleClick,
},
{
icon: <FontAwesomeIcon icon="trash-alt" />,
onClick: e => {
e.stopPropagation();
this.setState({ showModalDelete: true });
},
},
];
switch (this.props.settingType) {
case 'roles':
if (includes(this.protectedRoleIDs, get(this.props.item, 'type', ''))) {
links = [];
}
let links = [
{
icon: (
<CheckPermissions permissions={pluginPermissions.updateRole}>
<FontAwesomeIcon icon="pencil-alt" />
</CheckPermissions>
),
onClick: this.handleClick,
},
{
icon: (
<CheckPermissions permissions={pluginPermissions.deleteRole}>
<FontAwesomeIcon icon="trash-alt" />
</CheckPermissions>
),
onClick: e => {
e.stopPropagation();
this.setState({ showModalDelete: true });
},
},
];
if (includes(this.undeletableIDs, get(this.props.item, 'type', ''))) {
links = [
{
icon: <FontAwesomeIcon icon="pencil-alt" />,
icon: (
<CheckPermissions permissions={pluginPermissions.updateRole}>
<FontAwesomeIcon icon="pencil-alt" />
</CheckPermissions>
),
onClick: this.handleClick,
},
];
@ -75,8 +85,6 @@ class ListRow extends React.Component {
</Wrapper>
);
case 'providers':
links.pop(); // Remove the delete CTA
return (
<Wrapper className="row">
<div className="col-md-4">
@ -103,14 +111,23 @@ class ListRow extends React.Component {
)}
</div>
<div className="col-md-2">
<IconLinks links={links} />
<IconLinks
links={[
{
icon: (
<CheckPermissions permissions={pluginPermissions.updateProviders}>
<FontAwesomeIcon icon="pencil-alt" />
</CheckPermissions>
),
onClick: this.handleClick,
},
]}
/>
</div>
</Wrapper>
);
case 'email-templates':
links.pop(); // Remove the delete CTA
return (
<Wrapper className="row">
<div className="col-md-4">
@ -128,7 +145,18 @@ class ListRow extends React.Component {
</Flex>
</div>
<div className="col-md-8">
<IconLinks links={links} />
<IconLinks
links={[
{
icon: (
<CheckPermissions permissions={pluginPermissions.updateEmailTemplates}>
<FontAwesomeIcon icon="pencil-alt" />
</CheckPermissions>
),
onClick: this.handleClick,
},
]}
/>
</div>
</Wrapper>
);
@ -140,6 +168,7 @@ class ListRow extends React.Component {
handleClick = () => {
const { pathname, push } = this.context;
const { allowedActions } = this.props;
switch (this.props.settingType) {
case 'roles': {
@ -168,7 +197,7 @@ class ListRow extends React.Component {
render() {
return (
<Row onClick={this.handleClick}>
<Row>
<Container>{this.generateContent()}</Container>
<PopUpWarning
isOpen={this.state.showModalDelete}

View File

@ -6,16 +6,23 @@
*/
import React from 'react';
import { CheckPagePermissions } from 'strapi-helper-plugin';
import { Redirect } from 'react-router-dom';
import { LoadingIndicatorPage, useUserPermissions } from 'strapi-helper-plugin';
import pluginPermissions from '../../permissions';
import Main from '../Main';
const App = () => {
return (
<CheckPagePermissions permissions={pluginPermissions.main}>
<Main />
</CheckPagePermissions>
);
const { isLoading, allowedActions } = useUserPermissions(pluginPermissions);
if (isLoading) {
return <LoadingIndicatorPage />;
}
if (allowedActions.canMain) {
return <Main allowedActions={allowedActions} />;
}
return <Redirect to="/" />;
};
export default App;

View File

@ -11,7 +11,8 @@ import { injectIntl } from 'react-intl';
import { bindActionCreators, compose } from 'redux';
import { clone, get, includes, isEqual, isEmpty } from 'lodash';
import { Header } from '@buffetjs/custom';
import { GlobalContext, HeaderNav } from 'strapi-helper-plugin';
import { Button } from '@buffetjs/core';
import { GlobalContext, HeaderNav, CheckPermissions } from 'strapi-helper-plugin';
import pluginId from '../../pluginId';
import getTrad from '../../utils/getTrad';
import { HomePageContextProvider } from '../../contexts/HomePage';
@ -33,6 +34,7 @@ import {
} from './actions';
import saga from './saga';
import checkFormValidity from './checkFormValidity';
import pluginPermissions from '../../permissions';
/* eslint-disable consistent-return */
/* eslint-disable react/sort-comp */
@ -43,25 +45,6 @@ const keyBoardShortCuts = [18, 78];
export class HomePage extends React.Component {
state = { mapKey: {}, showModalEdit: false };
headerNavLinks = [
{
name: getTrad('HeaderNav.link.roles'),
to: `/plugins/${pluginId}/roles`,
},
{
name: getTrad('HeaderNav.link.providers'),
to: `/plugins/${pluginId}/providers`,
},
{
name: getTrad('HeaderNav.link.emailTemplates'),
to: `/plugins/${pluginId}/email-templates`,
},
{
name: getTrad('HeaderNav.link.advancedSettings'),
to: `/plugins/${pluginId}/advanced`,
},
];
pluginHeaderActions = [
{
label: this.context.formatMessage({
@ -71,6 +54,11 @@ export class HomePage extends React.Component {
onClick: () => this.props.cancelChanges(),
type: 'button',
key: 'button-cancel',
Component: props => (
<CheckPermissions permissions={pluginPermissions.updateAdvancedSettings}>
<Button {...props} />
</CheckPermissions>
),
},
{
color: 'success',
@ -80,6 +68,11 @@ export class HomePage extends React.Component {
onClick: () => this.props.submit(this.props.match.params.settingType),
type: 'submit',
key: 'button-submit',
Component: props => (
<CheckPermissions permissions={pluginPermissions.updateAdvancedSettings}>
<Button {...props} />
</CheckPermissions>
),
},
];
@ -191,6 +184,7 @@ export class HomePage extends React.Component {
render() {
const {
allowedActions,
data,
didCheckErrors,
formErrors,
@ -198,7 +192,9 @@ export class HomePage extends React.Component {
initialData,
match,
dataToEdit,
tabs,
} = this.props;
console.log(tabs);
const { formatMessage } = this.context;
const headerActions =
match.params.settingType === 'advanced' && !isEqual(modifiedData, initialData)
@ -229,9 +225,10 @@ export class HomePage extends React.Component {
})}
actions={headerActions}
/>
<HeaderNav links={this.headerNavLinks} style={{ marginTop: '4.6rem' }} />
<HeaderNav links={tabs} style={{ marginTop: '4.6rem' }} />
{!this.isAdvanded() ? (
<List
allowedActions={allowedActions}
data={get(data, this.getEndPoint(), [])}
deleteData={this.props.deleteData}
noButton={noButtonList}
@ -242,6 +239,7 @@ export class HomePage extends React.Component {
/>
) : (
<EditForm
disabled={!allowedActions.canUpdateAdvancedSettings}
onChange={this.props.onChange}
values={values}
showLoaders={this.showLoaders()}

View File

@ -8,17 +8,34 @@
import React from 'react';
import { Switch, Redirect, Route, useRouteMatch } from 'react-router-dom';
import { NotFound } from 'strapi-helper-plugin';
import { get, upperFirst, camelCase } from 'lodash';
import pluginId from '../../pluginId';
import getTrad from '../../utils/getTrad';
import EditPage from '../EditPage';
import HomePage from '../HomePage';
const Main = () => {
const Main = ({ allowedActions }) => {
const settingType = useRouteMatch(`/plugins/${pluginId}/:settingType`);
const tabs = ['roles', 'providers', 'email-templates', 'advanced-settings']
.map(tabName => {
const name = tabName === 'advanced-settings' ? 'advanced' : tabName;
const camelCaseName = camelCase(tabName);
return {
tabName,
to: `/plugins/${pluginId}/${name}`,
name: getTrad(`HeaderNav.link.${camelCaseName}`),
canAccess: allowedActions[`canRead${upperFirst(camelCaseName)}`],
};
})
.filter(tab => tab.canAccess);
const firstAllowedSettingEndPoint = get(tabs, '0.to', '');
// Todo check if the settingType is allowed
if (!settingType) {
return <Redirect to={`/plugins/${pluginId}/roles`} />;
return <Redirect to={firstAllowedSettingEndPoint} />;
}
return (
@ -29,11 +46,25 @@ const Main = () => {
component={EditPage}
exact
/>
<Route path={`/plugins/${pluginId}/:settingType`} component={HomePage} exact />
<Route
path={`/plugins/${pluginId}/:settingType`}
render={props => <HomePage {...props} tabs={tabs} allowedActions={allowedActions} />}
exact
/>
<Route component={NotFound} />
</Switch>
</div>
);
};
Main.defaultProps = {
allowedActions: {
canMain: false,
canReadAdvancedSettings: false,
canReadEmails: false,
canReadProviders: false,
canReadRoles: false,
},
};
export default Main;

View File

@ -5,14 +5,33 @@ const pluginPermissions = {
// plugin directly in the browser
main: [
{ action: 'plugins::users-permissions.advanced-settings.read', subject: null },
{ action: 'plugins::users-permissions.advanced-settings.update', subject: null },
{ action: 'plugins::users-permissions.email-templates.read', subject: null },
{ action: 'plugins::users-permissions.email-templates.update', subject: null },
{ action: 'plugins::users-permissions.providers.read', subject: null },
{ action: 'plugins::users-permissions.providers.update', subject: null },
{ action: 'plugins::users-permissions.roles.create', subject: null },
{ action: 'plugins::users-permissions.roles.read', subject: null },
],
createRole: [{ action: 'plugins::users-permissions.roles.create', subject: null }],
readAdvancedSettings: [
{ action: 'plugins::users-permissions.advanced-settings.read', subject: null },
// { action: 'plugins::users-permissions.advanced-settings.update', subject: null },
],
updateAdvancedSettings: [
{ action: 'plugins::users-permissions.advanced-settings.update', subject: null },
],
readEmailTemplates: [
{ action: 'plugins::users-permissions.email-templates.read', subject: null },
// { action: 'plugins::users-permissions.email-templates.update', subject: null },
],
updateEmailTemplates: [
{ action: 'plugins::users-permissions.email-templates.update', subject: null },
],
readProviders: [
{ action: 'plugins::users-permissions.providers.read', subject: null },
// { action: 'plugins::users-permissions.providers.update', subject: null },
],
updateProviders: [{ action: 'plugins::users-permissions.providers.update', subject: null }],
readRoles: [{ action: 'plugins::users-permissions.roles.read', subject: null }],
updateRole: [{ action: 'plugins::users-permissions.roles.update', subject: null }],
deleteRole: [{ action: 'plugins::users-permissions.roles.delete', subject: null }],
};
export default pluginPermissions;