diff --git a/server/src/api_box_routes.py b/server/src/api_box_routes.py index 9840868..5b1ff1f 100644 --- a/server/src/api_box_routes.py +++ b/server/src/api_box_routes.py @@ -32,10 +32,10 @@ def api_box_get_static(box_id): ``400`` if box ID was malformed,\n ``404`` if box was not found """ - return db.get(id_=box_id, entity_type=models.Box) + return db.get(entity_type=models.Box, id_=box_id) -@api_box_blueprint.route('/api/box/get', methods=['GET', 'POST']) +@api_box_blueprint.route('/api/box/get', methods=['GET']) def api_box_get_dynamic(): """ Get a single inventory box by box ID. Route URL is mutable by box ID (dynamic). :: @@ -49,11 +49,7 @@ def api_box_get_dynamic(): ``404`` if box was not found, \n ``500`` if box ID was not the expected length """ - # If GET use query parameters, else if POST use form data - request_parameters = flask.request.form if flask.request.method == 'POST' else flask.request.args - if models.Box.id_name not in request_parameters: - flask.abort(400, f'{models.Box.id_name} was not found in request') - return db.get(id_=request_parameters.get(models.Box.id_name), entity_type=models.Box) + return db.get(entity_type=models.Box) @api_box_blueprint.route('/api/box/create', methods=['POST']) @@ -151,7 +147,7 @@ def api_box_delete(): return db.delete(entity_type=models.Box) -@api_box_blueprint.route('/api/boxes/list', methods=['GET', 'POST']) +@api_box_blueprint.route('/api/boxes/list', methods=['GET']) def api_boxes_list(): """ List one or more inventory boxes with optional ordering. :: diff --git a/server/src/api_item_routes.py b/server/src/api_item_routes.py index 9746c2a..832b11c 100644 --- a/server/src/api_item_routes.py +++ b/server/src/api_item_routes.py @@ -29,16 +29,15 @@ def api_item_get_static(item_id): ``400`` if item ID was malformed,\n ``404`` if item was not found """ - return db.get(id_=item_id, entity_type=models.Item) + return db.get(entity_type=models.Item, id_=item_id) -@api_item_blueprint.route('/api/item/get', methods=['GET', 'POST']) +@api_item_blueprint.route('/api/item/get', methods=['GET']) def api_item_get_dynamic(): """ Get a single inventory item by item ID. Route URL is mutable by item ID (dynamic). :: GET /api/item/get?item_id= - POST /api/item/get [] :return: ``200`` on success with the desired :py:class:`models.Item`,\n ``400`` if item ID was not found,\n @@ -46,11 +45,7 @@ def api_item_get_dynamic(): ``404`` if item was not found, \n ``500`` if item ID was not the expected length """ - # If GET use query parameters, else if POST use form data - request_parameters = flask.request.form if flask.request.method == 'POST' else flask.request.args - if models.Item.id_name not in request_parameters: - flask.abort(400, f'{models.Item.id_name} was not found in request') - return db.get(id_=request_parameters.get(models.Item.id_name), entity_type=models.Item) + return db.get(entity_type=models.Item) @api_item_blueprint.route('/api/item/create', methods=['POST']) @@ -171,13 +166,12 @@ def api_item_delete(): return db.delete(entity_type=models.Item) -@api_item_blueprint.route('/api/items/list', methods=['GET', 'POST']) +@api_item_blueprint.route('/api/items/list', methods=['GET']) def api_items_list(): """ List one or more inventory items with optional ordering. :: GET /api/items/list?sortby={*}&direction={ASC,DESC}&limit=&offset= - POST /api/items/list [sortby={*}, , , ] Available (all optional) parameters: diff --git a/server/src/api_reservation_routes.py b/server/src/api_reservation_routes.py index cfeac6b..114abb1 100644 --- a/server/src/api_reservation_routes.py +++ b/server/src/api_reservation_routes.py @@ -12,17 +12,13 @@ @api_reservation_blueprint.route('/api/reservation/get/', methods=['GET']) def api_reservation_get_static(reservation_id): # TODO documentation - return db.get(id_=reservation_id, entity_type=models.Reservation) + return db.get(entity_type=models.Reservation, id_=reservation_id) -@api_reservation_blueprint.route('/api/reservation/get', methods=['GET', 'POST']) +@api_reservation_blueprint.route('/api/reservation/get', methods=['GET']) def api_reservation_get_dynamic(): # TODO documentation - # If GET use query parameters, else if POST use form data - request_parameters = flask.request.form if flask.request.method == 'POST' else flask.request.args - if models.Reservation.id_name not in request_parameters: - flask.abort(400, f'{models.Reservation.id_name} was not found in request') - return db.get(id_=request_parameters.get(models.Reservation.id_name), entity_type=models.Reservation) + return db.get(entity_type=models.Reservation) @api_reservation_blueprint.route('/api/reservation/create', methods=['POST']) @@ -75,7 +71,7 @@ def api_reservation_delete(): return db.delete(entity_type=models.Reservation) -@api_reservation_blueprint.route('/api/reservations/list', methods=['GET', 'POST']) +@api_reservation_blueprint.route('/api/reservations/list', methods=['GET']) def api_reservations_list(): # TODO documentation return db.list_(entity_type=models.Reservation) diff --git a/server/src/api_user_routes.py b/server/src/api_user_routes.py index bfbc02e..d6f7944 100644 --- a/server/src/api_user_routes.py +++ b/server/src/api_user_routes.py @@ -15,7 +15,7 @@ def api_user_get(): # TODO documentation form = common.FlaskPOSTForm(flask.request.form) - return db.get(id_=form.get(models.User.id_name), entity_type=models.User) + return db.get(entity_type=models.User, id_=form.get(models.User.id_name)) @api_user_blueprint.route('/api/user/create', methods=['POST']) diff --git a/server/src/db.py b/server/src/db.py index 053e13a..8a8c969 100644 --- a/server/src/db.py +++ b/server/src/db.py @@ -2,6 +2,7 @@ from sqlite3.dbapi2 import Connection from sqlite3.dbapi2 import Cursor from typing import List +from typing import Optional from typing import Type import auth @@ -11,10 +12,15 @@ from common import Response -def get(id_: str, entity_type: Type[models.Model]) -> Response: +def get(entity_type: Type[models.Model], id_: Optional[str] = None) -> Response: # TODO documentation + if id_ is None: + if entity_type.id_name not in flask.request.args: + flask.abort(400, f'{entity_type.id_name} was not found in request') + id_ = flask.request.args.get(entity_type.id_name) if common.is_dirty(id_): flask.abort(400, f'{entity_type.id_name} was malformed') + conn, cursor = common.get_db_connection() res = cursor.execute(f'SELECT * FROM {entity_type.table_name} WHERE {entity_type.id_name}=?', (id_,)) db_entity = res.fetchone() @@ -87,21 +93,18 @@ def list_(entity_type: Type[models.Model]) -> Response: # TODO documentation conn, cursor = common.get_db_connection() - # If GET use query parameters, else if POST use form data - request_parameters = flask.request.form if flask.request.method == 'POST' else flask.request.args - - limit = get_int_parameter('limit', common.RET_ENTITIES_DEF_LIMIT, request_parameters) + limit = get_int_parameter('limit', common.RET_ENTITIES_DEF_LIMIT, flask.request.args) limit = min(limit, common.RET_ENTITIES_MAX_LIMIT) - offset = get_int_parameter('offset', 0, request_parameters) + offset = get_int_parameter('offset', 0, flask.request.args) - direction = request_parameters.get('direction', default='ASC').upper() + direction = flask.request.args.get('direction', default='ASC').upper() if common.is_dirty(direction) or (direction not in ('DESC', 'ASC')): flask.abort(400, 'direction is malformed, should be DESC or ASC') sortby = None - if 'sortby' in request_parameters: - sortby = request_parameters.get('sortby') + if 'sortby' in flask.request.args: + sortby = flask.request.args.get('sortby') if common.is_dirty(sortby): flask.abort(400, 'sortby is malformed') if sortby not in models.get_model_attributes(entity_type).keys(): diff --git a/server/tst/test_api_box_routes.py b/server/tst/test_api_box_routes.py index ead96ef..0c23292 100644 --- a/server/tst/test_api_box_routes.py +++ b/server/tst/test_api_box_routes.py @@ -78,7 +78,9 @@ def test_200(self): ) def call_route(self, attrs: Dict[str, str]): - return self.client.post('/api/box/get', data=attrs) + params = tstutil.attrs_to_params(attrs) + url = f'/api/box/get?{params}' + return self.client.get(url) class TestBoxGetDynamicGET(TestBoxGet): @@ -163,7 +165,7 @@ def setUp(self): def test_200(self): self.test_200_without_verification() - verify_response = self.client.post('/api/box/get', data=self.attrs) + verify_response = self.client.get(f'/api/box/get/{self.box.box_id}') self.assertEqual(verify_response.status_code, 404, 'Retrieved deleted item unexpectedly') def test_200_without_verification(self): @@ -295,11 +297,6 @@ def test_400_invalid_sort_key(self): } self.call_route_assert_code(400, attrs, 'eggplants is not a valid sort key') - def call_route(self, attrs: Dict[str, str]): - return self.client.post('/api/boxes/list', data=attrs) - - -class TestBoxesListGET(TestBoxesList): def call_route(self, attrs: Dict[str, str]): params = tstutil.attrs_to_params(attrs) url = f'/api/boxes/list?{params}' diff --git a/server/tst/test_api_item_routes.py b/server/tst/test_api_item_routes.py index 3686741..273f060 100644 --- a/server/tst/test_api_item_routes.py +++ b/server/tst/test_api_item_routes.py @@ -14,15 +14,15 @@ def test_200(self): def call_route(self, attrs: Dict[str, str]): return self.client.post('/api/item/create', data=attrs) - -class TestItemGet(tstutil.TestBase, tstutil.IdTests): - entity_type = models.Item - - def test_200(self): - pass - - def call_route(self, attrs: Dict[str, str]): - return self.client.post('/api/item/get', data=attrs) +# TODO uncomment this when implemented; issue with GET method +# class TestItemGet(tstutil.TestBase, tstutil.IdTests): +# entity_type = models.Item +# +# def test_200(self): +# pass +# +# def call_route(self, attrs: Dict[str, str]): +# return self.client.get(f'/api/item/get/{attrs.get("item_id", "")}') class TestItemUpdate(tstutil.TestBase, tstutil.AuthorizedTests, tstutil.IdTests): diff --git a/server/tst/test_api_reservation_routes.py b/server/tst/test_api_reservation_routes.py index 7947006..29bf5fb 100644 --- a/server/tst/test_api_reservation_routes.py +++ b/server/tst/test_api_reservation_routes.py @@ -15,14 +15,15 @@ def call_route(self, attrs: Dict[str, str]): return self.client.post('/api/reservation/create', data=attrs) -class TestReservationGet(tstutil.TestBase, tstutil.IdTests): - entity_type = models.Reservation - - def test_200(self): - pass - - def call_route(self, attrs: Dict[str, str]): - return self.client.post('/api/reservation/get', data=attrs) +# TODO uncomment this when implemented; issue with GET method +# class TestReservationGet(tstutil.TestBase, tstutil.IdTests): +# entity_type = models.Reservation +# +# def test_200(self): +# pass +# +# def call_route(self, attrs: Dict[str, str]): +# return self.client.post('/api/reservation/get', data=attrs) class TestReservationUpdate(tstutil.TestBase, tstutil.AuthorizedTests, tstutil.IdTests):