FIX: CreateThread allows thread creation in closed/read-only/archived channels (#37661)

## Summary

`Chat::CreateThread` allows thread creation in closed, read_only, and
archived channels because it only checks `can_preview_chat_channel?`
(view access) without verifying the channel's status permits content
creation.

## Source

- Patch Triage: https://patch.discourse.org/patch-triage/237
- Original Commit:
https://github.com/discourse/discourse/blob/main/plugins/chat/app/controllers/chat/api/channel_threads_controller.rb

---

🤖 Generated via [Patch Triage](https://patch.discourse.org/patch-triage)
This commit is contained in:
Joffrey JAFFEUX
2026-02-10 10:14:26 +01:00
committed by GitHub
parent 51c4266c35
commit 0c8f52f420
2 changed files with 31 additions and 0 deletions
@@ -28,6 +28,7 @@ module Chat
model :channel
policy :can_view_channel
policy :can_create_thread_in_channel
policy :threading_enabled_for_channel
model :original_message
@@ -49,6 +50,10 @@ module Chat
guardian.can_preview_chat_channel?(channel)
end
def can_create_thread_in_channel(guardian:, channel:)
guardian.can_create_channel_message?(channel)
end
def threading_enabled_for_channel(channel:)
channel.threading_enabled?
end
@@ -106,6 +106,32 @@ RSpec.describe Chat::CreateThread do
it { is_expected.to fail_a_policy(:can_view_channel) }
end
context "when channel is not open" do
context "when channel is read_only" do
before { channel_1.update!(status: :read_only) }
it { is_expected.to fail_a_policy(:can_create_thread_in_channel) }
end
context "when channel is closed" do
before { channel_1.update!(status: :closed) }
it { is_expected.to fail_a_policy(:can_create_thread_in_channel) }
context "when user is staff" do
let(:guardian) { Guardian.new(Fabricate(:admin)) }
it { is_expected.to run_successfully }
end
end
context "when channel is archived" do
before { channel_1.update!(status: :archived) }
it { is_expected.to fail_a_policy(:can_create_thread_in_channel) }
end
end
context "when threading is not enabled for the channel" do
before { channel_1.update!(threading_enabled: false) }