FEATURE: new 'maximum new user accounts per registration IP' site setting

This commit is contained in:
Régis Hanol 2014-11-17 12:04:29 +01:00
parent 78f6cea16c
commit 7641d88224
9 changed files with 67 additions and 18 deletions

View File

@ -227,8 +227,7 @@ class UsersController < ApplicationController
authentication = UserAuthenticator.new(user, session) authentication = UserAuthenticator.new(user, session)
if !authentication.has_authenticator? && !SiteSetting.enable_local_logins if !authentication.has_authenticator? && !SiteSetting.enable_local_logins
render nothing: true, status: 500 return render nothing: true, status: 500
return
end end
authentication.start authentication.start

View File

@ -2,7 +2,6 @@
# receive, their trust level, etc. # receive, their trust level, etc.
class SpamRulesEnforcer class SpamRulesEnforcer
# The exclamation point means that this method may make big changes to posts and users.
def self.enforce!(arg) def self.enforce!(arg)
SpamRulesEnforcer.new(arg).enforce! SpamRulesEnforcer.new(arg).enforce!
end end
@ -13,12 +12,8 @@ class SpamRulesEnforcer
end end
def enforce! def enforce!
if @user SpamRule::AutoBlock.new(@user).perform if @user
SpamRule::AutoBlock.new(@user).perform SpamRule::FlagSockpuppets.new(@post).perform if @post
end
if @post
SpamRule::FlagSockpuppets.new(@post).perform
end
true true
end end

View File

@ -1,4 +1,5 @@
class UserAuthenticator class UserAuthenticator
def initialize(user, session, authenticator_finder = Users::OmniauthCallbacksController) def initialize(user, session, authenticator_finder = Users::OmniauthCallbacksController)
@user = user @user = user
@session = session[:authentication] @session = session[:authentication]
@ -18,10 +19,7 @@ class UserAuthenticator
end end
def finish def finish
if authenticator authenticator.after_create_account(@user, @session) if authenticator
authenticator.after_create_account(@user, @session)
end
@session = nil @session = nil
end end
@ -40,4 +38,5 @@ class UserAuthenticator
def authenticator_name def authenticator_name
@session && @session[:authenticator_name] @session && @session[:authenticator_name]
end end
end end

View File

@ -941,6 +941,7 @@ en:
staff_like_weight: "How much extra weighting factor to give staff likes." staff_like_weight: "How much extra weighting factor to give staff likes."
levenshtein_distance_spammer_emails: "When matching spammer emails, number of characters difference that will still allow a fuzzy match." levenshtein_distance_spammer_emails: "When matching spammer emails, number of characters difference that will still allow a fuzzy match."
max_new_accounts_per_registration_ip: "If there are already (n) trust level 0 accounts from this IP, stop accepting new signups from that IP."
reply_by_email_enabled: "Enable replying to topics via email." reply_by_email_enabled: "Enable replying to topics via email."
reply_by_email_address: "Template for reply by email incoming email address, for example: %{reply_key}@reply.example.com or replies+%{reply_key}@example.com" reply_by_email_address: "Template for reply by email incoming email address, for example: %{reply_key}@reply.example.com or replies+%{reply_key}@example.com"

View File

@ -576,6 +576,7 @@ spam:
default: 2 default: 2
min: 0 min: 0
max: 3 max: 3
max_new_accounts_per_registration_ip: 3
rate_limits: rate_limits:
unique_posts_mins: unique_posts_mins:

14
lib/spam_handler.rb Normal file
View File

@ -0,0 +1,14 @@
class SpamHandler
def self.should_prevent_registration_from_ip?(ip_address)
return false if SiteSetting.max_new_accounts_per_registration_ip <= 0
tl0_accounts_with_same_ip = User.unscoped
.where(trust_level: TrustLevel[0])
.where("ip_address = ?", ip_address.to_s)
.count
tl0_accounts_with_same_ip >= SiteSetting.max_new_accounts_per_registration_ip
end
end

View File

@ -1,9 +1,14 @@
require_dependency "spam_handler"
class AllowedIpAddressValidator < ActiveModel::EachValidator class AllowedIpAddressValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
if record.ip_address and ScreenedIpAddress.should_block?(record.ip_address) if record.ip_address
record.errors.add(attribute, options[:message] || I18n.t('user.ip_address.blocked')) if ScreenedIpAddress.should_block?(record.ip_address) ||
(record.trust_level == TrustLevel[0] && SpamHandler.should_prevent_registration_from_ip?(record.ip_address))
record.errors.add(attribute, options[:message] || I18n.t('user.ip_address.blocked'))
end
end end
end end
end end

View File

@ -0,0 +1,27 @@
require "spec_helper"
require "spam_handler"
describe SpamHandler do
describe "#should_prevent_registration_from_ip?" do
it "works" do
# max_new_accounts_per_registration_ip = 0 disables the check
SiteSetting.stubs(:max_new_accounts_per_registration_ip).returns(0)
Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[1])
Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[0])
# only prevents registration for TL0
SiteSetting.stubs(:max_new_accounts_per_registration_ip).returns(2)
Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[1])
Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[0])
Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[1])
-> { Fabricate(:user, ip_address: "42.42.42.42", trust_level: TrustLevel[0]) }.should raise_error(ActiveRecord::RecordInvalid)
end
end
end

View File

@ -2,7 +2,7 @@ require 'spec_helper'
describe AllowedIpAddressValidator do describe AllowedIpAddressValidator do
let(:record) { Fabricate.build(:user, ip_address: '99.232.23.123') } let(:record) { Fabricate.build(:user, trust_level: TrustLevel[0], ip_address: '99.232.23.123') }
let(:validator) { described_class.new({attributes: :ip_address}) } let(:validator) { described_class.new({attributes: :ip_address}) }
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) } subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
@ -14,6 +14,14 @@ describe AllowedIpAddressValidator do
end end
end end
context "ip address isn't allowed for registration" do
it 'should add an error' do
SpamHandler.stubs(:should_prevent_registration_from_ip?).returns(true)
validate
record.errors[:ip_address].should be_present
end
end
context "ip address should not be blocked" do context "ip address should not be blocked" do
it "shouldn't add an error" do it "shouldn't add an error" do
ScreenedIpAddress.stubs(:should_block?).returns(false) ScreenedIpAddress.stubs(:should_block?).returns(false)
@ -31,4 +39,4 @@ describe AllowedIpAddressValidator do
end end
end end
end end