diff --git a/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6 index 03f2d4bdb..414461eda 100644 --- a/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6 @@ -21,8 +21,16 @@ export default Ember.ArrayController.extend(Discourse.Presence, { return bootbox.confirm(I18n.t("admin.logs.screened_ips.roll_up_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function (confirmed) { if (confirmed) { self.set("loading", true) - return Discourse.ScreenedIpAddress.rollUp().then(function() { - self.send("show"); + return Discourse.ScreenedIpAddress.rollUp().then(function(results) { + if (results && results.subnets) { + if (results.subnets.length > 0) { + self.send("show"); + bootbox.alert(I18n.t("admin.logs.screened_ips.rolled_up_some_subnets", { subnets: results.subnets.join(", ") })); + } else { + self.set("loading", false); + bootbox.alert(I18n.t("admin.logs.screened_ips.rolled_up_no_subnet")); + } + } }); } }); diff --git a/app/controllers/admin/screened_ip_addresses_controller.rb b/app/controllers/admin/screened_ip_addresses_controller.rb index ea77a8b98..079e674fb 100644 --- a/app/controllers/admin/screened_ip_addresses_controller.rb +++ b/app/controllers/admin/screened_ip_addresses_controller.rb @@ -29,21 +29,51 @@ class Admin::ScreenedIpAddressesController < Admin::AdminController render json: success_json end - def roll_up - # 1 - retrieve all subnets that needs roll up - sql = <<-SQL - SELECT network(inet(host(ip_address) || './24')) AS ip_range + def star_subnets_query + @star_subnets_query ||= <<-SQL + SELECT network(inet(host(ip_address) || '/24')) AS ip_range FROM screened_ip_addresses - WHERE action_type = :action_type + WHERE action_type = #{ScreenedIpAddress.actions[:block]} AND family(ip_address) = 4 AND masklen(ip_address) = 32 GROUP BY ip_range HAVING COUNT(*) >= :min_count SQL + end - subnets = ScreenedIpAddress.exec_sql(sql, - action_type: ScreenedIpAddress.actions[:block], - min_count: SiteSetting.min_ban_entries_for_roll_up).values.flatten + def star_star_subnets_query + @star_star_subnets_query ||= <<-SQL + WITH weighted_subnets AS ( + SELECT network(inet(host(ip_address) || '/16')) AS ip_range, + CASE masklen(ip_address) + WHEN 32 THEN 1 + WHEN 24 THEN :roll_up_weight + ELSE 0 + END AS weight + FROM screened_ip_addresses + WHERE action_type = #{ScreenedIpAddress.actions[:block]} + AND family(ip_address) = 4 + ) + SELECT ip_range + FROM weighted_subnets + GROUP BY ip_range + HAVING SUM(weight) >= :min_count + SQL + end + + def star_subnets + min_count = SiteSetting.min_ban_entries_for_roll_up + ScreenedIpAddress.exec_sql(star_subnets_query, min_count: min_count).values.flatten + end + + def star_star_subnets + weight = SiteSetting.min_ban_entries_for_roll_up + ScreenedIpAddress.exec_sql(star_star_subnets_query, min_count: 10, roll_up_weight: weight).values.flatten + end + + def roll_up + # 1 - retrieve all subnets that needs roll up + subnets = [star_subnets, star_star_subnets].flatten # 2 - log the call StaffActionLogger.new(current_user).log_roll_up(subnets) unless subnets.blank? @@ -63,25 +93,23 @@ class Admin::ScreenedIpAddressesController < Admin::AdminController MIN(created_at) AS min_created_at, MAX(last_match_at) AS max_last_match_at FROM screened_ip_addresses - WHERE action_type = :action_type + WHERE action_type = #{ScreenedIpAddress.actions[:block]} AND family(ip_address) = 4 - AND masklen(ip_address) = 32 AND ip_address << :ip_address ) s WHERE ip_address = :ip_address SQL - ScreenedIpAddress.exec_sql(sql, action_type: ScreenedIpAddress.actions[:block], ip_address: subnet) + ScreenedIpAddress.exec_sql(sql, ip_address: subnet) # 5 - remove old matches ScreenedIpAddress.where(action_type: ScreenedIpAddress.actions[:block]) .where("family(ip_address) = 4") - .where("masklen(ip_address) = 32") .where("ip_address << ?", subnet) .delete_all end - render json: success_json + render json: success_json.merge!({ subnets: subnets }) end private diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 1da4d8709..317d37e42 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1862,6 +1862,8 @@ en: description: 'IP addresses that are being watched. Use "Allow" to whitelist IP addresses.' delete_confirm: "Are you sure you want to remove the rule for %{ip_address}?" roll_up_confirm: "Are you sure you want to roll up ban entries?" + rolled_up_some_subnets: "Successfully rolled up IP ban entries to these subnets: %{subnets}." + rolled_up_no_subnet: "There was nothing to roll up." actions: block: "Block" do_nothing: "Allow" diff --git a/script/import_scripts/tnation.rb b/script/import_scripts/tnation.rb new file mode 100644 index 000000000..bbc03abd6 --- /dev/null +++ b/script/import_scripts/tnation.rb @@ -0,0 +1,24 @@ +# custom importer for www.t-nation.com, feel free to borrow ideas + +require File.expand_path(File.dirname(__FILE__) + "/base.rb") +require "mysql2" + +class ImportScripts::Tnation < ImportScripts::Base + + DATABASE = "tnation" + + def initialize + super + + @client = Mysql2::Client.new( + host: "localhost", + database: DATABASE + ) + end + + def execute + end + +end + +ImportScripts::Tnation.new.perform diff --git a/spec/controllers/admin/screened_ip_addresses_controller_spec.rb b/spec/controllers/admin/screened_ip_addresses_controller_spec.rb index ddd1d1212..528134c9d 100644 --- a/spec/controllers/admin/screened_ip_addresses_controller_spec.rb +++ b/spec/controllers/admin/screened_ip_addresses_controller_spec.rb @@ -20,7 +20,7 @@ describe Admin::ScreenedIpAddressesController do describe 'roll_up' do - it "works" do + it "rolls up 1.2.3.* entries" do Fabricate(:screened_ip_address, ip_address: "1.2.3.4", match_count: 1) Fabricate(:screened_ip_address, ip_address: "1.2.3.5", match_count: 1) Fabricate(:screened_ip_address, ip_address: "1.2.3.6", match_count: 1) @@ -29,7 +29,7 @@ describe Admin::ScreenedIpAddressesController do Fabricate(:screened_ip_address, ip_address: "42.42.42.5", match_count: 1) StaffActionLogger.any_instance.expects(:log_roll_up) - SiteSetting.expects(:min_ban_entries_for_roll_up).returns(3) + SiteSetting.stubs(:min_ban_entries_for_roll_up).returns(3) xhr :post, :roll_up response.should be_success @@ -39,6 +39,26 @@ describe Admin::ScreenedIpAddressesController do subnet.match_count.should == 3 end + it "rolls up 1.2.*.* entries" do + Fabricate(:screened_ip_address, ip_address: "1.2.3.4", match_count: 1) + Fabricate(:screened_ip_address, ip_address: "1.2.3.5", match_count: 1) + Fabricate(:screened_ip_address, ip_address: "1.2.4.6", match_count: 1) + Fabricate(:screened_ip_address, ip_address: "1.2.7.8", match_count: 1) + Fabricate(:screened_ip_address, ip_address: "1.2.9.1", match_count: 1) + + Fabricate(:screened_ip_address, ip_address: "1.2.42.0/24", match_count: 1) + + StaffActionLogger.any_instance.expects(:log_roll_up) + SiteSetting.stubs(:min_ban_entries_for_roll_up).returns(5) + + xhr :post, :roll_up + response.should be_success + + subnet = ScreenedIpAddress.where(ip_address: "1.2.0.0/16").first + subnet.should be_present + subnet.match_count.should == 6 + end + end end