base_adresse: add parameter type=housenumber to prevent users from picking street addresses (#76376)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
8e215185ec
commit
84cd51957e
|
@ -125,10 +125,24 @@ class BaseAdresse(AddressResource):
|
|||
'Prioritize results according to coordinates. "lat" parameter must also be present.'
|
||||
)
|
||||
},
|
||||
'type': {
|
||||
'description': _(
|
||||
'Type of address to return, housenumber, street, locality, municipality or all. Default is all.'
|
||||
)
|
||||
},
|
||||
},
|
||||
)
|
||||
def addresses(
|
||||
self, request, id=None, q=None, zipcode='', citycode=None, lat=None, lon=None, page_limit=5
|
||||
self,
|
||||
request,
|
||||
id=None,
|
||||
q=None,
|
||||
zipcode='',
|
||||
citycode=None,
|
||||
lat=None,
|
||||
lon=None,
|
||||
page_limit=5,
|
||||
type=None,
|
||||
):
|
||||
if id is not None:
|
||||
return self.get_by_id(request, id=id, citycode=citycode)
|
||||
|
@ -156,6 +170,8 @@ class BaseAdresse(AddressResource):
|
|||
if self.latitude and self.longitude or lat and lon:
|
||||
query_args['lat'] = lat or self.latitude
|
||||
query_args['lon'] = lon or self.longitude
|
||||
if type in ('housenumber', 'street', 'locality', 'municipality'):
|
||||
query_args['type'] = type
|
||||
query = urlencode(query_args)
|
||||
url = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
|
||||
|
||||
|
@ -167,7 +183,8 @@ class BaseAdresse(AddressResource):
|
|||
|
||||
result = []
|
||||
|
||||
for feature in result_response.json().get('features'):
|
||||
features = result_response.json().get('features')
|
||||
for feature in features:
|
||||
if not feature['geometry']['type'] == 'Point':
|
||||
continue # skip unknown
|
||||
data = self.format_address_data(feature)
|
||||
|
@ -177,7 +194,6 @@ class BaseAdresse(AddressResource):
|
|||
)
|
||||
if not created:
|
||||
address.update_timestamp()
|
||||
|
||||
return {'data': result}
|
||||
|
||||
def get_by_id(self, request, id, citycode=None):
|
||||
|
@ -236,13 +252,25 @@ class BaseAdresse(AddressResource):
|
|||
'Prioritize results according to coordinates. "lon" parameter must be present.'
|
||||
)
|
||||
},
|
||||
'type': {
|
||||
'description': _(
|
||||
'Type of address to return, housenumber, street, locality, municipality or all. Default is all.'
|
||||
)
|
||||
},
|
||||
},
|
||||
)
|
||||
def search(self, request, q, zipcode='', citycode=None, lat=None, lon=None, **kwargs):
|
||||
def search(self, request, q, zipcode='', citycode=None, lat=None, lon=None, type=None, **kwargs):
|
||||
if kwargs.get('format', 'json') != 'json':
|
||||
raise NotImplementedError()
|
||||
result = self.addresses(
|
||||
request, q=q, zipcode=zipcode, citycode=citycode, lat=lat, lon=lon, page_limit=1
|
||||
request,
|
||||
q=q,
|
||||
zipcode=zipcode,
|
||||
citycode=citycode,
|
||||
lat=lat,
|
||||
lon=lon,
|
||||
page_limit=1,
|
||||
type=type,
|
||||
)
|
||||
return result['data']
|
||||
|
||||
|
@ -251,15 +279,23 @@ class BaseAdresse(AddressResource):
|
|||
parameters={
|
||||
'lat': {'description': _('Latitude'), 'example_value': 48.833708},
|
||||
'lon': {'description': _('Longitude'), 'example_value': 2.323349},
|
||||
'type': {
|
||||
'description': _(
|
||||
'Type of address to return, housenumber, street, locality, municipality or all. Default is all.'
|
||||
)
|
||||
},
|
||||
},
|
||||
)
|
||||
def reverse(self, request, lat, lon, **kwargs):
|
||||
def reverse(self, request, lat, lon, type=None, **kwargs):
|
||||
if kwargs.get('format', 'json') != 'json':
|
||||
raise NotImplementedError()
|
||||
|
||||
scheme, netloc, path, params, query, fragment = urlparse.urlparse(self.service_url)
|
||||
path = urlparse.urljoin(path, 'reverse/')
|
||||
query = urlencode({'lat': lat, 'lon': lon})
|
||||
query_dict = {'lat': lat, 'lon': lon}
|
||||
if type in ('housenumber', 'street', 'locality', 'municipality'):
|
||||
query_dict['type'] = type
|
||||
query = urlencode(query_dict)
|
||||
url = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
|
||||
|
||||
try:
|
||||
|
|
|
@ -211,6 +211,21 @@ def test_base_adresse_search(mocked_get, app, base_adresse):
|
|||
assert data['display_name'] == 'Rue Roger Halope 49000 Angers'
|
||||
|
||||
|
||||
@mock.patch('passerelle.utils.Request.get')
|
||||
def test_base_adresse_search_type_housenumber(mocked_get, app, base_adresse):
|
||||
endpoint = tests.utils.generic_endpoint_url('base-adresse', 'search', slug=base_adresse.slug)
|
||||
mocked_get.return_value = tests.utils.FakedResponse(content=FAKED_CONTENT, status_code=200)
|
||||
app.get(endpoint, params={'q': 'plop'}, status=200)
|
||||
assert 'type=' not in mocked_get.call_args[0][0]
|
||||
|
||||
for type in ['housenumber', 'street', 'locality', 'municipality']:
|
||||
app.get(endpoint, params={'q': 'plop', 'type': type}, status=200)
|
||||
assert f'type={type}' in mocked_get.call_args[0][0]
|
||||
|
||||
app.get(endpoint, params={'q': 'plop', 'type': 'foo'}, status=200)
|
||||
assert 'type=foo' not in mocked_get.call_args[0][0]
|
||||
|
||||
|
||||
@mock.patch('passerelle.utils.Request.get')
|
||||
def test_base_adresse_search_limit_to_200(mocked_get, app, base_adresse):
|
||||
endpoint = tests.utils.generic_endpoint_url('base-adresse', 'search', slug=base_adresse.slug)
|
||||
|
@ -366,6 +381,18 @@ def test_base_adresse_reverse_path(mocked_get, app, base_adresse):
|
|||
assert mocked_get.call_args[0][0].startswith('http://example.net/path/reverse/?')
|
||||
|
||||
|
||||
@mock.patch('passerelle.utils.Request.get')
|
||||
def test_base_adresse_reverse_type_housenumber(mocked_get, app, base_adresse):
|
||||
mocked_get.return_value = tests.utils.FakedResponse(content=json.dumps({'features': []}), status_code=200)
|
||||
app.get('/base-adresse/%s/reverse?lon=-0.593775&lat=47.474633' % base_adresse.slug)
|
||||
assert 'type=' not in mocked_get.call_args[0][0]
|
||||
app.get('/base-adresse/%s/reverse?lon=-0.593775&lat=47.474633&type=truc' % base_adresse.slug)
|
||||
assert 'type=' not in mocked_get.call_args[0][0]
|
||||
for type in ['housenumber', 'street', 'locality', 'municipality']:
|
||||
app.get(f'/base-adresse/%s/reverse?lon=-0.593775&lat=47.474633&type={type}' % base_adresse.slug)
|
||||
assert f'type={type}' in mocked_get.call_args[0][0]
|
||||
|
||||
|
||||
@mock.patch('passerelle.utils.Request.get')
|
||||
def test_base_adresse_reverse_api_timeout(mocked_get, app, base_adresse):
|
||||
mocked_get.side_effect = ConnectionError('Remote end closed connection without response')
|
||||
|
|
Loading…
Reference in New Issue