discourse/spec/models/reviewable_queued_post_spec.rb
Martin Brennan 77f63a45d3
FIX: Use site contact user + group for Revise... review action (#29271)
Followup 9762e65758

When we added the Revise... option for posts/new topics
in the review queue, which sends a PM to the user, we used
`SystemMessage.create_from_system_user`, which always sends
the PM from the system user. However, this makes it so if the
user replies to the PM, which they are encouraged to do,
no one will see it unless they actively monitor the system inbox.

This commit changes it so `SystemMessage.create` is used,
which uses the `site_contact_username` and `site_contact_group`
site settings as participants in the sent PM. Then, when the
user replies, it will send to that inbox instead.

If `site_contact_username` is blank, the system user is used.
2024-10-28 09:40:10 +10:00

364 lines
14 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
RSpec.describe ReviewableQueuedPost, type: :model do
fab!(:category)
fab!(:moderator) { Fabricate(:moderator, refresh_auto_groups: true) }
describe "creating a post" do
let!(:topic) { Fabricate(:topic, category: category) }
let(:reviewable) { Fabricate(:reviewable_queued_post, topic: topic) }
context "when creating" do
it "triggers queued_post_created" do
event = DiscourseEvent.track(:queued_post_created) { reviewable.save! }
expect(event).to be_present
expect(event[:params][0]).to eq(reviewable)
end
it "returns the appropriate create options" do
create_options = reviewable.create_options
expect(create_options[:topic_id]).to eq(topic.id)
expect(create_options[:raw]).to eq("hello world post contents.")
expect(create_options[:reply_to_post_number]).to eq(1)
expect(create_options[:via_email]).to eq(true)
expect(create_options[:raw_email]).to eq("store_me")
expect(create_options[:auto_track]).to eq(true)
expect(create_options[:custom_fields]).to eq("hello" => "world")
expect(create_options[:cooking_options]).to eq(cat: "hat")
expect(create_options[:cook_method]).to eq(Post.cook_methods[:raw_html])
expect(create_options[:not_create_option]).to eq(nil)
expect(create_options[:image_sizes]).to eq(
"http://foo.bar/image.png" => {
"width" => 0,
"height" => 222,
},
)
end
end
describe "actions" do
context "with approve_post" do
it "triggers an extensibility event" do
event =
DiscourseEvent.track(:approved_post) { reviewable.perform(moderator, :approve_post) }
expect(event).to be_present
expect(event[:params].first).to eq(reviewable)
end
it "creates a post" do
topic_count, post_count = Topic.count, Post.count
result = nil
Jobs.run_immediately!
event =
DiscourseEvent.track(:before_create_notifications_for_users) do
result = reviewable.perform(moderator, :approve_post)
end
expect(result.success?).to eq(true)
expect(result.created_post).to be_present
expect(event).to be_present
expect(result.created_post).to be_valid
expect(result.created_post.topic).to eq(topic)
expect(result.created_post.custom_fields["hello"]).to eq("world")
expect(result.created_post_topic).to eq(topic)
expect(result.created_post.user).to eq(reviewable.target_created_by)
expect(reviewable.target_id).to eq(result.created_post.id)
expect(Topic.count).to eq(topic_count)
expect(Post.count).to eq(post_count + 1)
notifications =
Notification.where(
user: reviewable.target_created_by,
notification_type: Notification.types[:post_approved],
)
expect(notifications).to be_present
# We can't approve twice
expect { reviewable.perform(moderator, :approve_post) }.to raise_error(
Reviewable::InvalidAction,
)
end
it "skips validations" do
reviewable.payload["raw"] = "x"
result = reviewable.perform(moderator, :approve_post)
expect(result.created_post).to be_present
end
it "Allows autosilenced users to post" do
newuser = reviewable.created_by
newuser.update!(trust_level: 0)
post = Fabricate(:post, user: newuser)
PostActionCreator.spam(moderator, post)
Reviewable.set_priorities(high: 1.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivities[:low]
SiteSetting.num_users_to_silence_new_user = 1
expect(Guardian.new(newuser).can_create_post?(topic)).to eq(false)
result = reviewable.perform(moderator, :approve_post)
expect(result.success?).to eq(true)
end
end
context "with reject_post" do
it "triggers an extensibility event" do
event =
DiscourseEvent.track(:rejected_post) { reviewable.perform(moderator, :reject_post) }
expect(event).to be_present
expect(event[:params].first).to eq(reviewable)
end
it "doesn't create a post" do
post_count = Post.count
result = reviewable.perform(moderator, :reject_post)
expect(result.success?).to eq(true)
expect(result.created_post).to be_nil
expect(Post.count).to eq(post_count)
# We can't reject twice
expect { reviewable.perform(moderator, :reject_post) }.to raise_error(
Reviewable::InvalidAction,
)
end
end
context "with revise_and_reject_post" do
fab!(:contact_group) { Fabricate(:group) }
fab!(:contact_user) { Fabricate(:user) }
before do
SiteSetting.site_contact_group_name = contact_group.name
SiteSetting.site_contact_username = contact_user.username
end
it "doesn't create the post the user intended" do
post_count = Post.public_posts.count
result = reviewable.perform(moderator, :revise_and_reject_post)
expect(result.success?).to eq(true)
expect(result.created_post).to be_nil
expect(Post.public_posts.count).to eq(post_count)
end
it "creates a private message to the creator of the post" do
args = { revise_reason: "Duplicate", revise_feedback: "This is old news" }
expect { reviewable.perform(moderator, :revise_and_reject_post, args) }.to change {
Topic.where(archetype: Archetype.private_message).count
}
topic = Topic.where(archetype: Archetype.private_message).last
expect(topic.title).to eq(
I18n.t(
"system_messages.reviewable_queued_post_revise_and_reject.subject_template",
topic_title: reviewable.topic.title,
),
)
translation_params = {
username: reviewable.target_created_by.username,
topic_title: reviewable.topic.title,
topic_url: reviewable.topic.url,
reason: args[:revise_reason],
feedback: args[:revise_feedback],
original_post: reviewable.payload["raw"],
site_name: SiteSetting.title,
}
expect(topic.topic_allowed_users.pluck(:user_id)).to include(contact_user.id)
expect(topic.topic_allowed_groups.pluck(:group_id)).to include(contact_group.id)
expect(topic.first_post.raw.chomp).to eq(
I18n.t(
"system_messages.reviewable_queued_post_revise_and_reject.text_body_template",
translation_params,
).chomp,
)
end
it "supports sending a custom revise reason" do
args = {
revise_reason: "Other...",
revise_feedback: "This is old news",
revise_custom_reason: "Boring",
}
expect { reviewable.perform(moderator, :revise_and_reject_post, args) }.to change {
Topic.where(archetype: Archetype.private_message).count
}
topic = Topic.where(archetype: Archetype.private_message).last
expect(topic.topic_allowed_users.pluck(:user_id)).to include(contact_user.id)
expect(topic.topic_allowed_groups.pluck(:group_id)).to include(contact_group.id)
expect(topic.first_post.raw).not_to include("Other...")
expect(topic.first_post.raw).to include("Boring")
end
context "when the topic is nil in the case of a new topic being created" do
let(:reviewable) { Fabricate(:reviewable_queued_post_topic) }
it "works" do
args = { revise_reason: "Duplicate", revise_feedback: "This is old news" }
expect { reviewable.perform(moderator, :revise_and_reject_post, args) }.to change {
Topic.where(archetype: Archetype.private_message).count
}
topic = Topic.where(archetype: Archetype.private_message).last
expect(topic.title).to eq(
I18n.t(
"system_messages.reviewable_queued_post_revise_and_reject_new_topic.subject_template",
topic_title: reviewable.payload["title"],
),
)
translation_params = {
username: reviewable.target_created_by.username,
topic_title: reviewable.payload["title"],
topic_url: nil,
reason: args[:revise_reason],
feedback: args[:revise_feedback],
original_post: reviewable.payload["raw"],
site_name: SiteSetting.title,
}
expect(topic.first_post.raw.chomp).to eq(
I18n.t(
"system_messages.reviewable_queued_post_revise_and_reject_new_topic.text_body_template",
translation_params,
).chomp,
)
end
end
end
context "with delete_user" do
it "deletes the user and rejects the post" do
other_reviewable =
Fabricate(:reviewable_queued_post, created_by: reviewable.target_created_by)
result = reviewable.perform(moderator, :delete_user)
expect(result.success?).to eq(true)
expect(User.find_by(id: reviewable.target_created_by)).to be_blank
expect(result.remove_reviewable_ids).to include(reviewable.id)
expect(result.remove_reviewable_ids).to include(other_reviewable.id)
expect(ReviewableQueuedPost.where(id: reviewable.id)).to be_present
expect(ReviewableQueuedPost.where(id: other_reviewable.id)).to be_blank
end
end
end
end
describe "creating a topic" do
let(:reviewable) { Fabricate(:reviewable_queued_post_topic, category: category) }
before do
SiteSetting.tagging_enabled = true
SiteSetting.create_tag_allowed_groups = Group::AUTO_GROUPS[:trust_level_0]
SiteSetting.tag_topic_allowed_groups = Group::AUTO_GROUPS[:trust_level_0]
end
context "when editing" do
it "is editable and returns the fields" do
fields = reviewable.editable_for(Guardian.new(moderator))
expect(fields.has?("category_id")).to eq(true)
expect(fields.has?("payload.raw")).to eq(true)
expect(fields.has?("payload.title")).to eq(true)
expect(fields.has?("payload.tags")).to eq(true)
end
it "is editable by a category group reviewer" do
fields = reviewable.editable_for(Guardian.new(Fabricate(:user)))
expect(fields.has?("category_id")).to eq(false)
expect(fields.has?("payload.raw")).to eq(true)
expect(fields.has?("payload.title")).to eq(true)
expect(fields.has?("payload.tags")).to eq(true)
end
end
it "returns the appropriate create options for a topic" do
create_options = reviewable.create_options
expect(create_options[:category]).to eq(reviewable.category.id)
expect(create_options[:archetype]).to eq("regular")
end
it "creates the post and topic when approved" do
topic_count, post_count = Topic.count, Post.count
result = reviewable.perform(moderator, :approve_post)
expect(result.success?).to eq(true)
expect(result.created_post).to be_present
expect(result.created_post).to be_valid
expect(result.created_post_topic).to be_present
expect(result.created_post_topic).to be_valid
expect(reviewable.target_id).to eq(result.created_post.id)
expect(reviewable.topic_id).to eq(result.created_post_topic.id)
expect(Topic.count).to eq(topic_count + 1)
expect(Post.count).to eq(post_count + 1)
end
it "creates a topic with staff tag when approved" do
hidden_tag = Fabricate(:tag)
staff_tag_group =
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [hidden_tag.name])
reviewable.payload["tags"] += [hidden_tag.name]
result = reviewable.perform(moderator, :approve_post)
expect(result.success?).to eq(true)
expect(result.created_post_topic).to be_present
expect(result.created_post_topic).to be_valid
expect(reviewable.topic_id).to eq(result.created_post_topic.id)
expect(result.created_post_topic.tags.pluck(:name)).to match_array(reviewable.payload["tags"])
end
it "does not create the post and topic when rejected" do
topic_count, post_count = Topic.count, Post.count
result = reviewable.perform(moderator, :reject_post)
expect(result.success?).to eq(true)
expect(result.created_post).to be_blank
expect(result.created_post_topic).to be_blank
expect(Topic.count).to eq(topic_count)
expect(Post.count).to eq(post_count)
end
end
describe "Callbacks" do
context "when creating a new pending reviewable" do
let(:reviewable) do
Fabricate.build(
:reviewable_queued_post_topic,
category: category,
created_by: moderator,
target_created_by: user,
)
end
let(:user) { Fabricate(:user) }
let(:user_stats) { user.user_stat }
it "updates user stats" do
user_stats.expects(:update_pending_posts)
reviewable.save!
end
end
context "when updating an existing reviewable" do
let!(:reviewable) { Fabricate(:reviewable_queued_post_topic, category: category) }
let(:user_stats) { reviewable.target_created_by.user_stat }
context "when status changes from 'pending' to something else" do
it "updates user stats" do
user_stats.expects(:update_pending_posts)
reviewable.update!(status: :approved)
end
end
context "when status doesnt change" do
it "doesnt update user stats" do
user_stats.expects(:update_pending_posts).never
reviewable.update!(score: 10)
end
end
end
end
end