Files
odoo_source/addons/http_routing/geoipresolver.py
T
Nicolas Lempereur 2c028ca2a6 [FIX] http_routing: geoip longitude/latitude available
In 2018 geoip2 support was added to allow the new database format that
are freely available. But for these, only a subset of properties are
available.

Since Odoo 13 (August 2019), the sign module is using geoip latitude and
longitude for logging access to sign module signatures, but this was
only working for database using the first version of GeoIP databases.

In other use case there would never be any geolocalization recorded.

With this change, latitude and longitude are available in the session if
the right module/database is installed.

opw-2426323

closes odoo/odoo#73997

X-original-commit: 2be13b57749ac2c45de60717544c3061bbb29671
Signed-off-by: Christophe Simonis <chs@odoo.com>
2021-07-19 18:49:19 +00:00

67 lines
2.1 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os.path
try:
import GeoIP # Legacy
except ImportError:
GeoIP = None
try:
import geoip2
import geoip2.database
except ImportError:
geoip2 = None
class GeoIPResolver(object):
def __init__(self, fname):
self.fname = fname
try:
self._db = geoip2.database.Reader(fname)
self.version = 2
except Exception:
try:
self._db = GeoIP.open(fname, GeoIP.GEOIP_STANDARD)
self.version = 1
assert self._db.database_info is not None
except Exception:
raise ValueError('Invalid GeoIP database: %r' % fname)
def __del__(self):
if self.version == 2:
self._db.close()
@classmethod
def open(cls, fname):
if not GeoIP and not geoip2:
return None
if not os.path.exists(fname):
return None
return GeoIPResolver(fname)
def resolve(self, ip):
if self.version == 1:
return self._db.record_by_addr(ip) or {}
elif self.version == 2:
try:
r = self._db.city(ip)
except (ValueError, geoip2.errors.AddressNotFoundError):
return {}
# Compatibility with Legacy database.
# Some ips cannot be located to a specific country. Legacy DB used to locate them in
# continent instead of country. Do the same to not change behavior of existing code.
country, attr = (r.country, 'iso_code') if r.country.geoname_id else (r.continent, 'code')
return {
'city': r.city.name,
'country_code': getattr(country, attr),
'country_name': country.name,
'latitude': r.location.latitude,
'longitude': r.location.longitude,
'region': r.subdivisions[0].iso_code if r.subdivisions else None,
'time_zone': r.location.time_zone,
}
# compat
def record_by_addr(self, addr):
return self.resolve(addr)