You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Strapi中如何实现仅允许用户置顶自身发布帖子的功能?

解决Strapi中用户仅能置顶自身帖子的方案

针对你遇到的问题,结合现有集合结构,提供几个可行的实现方式,从界面限制到API校验全覆盖:

1. 后台界面层限制:给关联字段添加筛选规则

直接在Strapi后台配置User集合的pinned关联字段,让用户只能看到自己创建的帖子:

  • 进入Strapi后台 → 内容类型生成器 → 编辑User集合
  • 找到pinned关联字段,点击「编辑」按钮
  • 切换到「高级设置」标签,在「筛选」区域添加规则:
    • 选择Creator → ID → 「等于」 → 输入$currentUser.id
  • 保存配置后,后台用户在选择置顶帖子时,只会显示自己发布的内容

2. API层强制校验:使用生命周期钩子

仅靠界面限制不够,必须在API层面拦截非法请求,防止前端绕过直接提交他人帖子ID。在User集合的生命周期钩子中添加校验逻辑:

创建/修改src/api/user/content-types/user/lifecycles.js文件,写入以下代码:

module.exports = {
  // 创建用户时校验置顶帖子
  async beforeCreate(event) {
    const { data } = event.params;
    // 取当前操作的用户ID(根据上下文调整,若为用户自己操作则取event.params.user.id)
    const userId = event.params.user?.id || data.id;

    // 校验置顶数量不超过3
    if (data.pinned?.length > 3) {
      throw new Error('最多只能置顶3篇帖子');
    }

    // 校验每篇置顶帖子的创作者是当前用户
    if (data.pinned) {
      for (const postId of data.pinned) {
        const post = await strapi.db.query('api::post.post').findOne({
          where: { id: postId },
          select: ['creator'],
        });
        if (!post || post.creator.id !== userId) {
          throw new Error('只能置顶自己发布的帖子');
        }
      }
    }
  },

  // 更新用户时校验置顶帖子
  async beforeUpdate(event) {
    const { data, where } = event.params;
    // 获取当前用户ID
    const user = await strapi.db.query('api::user.user').findOne({ where });
    const userId = user.id;

    if (data.pinned?.length > 3) {
      throw new Error('最多只能置顶3篇帖子');
    }

    if (data.pinned) {
      for (const postId of data.pinned) {
        const post = await strapi.db.query('api::post.post').findOne({
          where: { id: postId },
          select: ['creator'],
        });
        if (!post || post.creator.id !== userId) {
          throw new Error('只能置顶自己发布的帖子');
        }
      }
    }
  },
};

这段代码会在创建/更新用户时自动校验:

  • 置顶帖子数量不超过3篇
  • 每篇置顶帖子的创作者ID与当前用户ID一致

3. 进阶优化:自定义API路由(可选)

如果需要更灵活的逻辑控制,可以自定义User的更新路由,在路由层面做校验。例如修改src/api/user/routes/user.js:

module.exports = {
  routes: [
    {
      method: 'PUT',
      path: '/users/:id',
      handler: 'user.update',
      config: {
        middlewares: ['api::user.validate-pinned-posts'],
      },
    },
  ],
};

然后创建中间件src/api/user/middlewares/validate-pinned-posts.js:

module.exports = async (ctx, next) => {
  const { id: userId } = ctx.params;
  const { pinned } = ctx.request.body.data;

  // 校验逻辑和生命周期钩子一致
  if (pinned?.length > 3) {
    ctx.throw(400, '最多只能置顶3篇帖子');
  }

  if (pinned) {
    for (const postId of pinned) {
      const post = await strapi.db.query('api::post.post').findOne({
        where: { id: postId },
        select: ['creator'],
      });
      if (!post || post.creator.id !== parseInt(userId)) {
        ctx.throw(403, '只能置顶自己发布的帖子');
      }
    }
  }

  await next();
};

注意事项

  • 后台筛选仅优化用户操作体验,必须配合API层校验才能彻底限制非法请求
  • 生命周期钩子是Strapi中最简便的校验方式,推荐优先使用
  • 若使用JWT认证,确保在钩子中能正确获取当前操作的用户ID

内容的提问来源于stack exchange,提问作者katjasdf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:38:16