Created endpoint to fetch a location associated with a device
parent
a55211f0b5
commit
f3e67f9677
|
@ -2,6 +2,7 @@ import os
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
|
||||||
|
from public_api.endpoints.device_location import DeviceLocationEndpoint
|
||||||
from selene.api import SeleneResponse, selene_api
|
from selene.api import SeleneResponse, selene_api
|
||||||
from selene.api.base_config import get_base_config
|
from selene.api.base_config import get_base_config
|
||||||
from selene.api.public_endpoint import check_oauth_token
|
from selene.api.public_endpoint import check_oauth_token
|
||||||
|
@ -115,7 +116,11 @@ public.add_url_rule(
|
||||||
view_func=WolframAlphaSpokenEndpoint.as_view('wolfram_alpha_spoken_api'),
|
view_func=WolframAlphaSpokenEndpoint.as_view('wolfram_alpha_spoken_api'),
|
||||||
methods=['GET']
|
methods=['GET']
|
||||||
)
|
)
|
||||||
|
public.add_url_rule(
|
||||||
|
'/v1/device/<string:device_id>/location',
|
||||||
|
view_func=DeviceLocationEndpoint.as_view('device_location_api'),
|
||||||
|
methods=['GET']
|
||||||
|
)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This is a workaround to allow the API return 401 when we call a non existent path. Use case:
|
This is a workaround to allow the API return 401 when we call a non existent path. Use case:
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
from selene.api import PublicEndpoint
|
||||||
|
from selene.data.device import GeographyRepository
|
||||||
|
from selene.util.db import get_db_connection
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceLocationEndpoint(PublicEndpoint):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(DeviceLocationEndpoint, self).__init__()
|
||||||
|
|
||||||
|
def get(self, device_id):
|
||||||
|
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
|
||||||
|
location = GeographyRepository(db, None).get_location_by_device_id(device_id)
|
||||||
|
response = (location, HTTPStatus.OK) if location else ('', HTTPStatus.NOT_FOUND)
|
||||||
|
return response
|
|
@ -0,0 +1,5 @@
|
||||||
|
Feature: Fetch device's location
|
||||||
|
|
||||||
|
Scenario: Location is successfully retrieved from a device
|
||||||
|
When a api call to get the location is done
|
||||||
|
Then the location should be retrieved
|
|
@ -0,0 +1,47 @@
|
||||||
|
import json
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
from behave import when, then
|
||||||
|
from hamcrest import assert_that, equal_to, has_key
|
||||||
|
|
||||||
|
|
||||||
|
@when('a api call to get the location is done')
|
||||||
|
def get_device_location(context):
|
||||||
|
login = context.device_login
|
||||||
|
device_id = login['uuid']
|
||||||
|
access_token = login['accessToken']
|
||||||
|
headers = dict(Authorization='Bearer {token}'.format(token=access_token))
|
||||||
|
context.get_location_response = context.client.get(
|
||||||
|
'/v1/device/{uuid}/location'.format(uuid=device_id),
|
||||||
|
headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@then('the location should be retrieved')
|
||||||
|
def validate_location(context):
|
||||||
|
response = context.get_location_response
|
||||||
|
assert_that(response.status_code, equal_to(HTTPStatus.OK))
|
||||||
|
location = json.loads(response.data)
|
||||||
|
assert_that(location, has_key('coordinate'))
|
||||||
|
assert_that(location, has_key('timezone'))
|
||||||
|
assert_that(location, has_key('city'))
|
||||||
|
|
||||||
|
coordinate = location['coordinate']
|
||||||
|
assert_that(coordinate, has_key('latitude'))
|
||||||
|
assert_that(coordinate, has_key('longitude'))
|
||||||
|
|
||||||
|
timezone = location['timezone']
|
||||||
|
assert_that(timezone, has_key('name'))
|
||||||
|
assert_that(timezone, has_key('offset'))
|
||||||
|
assert_that(timezone, has_key('dstOffset'))
|
||||||
|
|
||||||
|
city = location['city']
|
||||||
|
assert_that(city, has_key('name'))
|
||||||
|
assert_that(city, has_key('state'))
|
||||||
|
|
||||||
|
state = city['state']
|
||||||
|
assert_that(state, has_key('name'))
|
||||||
|
assert_that(state, has_key('country'))
|
||||||
|
|
||||||
|
country = state['country']
|
||||||
|
assert_that(country, has_key('name'))
|
|
@ -46,3 +46,10 @@ class GeographyRepository(RepositoryBase):
|
||||||
db_result = self.cursor.insert_returning(db_request)
|
db_result = self.cursor.insert_returning(db_request)
|
||||||
|
|
||||||
return db_result['id']
|
return db_result['id']
|
||||||
|
|
||||||
|
def get_location_by_device_id(self, device_id):
|
||||||
|
db_request = self._build_db_request(
|
||||||
|
sql_file_name='get_location_by_device_id.sql',
|
||||||
|
args=dict(device_id=device_id)
|
||||||
|
)
|
||||||
|
return self.cursor.select_one(db_request)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
SELECT
|
||||||
|
json_build_object(
|
||||||
|
'latitude', city.latitude,
|
||||||
|
'longitude', city.longitude
|
||||||
|
) as coordinate,
|
||||||
|
json_build_object(
|
||||||
|
'name', timezone.name,
|
||||||
|
'offset', timezone.gmt_offset,
|
||||||
|
'dstOffset', timezone.dst_offset
|
||||||
|
) as timezone,
|
||||||
|
json_build_object(
|
||||||
|
'name', city.name,
|
||||||
|
'state', json_build_object(
|
||||||
|
'name', region.name,
|
||||||
|
'country', json_build_object(
|
||||||
|
'name', country.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) as city
|
||||||
|
FROM
|
||||||
|
device.device dev
|
||||||
|
INNER JOIN
|
||||||
|
device.geography geo ON dev.geography_id = geo.id
|
||||||
|
INNER JOIN
|
||||||
|
geography.country country ON geo.country_id = country.id
|
||||||
|
INNER JOIN
|
||||||
|
geography.region region ON geo.region_id = region.id
|
||||||
|
INNER JOIN
|
||||||
|
geography.city city ON geo.city_id = city.id
|
||||||
|
INNER JOIN
|
||||||
|
geography.timezone timezone ON geo.timezone_id = timezone.id
|
||||||
|
WHERE
|
||||||
|
dev.id = %(device_id)s
|
Loading…
Reference in New Issue