From d0ecccb7e4e2a30d5b549073901066985047d197 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Tue, 18 Feb 2014 13:00:46 -0500 Subject: [PATCH] Translate asterisks in ip addresses to mask format so people can enter things like 127.*.*.* in screened ip addresses form --- app/models/screened_ip_address.rb | 17 +++++++++- spec/models/screened_ip_address_spec.rb | 41 +++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/app/models/screened_ip_address.rb b/app/models/screened_ip_address.rb index 974e5baf7..e16c1babf 100644 --- a/app/models/screened_ip_address.rb +++ b/app/models/screened_ip_address.rb @@ -18,7 +18,22 @@ class ScreenedIpAddress < ActiveRecord::Base # In Rails 4.0.1, an exception is raised before validation happens, so we need this hack for # inet/cidr columns: def ip_address=(val) - write_attribute(:ip_address, val) + if val.nil? + self.errors.add(:ip_address, :invalid) + return + end + + num_wildcards = val.count('*') + if num_wildcards == 0 + write_attribute(:ip_address, val) + else + v = val.gsub(/\/.*/, '') + if v[v.index('*')..-1] =~ /[^\.\*]/ + self.errors.add(:ip_address, :invalid) + return + end + write_attribute(:ip_address, "#{v.gsub('*', '0')}/#{32 - (num_wildcards * 8)}") + end # this gets even messier, Ruby 1.9.2 raised a different exception to Ruby 2.0.0 # handle both exceptions diff --git a/spec/models/screened_ip_address_spec.rb b/spec/models/screened_ip_address_spec.rb index 861ae8946..f71f3757b 100644 --- a/spec/models/screened_ip_address_spec.rb +++ b/spec/models/screened_ip_address_spec.rb @@ -47,6 +47,45 @@ describe ScreenedIpAddress do end end + describe "ip_address=" do + let(:record) { described_class.new } + + def test_good_value(arg, expected) + record.ip_address = arg + record.ip_address_with_mask.should == expected + end + + def test_bad_value(arg) + r = described_class.new + r.ip_address = arg + r.should_not be_valid + r.errors[:ip_address].should be_present + end + + it "handles valid ip addresses" do + test_good_value("210.56.12.12", "210.56.12.12") + test_good_value("210.56.0.0/16", "210.56.0.0/16") + test_good_value("fc00::/7", "fc00::/7") + end + + it "translates * characters" do + test_good_value("123.*.*.*", "123.0.0.0/8") + test_good_value("123.12.*.*", "123.12.0.0/16") + test_good_value("123.12.1.*", "123.12.1.0/24") + test_good_value("123.12.*.*/16", "123.12.0.0/16") + end + + it "handles bad input" do + test_bad_value(nil) + test_bad_value("123.123") + test_bad_value("my house") + test_bad_value("123.*.1.12") + test_bad_value("*.123.*.12") + test_bad_value("*.*.*.12") + test_bad_value("123.*.1.12/8") + end + end + describe '#watch' do context 'ip_address is not being watched' do it 'should create a new record' do @@ -122,8 +161,6 @@ describe ScreenedIpAddress do it "doesn't block fc00::/7 addresses (IPv6)" do described_class.watch('fd12:db8::ff00:42:8329').action_type.should == described_class.actions[:do_nothing] end - - end describe '#should_block?' do