Replace quova with support for local Maxmind GeoIP lookups
authorTom Hughes <tom@compton.nu>
Thu, 20 Oct 2016 20:32:43 +0000 (21:32 +0100)
committerTom Hughes <tom@compton.nu>
Thu, 20 Oct 2016 20:40:03 +0000 (21:40 +0100)
Gemfile
Gemfile.lock
lib/country.rb
lib/osm.rb
lib/quova.rb [deleted file]
test/lib/country_test.rb

diff --git a/Gemfile b/Gemfile
index 5ef0eb9..2cbb1cb 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -81,9 +81,8 @@ gem "SystemTimer", ">= 1.1.3", :require => "system_timer", :platforms => :ruby_1
 # Load faraday for mockable HTTP client
 gem "faraday"
 
-# Load httpclient and soap4r for SOAP support for Quova GeoIP queries
-gem "httpclient"
-gem "soap4r-ruby1.9"
+# Load geoip for querying Maxmind GeoIP database
+gem "geoip"
 
 # Load memcache client in case we are using it
 gem "dalli"
index 9f9966e..1d44a8f 100644 (file)
@@ -42,11 +42,11 @@ GEM
     addressable (2.4.0)
     arel (6.0.3)
     ast (2.3.0)
-    autoprefixer-rails (6.4.1.1)
+    autoprefixer-rails (6.5.1)
       execjs
     bigdecimal (1.1.0)
     builder (3.2.2)
-    capybara (2.8.1)
+    capybara (2.10.1)
       addressable
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
@@ -91,12 +91,12 @@ GEM
     faraday (0.9.2)
       multipart-post (>= 1.2, < 3)
     fspath (3.0.1)
+    geoip (1.6.2)
     globalid (0.3.7)
       activesupport (>= 4.1.0)
-    hashie (3.4.4)
+    hashie (3.4.6)
     htmlentities (4.3.4)
     http_accept_language (2.0.5)
-    httpclient (2.8.2.4)
     i18n (0.7.0)
     i18n-js (3.0.0.rc14)
       i18n (~> 0.6, >= 0.6.6)
@@ -122,7 +122,7 @@ GEM
     jsonify-rails (0.3.2)
       actionpack
       jsonify (< 0.4.0)
-    jwt (1.5.4)
+    jwt (1.5.6)
     kgio (2.10.0)
     konacha (4.0.0)
       actionpack (>= 4.1, < 5)
@@ -148,14 +148,11 @@ GEM
       mime-types-data (~> 3.2015)
     mime-types-data (3.2016.0521)
     mimemagic (0.3.0)
-    mini_portile2 (2.1.0)
-    minitest (5.9.0)
+    minitest (5.9.1)
     multi_json (1.12.1)
     multi_xml (0.5.5)
     multipart-post (2.0.0)
-    nokogiri (1.6.8)
-      mini_portile2 (~> 2.1.0)
-      pkg-config (~> 1.1.7)
+    nokogiri (1.6.8.1)
     nokogumbo (1.4.9)
       nokogiri
     oauth (0.4.7)
@@ -198,11 +195,10 @@ GEM
       cocaine (~> 0.5.5)
       mime-types
       mimemagic (= 0.3.0)
-    parser (2.3.1.2)
+    parser (2.3.1.4)
       ast (~> 2.2)
-    pg (0.18.4)
-    pkg-config (1.1.7)
-    poltergeist (1.10.0)
+    pg (0.19.0)
+    poltergeist (1.11.0)
       capybara (~> 2.1)
       cliver (~> 0.3.1)
       websocket-driver (>= 0.2.0)
@@ -246,12 +242,12 @@ GEM
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
     rainbow (2.1.0)
-    rake (11.2.2)
+    rake (11.3.0)
     redcarpet (3.3.4)
     ref (2.0.0)
     request_store (1.3.1)
-    rinku (2.0.0)
-    rubocop (0.42.0)
+    rinku (2.0.2)
+    rubocop (0.44.1)
       parser (>= 2.3.1.1, < 3.0)
       powerpack (~> 0.1)
       rainbow (>= 1.99.1, < 3.0)
@@ -259,7 +255,7 @@ GEM
       unicode-display_width (~> 1.0, >= 1.0.1)
     ruby-openid (2.7.0)
     ruby-progressbar (1.8.1)
-    sanitize (4.2.0)
+    sanitize (4.4.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.4.4)
       nokogumbo (~> 1.4.1)
@@ -275,7 +271,6 @@ GEM
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.0)
-    soap4r-ruby1.9 (2.0.5)
     sprockets (3.7.0)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
@@ -283,7 +278,7 @@ GEM
       actionpack (>= 4.0)
       activesupport (>= 4.0)
       sprockets (>= 3.0.0)
-    term-ansicolor (1.3.2)
+    term-ansicolor (1.4.0)
       tins (~> 1.0)
     therubyracer (0.12.2)
       libv8 (~> 3.16.14.0)
@@ -323,9 +318,9 @@ DEPENDENCIES
   dynamic_form
   factory_girl_rails
   faraday
+  geoip
   htmlentities
   http_accept_language (~> 2.0.0)
-  httpclient
   i18n-js (>= 3.0.0.rc10)
   image_optim (>= 0.22.0)
   jquery-rails
@@ -358,7 +353,6 @@ DEPENDENCIES
   rubocop
   sanitize
   sass-rails (~> 5.0)
-  soap4r-ruby1.9
   timecop
   uglifier (>= 1.3.0)
   validates_email_format_of (>= 1.5.1)
index 48a721a..3af7e0a 100644 (file)
@@ -9,7 +9,7 @@ class Country
     @max_lon = max_lon
   end
 
-  def self.find_by_code(code)
+  def self.find(code)
     countries[code]
   end
 
index 502bc30..cd3a215 100644 (file)
@@ -505,20 +505,16 @@ module OSM
   end
 
   def self.ip_to_country(ip_address)
-    Timer.timeout(4) do
-      ipinfo = Quova::IpInfo.new(ip_address) if defined?(QUOVA_USERNAME)
-
-      if ipinfo && ipinfo.status == Quova::SUCCESS
-        country = ipinfo.country_code
-      else
-        country = http_client.get("http://api.hostip.info/country.php?ip=#{ip_address}").body
-        country = "GB" if country == "UK"
-      end
+    ipinfo = geoip_database.country(ip_address) if defined?(GEOIP_DATABASE)
 
-      return country.upcase
+    if ipinfo
+      country = ipinfo.country_code2
+    else
+      country = http_client.get("http://api.hostip.info/country.php?ip=#{ip_address}").body
+      country = "GB" if country == "UK"
     end
 
-    return nil
+    return country
   rescue StandardError
     return nil
   end
@@ -526,7 +522,7 @@ module OSM
   def self.ip_location(ip_address)
     code = OSM.ip_to_country(ip_address)
 
-    if code && country = Country.find_by_code(code)
+    if code && country = Country.find(code)
       return { :minlon => country.min_lon, :minlat => country.min_lat, :maxlon => country.max_lon, :maxlat => country.max_lat }
     end
 
@@ -577,4 +573,9 @@ module OSM
   def self.http_client=(client)
     @http_client = client
   end
+
+  # Return the GeoIP database handle
+  def self.geoip_database
+    @geoip_database ||= GeoIP.new(GEOIP_DATABASE) if defined?(GEOIP_DATABASE)
+  end
 end
diff --git a/lib/quova.rb b/lib/quova.rb
deleted file mode 100644 (file)
index cb6b936..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-##
-# Load required libraries
-require "soap/wsdlDriver"
-
-##
-# Monkey patch WSDL parser to stop it moaning
-module WSDL
-  class Parser
-    def warn(_msg)
-    end
-  end
-end
-
-##
-# Provide interface to Quova geolocation service
-module Quova
-  ##
-  # Access details for WSDL description
-  WSDL_URL = "https://webservices.quova.com/OnDemand/GeoPoint/v1/default.asmx?WSDL".freeze
-  WSDL_USER = QUOVA_USERNAME
-  WSDL_PASS = QUOVA_PASSWORD
-
-  ##
-  # Status codes
-  SUCCESS = 0
-  IPV6_NO_SUPPORT = 1
-  INVALID_CREDENTIALS = 2
-  NOT_MAPPED = 3
-  INVALID_IP_FORMAT = 4
-  IP_ADDRESS_NULL = 5
-  ACCESS_DENIED = 6
-  QUERY_LIMIT = 7
-  OUT_OF_SERVICE = 10
-
-  ##
-  # Create SOAP endpoint
-  @soap = SOAP::WSDLDriverFactory.new(WSDL_URL).create_rpc_driver
-  @soap.options["protocol.http.basic_auth"] << [WSDL_URL, WSDL_USER, WSDL_PASS]
-
-  ##
-  # Accessor for SOAP endpoint
-  def self.soap
-    @soap
-  end
-
-  ##
-  # Class representing geolocation details for an IP address
-  class IpInfo
-    def initialize(ip_address)
-      @ipinfo = Quova.soap.GetIpInfo(:ipAddress => ip_address)
-    end
-
-    def status
-      @ipinfo["GetIpInfoResult"]["Response"]["Status"].to_i
-    end
-
-    def country_code
-      @ipinfo["GetIpInfoResult"]["Location"]["Country"]["Name"]
-    end
-
-    def country_confidence
-      @ipinfo["GetIpInfoResult"]["Location"]["Country"]["Confidence"]
-    end
-  end
-end
index cc726e6..0e21a9e 100644 (file)
@@ -2,7 +2,7 @@ require "test_helper"
 
 class CountryTest < ActiveSupport::TestCase
   def test_gb
-    gb = Country.find_by_code("GB")
+    gb = Country.find("GB")
     assert_not_nil gb
     assert_equal "GB", gb.code
     assert_equal -8.623555, gb.min_lon
@@ -12,7 +12,7 @@ class CountryTest < ActiveSupport::TestCase
   end
 
   def test_au
-    au = Country.find_by_code("AU")
+    au = Country.find("AU")
     assert_not_nil au
     assert_equal "AU", au.code
     assert_equal 112.911057, au.min_lon
@@ -22,7 +22,7 @@ class CountryTest < ActiveSupport::TestCase
   end
 
   def test_xx
-    xx = Country.find_by_code("XX")
+    xx = Country.find("XX")
     assert_nil xx
   end
 end