[IMP] *: update modules to use the new geoip API

request.geoip is no more a dictionnary cached in the session. It is now
a full blown object with lazy and smart geolocalisation capabilities.

Among other things, the previous dictionnary API is now deprecated. The
changes are:

* `request.geoip['country_name']` -> `request.geoip.country_name`
* `request.geoip['country_code']` -> `request.geoip.country_code`
* `request.geoip['city']` -> `request.geoip.city.name`
* `request.geoip['latitude']` -> `request.geoip.location.latitude`
* `request.geoip['longitude']` -> `request.geoip.location.longitude`
* `request.geoip['region']` -> `(request.geoip.subdivisions[0].iso_code if request.geoip.subdivisions else None)`
* `request.geoip['time_zone']` -> `request.geoip.location.time_zone`

It is safe to access all the attributes. Doing `request.geoip.city.name`
when the geolocalization failed (missing db, invalid address, ...)
evaluates to None. It does not raise an AttributeError.

Task: 2848206
Part-of: odoo/odoo#91337
This commit is contained in:
Julien Castiaux
2023-01-03 13:16:02 +01:00
parent c59750d824
commit 3d1f486bcc
16 changed files with 43 additions and 47 deletions
+3 -3
View File
@@ -54,9 +54,9 @@ class Home(web_home.Home):
browser=request.httprequest.user_agent.browser.capitalize(),
platform=request.httprequest.user_agent.platform.capitalize(),
)
geoip = request.geoip
if geoip:
name += " (%s, %s)" % (geoip['city'], geoip['country_name'])
if request.geoip.city.name:
name += f" ({request.geoip.city.name}, {request.geoip.country_name})"
key = request.env['auth_totp.device']._generate("browser", name)
response.set_cookie(
@@ -88,15 +88,17 @@ class Users(models.Model):
template = self.env.ref('auth_totp_mail_enforce.mail_template_totp_mail_code').sudo()
context = {}
if request:
geoip = request.geoip
device = request.httprequest.user_agent.platform
browser = request.httprequest.user_agent.browser
context.update({
'location': f"{geoip['city']}, {geoip['country_name']}" if geoip else None,
'location': None,
'device': device and device.capitalize() or None,
'browser': browser and browser.capitalize() or None,
'ip': request.httprequest.environ['REMOTE_ADDR'],
})
if request.geoip.city.name:
context['location'] = f"{request.geoip.city.name}, {request.geoip.country_name}"
email_values = {
'email_to': self.email,
'email_cc': False,
+4 -6
View File
@@ -57,9 +57,8 @@ class LivechatController(http.Controller):
rule = {}
# find the country from the request
country_id = False
country_code = request.geoip.get('country_code')
if country_code:
country_id = request.env['res.country'].sudo().search([('code', '=', country_code)], limit=1).id
if request.geoip.country_code:
country_id = request.env['res.country'].sudo().search([('code', '=', request.geoip.country_code)], limit=1).id
# extract url
url = request.httprequest.headers.get('Referer')
# find the first matching rule for the given country and url
@@ -122,10 +121,9 @@ class LivechatController(http.Controller):
country_id = request.env.user.country_id.id
else:
# if geoip, add the country name to the anonymous name
if request.geoip:
if request.geoip.country_code:
# get the country of the anonymous person, if any
country_code = request.geoip.get('country_code', "")
country = request.env['res.country'].sudo().search([('code', '=', country_code)], limit=1) if country_code else None
country = request.env['res.country'].sudo().search([('code', '=', request.geoip.country_code)], limit=1)
if country:
country_id = country.id
+1 -2
View File
@@ -12,11 +12,10 @@ class LinkTracker(http.Controller):
@http.route('/r/<string:code>', type='http', auth='public', website=True)
def full_url_redirect(self, code, **post):
if not request.env['ir.http'].is_a_bot():
country_code = request.geoip.get('country_code')
request.env['link.tracker.click'].sudo().add_click(
code,
ip=request.httprequest.remote_addr,
country_code=country_code,
country_code=request.geoip.country_code,
)
redirect_url = request.env['link.tracker'].get_url_from_code(code)
if not redirect_url:
+1 -1
View File
@@ -96,7 +96,7 @@ class DiscussController(http.Controller):
if channel_sudo.group_public_id:
raise NotFound()
guest = channel_sudo.env['mail.guest'].create({
'country_id': channel_sudo.env['res.country'].search([('code', '=', request.geoip.get('country_code'))], limit=1).id,
'country_id': channel_sudo.env['res.country'].search([('code', '=', request.geoip.country_code)], limit=1).id,
'lang': get_lang(channel_sudo.env).code,
'name': _("Guest"),
'timezone': channel_sudo.env['mail.guest']._get_timezone_from_request(request),
+1 -5
View File
@@ -131,14 +131,10 @@ class MassMailController(http.Controller):
@http.route('/r/<string:code>/m/<int:mailing_trace_id>', type='http', auth="public")
def full_url_redirect(self, code, mailing_trace_id, **post):
# don't assume geoip is set, it is part of the website module
# which mass_mailing doesn't depend on
country_code = request.geoip.get('country_code')
request.env['link.tracker.click'].sudo().add_click(
code,
ip=request.httprequest.remote_addr,
country_code=country_code,
country_code=request.geoip.country_code,
mailing_trace_id=mailing_trace_id
)
return request.redirect(request.env['link.tracker'].get_url_from_code(code), code=301, local=False)
+2 -4
View File
@@ -39,10 +39,9 @@ class MailingSMSController(http.Controller):
check_res = self._check_trace(mailing_id, trace_code)
if not check_res.get('trace'):
return request.redirect('/web')
country_code = request.geoip.get('country_code')
# parse and validate number
sms_number = post.get('sms_number', '').strip(' ')
sanitize_res = phone_validation.phone_sanitize_numbers([sms_number], country_code, None)[sms_number]
sanitize_res = phone_validation.phone_sanitize_numbers([sms_number], request.geoip.country_code, None)[sms_number]
tocheck_number = sanitize_res['sanitized'] or sms_number
trace = check_res['trace'].filtered(lambda r: r.sms_number == tocheck_number)[:1]
@@ -86,7 +85,6 @@ class MailingSMSController(http.Controller):
@http.route('/r/<string:code>/s/<int:sms_sms_id>', type='http', auth="public")
def sms_short_link_redirect(self, code, sms_sms_id, **post):
country_code = request.geoip.get('country_code')
if sms_sms_id:
trace_id = request.env['mailing.trace'].sudo().search([('sms_sms_id_int', '=', int(sms_sms_id))]).id
else:
@@ -95,7 +93,7 @@ class MailingSMSController(http.Controller):
request.env['link.tracker.click'].sudo().add_click(
code,
ip=request.httprequest.remote_addr,
country_code=country_code,
country_code=request.geoip.country_code,
mailing_trace_id=trace_id
)
return request.redirect(request.env['link.tracker'].get_url_from_code(code), code=301, local=False)
+2 -3
View File
@@ -202,8 +202,7 @@ class Http(models.AbstractModel):
if not request.context.get('tz'):
with contextlib.suppress(pytz.UnknownTimeZoneError):
tz = request.geoip.get('time_zone', '')
request.update_context(tz=pytz.timezone(tz).zone)
request.update_context(tz=pytz.timezone(request.geoip.location.time_zone).zone)
website = request.env['website'].get_current_website()
user = request.env.user
@@ -379,7 +378,7 @@ class Http(models.AbstractModel):
@api.model
def get_frontend_session_info(self):
session_info = super(Http, self).get_frontend_session_info()
geoip_country_code = request.geoip.get('country_code')
geoip_country_code = request.geoip.country_code
geoip_phone_code = request.env['res.country']._phone_code_for(geoip_country_code) if geoip_country_code else None
session_info.update({
'is_website_user': request.env.user.id == request.website.user_id.id,
+1 -1
View File
@@ -1268,7 +1268,7 @@
</we-select>
</we-row>
<t t-if="request.geoip.get('country_code')">
<t t-if="request.geoip.country_code">
<t t-call="website.snippet_options_conditional_visibility">
<t t-set="option_name">Country</t>
<t t-set="attribute_rule" t-valuef="visibilityValueCountryRule"/>
@@ -16,7 +16,7 @@ class WebsiteForm(form.WebsiteForm):
country = visitor_partner.country_id or request.env.company.country_id
if country:
return country
country_code = request.geoip.get('country_code')
country_code = request.geoip.country_code
if country_code:
return request.env['res.country'].sudo().search([('code', '=', country_code)], limit=1)
return request.env['res.country']
@@ -55,8 +55,8 @@ class WebsiteForm(form.WebsiteForm):
request.params.update({phone_field: fmt_number})
if model_name == 'crm.lead' and not request.params.get('state_id'):
geoip_country_code = request.geoip.get('country_code')
geoip_state_code = request.geoip.get('region')
geoip_country_code = request.geoip.country_code
geoip_state_code = request.geoip.subdivisions[0].iso_code if request.geoip.subdivisions else None
if geoip_country_code and geoip_state_code:
state = request.env['res.country.state'].search([('code', '=', geoip_state_code), ('country_id.code', '=', geoip_country_code)])
if state:
@@ -20,8 +20,8 @@ class IrHttp(models.AbstractModel):
# We are avoiding to create a reveal_view if a lead is already
# created from another module, e.g. website_form
if not (visitor_sudo and visitor_sudo.lead_ids):
country_code = request.geoip.get('country_code')
state_code = request.geoip.get('region')
country_code = request.geoip.country_code
state_code = request.geoip.subdivisions[0].iso_code if request.geoip.subdivisions else None
if country_code:
try:
url = request.httprequest.url
@@ -222,9 +222,8 @@ class WebsiteCrmPartnerAssign(WebsitePartnerPage):
# group by grade
grade_domain = list(base_partner_domain)
if not country and not country_all:
country_code = request.geoip.get('country_code')
if country_code:
country = country_obj.search([('code', '=', country_code)], limit=1)
if request.geoip.country_code:
country = country_obj.search([('code', '=', request.geoip.country_code)], limit=1)
if country:
grade_domain += [('country_id', '=', country.id)]
grades = partner_obj.sudo().read_group(
@@ -44,9 +44,8 @@ class WebsiteHrRecruitment(http.Controller):
# Default search by user country
if not (country or department or office_id or contract_type_id or kwargs.get('all_countries')):
country_code = request.geoip.get('country_code')
if country_code:
countries_ = Country.search([('code', '=', country_code)])
if request.geoip.country_code:
countries_ = Country.search([('code', '=', request.geoip.country_code)])
country = countries_[0] if countries_ else None
if not any(j for j in jobs if j.address_id and j.address_id.country_id == country):
country = False
+2 -3
View File
@@ -1319,9 +1319,8 @@ class WebsiteSale(http.Controller):
def_country_id = order.partner_id.country_id
# IF PUBLIC ORDER
if order.partner_id.id == request.website.user_id.sudo().partner_id.id:
country_code = request.geoip.get('country_code')
if country_code:
def_country_id = request.env['res.country'].search([('code', '=', country_code)], limit=1)
if request.geoip.country_code:
def_country_id = request.env['res.country'].search([('code', '=', request.geoip.country_code)], limit=1)
else:
def_country_id = request.website.user_id.sudo().country_id
+3 -4
View File
@@ -230,7 +230,7 @@ class Website(models.Model):
return pl_id in self.get_pricelist_available(show_visible=False).ids
def _get_geoip_country_code(self):
return request and request.geoip.get('country_code') or False
return request and request.geoip.country_code or False
def _get_cached_pricelist_id(self):
return request and request.session.get('website_sale_current_pl') or None
@@ -463,9 +463,8 @@ class Website(models.Model):
# If the current user is the website public user, the fiscal position
# is computed according to geolocation.
if request.website.partner_id.id == partner_sudo.id:
country_code = request.geoip.get('country_code')
if country_code:
country_id = self.env['res.country'].search([('code', '=', country_code)], limit=1).id
if request.geoip.country_code:
country_id = self.env['res.country'].search([('code', '=', request.geoip.country_code)], limit=1).id
fpos = AccountFiscalPosition._get_fpos_by_region(country_id)
if not fpos:
+10 -2
View File
@@ -1059,6 +1059,14 @@ class GeoIP(collections.abc.Mapping):
except geoip2.errors.AddressNotFoundError:
return GEOIP_EMPTY_COUNTRY
@property
def country_name(self):
return self.country.name or self.continent.name
@property
def country_code(self):
return self.country.iso_code or self.continent.code
def __getattr__(self, attr):
# Be smart and determine whether the attribute exists on the
# country object or on the city object.
@@ -1074,10 +1082,10 @@ class GeoIP(collections.abc.Mapping):
# Old dict API, undocumented for now, will be deprecated some day
def __getitem__(self, item):
if item == 'country_name':
return self.country.name or self.continent.name
return self.country_name
if item == 'country_code':
return self.country.iso_code or self.continent.code
return self.country_code
if item == 'city':
return self.city.name