这个 bug 已经存在很长时间了。我去年研究过它,以下是重现它的步骤:
- 作为管理员,将“最多收藏徽章”设置为 2,并创建至少一个可以多次获得的徽章。
- 作为普通用户,将两个徽章设置为收藏,其中一个是可多次获得的徽章(称为徽章 A)。
- 作为管理员,再次授予用户徽章 A。
- 作为普通用户,刷新页面并尝试取消收藏徽章 A。您将遇到错误。
错误的原因是,每次授予可多次获得的徽章时,都会在数据库中创建一个新的 user_badge 记录。但是,当用户收藏了该徽章并再次获得它时,新的 user_badge 记录不会自动标记为 is_favorite。当用户尝试取消收藏徽章 A 时,前端默认会发送最新的 user_badge ID。由于此记录未标记为 is_favorite,后端会认为用户正在尝试将新徽章设为收藏(而不是取消收藏),这超出了 max favorite badges 的限制,从而导致错误。
相关代码位于:
一个可能的解决方案是将第 131 行修改为:
if UserBadge.where(badge: user_badge.badge, user: user_badge.user).pluck(:is_favorite).any? &&
然而,这并没有完全解决数据库记录中的不一致问题。
作为临时解决方法,普通用户可以通过在控制台中运行以下 JavaScript 代码来取消收藏所有徽章:
const user_name = require("discourse/models/user").default.current().username;
const badges = await require("discourse/models/user-badge").default.findByUsername(user_name);
const favorites = new Map();
badges.filter((b)=>b.is_favorite).forEach((b)=>favorites.set(b.badge_id,b));
favorites.forEach((b)=>b.favorite());