FEATURE: filter screened IP addresses

This commit is contained in:
Régis Hanol 2015-02-10 19:38:59 +01:00
parent 9b12e53d9c
commit c4e427cf73
8 changed files with 65 additions and 23 deletions

View file

@ -3,15 +3,16 @@ import { outputExportResult } from 'discourse/lib/export-result';
export default Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
itemController: 'admin-log-screened-ip-address',
filter: null,
show: function() {
show: Discourse.debounce(function() {
var self = this;
self.set('loading', true);
Discourse.ScreenedIpAddress.findAll().then(function(result) {
Discourse.ScreenedIpAddress.findAll(this.get("filter")).then(function(result) {
self.set('model', result);
self.set('loading', false);
});
},
}, 250).observes("filter"),
actions: {
recordAdded: function(arg) {

View file

@ -45,8 +45,8 @@ Discourse.ScreenedIpAddress = Discourse.Model.extend({
});
Discourse.ScreenedIpAddress.reopenClass({
findAll: function() {
return Discourse.ajax("/admin/logs/screened_ip_addresses.json").then(function(screened_ips) {
findAll: function(filter) {
return Discourse.ajax("/admin/logs/screened_ip_addresses.json", { data: { filter: filter } }).then(function(screened_ips) {
return screened_ips.map(function(b) {
return Discourse.ScreenedIpAddress.create(b);
});

View file

@ -1,5 +1,6 @@
<p>{{i18n 'admin.logs.screened_ips.description'}}</p>
<div class="pull-right">
{{text-field value=filter class="ip-address-input" placeholderKey="admin.logs.screened_ips.form.filter" autocorrect="off" autocapitalize="off"}}
<button class="btn" {{action "rollUp"}} title="{{i18n 'admin.logs.screened_ips.roll_up.title'}}">{{i18n 'admin.logs.screened_ips.roll_up.text'}}</button>
<button class="btn" {{action "exportScreenedIpList"}} title="{{i18n 'admin.export_csv.button_title.screened_ip'}}">{{fa-icon "download"}}{{i18n 'admin.export_csv.button_text'}}</button>
</div>

View file

@ -1,9 +1,24 @@
require_dependency 'ip_addr'
class Admin::ScreenedIpAddressesController < Admin::AdminController
before_filter :fetch_screened_ip_address, only: [:update, :destroy]
def index
screened_ip_addresses = ScreenedIpAddress.limit(200).order('match_count desc').to_a
filter = params[:filter]
filter = IPAddr.handle_wildcards(filter)
screened_ip_addresses = ScreenedIpAddress
screened_ip_addresses = screened_ip_addresses.where("cidr '#{filter}' >>= ip_address") if filter.present?
screened_ip_addresses = screened_ip_addresses.limit(200).order('match_count desc')
begin
screened_ip_addresses = screened_ip_addresses.to_a
rescue ActiveRecord::StatementInvalid
# postgresql throws a PG::InvalidTextRepresentation exception when filter isn't a valid cidr expression
screened_ip_addresses = []
end
render_serialized(screened_ip_addresses, ScreenedIpAddressSerializer)
end

View file

@ -24,23 +24,20 @@ class ScreenedIpAddress < ActiveRecord::Base
return
end
return write_attribute(:ip_address, val) if val.is_a?(IPAddr)
num_wildcards = val.count('*')
if num_wildcards == 0
if val.is_a?(IPAddr)
write_attribute(:ip_address, val)
else
v = val.gsub(/\/.*/, '') # strip ranges like "/16" from the end if present
if v[v.index('*')..-1] =~ /[^\.\*]/
self.errors.add(:ip_address, :invalid)
return
end
parts = v.split('.')
(4 - parts.size).times { parts << '*' } # support strings like 192.*
v = parts.join('.')
write_attribute(:ip_address, "#{v.gsub('*', '0')}/#{32 - (v.count('*') * 8)}")
return
end
v = IPAddr.handle_wildcards(val)
if v.nil?
self.errors.add(:ip_address, :invalid)
return
end
write_attribute(:ip_address, v)
# this gets even messier, Ruby 1.9.2 raised a different exception to Ruby 2.0.0
# handle both exceptions
rescue ArgumentError, IPAddr::InvalidAddressError

View file

@ -1928,6 +1928,7 @@ en:
label: "New:"
ip_address: "IP address"
add: "Add"
filter: "Search"
roll_up:
text: "Roll up"
title: "Creates new subnet ban entries if there are at least 'min_ban_entries_for_roll_up' entries."

View file

@ -1,5 +1,24 @@
class IPAddr
def self.handle_wildcards(val)
return if val.blank?
num_wildcards = val.count('*')
return val if num_wildcards == 0
# strip ranges like "/16" from the end if present
v = val.gsub(/\/.*/, '')
return if v[v.index('*')..-1] =~ /[^\.\*]/
parts = v.split('.')
(4 - parts.size).times { parts << '*' } # support strings like 192.*
v = parts.join('.')
"#{v.gsub('*', '0')}/#{32 - (v.count('*') * 8)}"
end
def to_cidr_s
if @addr
mask = @mask_addr.to_s(2).count('1')

View file

@ -10,10 +10,18 @@ describe Admin::ScreenedIpAddressesController do
describe 'index' do
it 'returns JSON' do
xhr :get, :index
it 'filters screened ip addresses' do
Fabricate(:screened_ip_address, ip_address: "1.2.3.4")
Fabricate(:screened_ip_address, ip_address: "1.2.3.5")
Fabricate(:screened_ip_address, ip_address: "1.2.3.6")
Fabricate(:screened_ip_address, ip_address: "4.5.6.7")
xhr :get, :index, filter: "4.*"
expect(response).to be_success
expect(JSON.parse(response.body)).to be_a(Array)
result = JSON.parse(response.body)
expect(result.length).to eq(1)
end
end