如何从插件创建管理面板权限

页面摘要: 插件可以通过服务端使用 strapi.admin.services.permission.actionProvider.registerMany() 注册管理面板权限,然后在管理面板侧使用 <Page.Protect> 组件、useRBAC hook 来保护页面、菜单链接和组件,从而强制执行基于角色的访问控制(RBAC)。

开发 Strapi 插件 时,你可能希望为自己的插件创建管理面板权限。这样一来,你就可以接入 Strapi 的 RBAC 系统,有选择性地向插件中的某些功能授予权限。

要为你的 Strapi 插件创建管理面板权限,需要先在服务端注册这些权限,然后再在管理面板侧实现它们。

在服务端注册权限

每一条权限都必须在插件的 bootstrap 函数中进行注册,如下所示:

JavaScript


'use strict';

const bootstrap = ({ strapi }) => {
  // Register permission actions.
  const actions = [
    {
      section: 'plugins',
      displayName: 'Access the overview page',
      uid: 'overview.access',
      pluginName: 'my-plugin',
    },
    {
      section: 'plugins',
      displayName: 'Access the content manager sidebar',
      uid: 'sidebar.access',
      pluginName: 'my-plugin',
    },
  ];

  strapi.admin.services.permission.actionProvider.registerMany(actions);
};

module.exports = bootstrap;

TypeScript


import type { Core } from '@strapi/strapi';

const bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {
  // Register permission actions.
  const actions = [
    {
      section: 'plugins',
      displayName: 'Access the overview page',
      uid: 'overview.access',
      pluginName: 'my-plugin',
    },
    {
      section: 'plugins',
      displayName: 'Access the content manager sidebar',
      uid: 'sidebar.access',
      pluginName: 'my-plugin',
    },
  ];

  strapi.admin.services.permission.actionProvider.registerMany(actions);
};

export default bootstrap;

在管理面板侧实现权限

在管理面板侧实现权限之前,我们需要先在一个可复用的配置文件中定义它们。该文件可以存放在插件管理面板代码的任意位置。定义方式如下:

const pluginPermissions = {
  'accessOverview': [{ action: 'plugin::my-plugin.overview.access', subject: null }],
  'accessSidebar': [{ action: 'plugin::my-plugin.sidebar.access', subject: null }],
};

export default pluginPermissions;

页面权限

创建好配置文件后,就可以开始实现权限了。如果你是使用 plugin SDK 的 init 命令 引导生成插件的,会有一个示例 HomePage.tsx 文件。实现页面权限的方式如下:

import { Main } from '@strapi/design-system';
import { Page } from '@strapi/strapi/admin';
import { useIntl } from 'react-intl';

import pluginPermissions from '../permissions';
import { getTranslation } from '../utils/getTranslation';

const HomePage = () => {
  const { formatMessage } = useIntl();

  return (
    <Page.Protect permissions={pluginPermissions.accessOverview}>
      <Main>
        <h1>Welcome to {formatMessage({ id: getTranslation('plugin.name') })}</h1>
      </Main>
    </Page.Protect>
  );
};

export { HomePage };

可以看到,我们如何将权限配置文件与 <Page.Protect> 组件结合使用,以要求具备特定权限才能查看此页面。

菜单链接权限

前面的示例可以确保直接访问页面的用户其权限得到校验。不过,你可能也想把指向该页面的菜单链接一并移除。为此,需要对 addMenuLink 的实现做一处修改。方式如下:

import { getTranslation } from './utils/getTranslation';
import { PLUGIN_ID } from './pluginId';
import { Initializer } from './components/Initializer';
import { PluginIcon } from './components/PluginIcon';
import pluginPermissions from './permissions';

export default {
  register(app) {
    app.addMenuLink({
      to: `plugins/${PLUGIN_ID}`,
      icon: PluginIcon,
      intlLabel: {
        id: `${PLUGIN_ID}.plugin.name`,
        defaultMessage: PLUGIN_ID,
      },
      Component: () => import('./pages/App'),
      permissions: [
        pluginPermissions.accessOverview[0],
      ],
    });

    app.registerPlugin({
      id: PLUGIN_ID,
      initializer: Initializer,
      isReady: false,
      name: PLUGIN_ID,
    });
  },
};

使用 useRBAC hook 实现自定义权限

若要对管理面板用户的权限进行更精细的控制,可以使用 useRBAC hook。借助此 hook,你可以按照自己的需要灵活地校验权限,如以下示例所示:

import React from 'react';
import { useRBAC } from '@strapi/strapi/admin';

import pluginPermissions from '../../permissions';

const Sidebar = () => {
  const {
    allowedActions: { canAccessSidebar },
  } = useRBAC(pluginPermissions);

  if (!canAccessSidebar) {
    return null;
  }

  return (
    <div>Sidebar component</div>
  );
};

export default Sidebar;