diff --git a/app/models/aaaa.rb b/app/models/aaaa.rb new file mode 100644 index 0000000..c0ac10a --- /dev/null +++ b/app/models/aaaa.rb @@ -0,0 +1,4 @@ +class AAAA < Record + validates :content, presence: true, ipv6: true + validates :name, presence: true, hostname: true +end diff --git a/lib/ipv6_validator.rb b/lib/ipv6_validator.rb new file mode 100644 index 0000000..09780c3 --- /dev/null +++ b/lib/ipv6_validator.rb @@ -0,0 +1,21 @@ +require 'ipaddr' +require 'socket' + +class Ipv6Validator < ActiveModel::EachValidator + + def valid_v6?(addr) + return false if addr['/'] # IPAddr accepts addr/mask format + return false if addr['['] + return false if addr[']'] + IPAddr.new(addr, Socket::AF_INET6) + true + rescue IPAddr::AddressFamilyError, IPAddr::InvalidAddressError + false + end + + def validate_each(record, attribute, value) + return if valid_v6?(value) + + record.errors[attribute] << 'is not a valid IPv6 address' + end +end diff --git a/test/factories/aaaa.rb b/test/factories/aaaa.rb new file mode 100644 index 0000000..75bfcf7 --- /dev/null +++ b/test/factories/aaaa.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :aaaa, class: 'AAAA' do + domain + name { generate(:subdomain) } + content '::1' + end +end diff --git a/test/models/aaaa_test.rb b/test/models/aaaa_test.rb new file mode 100644 index 0000000..0589acd --- /dev/null +++ b/test/models/aaaa_test.rb @@ -0,0 +1,34 @@ +require 'test_helper' + +class AAAAATest < ActiveSupport::TestCase + [ + '::', + '2001:db8::', + '2001:db8::1', + '2001:0db8:0000:0000:0000:0000:0000:0001', + '2001:DB8::1', + ].each { |ip| + test "content valid #{ip}" do + rec = build(:aaaa, content: ip) + rec.valid? + assert_empty rec.errors[:content], "#{ip} should be valid!" + end + } + + [ + 'noip', + 'no ip', + '1.2.3.4.5', + ':', + '2001:db8::1::1', + '[2001:db8::1]', + '2001:0db8:0000:0000:0000:0000:0000:0000:0001', + ].each { |ip| + test "content invalid #{ip}" do + rec = build(:aaaa, content: ip) + rec.valid? + assert_not_empty rec.errors[:content], "#{name} should be invalid!" + end + } + +end