2019-04-29 20:27:42 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2022-07-27 22:27:38 -04:00
|
|
|
RSpec.describe WatchedWord do
|
2023-11-21 13:31:42 -05:00
|
|
|
fab!(:tl2_user) { Fabricate(:user, trust_level: TrustLevel[2], refresh_auto_groups: true) }
|
2023-11-09 17:47:59 -05:00
|
|
|
fab!(:admin)
|
|
|
|
fab!(:moderator)
|
2017-06-28 16:56:44 -04:00
|
|
|
|
2023-11-09 17:47:59 -05:00
|
|
|
fab!(:topic)
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:first_post) { Fabricate(:post, topic: topic) }
|
2017-06-28 16:56:44 -04:00
|
|
|
|
|
|
|
let(:require_approval_word) do
|
|
|
|
Fabricate(:watched_word, action: WatchedWord.actions[:require_approval])
|
2023-01-09 06:18:21 -05:00
|
|
|
end
|
2017-06-28 16:56:44 -04:00
|
|
|
let(:flag_word) { Fabricate(:watched_word, action: WatchedWord.actions[:flag]) }
|
|
|
|
let(:block_word) { Fabricate(:watched_word, action: WatchedWord.actions[:block]) }
|
2019-07-22 07:59:56 -04:00
|
|
|
let(:another_block_word) { Fabricate(:watched_word, action: WatchedWord.actions[:block]) }
|
2017-06-28 16:56:44 -04:00
|
|
|
|
2019-06-02 20:21:38 -04:00
|
|
|
before_all { WordWatcher.clear_cache! }
|
|
|
|
|
|
|
|
after { WordWatcher.clear_cache! }
|
2017-07-27 12:26:55 -04:00
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "with block" do
|
2017-06-28 16:56:44 -04:00
|
|
|
def should_block_post(manager)
|
|
|
|
expect {
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to_not be_success
|
2019-07-22 07:59:56 -04:00
|
|
|
expect(result.errors[:base]&.first).to eq(
|
|
|
|
I18n.t("contains_blocked_word", word: block_word.word),
|
|
|
|
)
|
2017-06-28 16:56:44 -04:00
|
|
|
}.to_not change { Post.count }
|
|
|
|
end
|
|
|
|
|
2021-09-24 04:55:15 -04:00
|
|
|
it "escapes the blocked word in error message" do
|
|
|
|
block_word = Fabricate(:watched_word, action: WatchedWord.actions[:block], word: "<a>")
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
raw: "Want some #{block_word.word} for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to_not be_success
|
|
|
|
expect(result.errors[:base]&.first).to eq(I18n.t("contains_blocked_word", word: "<a>"))
|
|
|
|
end
|
|
|
|
|
2017-06-28 16:56:44 -04:00
|
|
|
it "should prevent the post from being created" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
raw: "Want some #{block_word.word} for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
should_block_post(manager)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "look at title too" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
title: "We sell #{block_word.word} online",
|
|
|
|
raw: "Want some poutine for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
should_block_post(manager)
|
|
|
|
end
|
|
|
|
|
2023-05-15 05:45:04 -04:00
|
|
|
it "should handle UTF-8 characters" do
|
|
|
|
block_word = Fabricate(:watched_word, action: WatchedWord.actions[:block], word: "abc")
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(tl2_user, title: "Hello world", raw: "abcódef", topic_id: topic.id)
|
|
|
|
|
|
|
|
expect(manager.perform).to be_success
|
|
|
|
end
|
|
|
|
|
2019-05-16 10:19:41 -04:00
|
|
|
it "should block the post from admin" do
|
2017-06-28 16:56:44 -04:00
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
admin,
|
|
|
|
raw: "Want some #{block_word.word} for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
2019-05-16 10:19:41 -04:00
|
|
|
should_block_post(manager)
|
2017-06-28 16:56:44 -04:00
|
|
|
end
|
|
|
|
|
2019-05-16 10:19:41 -04:00
|
|
|
it "should block the post from moderator" do
|
2017-06-28 16:56:44 -04:00
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
moderator,
|
|
|
|
raw: "Want some #{block_word.word} for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
2019-05-16 10:19:41 -04:00
|
|
|
should_block_post(manager)
|
2017-06-28 16:56:44 -04:00
|
|
|
end
|
|
|
|
|
2019-07-22 07:59:56 -04:00
|
|
|
it "should block the post if it contains multiple blocked words" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
moderator,
|
|
|
|
raw: "Want some #{block_word.word} #{another_block_word.word} for cheap?",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
expect {
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to_not be_success
|
2019-07-23 12:04:53 -04:00
|
|
|
expect(result.errors[:base]&.first).to eq(
|
|
|
|
I18n.t(
|
|
|
|
"contains_blocked_words",
|
|
|
|
words: [block_word.word, another_block_word.word].sort.join(", "),
|
2023-01-09 06:18:21 -05:00
|
|
|
),
|
2019-07-23 12:04:53 -04:00
|
|
|
)
|
2019-07-22 07:59:56 -04:00
|
|
|
}.to_not change { Post.count }
|
|
|
|
end
|
|
|
|
|
2017-06-28 16:56:44 -04:00
|
|
|
it "should block in a private message too" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
raw: "Want some #{block_word.word} for cheap?",
|
|
|
|
title: "this is a new title",
|
|
|
|
archetype: Archetype.private_message,
|
|
|
|
target_usernames: Fabricate(:user, trust_level: TrustLevel[2]).username,
|
|
|
|
)
|
|
|
|
should_block_post(manager)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "blocks on revisions" do
|
2019-05-08 23:28:28 -04:00
|
|
|
post = Fabricate(:post, topic: Fabricate(:topic, user: tl2_user), user: tl2_user)
|
2017-06-28 16:56:44 -04:00
|
|
|
expect {
|
|
|
|
PostRevisor.new(post).revise!(
|
|
|
|
post.user,
|
|
|
|
{ raw: "Want some #{block_word.word} for cheap?" },
|
|
|
|
revised_at: post.updated_at + 10.seconds,
|
|
|
|
)
|
|
|
|
expect(post.errors).to be_present
|
|
|
|
post.reload
|
|
|
|
}.to_not change { post.raw }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "with require_approval" do
|
2017-06-28 16:56:44 -04:00
|
|
|
it "should queue the post for approval" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
raw: "My dog's name is #{require_approval_word.word}.",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result.action).to eq(:enqueued)
|
2019-04-10 17:42:49 -04:00
|
|
|
expect(result.reason).to eq(:watched_word)
|
2017-06-28 16:56:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "looks at title too" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
title: "You won't believe these #{require_approval_word.word} dog names!",
|
|
|
|
raw: "My dog's name is Porkins.",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result.action).to eq(:enqueued)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should not queue posts from admin" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
admin,
|
|
|
|
raw: "My dog's name is #{require_approval_word.word}.",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to be_success
|
|
|
|
expect(result.action).to eq(:create_post)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should not queue posts from moderator" do
|
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
moderator,
|
|
|
|
raw: "My dog's name is #{require_approval_word.word}.",
|
|
|
|
topic_id: topic.id,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to be_success
|
|
|
|
expect(result.action).to eq(:create_post)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't need approval in a private message" do
|
2022-10-04 20:50:20 -04:00
|
|
|
Group.refresh_automatic_groups!
|
2017-06-28 16:56:44 -04:00
|
|
|
manager =
|
|
|
|
NewPostManager.new(
|
|
|
|
tl2_user,
|
|
|
|
raw: "Want some #{require_approval_word.word} for cheap?",
|
|
|
|
title: "this is a new title",
|
|
|
|
archetype: Archetype.private_message,
|
|
|
|
target_usernames: Fabricate(:user, trust_level: TrustLevel[2]).username,
|
|
|
|
)
|
|
|
|
result = manager.perform
|
|
|
|
expect(result).to be_success
|
|
|
|
expect(result.action).to eq(:create_post)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "with flag" do
|
2017-06-28 16:56:44 -04:00
|
|
|
def should_flag_post(author, raw, topic)
|
|
|
|
post = Fabricate(:post, raw: raw, topic: topic, user: author)
|
|
|
|
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to change { PostAction.count }.by(
|
2023-01-09 06:18:21 -05:00
|
|
|
1,
|
2017-06-28 16:56:44 -04:00
|
|
|
)
|
|
|
|
expect(
|
|
|
|
PostAction.where(
|
|
|
|
post_id: post.id,
|
|
|
|
post_action_type_id: PostActionType.types[:inappropriate],
|
|
|
|
).exists?,
|
|
|
|
).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
def should_not_flag_post(author, raw, topic)
|
|
|
|
post = Fabricate(:post, raw: raw, topic: topic, user: author)
|
|
|
|
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to_not change { PostAction.count }
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should flag the post as inappropriate" do
|
2020-06-02 11:49:02 -04:00
|
|
|
topic = Fabricate(:topic, user: tl2_user)
|
|
|
|
post = Fabricate(:post, raw: "I said.... #{flag_word.word}", topic: topic, user: tl2_user)
|
|
|
|
Jobs::ProcessPost.new.execute(post_id: post.id)
|
|
|
|
expect(
|
|
|
|
PostAction.where(
|
|
|
|
post_id: post.id,
|
|
|
|
post_action_type_id: PostActionType.types[:inappropriate],
|
|
|
|
).exists?,
|
|
|
|
).to eq(true)
|
|
|
|
reviewable = ReviewableFlaggedPost.where(target: post)
|
|
|
|
expect(reviewable).to be_present
|
|
|
|
expect(ReviewableScore.where(reviewable: reviewable, reason: "watched_word")).to be_present
|
2017-06-28 16:56:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should look at the title too" do
|
|
|
|
should_flag_post(
|
|
|
|
tl2_user,
|
|
|
|
"I thought the movie was not bad actually.",
|
|
|
|
Fabricate(:topic, user: tl2_user, title: "Read my #{flag_word.word} review!"),
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "shouldn't flag posts by admin" do
|
|
|
|
should_not_flag_post(
|
|
|
|
admin,
|
|
|
|
"I thought the #{flag_word.word} was bad.",
|
|
|
|
Fabricate(:topic, user: admin),
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "shouldn't flag posts by moderator" do
|
|
|
|
should_not_flag_post(
|
|
|
|
moderator,
|
|
|
|
"I thought the #{flag_word.word} was bad.",
|
|
|
|
Fabricate(:topic, user: moderator),
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is compatible with flag_sockpuppets" do
|
|
|
|
SiteSetting.flag_sockpuppets = true
|
|
|
|
ip_address = "182.189.119.174"
|
|
|
|
user1 = Fabricate(:user, ip_address: ip_address, created_at: 2.days.ago)
|
|
|
|
user2 = Fabricate(:user, ip_address: ip_address)
|
|
|
|
first = create_post(user: user1, created_at: 2.days.ago)
|
|
|
|
sockpuppet_post =
|
|
|
|
create_post(
|
|
|
|
user: user2,
|
|
|
|
topic: first.topic,
|
|
|
|
raw: "I thought the #{flag_word.word} was bad.",
|
|
|
|
)
|
|
|
|
expect(PostAction.where(post_id: sockpuppet_post.id).count).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "flags in private message too" do
|
|
|
|
post =
|
|
|
|
Fabricate(
|
|
|
|
:private_message_post,
|
|
|
|
raw: "Want some #{flag_word.word} for cheap?",
|
|
|
|
user: tl2_user,
|
|
|
|
)
|
|
|
|
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to change { PostAction.count }.by(
|
2023-01-09 06:18:21 -05:00
|
|
|
1,
|
2017-06-28 16:56:44 -04:00
|
|
|
)
|
|
|
|
expect(
|
|
|
|
PostAction.where(
|
|
|
|
post_id: post.id,
|
|
|
|
post_action_type_id: PostActionType.types[:inappropriate],
|
|
|
|
).exists?,
|
|
|
|
).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "flags on revisions" do
|
2019-03-14 10:47:38 -04:00
|
|
|
Jobs.run_immediately!
|
2017-06-28 16:56:44 -04:00
|
|
|
post = Fabricate(:post, topic: Fabricate(:topic, user: tl2_user), user: tl2_user)
|
|
|
|
expect {
|
|
|
|
PostRevisor.new(post).revise!(
|
|
|
|
post.user,
|
|
|
|
{ raw: "Want some #{flag_word.word} for cheap?" },
|
|
|
|
revised_at: post.updated_at + 10.seconds,
|
|
|
|
)
|
|
|
|
}.to change { PostAction.count }.by(1)
|
|
|
|
expect(
|
|
|
|
PostAction.where(
|
|
|
|
post_id: post.id,
|
|
|
|
post_action_type_id: PostActionType.types[:inappropriate],
|
|
|
|
).exists?,
|
|
|
|
).to eq(true)
|
|
|
|
end
|
2017-10-12 15:34:22 -04:00
|
|
|
|
|
|
|
it "should not flag on rebake" do
|
|
|
|
post =
|
|
|
|
Fabricate(
|
|
|
|
:post,
|
|
|
|
topic: Fabricate(:topic, user: tl2_user),
|
|
|
|
user: tl2_user,
|
|
|
|
raw: "I have coupon codes. Message me.",
|
|
|
|
)
|
|
|
|
Fabricate(:watched_word, action: WatchedWord.actions[:flag], word: "coupon")
|
|
|
|
expect { post.rebake! }.to_not change { PostAction.count }
|
|
|
|
end
|
2017-06-28 16:56:44 -04:00
|
|
|
end
|
|
|
|
end
|