Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chatty-planets-stay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"strapi-plugin-webtools": patch
---

fix: use RBAC hook instead of <Page.Protect> for the permission check of the sidebar view
5 changes: 5 additions & 0 deletions .changeset/ready-lands-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"strapi-plugin-webtools": minor
---

feat: introduce a new rbac permission 'overview'
5 changes: 5 additions & 0 deletions .changeset/social-goats-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"strapi-plugin-webtools": patch
---

fix: cleanup rbac permission usage
5 changes: 5 additions & 0 deletions .changeset/tall-mangos-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"strapi-plugin-webtools": patch
---

fix: prevent the whole form from being removed when a user doesn't have url_alias permissions
2 changes: 1 addition & 1 deletion packages/addons/sitemap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"watch": "../../../node_modules/.bin/pack-up watch",
"watch:link": "../../../node_modules/.bin/strapi-plugin watch:link",
"develop:copy-files": "copyfiles -u 1 xsl/**/* ../../../playground/src/plugins/webtools-addon-sitemap/xsl/",
"eslint": "../../../node_modules/.bin/eslint './**/*.{js,jsx,ts,tsx}'",
"eslint": "../../../node_modules/.bin/eslint --max-warnings=0 './**/*.{js,jsx,ts,tsx}'",
"eslint:fix": "../../../node_modules/.bin/eslint --fix './**/*.{js,jsx,ts,tsx}'"
},
"peerDependencies": {
Expand Down
1 change: 0 additions & 1 deletion packages/addons/sitemap/server/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { logMessage } from './utils';
import { getPluginService } from './utils/getPluginService';

export default async () => {
const sitemap = strapi.plugin('webtools-addon-sitemap');
const cron = strapi.config.get('plugin::webtools-addon-sitemap.cron');

try {
Expand Down
30 changes: 16 additions & 14 deletions packages/core/admin/components/EditView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { useEffect } from 'react';
import { useQuery } from 'react-query';
import { unstable_useContentManagerContext, Page, useFetchClient } from '@strapi/strapi/admin';
import {
unstable_useContentManagerContext,
useFetchClient,
useRBAC,
} from '@strapi/strapi/admin';
import EditForm from '../EditForm';
import Permalink from './Permalink';
import { isContentTypeEnabled } from '../../../server/util/enabledContentTypes';
Expand All @@ -9,6 +13,9 @@ import pluginPermissions from '../../permissions';

const EditView = () => {
const { get } = useFetchClient();
const {
allowedActions: { canSidebar },
} = useRBAC(pluginPermissions);
const context = unstable_useContentManagerContext();
const {
contentType,
Expand All @@ -31,19 +38,13 @@ const EditView = () => {
useEffect(() => {
const label = Array.from(document.querySelectorAll('label')).find((l) => l.textContent.startsWith('url_alias'));
if (label) {
let parentDiv = label.closest('div');
for (let i = 0; i < 3; i++) {
if (parentDiv) {
// @ts-expect-error
parentDiv = parentDiv.parentElement;
}
}
if (parentDiv) {
parentDiv.remove();
}
label.closest('div').remove();
}
}, []);

// Early return if the user has no permissions to view the sidebar.
if (!canSidebar) return null;

// @ts-expect-error
// Early return if the content type is not enabled.
if (!isContentTypeEnabled(contentType)) return null;
Expand All @@ -54,12 +55,13 @@ const EditView = () => {
aliases.refetch();
}

// Early return for loading and error states.
// Early return for loading, error and empty states.
if (aliases.isLoading) return null;
if (aliases.error) return null;
if (!aliases.data) return null;

return (
<Page.Protect permissions={pluginPermissions['edit-view.sidebar']}>
<>
<EditForm />
{aliases.data.data.length === 0 && (
<div>Save the form to generate the URL alias</div>
Expand All @@ -69,7 +71,7 @@ const EditView = () => {
path={aliases.data.data[0].url_path}
/>
)}
</Page.Protect>
</>
);
};

Expand Down
65 changes: 39 additions & 26 deletions packages/core/admin/containers/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import {
SubNavSection,
SubNavLink,
} from '@strapi/design-system';
import { Page, useStrapiApp, Layouts } from '@strapi/strapi/admin';
import {
useStrapiApp,
Layouts,
useRBAC,
} from '@strapi/strapi/admin';

import pluginPermissions from '../../permissions';
import pluginId from '../../helpers/pluginId';
Expand All @@ -27,6 +31,9 @@ import { InjectedRoute } from '../../types/injection-zones';

const App = () => {
const getPlugin = useStrapiApp('MyComponent', (state) => state.getPlugin);
const {
allowedActions: { canList, canPatterns, canOverview },
} = useRBAC(pluginPermissions);

const plugin = getPlugin(pluginId);

Expand All @@ -36,48 +43,54 @@ const App = () => {
const currentPath = location.pathname;

return (
<Page.Protect permissions={pluginPermissions['settings.patterns']}>
<Layouts.Root
sideNav={(
<SubNav>
<SubNavHeader value="" label="Webtools" />
<SubNavSections>
<SubNavSection label="Core">
<Layouts.Root
sideNav={(
<SubNav>
<SubNavHeader value="" label="Webtools" />
<SubNavSections>
<SubNavSection label="Core">
{canOverview && (
<SubNavLink tag={Link} to="/plugins/webtools" key="test" className={currentPath === '/plugins/webtools' ? 'active' : ''}>
Overview
</SubNavLink>
)}
{canList && (
<SubNavLink tag={Link} to="/plugins/webtools/urls" key="test" className={currentPath.startsWith('/plugins/webtools/urls') ? 'active' : ''}>
All URLs
</SubNavLink>
)}
{canPatterns && (
<SubNavLink tag={Link} to="/plugins/webtools/patterns" key="test" className={currentPath.startsWith('/plugins/webtools/patterns') ? 'active' : ''}>
Url Patterns
</SubNavLink>
</SubNavSection>
)}
</SubNavSection>
{routerComponents.length > 0 && (
<SubNavSection label="Addons">
{routerComponents.map(({ path, label }) => (
<SubNavLink tag={Link} to={`/plugins/webtools${path}`} key={path} className={currentPath.startsWith(`/plugins/webtools${path}`) ? 'active' : ''}>
{label}
</SubNavLink>
))}
</SubNavSection>
</SubNavSections>
</SubNav>
)}
>
<Routes>
<Route path="/" element={<Overview />} />
<Route path="/urls" element={<List />} />
<Route path="/patterns" element={<PatternsListPage />} />
<Route path="/patterns/new" element={<PatternsCreatePage />} />
<Route path="/patterns/:id" element={<PatternsEditPage />} />
{routerComponents.map(({ path, Component }) => (
<Route path={path} element={<Component />} />
))}
)}
</SubNavSections>
</SubNav>
)}
>
<Routes>
<Route path="/" element={<Overview />} />
<Route path="/urls" element={<List />} />
<Route path="/patterns" element={<PatternsListPage />} />
<Route path="/patterns/new" element={<PatternsCreatePage />} />
<Route path="/patterns/:id" element={<PatternsEditPage />} />
{routerComponents.map(({ path, Component }) => (
<Route path={path} element={<Component />} />
))}

<Route path="*" element={<PageNotFound />} />
</Routes>
</Layouts.Root>
</Page.Protect>
<Route path="*" element={<PageNotFound />} />
</Routes>
</Layouts.Root>
);
};

Expand Down
7 changes: 6 additions & 1 deletion packages/core/admin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { prefixPluginTranslations } from './helpers/prefixPluginTranslations';
import CheckboxConfirmation from './components/ContentManagerHooks/ConfirmationCheckbox';

import { PluginIcon } from './components/PluginIcon';
import pluginPermissions from './permissions';

const { name } = pluginPkg.strapi;

Expand Down Expand Up @@ -41,7 +42,11 @@ export default {

return component;
},
permissions: [], // permissions to apply to the link
permissions: [
pluginPermissions['settings.overview'][0],
pluginPermissions['settings.list'][0],
pluginPermissions['settings.patterns'][0],
],
});
},
bootstrap(app: StrapiApp) {
Expand Down
7 changes: 6 additions & 1 deletion packages/core/admin/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
/**
* @todo
* Change the permission keys to be single words.
* That way the permissions work better wit the useRBAC hook.
*/
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
'settings.list': [{ action: 'plugin::webtools.settings.list', subject: null }],
// 'settings.overview': [{ action: 'plugin::webtools.settings.overview', subject: null }],
'settings.overview': [{ action: 'plugin::webtools.settings.overview', subject: null }],
'settings.patterns': [{ action: 'plugin::webtools.settings.patterns', subject: null }],
'edit-view.sidebar': [{ action: 'plugin::webtools.edit-view.sidebar', subject: null }],
};
Expand Down
2 changes: 1 addition & 1 deletion packages/core/admin/screens/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const List = () => {
}

return (
<Page.Protect permissions={pluginPermissions['settings.patterns']}>
<Page.Protect permissions={pluginPermissions['settings.list']}>
<Layouts.Header
title={formatMessage({ id: 'webtools.settings.page.list.title', defaultMessage: 'URLs' })}
subtitle={formatMessage({ id: 'webtools.settings.page.list.description', defaultMessage: 'A list of all the known URL aliases.' })}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/admin/screens/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const List = () => {
);
}
return (
<Page.Protect permissions={pluginPermissions['settings.patterns']}>
<Page.Protect permissions={pluginPermissions['settings.overview']}>
<Layouts.Header
title={formatMessage({ id: 'webtools.settings.page.overview.title', defaultMessage: 'Overview' })}
subtitle={formatMessage({ id: 'webtools.settings.page.overview.description', defaultMessage: 'Webtools global information' })}
Expand Down
Loading