diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb index da5dcd3706..f68189feb9 100644 --- a/app/controllers/embed_controller.rb +++ b/app/controllers/embed_controller.rb @@ -1,4 +1,3 @@ -require_relative '../../lib/geo_i_p_country' require_relative '../../lib/aapb' class EmbedController < CatalogController diff --git a/app/models/user.rb b/app/models/user.rb index dc862464c3..8f27fe15f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,6 @@ require 'set' require 'ipaddr' -require_relative '../../lib/geo_i_p_country' +require 'geo_location' class User DARTMOUTH_HOST_RE = /^(.+\.)?meptest\.dartmouth\.edu$/ @@ -22,7 +22,7 @@ def onsite? end def usa? - %w(US PR WS GU MP VI).include?(::GeoIPCountry.instance.country_code(request.remote_ip)) || onsite? + %w(US PR WS GU MP VI).include?(GeoLocation.country_code(request.remote_ip)) || onsite? # WGBH doesn't actually geocode to USA. No idea why. end diff --git a/config/application.rb b/config/application.rb index d5842f0894..cea5f4489d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -37,10 +37,7 @@ class Application < Rails::Application config.exceptions_app = routes config.cache_store = :memory_store - # load that geocode ip! - config.after_initialize do - @mmdb = MaxMindDB.new(Rails.root + 'config/GeoLite2-Country.mmdb') - Rails.cache.write('maxmind_db', @mmdb) - end + # Call GeoLocation.mmdb to warm the cache. + config.after_initialize { GeoLocation.mmdb } end end diff --git a/lib/geo_i_p_country.rb b/lib/geo_i_p_country.rb deleted file mode 100644 index 2d2cb37b01..0000000000 --- a/lib/geo_i_p_country.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'singleton' - -class GeoIPCountry - include Singleton - - def initialize - @mmdb = Rails.cache.fetch('maxmind_db') - end - - def country_code(ip) - look = @mmdb.lookup(ip) - look.found? && look.country.iso_code - end -end diff --git a/lib/geo_location.rb b/lib/geo_location.rb new file mode 100644 index 0000000000..7ffa795ab6 --- /dev/null +++ b/lib/geo_location.rb @@ -0,0 +1,23 @@ +require 'maxminddb' + +class GeoLocation + MMDB_PATH = Rails.root + 'config/GeoLite2-Country.mmdb' + CACHE_KEY = 'maxmind_db'.freeze + + class << self + # Looks up an IP address to find out what country it's coming from. + # @return [String] capitalized, two-character ISO country code of the IP's + # origin according to our current copy of MaxMindDB's GeoLite2 Country db. + def country_code(ip) + mmdb.lookup(ip).country.iso_code + end + + # Caches a new instance of MaxMindDB::Client at CACHE_KEY loaded with data + # from MMDB_PATH and returns it. + # @return [MaxMindDB::Client] client instance used to look up country of + # origin for IP address. + def mmdb + Rails.cache.fetch(CACHE_KEY) { MaxMindDB.new(MMDB_PATH) } + end + end +end diff --git a/spec/lib/geo_i_p_country_spec.rb b/spec/lib/geo_i_p_country_spec.rb deleted file mode 100644 index 6eeb7ea3b6..0000000000 --- a/spec/lib/geo_i_p_country_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require_relative '../../lib/geo_i_p_country' -require 'resolv' -require 'maxminddb' - -describe GeoIPCountry do - def country_for_domain(domain) - GeoIPCountry.instance.country_code(Resolv.getaddress(domain)) - end - - before :each do - # hope this works! - Rails.stub_chain(:cache, :fetch).and_return(MaxMindDB.new(Rails.root + 'config/GeoLite2-Country.mmdb')) - end - - it 'fails gracefully' do - expect(GeoIPCountry.instance.country_code('0.0.0.0')).to eq false - end - - it 'puts UMass in US' do - expect(country_for_domain('umass.edu')).to eq 'US' - end - - it 'puts canada.ca in CA' do - expect(country_for_domain('canada.ca')).to eq 'CA' - end - - # Site seems to be down... - xit 'puts india.gov.in in IN' do - expect(country_for_domain('www.mygov.in')).to eq 'IN' - end - - it 'puts www.gob.mx in US!!!' do - expect(country_for_domain('www.gob.mx')).to eq 'US' - end - - # but... - - # it 'puts WGBH in US', :caching do # currently '--' - # expect(country_for_domain('wgbh.org')).to eq 'US' - # end - # - # it 'puts english.gov.cn in CN', :caching do # response varies - # expect(country_for_domain('english.gov.cn')).to eq 'US' - # end -end diff --git a/spec/lib/geo_location_spec.rb b/spec/lib/geo_location_spec.rb new file mode 100644 index 0000000000..86684a601b --- /dev/null +++ b/spec/lib/geo_location_spec.rb @@ -0,0 +1,18 @@ +require 'geo_location' +require 'resolv' + +describe GeoLocation do + describe '.country_code' do + let(:subject) { GeoLocation.country_code(ip) } + + context 'when IP is invalid' do + let(:ip) { '0.0.0.0' } + it { is_expected.to be_nil } + end + + context 'when IP is valid' do + let(:ip) { Resolv.getaddress('americanarchive.org') } + it { is_expected.to eq 'US' } + end + end +end