From 0398ab7514114154cd5b6c0782f80f1ff8523990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Fri, 21 Nov 2014 18:16:06 +0100 Subject: [PATCH] FIX: when adding an IP to the spammer list, check the broader ban list first FEATURE: allow admins to search users using IP ranges --- app/models/screened_ip_address.rb | 13 ++----------- app/services/user_destroyer.rb | 11 +++++++++-- lib/admin_user_index_query.rb | 4 ++-- lib/ip_addr.rb | 16 ++++++++++++++++ lib/spam_handler.rb | 6 +++--- 5 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 lib/ip_addr.rb diff --git a/app/models/screened_ip_address.rb b/app/models/screened_ip_address.rb index a4eb6e148..d55476602 100644 --- a/app/models/screened_ip_address.rb +++ b/app/models/screened_ip_address.rb @@ -1,4 +1,5 @@ require_dependency 'screening_model' +require_dependency 'ip_addr' # A ScreenedIpAddress record represents an IP address or subnet that is being watched, # and possibly blocked from creating accounts. @@ -47,18 +48,8 @@ class ScreenedIpAddress < ActiveRecord::Base end # Return a string with the ip address and mask in standard format. e.g., "127.0.0.0/8". - # Ruby's IPAddr class has no method for getting this. def ip_address_with_mask - if ip_address - mask = ip_address.instance_variable_get(:@mask_addr).to_s(2).count('1') - if mask == 32 - ip_address.to_s - else - "#{ip_address}/#{ip_address.instance_variable_get(:@mask_addr).to_s(2).count('1')}" - end - else - nil - end + ip_address.try(:to_cidr_s) end def self.match_for_ip_address(ip_address) diff --git a/app/services/user_destroyer.rb b/app/services/user_destroyer.rb index def4bc3a9..4c0b34741 100644 --- a/app/services/user_destroyer.rb +++ b/app/services/user_destroyer.rb @@ -1,3 +1,5 @@ +require_dependency 'ip_addr' + # Responsible for destroying a User record class UserDestroyer @@ -45,16 +47,21 @@ class UserDestroyer user.destroy.tap do |u| if u + if opts[:block_email] b = ScreenedEmail.block(u.email, ip_address: u.ip_address) b.record_match! if b end + if opts[:block_ip] && u.ip_address - b.record_match! if b = ScreenedIpAddress.watch(u.ip_address) + b = ScreenedIpAddress.watch(u.ip_address) + b.record_match! if b if u.registration_ip_address && u.ip_address != u.registration_ip_address - b.record_match! if b = ScreenedIpAddress.watch(u.registration_ip_address) + b = ScreenedIpAddress.watch(u.registration_ip_address) + b.record_match! if b end end + Post.with_deleted.where(user_id: user.id).update_all("user_id = NULL") # If this user created categories, fix those up: diff --git a/lib/admin_user_index_query.rb b/lib/admin_user_index_query.rb index c0e11cdc7..17d07feb1 100644 --- a/lib/admin_user_index_query.rb +++ b/lib/admin_user_index_query.rb @@ -42,8 +42,8 @@ class AdminUserIndexQuery def filter_by_search if params[:filter].present? - if params[:filter] =~ Resolv::IPv4::Regex || params[:filter] =~ Resolv::IPv6::Regex - @query.where('ip_address = :ip OR registration_ip_address = :ip', ip: params[:filter]) + if ip = IPAddr.new(params[:filter]) rescue nil + @query.where('ip_address <<= :ip OR registration_ip_address <<= :ip', ip: ip.to_cidr_s) else @query.where('username_lower ILIKE :filter OR email ILIKE :filter', filter: "%#{params[:filter]}%") end diff --git a/lib/ip_addr.rb b/lib/ip_addr.rb new file mode 100644 index 000000000..c8afcde48 --- /dev/null +++ b/lib/ip_addr.rb @@ -0,0 +1,16 @@ +class IPAddr + + def to_cidr_s + if @addr + mask = @mask_addr.to_s(2).count('1') + if mask == 32 + to_s + else + "#{to_s}/#{mask}" + end + else + nil + end + end + +end diff --git a/lib/spam_handler.rb b/lib/spam_handler.rb index 1df501bab..6fc184e74 100644 --- a/lib/spam_handler.rb +++ b/lib/spam_handler.rb @@ -4,21 +4,21 @@ class SpamHandler return false if SiteSetting.max_new_accounts_per_registration_ip <= 0 tl2_plus_accounts_with_same_ip = User.where("trust_level >= ?", TrustLevel[2]) - .where("ip_address = ?", ip_address.to_s) + .where(ip_address: ip_address.to_s) .count return false if tl2_plus_accounts_with_same_ip > 0 staff_user_ids = Group[:staff].user_ids - [-1] staff_members_with_same_ip = User.where(id: staff_user_ids) - .where("ip_address = ?", ip_address.to_s) + .where(ip_address: ip_address.to_s) .count return false if staff_members_with_same_ip > 0 tl0_accounts_with_same_ip = User.unscoped .where(trust_level: TrustLevel[0]) - .where("ip_address = ?", ip_address.to_s) + .where(ip_address: ip_address.to_s) .count tl0_accounts_with_same_ip >= SiteSetting.max_new_accounts_per_registration_ip