From 3a0bddd79a13ff8eaadcaae7f271a13a43ac173b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 15 Aug 2013 22:40:22 +0200 Subject: [PATCH] Moved to adapter backends for geo location and geo ip lookups. --- app/controllers/application_controller.rb | 4 +- app/models/observer/user/geo.rb | 9 +--- db/migrate/20130815000001_update_geo2.rb | 52 +++++++++++++++++++++++ db/seeds.rb | 30 +++++++++++-- lib/application_lib.rb | 17 ++++++++ lib/geo_ip.rb | 36 ++++++++++++++++ lib/{geoip.rb => geo_ip/freegeoip.rb} | 4 +- lib/geo_location.rb | 46 ++++++++++++++++++++ lib/{ => geo_location}/gmaps.rb | 9 ++-- 9 files changed, 187 insertions(+), 20 deletions(-) create mode 100644 db/migrate/20130815000001_update_geo2.rb create mode 100644 lib/application_lib.rb create mode 100644 lib/geo_ip.rb rename lib/{geoip.rb => geo_ip/freegeoip.rb} (89%) create mode 100644 lib/geo_location.rb rename lib/{ => geo_location}/gmaps.rb (96%) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bd2d0293d..9215386e3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,5 @@ # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/ -require 'geoip' - class ApplicationController < ActionController::Base # http_basic_authenticate_with :name => "test", :password => "ttt" @@ -82,7 +80,7 @@ class ApplicationController < ActionController::Base # check if remote ip need to be updated if !session[:remote_id] || session[:remote_id] != request.remote_ip session[:remote_id] = request.remote_ip - session[:geo] = Geoip.location( request.remote_ip ) + session[:geo] = GeoIp.location( request.remote_ip ) end # fill user agent diff --git a/app/models/observer/user/geo.rb b/app/models/observer/user/geo.rb index 0d6053204..bf4d6ca65 100644 --- a/app/models/observer/user/geo.rb +++ b/app/models/observer/user/geo.rb @@ -53,13 +53,8 @@ class Observer::User::Geo < ActiveRecord::Observer # return if no address is given return if address == '' - # load adapter - adapter = Setting.get('geo_backend') - return if !adapter - adapter_module = Object.const_get(adapter) - - # db lookup - latlng = adapter_module.geocode(address) + # lookup + latlng = GeoLocation.geocode( address ) return if !latlng # store data diff --git a/db/migrate/20130815000001_update_geo2.rb b/db/migrate/20130815000001_update_geo2.rb new file mode 100644 index 000000000..a3e57394b --- /dev/null +++ b/db/migrate/20130815000001_update_geo2.rb @@ -0,0 +1,52 @@ +class UpdateGeo2 < ActiveRecord::Migration + def up + Setting.where( :name => 'geo_backend' ).destroy_all + Setting.create_if_not_exists( + :title => 'Geo Location Backend', + :name => 'geo_location_backend', + :area => 'System::Geo', + :description => 'Defines the backend for geo location lookups.', + :options => { + :form => [ + { + :display => '', + :null => true, + :name => 'geo_location_backend', + :tag => 'select', + :options => { + '' => '-', + 'GeoLocation::Gmaps' => 'Google Maps', + }, + }, + ], + }, + :state => 'GeoLocation::Gmaps', + :frontend => false + ) + Setting.create_if_not_exists( + :title => 'Geo IP Backend', + :name => 'geo_ip_backend', + :area => 'System::Geo', + :description => 'Defines the backend for geo ip lookups.', + :options => { + :form => [ + { + :display => '', + :null => true, + :name => 'geo_ip_backend', + :tag => 'select', + :options => { + '' => '-', + 'GeoIp::Freegeoip' => 'freegeoip.net', + }, + }, + ], + }, + :state => 'GeoIp::Freegeoip', + :frontend => false + ) + end + def down + end +end + diff --git a/db/seeds.rb b/db/seeds.rb index c78b669d0..b245f8cb3 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -135,7 +135,7 @@ Setting.create_if_not_exists( ) Setting.create_if_not_exists( :title => 'Geo Location Backend', - :name => 'geo_backend', + :name => 'geo_location_backend', :area => 'System::Geo', :description => 'Defines the backend for geo location lookups.', :options => { @@ -143,16 +143,38 @@ Setting.create_if_not_exists( { :display => '', :null => true, - :name => 'geo_backend', + :name => 'geo_location_backend', :tag => 'select', :options => { '' => '-', - 'Gmaps' => 'Google Maps', + 'GeoLocation::Gmaps' => 'Google Maps', }, }, ], }, - :state => 'Gmaps', + :state => 'GeoLocation::Gmaps', + :frontend => false +) +Setting.create_if_not_exists( + :title => 'Geo IP Backend', + :name => 'geo_ip_backend', + :area => 'System::Geo', + :description => 'Defines the backend for geo ip lookups.', + :options => { + :form => [ + { + :display => '', + :null => true, + :name => 'geo_ip_backend', + :tag => 'select', + :options => { + '' => '-', + 'GeoIp::Freegeoip' => 'freegeoip.net', + }, + }, + ], + }, + :state => 'GeoIp::Freegeoip', :frontend => false ) diff --git a/lib/application_lib.rb b/lib/application_lib.rb new file mode 100644 index 000000000..9f0dae9e3 --- /dev/null +++ b/lib/application_lib.rb @@ -0,0 +1,17 @@ +class ApplicationLib + def self.load_adapter_by_setting(setting) + adapter = Setting.get( setting ) + return if !adapter + + # load backend + self.load_adapter(adapter) + end + def self.load_adapter(adapter) + + # load adapter + backend = Object.const_get(adapter) + + # return backend + return backend + end +end diff --git a/lib/geo_ip.rb b/lib/geo_ip.rb new file mode 100644 index 000000000..cea0858af --- /dev/null +++ b/lib/geo_ip.rb @@ -0,0 +1,36 @@ +class GeoIp < ApplicationLib + +=begin + +lookup location based on ip or hostname + + result = GeoIp.location( '172.0.0.1' ) + +returns + + result = { + "ip" => "172.0.0.1" + "country_code" => "DE", + "country_name" => "Germany", + "region_code" => "05", + "region_name" => "Hessen", + "city" => "Frankfurt Am Main" + "zipcode" => "12345", + "latitude" => 50.1167, + "longitude" => 8.6833, + "metro_code" => "", + "areacode" => "" + } + +=end + + def self.location(address) + + # load backend + backend = self.load_adapter_by_setting( 'geo_ip_backend' ) + return if !backend + + # db lookup + backend.location(address) + end +end diff --git a/lib/geoip.rb b/lib/geo_ip/freegeoip.rb similarity index 89% rename from lib/geoip.rb rename to lib/geo_ip/freegeoip.rb index 319072439..1d111e792 100644 --- a/lib/geoip.rb +++ b/lib/geo_ip/freegeoip.rb @@ -1,11 +1,11 @@ require 'faraday' require 'cache' -module Geoip +module GeoIp::Freegeoip def self.location(address) # check cache - cache_key = "geoip::#{address}" + cache_key = "freegeoip::#{address}" cache = Cache.get( cache_key ) return cache if cache diff --git a/lib/geo_location.rb b/lib/geo_location.rb new file mode 100644 index 000000000..4a574154f --- /dev/null +++ b/lib/geo_location.rb @@ -0,0 +1,46 @@ +class GeoLocation < ApplicationLib + +=begin + +lookup lat and lng for address + + result = GeoLocation.geocode( 'Marienstrasse 13, 10117 Berlin' ) + +returns + + result = [ 4.21312, 1.3123 ] + +=end + + def self.geocode(address) + + # load backend + backend = self.load_adapter_by_setting( 'geo_location_backend' ) + return if !backend + + # db lookup + backend.geocode(address) + end + +=begin + +lookup address for lat and lng + + result = GeoLocation.reverse_geocode( 4.21312, 1.3123 ) + +returns + + result = 'some address' + +=end + + def self.reverse_geocode(lat,lng) + + # load backend + backend = self.load_adapter_by_setting( 'geo_location_backend' ) + return if !backend + + # db lookup + backend.reverse_geocode(lat,lng) + end +end diff --git a/lib/gmaps.rb b/lib/geo_location/gmaps.rb similarity index 96% rename from lib/gmaps.rb rename to lib/geo_location/gmaps.rb index 133d0b77c..6b619c634 100644 --- a/lib/gmaps.rb +++ b/lib/geo_location/gmaps.rb @@ -1,4 +1,5 @@ -module Gmaps +class GeoLocation::Gmaps + def self.geocode(address) url = "http://maps.googleapis.com/maps/api/geocode/json?address=#{CGI::escape address}&sensor=true" response = Net::HTTP.get_response( URI.parse(url) ) @@ -10,15 +11,15 @@ module Gmaps lng = result['results'].first['geometry']['location']['lng'] latlng = [lat,lng] end - + def self.reverse_geocode(lat,lng) url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=#{lat},#{lng}&sensor=true" response = Net::HTTP.get_response( URI.parse(url) ) return if response.code.to_s != '200' result = JSON.parse( response.body ) - + address = result['results'].first['address_components'].first['long_name'] return address end -end \ No newline at end of file +end