カスタムコンテンツでフラグを送信した際のTypeError(require_messageフラグ)

バグの説明

ユーザーがカスタムメッセージを必要とするフラグタイプ(例:notify_moderatorsnotify_user、または「メッセージ必須」が有効な管理者作成のカスタムフラグなど)を選択し、メッセージを入力して送信すると、ブラウザで未処理の TypeError が発生し、フラグが送信されません。

再現手順

  1. 任意のトピック投稿にアクセス
  2. フラグボタンをクリックしてフラグモーダルを開く
  3. メッセージを必要とするフラグタイプを選択(例:「その他」/ notify_moderators、または「管理者 → フラグ」で「メッセージ必須」が有効なカスタムフラグ)
  4. テキストエリアにメッセージを入力(最小長さを満たす長さ)
  5. 送信ボタンをクリック

期待される動作

フラグが正常に送信される。

実際の動作

フラグモーダルは閉じるが、フラグは送信されない。ブラウザコンソールには以下が表示される:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'act')
    at n.create (flag.js:24:8)
    at S.createFlag (flag.gjs:205:32)
    at S.takeAction (flag.gjs:196:12)
    at m.perform (reviewable-bundled-action.gjs:47:17)
    at ej._boundaryActionHandler (select-kit.js:685:34)
    ...

根本原因の分析

クラッシュは Flag#createflag.js:24)で発生している:

create(flagModal, opts) {
  const postAction = this.postActionFor(flagModal); // undefined を返す
  // ...
  postAction.act(...) // ← TypeError: Cannot read properties of undefined
}

PostFlag 内の postActionFor は、actions_summary 内で数値の id によって選択されたフラグを検索する:

// post-flag.js
postActionFor(flagModal) {
  return flagModal.args.model.flagModel.actions_summary.find(
    (item) => item.id === flagModal.selected.id
  );
}

バックエンドの PostSerializer は、can_actcountacted のいずれかが真である場合のみ、actions_summary にフラグエントリを含める:

result << summary if summary[:can_act] || summary[:count] || summary[:acted]

require_message: true のフラグ(すべて notify_type: true)の場合、already_did_flagging が真(つまり、ユーザーがその投稿に対して以前に通知タイプのフラグを提出している)であると、post_can_act?can_act: false に設定する。その場合、エントリは actions_summary に存在せず、postActionForundefined を返し、クラッシュが発生する。

一方、Post#flagsAvailable(UI でユーザーが選択できるものを制御)は、ページ読み込み時に構築された actionByName マップを使用するため、actions_summary にエントリが存在しなくなっても、フラグは引き続き選択可能として表示される。

副次的なバグ

flag.gjs には、比較が破綻している箇所もある:

const NOTIFY_MODERATORS_KEY = "notify_moderators"; // 文字列

get notifyModeratorsFlag() {
  return this.flagsAvailable.find((f) => f.id === NOTIFY_MODERATORS_KEY);
  //                                      ^ 数値   ^ 文字列 — 常に false
}

f.id は数値だが NOTIFY_MODERATORS_KEY は文字列であるため、=== は常に false を返し、notifyModeratorsFlag は常に undefined になる。これにより、flagForReview() 内の「レビュー用にフラグ」ボタンのロジックが破綻する。

提案される修正

PostFlag#postActionFor は、TopicFlag#postActionFor がすでに採用している方法と同様に、id による actions_summary の検索ではなく、name_key をキーとする actionByName マップを使用すべきである:

// post-flag.js
postActionFor(flagModal) {
  return flagModal.args.model.flagModel.actionByName[
    flagModal.selected.name_key
  ];
}

また、notifyModeratorsFlagid ではなく name_key で比較すべきである:

get notifyModeratorsFlag() {
  return this.flagsAvailable.find((f) => f.name_key === NOTIFY_MODERATORS_KEY);
}

Discourse バージョン

2026.5.0-latest

再現環境

  • 最新の main ブランチ
「いいね!」 1