DEV: Use AR enums in reviewables related code

This is the first patch of many to replace our custom enums in Ruby by
the ones provided by `ActiveRecord`.
This commit is contained in:
Loïc Guitaut 2021-12-08 18:12:24 +01:00 committed by Loïc Guitaut
parent 0c743a591f
commit 26fe047724
36 changed files with 220 additions and 228 deletions

View File

@ -268,7 +268,7 @@ protected
end
def allowed_statuses
@allowed_statuses ||= (%i[reviewed all] + Reviewable.statuses.keys)
@allowed_statuses ||= (%i[reviewed all] + Reviewable.statuses.symbolize_keys.keys)
end
def version_required

View File

@ -361,7 +361,7 @@ module Jobs
yield [
rev.id,
Reviewable.statuses[rev.status],
rev.status,
rev.category_id,
rev.topic_id,
rev.payload['raw'],

View File

@ -11,7 +11,7 @@ module Jobs
return unless SiteSetting.auto_handle_queued_age.to_i > 0
Reviewable
.where(status: Reviewable.statuses[:pending])
.pending
.where('created_at < ?', SiteSetting.auto_handle_queued_age.to_i.days.ago)
.each do |reviewable|

View File

@ -27,7 +27,7 @@ module Jobs
end
def should_notify_ids
ReviewableQueuedPost.where(status: Reviewable.statuses[:pending]).where(
ReviewableQueuedPost.pending.where(
'created_at < ?', SiteSetting.notify_about_queued_posts_after.to_f.hours.ago
).pluck(:id)
end

View File

@ -15,11 +15,7 @@ class Jobs::ReviewablePriorities < ::Jobs::Scheduled
def execute(args)
min_priority_threshold = SiteSetting.reviewable_low_priority_threshold
reviewable_count = Reviewable.where(
"score > ? AND status = ?",
min_priority_threshold,
Reviewable.statuses[:approved]
).count
reviewable_count = Reviewable.approved.where("score > ?", min_priority_threshold).count
return if reviewable_count < self.class.min_reviewables
res = DB.query_single(<<~SQL, target_count: self.class.target_count, min_priority: min_priority_threshold)

View File

@ -80,7 +80,7 @@ module Roleable
private
def auto_approve_user
if reviewable = ReviewableUser.find_by(target: self, status: Reviewable.statuses[:pending])
if reviewable = ReviewableUser.pending.find_by(target: self)
reviewable.perform(Discourse.system_user, :approve_user, send_email: false)
else
ReviewableUser.set_approved_fields!(self, Discourse.system_user)

View File

@ -31,6 +31,25 @@ class Reviewable < ActiveRecord::Base
has_many :reviewable_histories
has_many :reviewable_scores, -> { order(created_at: :desc) }
enum :status, {
pending: 0,
approved: 1,
rejected: 2,
ignored: 3,
deleted: 4
}
enum :priority, {
low: 0,
medium: 5,
high: 10
}, scopes: false, suffix: true
enum :sensitivity, {
disabled: 0,
low: 9,
medium: 6,
high: 3
}, scopes: false, suffix: true
after_create do
log_history(:created, created_by)
end
@ -48,47 +67,12 @@ class Reviewable < ActiveRecord::Base
{}
end
# The gaps are in case we want more precision in the future
def self.priorities
@priorities ||= Enum.new(
low: 0,
medium: 5,
high: 10
)
end
# The gaps are in case we want more precision in the future
def self.sensitivity
@sensitivity ||= Enum.new(
disabled: 0,
low: 9,
medium: 6,
high: 3
)
end
def self.statuses
@statuses ||= Enum.new(
pending: 0,
approved: 1,
rejected: 2,
ignored: 3,
deleted: 4
)
end
# This number comes from looking at forums in the wild and what numbers work.
# As the site accumulates real data it'll be based on the site activity instead.
def self.typical_sensitivity
12.5
end
# Generate `pending?`, `rejected?`, etc helper methods
statuses.each do |name, id|
define_method("#{name}?") { status == id }
singleton_class.define_method(name) { where(status: id) }
end
def self.default_visible
where("score >= ?", min_score_for_priority)
end
@ -211,7 +195,7 @@ class Reviewable < ActiveRecord::Base
rs = reviewable_scores.new(
user: user,
status: ReviewableScore.statuses[:pending],
status: :pending,
reviewable_score_type: reviewable_score_type,
score: sub_total,
user_accuracy_bonus: user_accuracy_bonus,
@ -232,7 +216,7 @@ class Reviewable < ActiveRecord::Base
def self.set_priorities(values)
values.each do |k, v|
id = Reviewable.priorities[k]
id = priorities[k]
PluginStore.set('reviewables', "priority_#{id}", v) unless id.nil?
end
end
@ -240,9 +224,9 @@ class Reviewable < ActiveRecord::Base
def self.sensitivity_score_value(sensitivity, scale)
return Float::MAX if sensitivity == 0
ratio = sensitivity / Reviewable.sensitivity[:low].to_f
ratio = sensitivity / sensitivities[:low].to_f
high = (
PluginStore.get('reviewables', "priority_#{Reviewable.priorities[:high]}") ||
PluginStore.get('reviewables', "priority_#{priorities[:high]}") ||
typical_sensitivity
).to_f
@ -271,7 +255,7 @@ class Reviewable < ActiveRecord::Base
def self.min_score_for_priority(priority = nil)
priority ||= SiteSetting.reviewable_default_visibility
id = Reviewable.priorities[priority.to_sym]
id = priorities[priority]
return 0.0 if id.nil?
PluginStore.get('reviewables', "priority_#{id}").to_f
end
@ -282,7 +266,7 @@ class Reviewable < ActiveRecord::Base
def log_history(reviewable_history_type, performed_by, edited: nil)
reviewable_histories.create!(
reviewable_history_type: ReviewableHistory.types[reviewable_history_type],
reviewable_history_type: reviewable_history_type,
status: status,
created_by: performed_by,
edited: edited
@ -386,9 +370,7 @@ class Reviewable < ActiveRecord::Base
end
def transition_to(status_symbol, performed_by)
was_pending = pending?
self.status = Reviewable.statuses[status_symbol]
self.status = status_symbol
save!
log_history(:transitioned, performed_by)
@ -402,7 +384,7 @@ class Reviewable < ActiveRecord::Base
)
end
was_pending
status_previously_changed?(from: "pending")
end
def post_options
@ -503,13 +485,13 @@ class Reviewable < ActiveRecord::Base
SELECT reviewable_id
FROM reviewable_histories
WHERE reviewable_history_type = #{ReviewableHistory.types[:transitioned]} AND
status <> #{Reviewable.statuses[:pending]} AND created_by_id = #{reviewed_by_id}
status <> #{statuses[:pending]} AND created_by_id = #{reviewed_by_id}
) AS rh ON rh.reviewable_id = reviewables.id
SQL
)
end
min_score = Reviewable.min_score_for_priority(priority)
min_score = min_score_for_priority(priority)
if min_score > 0 && status == :pending
result = result.where("reviewables.score >= ? OR reviewables.force_review", min_score)
@ -678,8 +660,8 @@ class Reviewable < ActiveRecord::Base
DB.query(
sql,
topic_id: topic_id,
pending: Reviewable.statuses[:pending],
approved: Reviewable.statuses[:approved]
pending: self.class.statuses[:pending],
approved: self.class.statuses[:approved]
)
self.score = result[0].score
@ -776,7 +758,7 @@ end
#
# id :bigint not null, primary key
# type :string not null
# status :integer default(0), not null
# status :integer default("pending"), not null
# created_by_id :integer not null
# reviewable_by_moderator :boolean default(FALSE), not null
# reviewable_by_group_id :integer

View File

@ -13,7 +13,7 @@ class ReviewableFlaggedPost < Reviewable
def self.counts_for(posts)
result = {}
counts = DB.query(<<~SQL, pending: Reviewable.statuses[:pending])
counts = DB.query(<<~SQL, pending: statuses[:pending])
SELECT r.target_id AS post_id,
rs.reviewable_score_type,
count(*) as total
@ -336,7 +336,7 @@ end
#
# id :bigint not null, primary key
# type :string not null
# status :integer default(0), not null
# status :integer default("pending"), not null
# created_by_id :integer not null
# reviewable_by_moderator :boolean default(FALSE), not null
# reviewable_by_group_id :integer

View File

@ -4,16 +4,22 @@ class ReviewableHistory < ActiveRecord::Base
belongs_to :reviewable
belongs_to :created_by, class_name: 'User'
def self.types
@types ||= Enum.new(
enum status: {
pending: 0,
approved: 1,
rejected: 2,
ignored: 3,
deleted: 4
}
alias_attribute :type, :reviewable_history_type
enum type: {
created: 0,
transitioned: 1,
edited: 2,
claimed: 3,
unclaimed: 4
)
end
}
end
# == Schema Information

View File

@ -8,7 +8,7 @@ class ReviewablePost < Reviewable
def self.queue_for_review_if_possible(post, created_or_edited_by)
return unless SiteSetting.review_every_post
return if post.post_type != Post.types[:regular] || post.topic.private_message?
return if Reviewable.where(target: post, status: Reviewable.statuses[:pending]).exists?
return if Reviewable.pending.where(target: post).exists?
return if created_or_edited_by.bot? || created_or_edited_by.staff? || created_or_edited_by.has_trust_level?(TrustLevel[4])
system_user = Discourse.system_user
@ -116,7 +116,7 @@ end
#
# id :bigint not null, primary key
# type :string not null
# status :integer default(0), not null
# status :integer default("pending"), not null
# created_by_id :integer not null
# reviewable_by_moderator :boolean default(FALSE), not null
# reviewable_by_group_id :integer

View File

@ -174,7 +174,7 @@ class ReviewableQueuedPost < Reviewable
def status_changed_from_or_to_pending?
saved_change_to_id?(from: nil) && pending? ||
saved_change_to_status?(from: self.class.statuses[:pending])
saved_change_to_status?(from: "pending")
end
end
@ -184,7 +184,7 @@ end
#
# id :bigint not null, primary key
# type :string not null
# status :integer default(0), not null
# status :integer default("pending"), not null
# created_by_id :integer not null
# reviewable_by_moderator :boolean default(FALSE), not null
# reviewable_by_group_id :integer

View File

@ -6,6 +6,13 @@ class ReviewableScore < ActiveRecord::Base
belongs_to :reviewed_by, class_name: 'User'
belongs_to :meta_topic, class_name: 'Topic'
enum status: {
pending: 0,
agreed: 1,
disagreed: 2,
ignored: 3
}
# To keep things simple the types correspond to `PostActionType` for backwards
# compatibility, but we can add extra reasons for scores.
def self.types
@ -29,15 +36,6 @@ class ReviewableScore < ActiveRecord::Base
end
end
def self.statuses
@statuses ||= Enum.new(
pending: 0,
agreed: 1,
disagreed: 2,
ignored: 3
)
end
def self.score_transitions
{
approved: statuses[:agreed],
@ -46,12 +44,6 @@ class ReviewableScore < ActiveRecord::Base
}
end
# Generate `pending?`, `rejected?`, etc helper methods
statuses.each do |name, id|
define_method("#{name}?") { status == id }
singleton_class.define_method(name) { where(status: id) }
end
def score_type
Reviewable::Collection::Item.new(reviewable_score_type)
end

View File

@ -7,7 +7,7 @@ class ReviewableSensitivitySetting < EnumSiteSetting
end
def self.values
Reviewable.sensitivity.map do |p|
Reviewable.sensitivities.map do |p|
{ name: I18n.t("reviewables.sensitivity.#{p[0]}"), value: p[1] }
end
end

View File

@ -105,7 +105,7 @@ end
#
# id :bigint not null, primary key
# type :string not null
# status :integer default(0), not null
# status :integer default("pending"), not null
# created_by_id :integer not null
# reviewable_by_moderator :boolean default(FALSE), not null
# reviewable_by_group_id :integer

View File

@ -1396,7 +1396,7 @@ class User < ActiveRecord::Base
def number_of_rejected_posts
ReviewableQueuedPost
.where(status: Reviewable.statuses[:rejected])
.rejected
.where(created_by_id: self.id)
.count
end

View File

@ -2,7 +2,6 @@
# Deprecated, should be removed once users have sufficient opportunity to do so
class QueuedPostSerializer < ApplicationSerializer
attributes(
:id,
:queue,
@ -33,11 +32,11 @@ class QueuedPostSerializer < ApplicationSerializer
end
def approved_by_id
who_did(:approved)
post_history.approved.last&.created_by_id
end
def rejected_by_id
who_did(:rejected)
post_history.rejected.last&.created_by_id
end
def raw
@ -56,17 +55,12 @@ class QueuedPostSerializer < ApplicationSerializer
created_by && created_by.trust_level == TrustLevel[0]
end
protected
private
def who_did(status)
def post_history
object.
reviewable_histories.
where(
reviewable_history_type: ReviewableHistory.types[:transitioned],
status: Reviewable.statuses[status]
).
transitioned.
order(:created_at)
.last&.created_by_id
end
end

View File

@ -1,8 +1,10 @@
# frozen_string_literal: true
class ReviewableHistorySerializer < ApplicationSerializer
attributes :id, :created_at
attribute :reviewable_history_type_for_database, key: :reviewable_history_type
attribute :status_for_database, key: :status
attributes :id, :reviewable_history_type, :status, :created_at
has_one :created_by, serializer: BasicUserSerializer, root: 'users'
end

View File

@ -15,7 +15,10 @@ class ReviewableScoreSerializer < ApplicationSerializer
contains_media: 'review_media_unless_trust_level',
}
attributes :id, :score, :agree_stats, :status, :reason, :created_at, :reviewed_at
attributes :id, :score, :agree_stats, :reason, :created_at, :reviewed_at
attribute :status_for_database, key: :status
has_one :user, serializer: BasicUserSerializer, root: 'users'
has_one :score_type, serializer: ReviewableScoreTypeSerializer
has_one :reviewable_conversation, serializer: ReviewableConversationSerializer

View File

@ -6,7 +6,6 @@ class ReviewableSerializer < ApplicationSerializer
attributes(
:id,
:status,
:type,
:topic_id,
:topic_url,
@ -20,6 +19,8 @@ class ReviewableSerializer < ApplicationSerializer
:target_created_by_trust_level
)
attribute :status_for_database, key: :status
has_one :created_by, serializer: UserWithCustomFieldsSerializer, root: 'users'
has_one :target_created_by, serializer: UserWithCustomFieldsSerializer, root: 'users'
has_one :topic, serializer: ListableTopicSerializer

View File

@ -47,8 +47,7 @@ class SpamRule::FlagSockpuppets
private
def flag_post(post, message)
can_trust_user = ReviewableFlaggedPost.where(status: Reviewable.statuses[:rejected], target_created_by: post.user).exists?
return if can_trust_user
return if ReviewableFlaggedPost.rejected.exists?(target_created_by: post.user)
PostActionCreator.create(Discourse.system_user, post, :spam, message: message)
end

View File

@ -152,7 +152,7 @@ private
def cannot_flag_again?(reviewable)
return false if @post_action_type_id == PostActionType.types[:notify_moderators]
flag_type_already_used = reviewable.reviewable_scores.any? { |rs| rs.reviewable_score_type == @post_action_type_id && rs.status != ReviewableScore.statuses[:pending] }
flag_type_already_used = reviewable.reviewable_scores.any? { |rs| rs.reviewable_score_type == @post_action_type_id && !rs.pending? }
not_edited_since_last_review = @post.last_version_at.blank? || reviewable.updated_at > @post.last_version_at
handled_recently = reviewable.updated_at > SiteSetting.cooldown_hours_until_reflag.to_i.hours.ago

View File

@ -9,9 +9,9 @@ RSpec.describe "spam rules for users" do
fab!(:user2) { Fabricate(:user) }
before do
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:disabled]
Reviewable.set_priorities(high: 4.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivities[:low]
SiteSetting.num_users_to_silence_new_user = 2
end
@ -74,7 +74,7 @@ RSpec.describe "spam rules for users" do
context 'with hide_post_sensitivity' do
it 'should silence the spammer' do
Reviewable.set_priorities(high: 2.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:low]
PostActionCreator.create(user2, spam_post, :spam)
expect(spammer.reload).to be_silenced
expect(Guardian.new(spammer).can_create_topic?(nil)).to be false

View File

@ -1012,28 +1012,36 @@ RSpec.describe PostDestroyer do
end
end
describe '#delete_with_replies' do
let(:reporter) { Discourse.system_user }
describe '.delete_with_replies' do
subject(:delete_with_replies) { PostDestroyer.delete_with_replies(reporter, post, defer_reply_flags: defer_reply_flags) }
fab!(:post) { Fabricate(:post) }
let(:reporter) { Discourse.system_user }
let(:reply) { Fabricate(:post, topic: post.topic) }
let(:reviewable_reply) { PostActionCreator.off_topic(reporter, reply).reviewable }
before do
reply = Fabricate(:post, topic: post.topic)
post.update(replies: [reply])
PostActionCreator.off_topic(reporter, post)
@reviewable_reply = PostActionCreator.off_topic(reporter, reply).reviewable
reviewable_reply
end
context 'when deferring reply flags' do
let(:defer_reply_flags) { true }
it 'ignores flagged replies' do
PostDestroyer.delete_with_replies(reporter, post)
expect(@reviewable_reply.reload.status).to eq Reviewable.statuses[:ignored]
delete_with_replies
expect(reviewable_reply.reload).to be_ignored
end
end
it 'approves flagged replies' do
PostDestroyer.delete_with_replies(reporter, post, defer_reply_flags: false)
context 'when not deferring reply flags' do
let(:defer_reply_flags) { false }
expect(@reviewable_reply.reload.status).to eq Reviewable.statuses[:approved]
it 'approves flagged replies' do
delete_with_replies
expect(reviewable_reply.reload).to be_approved
end
end
end

View File

@ -518,7 +518,7 @@ RSpec.describe PostAction do
post = Fabricate(:post, user: mod)
Reviewable.set_priorities(high: 2.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -533,7 +533,7 @@ RSpec.describe PostAction do
post = Fabricate(:post, user: mod)
Reviewable.set_priorities(high: 8.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -563,7 +563,7 @@ RSpec.describe PostAction do
walterwhite = Fabricate(:walter_white)
Reviewable.set_priorities(high: 3.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -687,9 +687,9 @@ RSpec.describe PostAction do
fab!(:flagger2) { Fabricate(:user) }
before do
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:disabled]
Reviewable.set_priorities(high: 4.5)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivities[:low]
SiteSetting.num_flaggers_to_close_topic = 2
SiteSetting.num_hours_to_close_topic = 1
end
@ -753,7 +753,7 @@ RSpec.describe PostAction do
SiteSetting.num_flaggers_to_close_topic = 1
Reviewable.set_priorities(high: 0.5)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivities[:low]
post = Fabricate(:post, topic: topic)
PostActionCreator.spam(flagger1, post)
@ -772,7 +772,7 @@ RSpec.describe PostAction do
freeze_time timer.execute_at
SiteSetting.num_flaggers_to_close_topic = 10
Reviewable.set_priorities(high: 10.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivities[:low]
Jobs::ToggleTopicClosed.new.execute(topic_timer_id: timer.id, state: false)

View File

@ -292,7 +292,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
flagged_reply = Fabricate(:reviewable_flagged_post, target: reply)
flagged_post.perform(moderator, :delete_and_agree_replies)
expect(flagged_reply.reload.status).to eq(Reviewable.statuses[:ignored])
expect(flagged_reply.reload).to be_ignored
end
it "notifies users that responded to flagged post" do
@ -308,7 +308,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
flagged_reply = Fabricate(:reviewable_flagged_post, target: reply)
flagged_post.perform(moderator, :delete_and_agree_replies)
expect(flagged_reply.reload.status).to eq(Reviewable.statuses[:ignored])
expect(flagged_reply.reload).to be_ignored
end
end

View File

@ -14,8 +14,8 @@ RSpec.describe ReviewableHistory, type: :model do
history = reviewable.history
expect(history.size).to eq(3)
expect(history[0].reviewable_history_type).to eq(ReviewableHistory.types[:created])
expect(history[0].status).to eq(Reviewable.statuses[:pending])
expect(history[0]).to be_created
expect(history[0]).to be_pending
expect(history[0].created_by).to eq(admin)
end
@ -26,12 +26,12 @@ RSpec.describe ReviewableHistory, type: :model do
history = reviewable.history
expect(history.size).to eq(3)
expect(history[1].reviewable_history_type).to eq(ReviewableHistory.types[:transitioned])
expect(history[1].status).to eq(Reviewable.statuses[:approved])
expect(history[1]).to be_transitioned
expect(history[1]).to be_approved
expect(history[1].created_by).to eq(moderator)
expect(history[2].reviewable_history_type).to eq(ReviewableHistory.types[:transitioned])
expect(history[2].status).to eq(Reviewable.statuses[:pending])
expect(history[2]).to be_transitioned
expect(history[2]).to be_pending
expect(history[2].created_by).to eq(admin)
end
@ -52,7 +52,7 @@ RSpec.describe ReviewableHistory, type: :model do
history = reviewable.history
expect(history.size).to eq(2)
expect(history[1].reviewable_history_type).to eq(ReviewableHistory.types[:edited])
expect(history[1]).to be_edited
expect(history[1].created_by).to eq(moderator)
expect(history[1].edited).to eq("category_id" => [old_category.id, nil])
end

View File

@ -9,8 +9,8 @@ RSpec.describe ReviewablePost do
let(:guardian) { Guardian.new }
it 'Does not return available actions when the reviewable is no longer pending' do
available_actions = (Reviewable.statuses.keys - [:pending]).reduce([]) do |actions, status|
reviewable.status = Reviewable.statuses[status]
available_actions = (Reviewable.statuses.keys - ["pending"]).reduce([]) do |actions, status|
reviewable.status = status
actions.concat reviewable_actions(guardian).to_a
end

View File

@ -85,7 +85,7 @@ RSpec.describe ReviewableQueuedPost, type: :model do
post = Fabricate(:post, user: newuser)
PostActionCreator.spam(moderator, post)
Reviewable.set_priorities(high: 1.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
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)
@ -212,7 +212,7 @@ RSpec.describe ReviewableQueuedPost, type: :model do
context "when status changes from 'pending' to something else" do
it "updates user stats" do
user_stats.expects(:update_pending_posts)
reviewable.update!(status: described_class.statuses[:approved])
reviewable.update!(status: :approved)
end
end

View File

@ -427,8 +427,8 @@ RSpec.describe Reviewable, type: :model do
expect { PostActionCreator.spam(Fabricate(:user), post) }
.to change { reviewable.reload.status }
.from(Reviewable.statuses[:rejected])
.to(Reviewable.statuses[:pending])
.from("rejected")
.to("pending")
.and change { Jobs::NotifyReviewable.jobs.size }
.by(1)
end
@ -521,77 +521,77 @@ RSpec.describe Reviewable, type: :model do
describe ".score_required_to_hide_post" do
it "will return the default visibility if it's higher" do
Reviewable.set_priorities(low: 40.0, high: 100.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_required_to_hide_post).to eq(40.0)
described_class.set_priorities(low: 40.0, high: 100.0)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:high]
expect(described_class.score_required_to_hide_post).to eq(40.0)
end
it "returns a default if we can't calculated any percentiles" do
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.score_required_to_hide_post).to eq(12.5)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_required_to_hide_post).to eq(4.16)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:low]
expect(described_class.score_required_to_hide_post).to eq(12.5)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:medium]
expect(described_class.score_required_to_hide_post).to eq(8.33)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:high]
expect(described_class.score_required_to_hide_post).to eq(4.16)
end
it "returns a fraction of the high percentile" do
Reviewable.set_priorities(high: 100.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(Float::MAX)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(100.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(66.66)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(33.33)
described_class.set_priorities(high: 100.0)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:disabled]
expect(described_class.score_required_to_hide_post.to_f.truncate(2)).to eq(Float::MAX)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:low]
expect(described_class.score_required_to_hide_post.to_f.truncate(2)).to eq(100.0)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:medium]
expect(described_class.score_required_to_hide_post.to_f.truncate(2)).to eq(66.66)
SiteSetting.hide_post_sensitivity = described_class.sensitivities[:high]
expect(described_class.score_required_to_hide_post.to_f.truncate(2)).to eq(33.33)
end
end
describe ".spam_score_to_silence_new_user" do
it "returns a default value if we can't calculated any percentiles" do
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.spam_score_to_silence_new_user).to eq(7.5)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.spam_score_to_silence_new_user).to eq(4.99)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.spam_score_to_silence_new_user).to eq(2.49)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:low]
expect(described_class.spam_score_to_silence_new_user).to eq(7.5)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:medium]
expect(described_class.spam_score_to_silence_new_user).to eq(4.99)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:high]
expect(described_class.spam_score_to_silence_new_user).to eq(2.49)
end
it "returns a fraction of the high percentile" do
Reviewable.set_priorities(high: 100.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:disabled]
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(Float::MAX)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(60.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(39.99)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(19.99)
described_class.set_priorities(high: 100.0)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:disabled]
expect(described_class.spam_score_to_silence_new_user.to_f).to eq(Float::MAX)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:low]
expect(described_class.spam_score_to_silence_new_user.to_f).to eq(60.0)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:medium]
expect(described_class.spam_score_to_silence_new_user.to_f).to eq(39.99)
SiteSetting.silence_new_user_sensitivity = described_class.sensitivities[:high]
expect(described_class.spam_score_to_silence_new_user.to_f).to eq(19.99)
end
end
describe ".score_to_auto_close_topic" do
it "returns the default if we can't calculated any percentiles" do
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.score_to_auto_close_topic).to eq(31.25)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_to_auto_close_topic).to eq(20.83)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_to_auto_close_topic).to eq(10.41)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:low]
expect(described_class.score_to_auto_close_topic).to eq(31.25)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:medium]
expect(described_class.score_to_auto_close_topic).to eq(20.83)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:high]
expect(described_class.score_to_auto_close_topic).to eq(10.41)
end
it "returns a fraction of the high percentile" do
Reviewable.set_priorities(high: 100.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:disabled]
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(Float::MAX)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(250.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(166.66)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(83.33)
described_class.set_priorities(high: 100.0)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:disabled]
expect(described_class.score_to_auto_close_topic.to_f.truncate(2)).to eq(Float::MAX)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:low]
expect(described_class.score_to_auto_close_topic.to_f.truncate(2)).to eq(250.0)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:medium]
expect(described_class.score_to_auto_close_topic.to_f.truncate(2)).to eq(166.66)
SiteSetting.auto_close_topic_sensitivity = described_class.sensitivities[:high]
expect(described_class.score_to_auto_close_topic.to_f.truncate(2)).to eq(83.33)
end
end

View File

@ -2909,7 +2909,7 @@ RSpec.describe Topic do
Reviewable.set_priorities(low: 2.0, medium: 6.0, high: 9.0)
SiteSetting.num_flaggers_to_close_topic = 2
SiteSetting.reviewable_default_visibility = 'medium'
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivities[:high]
post = Fabricate(:post)
@topic = post.topic
@reviewable = Fabricate(:reviewable_flagged_post, target: post, topic: @topic)

View File

@ -2602,35 +2602,44 @@ RSpec.describe User do
end
describe 'Granting admin or moderator status' do
fab!(:reviewable_user) { Fabricate(:reviewable_user) }
context 'when granting admin status' do
context 'when there is a reviewable' do
fab!(:user) { Fabricate(:reviewable_user) }
it 'approves the associated reviewable when granting admin status' do
reviewable_user.target.grant_admin!
expect(reviewable_user.reload.status).to eq Reviewable.statuses[:approved]
context 'when the user isnt approved yet' do
it 'approves the associated reviewable' do
expect { user.target.grant_admin! }.to change { user.reload.dup }.to be_approved
end
end
it 'does nothing when the user is already approved' do
reviewable_user = Fabricate(:reviewable_user)
reviewable_user.perform(Discourse.system_user, :approve_user)
reviewable_user.target.grant_admin!
expect(reviewable_user.reload.status).to eq Reviewable.statuses[:approved]
context "when the user is already approved" do
before do
user.perform(Discourse.system_user, :approve_user)
end
it 'approves the associated reviewable when granting moderator status' do
reviewable_user.target.grant_moderation!
expect(reviewable_user.reload.status).to eq Reviewable.statuses[:approved]
it 'does nothing' do
expect { user.target.grant_admin! }.not_to change { user.reload.approved? }
end
end
end
it 'approves the user if there is no reviewable' do
user = Fabricate(:user, approved: false)
context 'when there is no reviewable' do
let(:user) { Fabricate(:user, approved: false) }
user.grant_admin!
it 'approves the user' do
expect { user.grant_admin! }.to change { user.reload.approved }.to true
end
end
end
expect(user.approved).to eq(true)
context 'when granting moderator status' do
context 'when there is a reviewable' do
let(:user) { Fabricate(:reviewable_user) }
it 'approves the associated reviewable' do
expect { user.target.grant_moderation! }.to change { user.reload.dup }.to be_approved
end
end
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe ReviewableSerializer do
json = described_class.new(reviewable, scope: Guardian.new(admin), root: nil).as_json
expect(json[:id]).to eq(reviewable.id)
expect(json[:status]).to eq(reviewable.status)
expect(json[:status]).to eq(reviewable.status_for_database)
expect(json[:type]).to eq(reviewable.type)
expect(json[:created_at]).to eq(reviewable.created_at)
expect(json[:category_id]).to eq(reviewable.category_id)

View File

@ -2,9 +2,9 @@
RSpec.describe SpamRule::AutoSilence do
before do
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:disabled]
Reviewable.set_priorities(high: 4.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivities[:low]
SiteSetting.num_users_to_silence_new_user = 2
end
@ -20,7 +20,7 @@ RSpec.describe SpamRule::AutoSilence do
it 'delivers punishment when user should be silenced' do
Reviewable.set_priorities(high: 2.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivities[:low]
SiteSetting.num_users_to_silence_new_user = 1
PostActionCreator.spam(Discourse.system_user, post)
subject.perform
@ -194,7 +194,7 @@ RSpec.describe SpamRule::AutoSilence do
end
it 'returns false if silence_new_user_sensitivity is disabled' do
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:disabled]
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivities[:disabled]
PostActionCreator.spam(flagger, post)
PostActionCreator.spam(flagger2, post)
expect(subject.should_autosilence?).to eq(false)

View File

@ -156,7 +156,7 @@ RSpec.describe SpamRule::FlagSockpuppets do
described_class.new(post2).perform
expect(flagged_post.reload.status).to eq(Reviewable.statuses[:rejected])
expect(flagged_post.reload).to be_rejected
end
it "doesn't flag the post if another post of the same user was rejected by staff before" do

View File

@ -308,7 +308,7 @@ RSpec.describe PostAlerter do
PostActionNotifier.enable
Reviewable.set_priorities(high: 4.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.hide_post_sensitivity = Reviewable.sensitivities[:low]
PostActionCreator.spam(evil_trout, post)
PostActionCreator.spam(walterwhite, post)

View File

@ -106,7 +106,7 @@ RSpec.describe UserDestroyer do
it 'sets the reviewable user as rejected' do
UserDestroyer.new(admin).destroy(reviewable.target)
expect(reviewable.reload.status).to eq(Reviewable.statuses[:rejected])
expect(reviewable.reload).to be_rejected
end
end