From 3d1f486bccfcc06dac136d520ea95997501ef933 Mon Sep 17 00:00:00 2001 From: Julien Castiaux Date: Mon, 16 May 2022 16:13:42 +0000 Subject: [PATCH] [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 --- addons/auth_totp/controllers/home.py | 6 +++--- addons/auth_totp_mail_enforce/models/res_users.py | 6 ++++-- addons/im_livechat/controllers/main.py | 10 ++++------ addons/link_tracker/controller/main.py | 3 +-- addons/mail/controllers/discuss.py | 2 +- addons/mass_mailing/controllers/main.py | 6 +----- addons/mass_mailing_sms/controllers/main.py | 6 ++---- addons/website/models/ir_http.py | 5 ++--- addons/website/views/snippets/snippets.xml | 2 +- addons/website_crm/controllers/website_form.py | 6 +++--- addons/website_crm_iap_reveal/models/ir_http.py | 4 ++-- .../website_crm_partner_assign/controllers/main.py | 5 ++--- addons/website_hr_recruitment/controllers/main.py | 5 ++--- addons/website_sale/controllers/main.py | 5 ++--- addons/website_sale/models/website.py | 7 +++---- odoo/http.py | 12 ++++++++++-- 16 files changed, 43 insertions(+), 47 deletions(-) diff --git a/addons/auth_totp/controllers/home.py b/addons/auth_totp/controllers/home.py index aaeae55de76..ffbfe63987e 100644 --- a/addons/auth_totp/controllers/home.py +++ b/addons/auth_totp/controllers/home.py @@ -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( diff --git a/addons/auth_totp_mail_enforce/models/res_users.py b/addons/auth_totp_mail_enforce/models/res_users.py index 577a425455d..b730af1d007 100644 --- a/addons/auth_totp_mail_enforce/models/res_users.py +++ b/addons/auth_totp_mail_enforce/models/res_users.py @@ -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, diff --git a/addons/im_livechat/controllers/main.py b/addons/im_livechat/controllers/main.py index 7ee18094ce3..ce02f157ccc 100644 --- a/addons/im_livechat/controllers/main.py +++ b/addons/im_livechat/controllers/main.py @@ -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 diff --git a/addons/link_tracker/controller/main.py b/addons/link_tracker/controller/main.py index a68e2cc7d2a..daf8b1eab26 100644 --- a/addons/link_tracker/controller/main.py +++ b/addons/link_tracker/controller/main.py @@ -12,11 +12,10 @@ class LinkTracker(http.Controller): @http.route('/r/', 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: diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index 5adbbe1b001..03b794aeac0 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -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), diff --git a/addons/mass_mailing/controllers/main.py b/addons/mass_mailing/controllers/main.py index b567759b5d8..afcd83d254d 100644 --- a/addons/mass_mailing/controllers/main.py +++ b/addons/mass_mailing/controllers/main.py @@ -131,14 +131,10 @@ class MassMailController(http.Controller): @http.route('/r//m/', 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) diff --git a/addons/mass_mailing_sms/controllers/main.py b/addons/mass_mailing_sms/controllers/main.py index ea90099eff5..455569aaa84 100644 --- a/addons/mass_mailing_sms/controllers/main.py +++ b/addons/mass_mailing_sms/controllers/main.py @@ -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//s/', 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) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 5f58ebab4e8..f110da79145 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -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, diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index e6b9b7bcd1c..ea60117c837 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -1268,7 +1268,7 @@ - + Country diff --git a/addons/website_crm/controllers/website_form.py b/addons/website_crm/controllers/website_form.py index 55c4579db18..7f9d43b666f 100644 --- a/addons/website_crm/controllers/website_form.py +++ b/addons/website_crm/controllers/website_form.py @@ -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: diff --git a/addons/website_crm_iap_reveal/models/ir_http.py b/addons/website_crm_iap_reveal/models/ir_http.py index 00b893c9e51..b622b7c9c96 100644 --- a/addons/website_crm_iap_reveal/models/ir_http.py +++ b/addons/website_crm_iap_reveal/models/ir_http.py @@ -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 diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py index 85dc5a36aa8..0b1d33d6cfd 100644 --- a/addons/website_crm_partner_assign/controllers/main.py +++ b/addons/website_crm_partner_assign/controllers/main.py @@ -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( diff --git a/addons/website_hr_recruitment/controllers/main.py b/addons/website_hr_recruitment/controllers/main.py index 33af683f064..29259a75863 100644 --- a/addons/website_hr_recruitment/controllers/main.py +++ b/addons/website_hr_recruitment/controllers/main.py @@ -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 diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index dd140eacd34..3b091590312 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -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 diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py index 46bdf7feb13..8283d0c806d 100644 --- a/addons/website_sale/models/website.py +++ b/addons/website_sale/models/website.py @@ -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: diff --git a/odoo/http.py b/odoo/http.py index 187f5ae6bc8..662496813db 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -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