mirror of
https://github.com/discourse/discourse.git
synced 2025-05-31 22:09:12 +08:00
SECURITY: Limit chat drafts length and preloaded count (#19987)
Only allow maximum of `50_000` characters for chat drafts. A hidden `max_chat_draft_length` setting can control this limit. A migration is also provided to delete any abusive draft in the database. The number of drafts loaded on current user has also been limited and ordered by most recent update. Note that spec files moved are not directly related to the fix. Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com> Co-authored-by: Régis Hanol <regis@hanol.fr>
This commit is contained in:
@ -126,3 +126,16 @@ Fabricator(:user_chat_channel_membership_for_dm, from: :user_chat_channel_member
|
||||
desktop_notification_level 2
|
||||
mobile_notification_level 2
|
||||
end
|
||||
|
||||
Fabricator(:chat_draft) do
|
||||
user
|
||||
chat_channel
|
||||
|
||||
transient :value, "chat draft message"
|
||||
transient :uploads, []
|
||||
transient :reply_to_msg
|
||||
|
||||
data do |attrs|
|
||||
{ value: attrs[:value], replyToMsg: attrs[:reply_to_msg], uploads: attrs[:uploads] }.to_json
|
||||
end
|
||||
end
|
||||
|
18
plugins/chat/spec/models/chat_draft_spec.rb
Normal file
18
plugins/chat/spec/models/chat_draft_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe ChatDraft do
|
||||
before { SiteSetting.max_chat_draft_length = 100 }
|
||||
|
||||
it "errors when data.value is greater than `max_chat_draft_length`" do
|
||||
draft =
|
||||
described_class.create(
|
||||
user_id: Fabricate(:user).id,
|
||||
chat_channel_id: Fabricate(:chat_channel).id,
|
||||
data: { value: "A" * (SiteSetting.max_chat_draft_length + 1) }.to_json,
|
||||
)
|
||||
|
||||
expect(draft.errors.full_messages).to eq(
|
||||
[I18n.t("chat.errors.draft_too_long", { maximum: SiteSetting.max_chat_draft_length })],
|
||||
)
|
||||
end
|
||||
end
|
@ -1286,6 +1286,19 @@ RSpec.describe Chat::ChatController do
|
||||
post "/chat/drafts.json", params: { chat_channel_id: dm_channel.id, data: "{}" }
|
||||
}.to change { ChatDraft.count }.by(1)
|
||||
end
|
||||
|
||||
it "cannot create a too long chat draft" do
|
||||
SiteSetting.max_chat_draft_length = 100
|
||||
|
||||
post "/chat/drafts.json",
|
||||
params: {
|
||||
chat_channel_id: chat_channel.id,
|
||||
data: { value: "a" * (SiteSetting.max_chat_draft_length + 1) }.to_json,
|
||||
}
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.parsed_body["errors"]).to eq([I18n.t("chat.errors.draft_too_long")])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#message_link" do
|
||||
|
@ -0,0 +1,40 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe CurrentUserSerializer do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
let(:serializer) do
|
||||
described_class.new(current_user, scope: Guardian.new(current_user), root: false)
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.chat_enabled = true
|
||||
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:everyone]
|
||||
current_user.user_option.update(chat_enabled: true)
|
||||
end
|
||||
|
||||
describe "#chat_drafts" do
|
||||
context "when user can't chat" do
|
||||
before { SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:staff] }
|
||||
|
||||
it "is not present" do
|
||||
expect(serializer.as_json[:chat_drafts]).to be_blank
|
||||
end
|
||||
end
|
||||
|
||||
it "is ordered by most recent drafts" do
|
||||
Fabricate(:chat_draft, user: current_user, value: "second draft")
|
||||
Fabricate(:chat_draft, user: current_user, value: "first draft")
|
||||
|
||||
values =
|
||||
serializer.as_json[:chat_drafts].map { |draft| MultiJson.load(draft[:data])["value"] }
|
||||
expect(values).to eq(["first draft", "second draft"])
|
||||
end
|
||||
|
||||
it "limits the numbers of drafts" do
|
||||
21.times { Fabricate(:chat_draft, user: current_user) }
|
||||
|
||||
expect(serializer.as_json[:chat_drafts].length).to eq(20)
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user