Strapi自定义更新用户端点未在角色权限面板显示的问题排查
问题描述
尝试扩展Strapi的users-permissions插件,添加一个更新用户信息的自定义端点updateMe,但新端点未出现在后台面板的「设置/用户与权限插件/角色/已认证用户/用户权限/user」区域中。
操作步骤
- 在
src/extensions/users-permissions/目录下创建strapi-server.js,代码如下:
const _ = require("lodash"); const utils = require("@strapi/utils"); const { ApplicationError, ValidationError } = utils.errors; module.exports = (plugin) => { plugin.controllers.user.updateMe = async (ctx) => { // 需要登录验证 if (!ctx.state.user || !ctx.state.user.id) { throw new ApplicationError("You need to be logged"); } if ( !_.has(ctx.request.body, "username") || ctx.request.body.username === "" ) { throw new ValidationError("Invalid data"); } const allowedProperties = ["username"]; const bodyKeys = Object.keys(ctx.request.body); if (bodyKeys.filter((key) => !allowedProperties.includes(key)).length > 0) { throw new ValidationError("Invalid data"); } const newBody = {}; bodyKeys.map( (key) => (newBody[key] = ctx.request.body[key].trim().replace(/[<>]/g, "")) ); if (_.has(ctx.request.body, "username")) { const userWithSameUsername = await strapi .query("plugin::users-permissions.user") .findOne({ where: { username: ctx.request.body.username } }); if ( userWithSameUsername && _.toString(userWithSameUsername.id) !== _.toString(ctx.state.user.id) ) { throw new ApplicationError("Username already taken"); } } await strapi .query("plugin::users-permissions.user") .update({ where: { id: ctx.state.user.id }, data: newBody, }) .then((res) => { ctx.response.body = { username: res.username }; ctx.response.status = 200; }); }; plugin.routes["content-api"].routes.push({ method: "PUT", path: "/user/me", handler: "user.updateMe", config: { prefix: "", policies: [], }, }); return plugin; };
- 在
config/plugins.js中注册插件:
module.exports = ({ env }) => ({ email: { config: { provider: "nodemailer", providerOptions: { host: env("SMTP_HOST"), port: env("SMTP_PORT"), auth: { user: env("SMTP_USER"), pass: env("SMTP_PASS"), }, }, settings: { defaultFrom: env("SMTP_DEFAULT_FROM"), defaultReplyTo: env("SMTP_DEFAULT_REPLYTO"), }, }, }, "users-permissions": { enabled: true, resolve: "./src/extensions/users-permissions", }, });
服务正常启动,但后台权限面板中找不到updateMe权限选项,当前使用Strapi版本为4.24.4,降级会引发其他问题。
解决方案
Strapi 4.20+版本对自定义路由的权限配置做了调整,需要显式添加权限元数据才能在后台面板显示对应的权限选项。修改strapi-server.js,补充权限注册逻辑:
修改后的完整代码:
const _ = require("lodash"); const utils = require("@strapi/utils"); const { ApplicationError, ValidationError } = utils.errors; module.exports = (plugin) => { // 保留原控制器逻辑 plugin.controllers.user.updateMe = async (ctx) => { if (!ctx.state.user || !ctx.state.user.id) { throw new ApplicationError("请先登录"); } if ( !_.has(ctx.request.body, "username") || ctx.request.body.username === "" ) { throw new ValidationError("数据无效"); } const allowedProperties = ["username"]; const bodyKeys = Object.keys(ctx.request.body); if (bodyKeys.filter((key) => !allowedProperties.includes(key)).length > 0) { throw new ValidationError("数据无效"); } const newBody = {}; bodyKeys.map( (key) => (newBody[key] = ctx.request.body[key].trim().replace(/[<>]/g, "")) ); if (_.has(ctx.request.body, "username")) { const userWithSameUsername = await strapi .query("plugin::users-permissions.user") .findOne({ where: { username: ctx.request.body.username } }); if ( userWithSameUsername && _.toString(userWithSameUsername.id) !== _.toString(ctx.state.user.id) ) { throw new ApplicationError("用户名已被占用"); } } const updatedUser = await strapi .query("plugin::users-permissions.user") .update({ where: { id: ctx.state.user.id }, data: newBody, }); ctx.response.body = { username: updatedUser.username }; ctx.response.status = 200; }; // 修改路由配置,添加权限范围 plugin.routes["content-api"].routes.push({ method: "PUT", path: "/user/me", handler: "user.updateMe", config: { prefix: "", policies: [], auth: { scope: "plugin::users-permissions.user.updateMe" // 新增权限标识 } }, }); // 注册新权限到插件权限列表 plugin.permissions["content-api"].routes.push({ method: "PUT", path: "/user/me", policy: "", scope: "plugin::users-permissions.user.updateMe" }); // 为权限添加后台显示名称(可选) if (!plugin.permissions["content-api"].controllers.user) { plugin.permissions["content-api"].controllers.user = {}; } plugin.permissions["content-api"].controllers.user.updateMe = { enabled: true, policy: "", scope: "plugin::users-permissions.user.updateMe", displayName: "更新自己的用户信息", description: "允许用户修改自身用户名" }; return plugin; };
关键修改说明
- 在路由的
config.auth.scope中定义权限唯一标识,格式为plugin::插件名.控制器名.方法名 - 将新权限添加到
plugin.permissions["content-api"].routes数组,让Strapi识别该权限 - 可选配置
displayName和description,让后台面板显示更友好的权限名称和说明
修改完成后重启Strapi服务,就能在「已认证用户」的用户权限列表中找到对应的权限选项了。
内容的提问来源于stack exchange,提问作者FD3
相关产品推荐
相关产品推荐

