Migrate score settings to use sensitivities

We hide scores so these settings no longer made sense.
This commit is contained in:
Robin Ward 2019-05-24 14:13:03 -04:00
parent fad5d9c49b
commit 89b84651c3
14 changed files with 182 additions and 39 deletions

View File

@ -41,7 +41,7 @@ class Reviewable < ActiveRecord::Base
Jobs.enqueue(:notify_reviewable, reviewable_id: self.id) if pending?
end
# The gaps are in case we want more accuracy in the future
# The gaps are in case we want more precision in the future
def self.priorities
@priorities ||= Enum.new(
low: 0,
@ -50,6 +50,16 @@ class Reviewable < ActiveRecord::Base
)
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,
@ -173,6 +183,29 @@ class Reviewable < ActiveRecord::Base
end
end
def self.sensitivity_score(sensitivity, scale: 1.0)
return Float::MAX if sensitivity == 0
ratio = sensitivity / Reviewable.sensitivity[:low].to_f
high = PluginStore.get('reviewables', "priority_#{Reviewable.priorities[:high]}")
return (10.0 * scale) if high.nil?
# We want this to be hard to reach
(high.to_f * ratio) * scale
end
def self.score_to_auto_close_topic
sensitivity_score(SiteSetting.auto_close_topic_sensitivity, scale: 2.5)
end
def self.spam_score_to_silence_new_user
sensitivity_score(SiteSetting.silence_new_user_sensitivity, scale: 0.6)
end
def self.score_required_to_hide_post
sensitivity_score(SiteSetting.hide_post_sensitivity)
end
def self.min_score_for_priority(priority = nil)
priority ||= SiteSetting.reviewable_default_visibility
id = Reviewable.priorities[priority.to_sym]

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
require_dependency 'enum_site_setting'
class ReviewableSensitivitySetting < EnumSiteSetting
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
def self.values
Reviewable.sensitivity.map do |p|
{ name: I18n.t("reviewables.sensitivity.#{p[0]}"), value: p[1] }
end
end
def self.translate_names?
false
end
end

View File

@ -1373,7 +1373,7 @@ class Topic < ActiveRecord::Base
.pluck("COUNT(DISTINCT reviewable_scores.user_id), COALESCE(SUM(reviewable_scores.score), 0.0)")
.first
scores[0] >= SiteSetting.num_flaggers_to_close_topic && scores[1] >= SiteSetting.score_to_auto_close_topic
scores[0] >= SiteSetting.num_flaggers_to_close_topic && scores[1] >= Reviewable.score_to_auto_close_topic
end
def update_category_topic_count_by(num)

View File

@ -24,14 +24,9 @@ class SpamRule::AutoSilence
return false if @user.staged?
return false if @user.has_trust_level?(TrustLevel[1])
if SiteSetting.spam_score_to_silence_new_user > 0 &&
SiteSetting.num_users_to_silence_new_user > 0 &&
user_spam_stats.total_spam_score >= SiteSetting.spam_score_to_silence_new_user &&
user_spam_stats.spam_user_count >= SiteSetting.num_users_to_silence_new_user
return true
end
false
SiteSetting.num_users_to_silence_new_user > 0 &&
user_spam_stats.total_spam_score >= Reviewable.spam_score_to_silence_new_user &&
user_spam_stats.spam_user_count >= SiteSetting.num_users_to_silence_new_user
end
def user_spam_stats

View File

@ -1388,7 +1388,10 @@ en:
anon_polling_interval: "How often should anonymous clients poll in milliseconds"
background_polling_interval: "How often should the clients poll in milliseconds (when the window is in the background)"
score_required_to_hide_post: "Score threshold that causes a post to be automatically hidden and message sent to the user (0 to disable)"
hide_post_sensitivity: "The likelyhood that a flagged post will be hidden"
silence_new_user_sensitivity: "The likelyhood that a new user will be silenced based on spam flags"
auto_close_topic_sensitivity: "The likelyhood that a flagged topic will be automatically closed"
cooldown_minutes_after_hiding_posts: "Number of minutes a user must wait before they can edit a post hidden via community flagging"
max_topics_in_first_day: "The maximum number of topics a user is allowed to create in the 24 hour period after creating their first post"
@ -1397,8 +1400,6 @@ en:
tl2_additional_likes_per_day_multiplier: "Increase limit of likes per day for tl2 (member) by multiplying with this number"
tl3_additional_likes_per_day_multiplier: "Increase limit of likes per day for tl3 (regular) by multiplying with this number"
tl4_additional_likes_per_day_multiplier: "Increase limit of likes per day for tl4 (leader) by multiplying with this number"
spam_score_to_silence_new_user: "If a new user's posts receive this score from num_users_to_silence_new_user different users, hide all their posts and prevent future posting. 0 to disable."
num_users_to_silence_new_user: "If a new user's posts get num_spam_flags_to_silence_new_user spam flags from this many different users, hide all their posts and prevent future posting. 0 to disable."
num_tl3_flags_to_silence_new_user: "If a new user's posts get this many flags from num_tl3_users_to_silence_new_user different trust level 3 users, hide all their posts and prevent future posting. 0 to disable."
num_tl3_users_to_silence_new_user: "If a new user's posts get num_tl3_flags_to_silence_new_user flags from this many different trust level 3 users, hide all their posts and prevent future posting. 0 to disable."
@ -1745,7 +1746,6 @@ en:
max_age_unmatched_ips: "Delete unmatched screened IP entries after (N) days."
num_flaggers_to_close_topic: "Minimum number of unique flaggers that is required to automatically pause a topic for intervention"
score_to_auto_close_topic: "The total flag score of that is required to automatically pause a topic for intervention"
num_hours_to_close_topic: "Number of hours to pause a topic for intervention."
auto_respond_to_flag_actions: "Enable automatic reply when disposing a flag."
@ -4418,7 +4418,11 @@ en:
low: "Low"
medium: "Medium"
high: "High"
sensitivity:
disabled: "Disabled"
low: "Low"
medium: "Medium"
high: "High"
must_claim: "You must claim items before acting on them."
user_claimed: "This item has been claimed by another user."
missing_version: "You must supply a version parameter"

View File

@ -1366,9 +1366,15 @@ onebox:
spam:
add_rel_nofollow_to_user_content: true
score_required_to_hide_post: 10
hide_post_sensitivity:
type: enum
enum: "ReviewableSensitivitySetting"
default: 6
cooldown_minutes_after_hiding_posts: 10
spam_score_to_silence_new_user: 6.0
silence_new_user_sensitivity:
type: enum
enum: "ReviewableSensitivitySetting"
default: 9
num_users_to_silence_new_user: 3
notify_mods_when_user_silenced: false
flag_sockpuppets: false
@ -1384,7 +1390,10 @@ spam:
max_age_unmatched_emails: 365
max_age_unmatched_ips: 365
num_flaggers_to_close_topic: 5
score_to_auto_close_topic: 25.0
auto_close_topic_sensitivity:
type: enum
enum: "ReviewableSensitivitySetting"
default: 3
num_hours_to_close_topic:
default: 4
min: 1

View File

@ -166,9 +166,9 @@ private
@post.user&.trust_level != TrustLevel[4]
@post.hide!(@post_action_type_id, Post.hidden_reasons[:flagged_by_tl4_user])
elsif SiteSetting.score_required_to_hide_post > 0
else
score = ReviewableFlaggedPost.find_by(target: @post)&.score || 0
if score >= SiteSetting.score_required_to_hide_post
if score >= Reviewable.score_required_to_hide_post
@post.hide!(@post_action_type_id)
end
end

View File

@ -12,8 +12,9 @@ describe "spam rules for users" do
fab!(:user2) { Fabricate(:user) }
before do
SiteSetting.score_required_to_hide_post = 0
SiteSetting.spam_score_to_silence_new_user = 4.0
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
Reviewable.set_priorities(high: 4.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.num_users_to_silence_new_user = 2
end
@ -73,9 +74,10 @@ describe "spam rules for users" do
end
end
context 'score_required_to_hide_post takes effect too' do
context 'hide_post_sensitivity' do
it 'should silence the spammer' do
SiteSetting.score_required_to_hide_post = 2.0
Reviewable.set_priorities(high: 2.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[: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

@ -517,7 +517,8 @@ describe PostAction do
mod = Fabricate(:moderator)
post = Fabricate(:post, user: mod)
SiteSetting.score_required_to_hide_post = 2.0
Reviewable.set_priorities(high: 2.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -531,7 +532,8 @@ describe PostAction do
mod = Fabricate(:moderator)
post = Fabricate(:post, user: mod)
SiteSetting.score_required_to_hide_post = 8.0
Reviewable.set_priorities(high: 8.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -547,7 +549,8 @@ describe PostAction do
post = create_post
walterwhite = Fabricate(:walter_white)
SiteSetting.score_required_to_hide_post = 3.0
Reviewable.set_priorities(high: 3.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
Discourse.stubs(:site_contact_user).returns(admin)
PostActionCreator.spam(eviltrout, post)
@ -707,8 +710,9 @@ describe PostAction do
fab!(:flagger2) { Fabricate(:user) }
before do
SiteSetting.score_required_to_hide_post = 0
SiteSetting.score_to_auto_close_topic = 12.0
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
Reviewable.set_priorities(high: 4.5)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.num_flaggers_to_close_topic = 2
SiteSetting.num_hours_to_close_topic = 1
end
@ -769,7 +773,8 @@ describe PostAction do
freeze_time
SiteSetting.num_flaggers_to_close_topic = 1
SiteSetting.score_to_auto_close_topic = 2.0
Reviewable.set_priorities(high: 0.5)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
post = Fabricate(:post, topic: topic)
PostActionCreator.spam(flagger1, post)
@ -792,7 +797,8 @@ describe PostAction do
freeze_time timer.execute_at
SiteSetting.num_flaggers_to_close_topic = 10
SiteSetting.score_to_auto_close_topic = 20.0
Reviewable.set_priorities(high: 10.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
Jobs::ToggleTopicClosed.new.execute(topic_timer_id: timer.id, state: false)

View File

@ -87,7 +87,8 @@ RSpec.describe ReviewableQueuedPost, type: :model do
newuser.update!(trust_level: 0)
post = Fabricate(:post, user: newuser)
PostActionCreator.spam(moderator, post)
SiteSetting.spam_score_to_silence_new_user = 1
Reviewable.set_priorities(high: 1.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.num_users_to_silence_new_user = 1
expect(Guardian.new(newuser).can_create_post?(topic)).to eq(false)

View File

@ -282,6 +282,73 @@ RSpec.describe Reviewable, type: :model do
end
end
context ".score_required_to_hide_post" do
it "returns 10 if we can't calculated any percentiles" do
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.score_required_to_hide_post).to eq(10.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_required_to_hide_post).to eq(10.0)
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)
end
end
context ".spam_score_to_silence_new_user" do
it "returns 6 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(6.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.spam_score_to_silence_new_user).to eq(6.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.spam_score_to_silence_new_user).to eq(6.0)
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.truncate(2)).to eq(Float::MAX)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
expect(Reviewable.spam_score_to_silence_new_user.to_f.truncate(2)).to eq(60.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.spam_score_to_silence_new_user.to_f.truncate(2)).to eq(39.99)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.spam_score_to_silence_new_user.to_f.truncate(2)).to eq(19.99)
end
end
context ".score_to_auto_close_topic" do
it "returns 25 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(25.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:medium]
expect(Reviewable.score_to_auto_close_topic).to eq(25.0)
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
expect(Reviewable.score_to_auto_close_topic).to eq(25.0)
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)
end
end
context "priorities" do
it "returns 0 for unknown priorities" do
expect(Reviewable.min_score_for_priority(:wat)).to eq(0.0)

View File

@ -115,7 +115,8 @@ RSpec.describe Admin::FlagsController do
context '#disagree' do
it "unhides the post and unsilences the user if disagreed" do
SiteSetting.spam_score_to_silence_new_user = 1.0
Reviewable.set_priorities(high: 1.0)
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
SiteSetting.num_users_to_silence_new_user = 1
new_user = Fabricate(:newuser)

View File

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

View File

@ -128,7 +128,8 @@ describe PostAlerter do
coding_horror = Fabricate(:coding_horror)
PostActionNotifier.enable
SiteSetting.score_required_to_hide_post = 4.0
Reviewable.set_priorities(high: 4.0)
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
PostActionCreator.spam(evil_trout, post)
PostActionCreator.spam(walterwhite, post)