Add an extra check for google credentials
If the user has a wrong base64 padded secret key the googlemaps python library is returning "TypeError: Incorrect padding" which is very hard to understand. So now we check if the secret key is a valid base64 string
This commit is contained in:
parent
ddcc7162fb
commit
61efb66aba
@ -2,6 +2,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
class InvalidGoogleCredentials(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class BadGeocodingParams(Exception):
|
class BadGeocodingParams(Exception):
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#!/usr/local/bin/python
|
#!/usr/local/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import base64
|
||||||
import googlemaps
|
import googlemaps
|
||||||
|
|
||||||
from exceptions import MalformedResult
|
from exceptions import MalformedResult, InvalidGoogleCredentials
|
||||||
|
|
||||||
|
|
||||||
class GoogleMapsGeocoder:
|
class GoogleMapsGeocoder:
|
||||||
"""A Google Maps Geocoder wrapper for python"""
|
"""A Google Maps Geocoder wrapper for python"""
|
||||||
|
|
||||||
def __init__(self, client_id, client_secret, logger):
|
def __init__(self, client_id, client_secret, logger):
|
||||||
|
if not self._valid_credentials(client_secret):
|
||||||
|
raise InvalidGoogleCredentials('Invalid google secret key')
|
||||||
self.client_id = self._clean_client_id(client_id)
|
self.client_id = self._clean_client_id(client_id)
|
||||||
self.client_secret = client_secret
|
self.client_secret = client_secret
|
||||||
self.geocoder = googlemaps.Client(
|
self.geocoder = googlemaps.Client(
|
||||||
@ -36,7 +39,7 @@ class GoogleMapsGeocoder:
|
|||||||
return [longitude, latitude]
|
return [longitude, latitude]
|
||||||
|
|
||||||
def _build_optional_parameters(self, city=None, state=None,
|
def _build_optional_parameters(self, city=None, state=None,
|
||||||
country=None):
|
country=None):
|
||||||
optional_params = {}
|
optional_params = {}
|
||||||
if city:
|
if city:
|
||||||
optional_params['locality'] = city
|
optional_params['locality'] = city
|
||||||
@ -49,3 +52,13 @@ class GoogleMapsGeocoder:
|
|||||||
def _clean_client_id(self, client_id):
|
def _clean_client_id(self, client_id):
|
||||||
# Consistency with how the client_id is saved in metadata
|
# Consistency with how the client_id is saved in metadata
|
||||||
return client_id.replace('client=', '')
|
return client_id.replace('client=', '')
|
||||||
|
|
||||||
|
def _valid_credentials(self, private_key):
|
||||||
|
try:
|
||||||
|
# Only fails if the string dont have a correct padding for b64
|
||||||
|
# but this way we could provide a more clear error than
|
||||||
|
# TypeError: Incorrect padding
|
||||||
|
base64.b64decode(private_key)
|
||||||
|
return True
|
||||||
|
except TypeError:
|
||||||
|
return False
|
||||||
|
@ -359,10 +359,10 @@ class GeocoderConfig(ServiceConfig):
|
|||||||
if self._geocoder_provider == self.NOKIA_GEOCODER:
|
if self._geocoder_provider == self.NOKIA_GEOCODER:
|
||||||
if not set(self.NOKIA_GEOCODER_REDIS_MANDATORY_KEYS).issubset(set(filtered_config.keys())) or \
|
if not set(self.NOKIA_GEOCODER_REDIS_MANDATORY_KEYS).issubset(set(filtered_config.keys())) or \
|
||||||
not self.heremaps_app_id or not self.heremaps_app_code:
|
not self.heremaps_app_id or not self.heremaps_app_code:
|
||||||
raise ConfigException("""Some mandatory parameter/s for Nokia geocoder are missing. Check it please""")
|
raise ConfigException("""Heremaps app id or app code is not set up""")
|
||||||
elif self._geocoder_provider == self.GOOGLE_GEOCODER:
|
elif self._geocoder_provider == self.GOOGLE_GEOCODER:
|
||||||
if self.GOOGLE_GEOCODER_API_KEY not in filtered_config.keys():
|
if self.GOOGLE_GEOCODER_API_KEY not in filtered_config.keys():
|
||||||
raise ConfigException("""Google geocoder need the mandatory parameter 'google_maps_private_key'""")
|
raise ConfigException("""Google geocoder private key is not set up""")
|
||||||
elif self._geocoder_provider == self.MAPZEN_GEOCODER:
|
elif self._geocoder_provider == self.MAPZEN_GEOCODER:
|
||||||
if not self.mapzen_api_key:
|
if not self.mapzen_api_key:
|
||||||
raise ConfigException("""Mapzen config is not set up""")
|
raise ConfigException("""Mapzen config is not set up""")
|
||||||
|
@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
|||||||
setup(
|
setup(
|
||||||
name='cartodb_services',
|
name='cartodb_services',
|
||||||
|
|
||||||
version='0.15.0',
|
version='0.15.1',
|
||||||
|
|
||||||
description='CartoDB Services API Python Library',
|
description='CartoDB Services API Python Library',
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ import requests_mock
|
|||||||
from mock import Mock
|
from mock import Mock
|
||||||
|
|
||||||
from cartodb_services.google import GoogleMapsGeocoder
|
from cartodb_services.google import GoogleMapsGeocoder
|
||||||
from cartodb_services.google.exceptions import BadGeocodingParams
|
from cartodb_services.google.exceptions import MalformedResult, InvalidGoogleCredentials
|
||||||
from cartodb_services.google.exceptions import NoGeocodingParams
|
|
||||||
from cartodb_services.google.exceptions import MalformedResult
|
|
||||||
|
|
||||||
requests_mock.Mocker.TEST_PREFIX = 'test_'
|
requests_mock.Mocker.TEST_PREFIX = 'test_'
|
||||||
|
|
||||||
@ -92,7 +90,8 @@ class GoogleGeocoderTestCase(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
logger = Mock()
|
logger = Mock()
|
||||||
self.geocoder = GoogleMapsGeocoder('dummy_client_id',
|
self.geocoder = GoogleMapsGeocoder('dummy_client_id',
|
||||||
'MgxyOFxjZXIyOGO52jJlMzEzY1Oqy4hsO49E', logger)
|
'MgxyOFxjZXIyOGO52jJlMzEzY1Oqy4hsO49E',
|
||||||
|
logger)
|
||||||
|
|
||||||
def test_geocode_address_with_valid_params(self, req_mock):
|
def test_geocode_address_with_valid_params(self, req_mock):
|
||||||
req_mock.register_uri('GET', self.GOOGLE_MAPS_GEOCODER_URL,
|
req_mock.register_uri('GET', self.GOOGLE_MAPS_GEOCODER_URL,
|
||||||
@ -119,3 +118,9 @@ class GoogleGeocoderTestCase(unittest.TestCase):
|
|||||||
searchtext='Calle Eloy Gonzalo 27',
|
searchtext='Calle Eloy Gonzalo 27',
|
||||||
city='Madrid',
|
city='Madrid',
|
||||||
country='España')
|
country='España')
|
||||||
|
|
||||||
|
def test_invalid_credentials(self, req_mock):
|
||||||
|
with self.assertRaises(InvalidGoogleCredentials):
|
||||||
|
GoogleMapsGeocoder('dummy_client_id',
|
||||||
|
'lalala',
|
||||||
|
None)
|
||||||
|
Loading…
Reference in New Issue
Block a user