'FAILED'-Fehler beim Versuch, die 'Bug Reporter'-Abzeichen zu entsternen

Dieser Fehler besteht schon seit langer Zeit. Ich habe ihn letztes Jahr recherchiert, und hier sind die Schritte, um ihn zu reproduzieren:

  1. Als Administrator setzen Sie max favorite badges auf 2 und erstellen Sie mindestens eine Auszeichnung, die mehrmals verdient werden kann.
  2. Als normaler Benutzer markieren Sie zwei Auszeichnungen als Favoriten, eine davon ist die Auszeichnung, die mehrmals verdient werden kann (im Folgenden als Auszeichnung A bezeichnet).
  3. Als Administrator verleihen Sie dem Benutzer Auszeichnung A erneut.
  4. Als normaler Benutzer aktualisieren Sie die Seite und versuchen Sie, Auszeichnung A zu entfavorisieren. Sie werden auf den Fehler stoßen.

Der Grund für den Fehler ist, dass jedes Mal, wenn eine Auszeichnung, die mehrmals verdient werden kann, verliehen wird, ein neuer user_badge-Datensatz in der Datenbank erstellt wird. Wenn der Benutzer die Auszeichnung jedoch favorisiert hat und sie dann erneut erhält, wird der neue user_badge-Datensatz nicht automatisch als is_favorite markiert. Wenn der Benutzer versucht, Auszeichnung A zu entfavorisieren, sendet das Frontend standardmäßig die aktuellste user_badge-ID. Da dieser Datensatz nicht als is_favorite markiert ist, geht das Backend davon aus, dass der Benutzer versucht, eine neue Auszeichnung als Favorit zu setzen (anstatt sie zu entfavorisieren), was das Limit von max favorite badges überschreitet und zu dem Fehler führt.

Der relevante Code befindet sich hier:

Eine mögliche Lösung besteht darin, Zeile 131 zu ändern in:

if UserBadge.where(badge: user_badge.badge, user: user_badge.user).pluck(:is_favorite).any? &&

Dies behebt jedoch nicht vollständig die Inkonsistenz in den Datenbankeinträgen.

Als vorübergehende Lösung kann ein normaler Benutzer alle Auszeichnungen entfavorisieren, indem er den folgenden JavaScript-Code in der Konsole ausführt:

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());
9 „Gefällt mir“