diff --git a/README.md b/README.md index 0a3ba221..83f48a22 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,15 @@ ICAT API to interface with the Data Gateway ## Requirements +All requirements can be installed with `pip install -r requirements.txt` + The required python libraries: - [SQLAlchemy](https://www.sqlalchemy.org/) - [flask-restful](https://github.com/flask-restful/flask-restful/) - [pymysql](https://pymysql.readthedocs.io/en/latest/) - [requests](https://2.python-requests.org/en/master/) - [pyyaml](https://pyyaml.org/wiki/PyYAMLDocumentation) (For the swagger generation) + - [pip-tools](https://github.com/jazzband/pip-tools) (For generating requirements.txt) ## Setup and running the API The database connection needs to be set up first. This is set in config.json, an example config file called `config.json.example` is provided. @@ -116,6 +119,7 @@ and updating them, in a form easily converted to JSON. - +## Running Tests +To run the tests use `python -m unittest discover` diff --git a/common/config.py b/common/config.py index 701d42a6..ecb2afa5 100644 --- a/common/config.py +++ b/common/config.py @@ -35,4 +35,17 @@ def is_generate_swagger(self): except: sys.exit("Missing config value, generate_swagger") + def get_host(self): + try: + return self.config["host"] + except: + sys.exit("Missing config value, host") + + def get_port(self): + try: + return self.config["port"] + except: + sys.exit("Missing config value, port") + + config = Config() diff --git a/common/database_helpers.py b/common/database_helpers.py index b2bcd754..fb1673c7 100644 --- a/common/database_helpers.py +++ b/common/database_helpers.py @@ -5,7 +5,7 @@ from sqlalchemy import asc, desc from sqlalchemy.orm import aliased -from common.exceptions import MissingRecordError, BadFilterError, BadRequestError +from common.exceptions import MissingRecordError, BadFilterError, BadRequestError, MultipleIncludeError from common.models.db_models import INVESTIGATIONUSER, INVESTIGATION, INSTRUMENT, FACILITYCYCLE, \ INVESTIGATIONINSTRUMENT, FACILITY from common.session_manager import session_manager @@ -86,6 +86,7 @@ class CreateQuery(Query): def __init__(self, table, row): super().__init__(table) self.row = row + self.inserted_row = None def execute_query(self): """Determines if the row is a row object or dictionary then commits it to the table""" @@ -100,7 +101,8 @@ def execute_query(self): record.MOD_ID = "user" # These will need changing self.session.add(record) self.commit_changes() - + self.session.refresh(record) + self.inserted_row = record class UpdateQuery(Query): @@ -219,7 +221,10 @@ def __init__(self, included_filters): self.included_filters = included_filters["include"] def apply_filter(self, query): - query.include_related_entities = True + if not query.include_related_entities: + query.include_related_entities = True + else: + raise MultipleIncludeError("Attempted multiple includes on a single query") class QueryFilterFactory(object): @@ -292,16 +297,28 @@ def insert_row_into_table(table, row): create_query.execute_query() -def create_row_from_json(table, json): +def create_row_from_json(table, data): """ Given a json dictionary create a row in the table from it :param table: the table for the row to be inserted into - :param json: the dictionary containing the values - :return: nothing atm + :param data: the dictionary containing the values + :return: The inserted row as a dictionary """ - with CreateQuery(table, json) as create_query: + with CreateQuery(table, data) as create_query: create_query.execute_query() + return create_query.inserted_row.to_dict() +def create_rows_from_json(table, data): + """ + Given a List containing dictionary representations of entities, or a dictionary representation of an entity, insert + the entities into the table and return the created entities + :param table: The table to insert the entities in + :param data: The entities to be inserted + :return: The inserted entities + """ + if type(data) is list: + return [create_row_from_json(table, entity) for entity in data] + return create_row_from_json(table, data) def get_row_by_id(table, id): """ diff --git a/common/exceptions.py b/common/exceptions.py index f80a9c20..369ad2de 100644 --- a/common/exceptions.py +++ b/common/exceptions.py @@ -10,6 +10,10 @@ class BadFilterError(ApiError): pass +class MultipleIncludeError(BadFilterError): + pass + + class AuthenticationError(ApiError): pass diff --git a/common/helpers.py b/common/helpers.py index 3adc75d4..a9ef36dd 100644 --- a/common/helpers.py +++ b/common/helpers.py @@ -8,7 +8,7 @@ from common.database_helpers import QueryFilterFactory from common.exceptions import MissingRecordError, BadFilterError, AuthenticationError, BadRequestError, \ - MissingCredentialsError + MissingCredentialsError, MultipleIncludeError from common.models.db_models import SESSION from common.session_manager import session_manager @@ -63,6 +63,9 @@ def wrapper_gets_records(*args, **kwargs): except MissingRecordError as e: log.exception(e) return "No such record in table", 404 + except MultipleIncludeError as e: + log.exception(e) + return "Bad request, only one include filter may be given per request", 400 except BadFilterError as e: log.exception(e) return "Invalid filter requested", 400 @@ -78,7 +81,6 @@ def wrapper_gets_records(*args, **kwargs): except BadRequestError as e: log.exception(e) return "Bad request", 400 - return wrapper_gets_records @@ -109,6 +111,8 @@ def is_valid_json(string): json_object = json.loads(string) except ValueError: return False + except TypeError: + return False return True diff --git a/config.json.example b/config.json.example index 70c182f6..6ff8e463 100644 --- a/config.json.example +++ b/config.json.example @@ -2,7 +2,9 @@ "DB_URL": "mysql+pymysql://root:rootpw@localhost:13306/icatdb", "log_level": "WARN", "debug_mode": false, - "generate_swagger": false + "generate_swagger": false, + "host": "127.0.0.1", + "port": "5000" } diff --git a/requirements.in b/requirements.in new file mode 100644 index 00000000..0b55dde5 --- /dev/null +++ b/requirements.in @@ -0,0 +1,5 @@ +flask_restful == 0.3.7 +sqlalchemy == 1.3.8 +pymysql == 0.9.3 +pyyaml == 5.1.2 +flask-cors == 3.0.8 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..eaf2bacd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,20 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile +# +aniso8601==8.0.0 # via flask-restful +click==7.0 # via flask +flask-cors==3.0.8 +flask==1.1.1 # via flask-cors, flask-restful +flask_restful==0.3.7 +itsdangerous==1.1.0 # via flask +jinja2==2.10.1 # via flask +markupsafe==1.1.1 # via jinja2 +pymysql==0.9.3 +pytz==2019.2 # via flask-restful +pyyaml==5.1.2 +six==1.12.0 # via flask-cors, flask-restful +sqlalchemy==1.3.8 +werkzeug==0.16.0 # via flask diff --git a/src/main.py b/src/main.py index d8b8b694..47effc55 100644 --- a/src/main.py +++ b/src/main.py @@ -1,4 +1,5 @@ from flask import Flask +from flask_cors import CORS from flask_restful import Api from common.config import config @@ -49,6 +50,7 @@ swagger_gen.write_swagger_spec() app = Flask(__name__) +cors = CORS(app) app.url_map.strict_slashes = False api = Api(app) @@ -215,4 +217,6 @@ "/instruments//facilitycycles//investigations/count") if __name__ == "__main__": + app.run(host=config.get_host(), port=config.get_port()) app.run(debug=config.is_debug_mode()) + diff --git a/src/resources/entities/applications_endpoints.py b/src/resources/entities/applications_endpoints.py index f47ef231..f19f65b2 100644 --- a/src/resources/entities/applications_endpoints.py +++ b/src/resources/entities/applications_endpoints.py @@ -3,7 +3,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(APPLICATION, request.json) - return get_row_by_id(APPLICATION, request.json["id"].to_dict()), 200 + return create_rows_from_json(APPLICATION, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datacollection_datafiles_endpoints.py b/src/resources/entities/datacollection_datafiles_endpoints.py index 9fac3085..11e36a28 100644 --- a/src/resources/entities/datacollection_datafiles_endpoints.py +++ b/src/resources/entities/datacollection_datafiles_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATACOLLECTIONDATAFILE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,8 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATACOLLECTIONDATAFILE, request.json) - return get_row_by_id(DATACOLLECTIONDATAFILE, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATACOLLECTIONDATAFILE, request.json), 200 + @requires_session_id @queries_records diff --git a/src/resources/entities/datacollection_datasets_endpoints.py b/src/resources/entities/datacollection_datasets_endpoints.py index 2d4447aa..f8918f7f 100644 --- a/src/resources/entities/datacollection_datasets_endpoints.py +++ b/src/resources/entities/datacollection_datasets_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATACOLLECTIONDATASET from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATACOLLECTIONDATASET, request.json) - return get_row_by_id(DATACOLLECTIONDATASET, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATACOLLECTIONDATASET, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datacollection_parameters_endpoints.py b/src/resources/entities/datacollection_parameters_endpoints.py index d2c9bd4b..0c943108 100644 --- a/src/resources/entities/datacollection_parameters_endpoints.py +++ b/src/resources/entities/datacollection_parameters_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, patch_entities, create_rows_from_json from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATACOLLECTIONPARAMETER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATACOLLECTIONPARAMETER, request.json) - return get_row_by_id(DATACOLLECTIONPARAMETER, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATACOLLECTIONPARAMETER, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datacollections_endpoints.py b/src/resources/entities/datacollections_endpoints.py index 5eed7f95..b3e2d38c 100644 --- a/src/resources/entities/datacollections_endpoints.py +++ b/src/resources/entities/datacollections_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATACOLLECTION from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATACOLLECTION, request.json) - return get_row_by_id(DATACOLLECTION, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATACOLLECTION, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datafile_formats_endpoints.py b/src/resources/entities/datafile_formats_endpoints.py index ed86621a..fd4a4db9 100644 --- a/src/resources/entities/datafile_formats_endpoints.py +++ b/src/resources/entities/datafile_formats_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATAFILEFORMAT from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATAFILEFORMAT, request.json) - return get_row_by_id(DATAFILEFORMAT, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATAFILEFORMAT, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datafile_parameters_endpoints.py b/src/resources/entities/datafile_parameters_endpoints.py index 5511eedf..99f181d8 100644 --- a/src/resources/entities/datafile_parameters_endpoints.py +++ b/src/resources/entities/datafile_parameters_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATAFILEPARAMETER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATAFILEPARAMETER, request.json) - return get_row_by_id(DATAFILEPARAMETER, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATAFILEPARAMETER, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datafiles_endpoints.py b/src/resources/entities/datafiles_endpoints.py index 8d891607..7101ae1a 100644 --- a/src/resources/entities/datafiles_endpoints.py +++ b/src/resources/entities/datafiles_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATAFILE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATAFILE, request.json) - return "", 200 + return create_rows_from_json(DATAFILE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/dataset_type_endpoints.py b/src/resources/entities/dataset_type_endpoints.py index 0455b828..a8667ea9 100644 --- a/src/resources/entities/dataset_type_endpoints.py +++ b/src/resources/entities/dataset_type_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATASETTYPE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATASETTYPE, request.json) - return get_row_by_id(DATASETTYPE, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATASETTYPE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/datasets_endpoints.py b/src/resources/entities/datasets_endpoints.py index dd2f736f..002ae716 100644 --- a/src/resources/entities/datasets_endpoints.py +++ b/src/resources/entities/datasets_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import DATASET from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(DATASET, request.json) - return get_row_by_id(DATASET, request.json["id"].to_dict()), 200 + return create_rows_from_json(DATASET, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/facilities_endpoints.py b/src/resources/entities/facilities_endpoints.py index 3ce016d0..4cdb5d28 100644 --- a/src/resources/entities/facilities_endpoints.py +++ b/src/resources/entities/facilities_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import FACILITY from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(FACILITY, request.json) - return get_row_by_id(FACILITY, request.json["id"].to_dict()), 200 + return create_rows_from_json(FACILITY, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/facility_cycles_endpoints.py b/src/resources/entities/facility_cycles_endpoints.py index 3bdf54c7..a28cdec9 100644 --- a/src/resources/entities/facility_cycles_endpoints.py +++ b/src/resources/entities/facility_cycles_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import FACILITYCYCLE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(FACILITYCYCLE, request.json) - return get_row_by_id(FACILITYCYCLE, request.json["id"].to_dict()), 200 + return create_rows_from_json(FACILITYCYCLE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/groupings_endpoints.py b/src/resources/entities/groupings_endpoints.py index b4c0000b..73f9067b 100644 --- a/src/resources/entities/groupings_endpoints.py +++ b/src/resources/entities/groupings_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import GROUPING from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(GROUPING, request.json) - return get_row_by_id(GROUPING, request.json["id"].to_dict()), 200 + return create_rows_from_json(GROUPING, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/instrument_scientists_endpoints.py b/src/resources/entities/instrument_scientists_endpoints.py index 293d5db0..28d2e56d 100644 --- a/src/resources/entities/instrument_scientists_endpoints.py +++ b/src/resources/entities/instrument_scientists_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INSTRUMENTSCIENTIST from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INSTRUMENTSCIENTIST, request.json) - return get_row_by_id(INSTRUMENTSCIENTIST, request.json["id"].to_dict()), 200 + return create_rows_from_json(INSTRUMENTSCIENTIST, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/instruments_endpoints.py b/src/resources/entities/instruments_endpoints.py index 7dcfc204..46b80d63 100644 --- a/src/resources/entities/instruments_endpoints.py +++ b/src/resources/entities/instruments_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INSTRUMENT from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INSTRUMENT, request.json) - return get_row_by_id(INSTRUMENT, request.json["id"].to_dict()), 200 + return create_rows_from_json(INSTRUMENT, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigation_groups_endpoints.py b/src/resources/entities/investigation_groups_endpoints.py index f2e76927..c608b207 100644 --- a/src/resources/entities/investigation_groups_endpoints.py +++ b/src/resources/entities/investigation_groups_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATIONGROUP from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATIONGROUP, request.json) - return get_row_by_id(INVESTIGATIONGROUP, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATIONGROUP, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigation_instruments_endpoints.py b/src/resources/entities/investigation_instruments_endpoints.py index e969b4b2..e8b6cb38 100644 --- a/src/resources/entities/investigation_instruments_endpoints.py +++ b/src/resources/entities/investigation_instruments_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATIONINSTRUMENT from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATIONINSTRUMENT, request.json) - return get_row_by_id(INVESTIGATIONINSTRUMENT, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATIONINSTRUMENT, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigation_parameters_endpoints.py b/src/resources/entities/investigation_parameters_endpoints.py index b5b068d9..77da3f50 100644 --- a/src/resources/entities/investigation_parameters_endpoints.py +++ b/src/resources/entities/investigation_parameters_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATIONPARAMETER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATIONPARAMETER, request.json) - return get_row_by_id(INVESTIGATIONPARAMETER, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATIONPARAMETER, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigation_types_endpoints.py b/src/resources/entities/investigation_types_endpoints.py index 7bb7bd75..c4111b26 100644 --- a/src/resources/entities/investigation_types_endpoints.py +++ b/src/resources/entities/investigation_types_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATIONTYPE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATIONTYPE, request.json) - return get_row_by_id(INVESTIGATIONTYPE, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATIONTYPE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigation_users_endpoints.py b/src/resources/entities/investigation_users_endpoints.py index f63acbaa..9c6c9037 100644 --- a/src/resources/entities/investigation_users_endpoints.py +++ b/src/resources/entities/investigation_users_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATIONUSER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATIONUSER, request.json) - return get_row_by_id(INVESTIGATIONUSER, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATIONUSER, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/investigations_endpoints.py b/src/resources/entities/investigations_endpoints.py index 8e2607b4..f420ebc3 100644 --- a/src/resources/entities/investigations_endpoints.py +++ b/src/resources/entities/investigations_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import INVESTIGATION from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(INVESTIGATION, request.json) - return get_row_by_id(INVESTIGATION, request.json["id"].to_dict()), 200 + return create_rows_from_json(INVESTIGATION, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/jobs_endpoints.py b/src/resources/entities/jobs_endpoints.py index 12e7cdd5..54696598 100644 --- a/src/resources/entities/jobs_endpoints.py +++ b/src/resources/entities/jobs_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import JOB from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(JOB, request.json) - return get_row_by_id(JOB, request.json["id"].to_dict()), 200 + return create_rows_from_json(JOB, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/keywords_endpoints.py b/src/resources/entities/keywords_endpoints.py index 500b0a4a..1e0c263e 100644 --- a/src/resources/entities/keywords_endpoints.py +++ b/src/resources/entities/keywords_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import KEYWORD from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(KEYWORD, request.json) - return get_row_by_id(KEYWORD, request.json["id"].to_dict()), 200 + return create_rows_from_json(KEYWORD, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/parameter_types_endpoints.py b/src/resources/entities/parameter_types_endpoints.py index 981aaa77..28010ae1 100644 --- a/src/resources/entities/parameter_types_endpoints.py +++ b/src/resources/entities/parameter_types_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import PARAMETERTYPE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(PARAMETERTYPE, request.json) - return get_row_by_id(PARAMETERTYPE, request.json["id"].to_dict()), 200 + return create_rows_from_json(PARAMETERTYPE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/permissible_string_values_endpoints.py b/src/resources/entities/permissible_string_values_endpoints.py index 1053120f..e2b8900a 100644 --- a/src/resources/entities/permissible_string_values_endpoints.py +++ b/src/resources/entities/permissible_string_values_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import PERMISSIBLESTRINGVALUE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(PERMISSIBLESTRINGVALUE, request.json) - return get_row_by_id(PERMISSIBLESTRINGVALUE, request.json["id"].to_dict()), 200 + return create_rows_from_json(PERMISSIBLESTRINGVALUE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/public_steps_endpoints.py b/src/resources/entities/public_steps_endpoints.py index 0cd519ac..8247a88f 100644 --- a/src/resources/entities/public_steps_endpoints.py +++ b/src/resources/entities/public_steps_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import PUBLICSTEP from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(PUBLICSTEP, request.json) - return get_row_by_id(PUBLICSTEP, request.json["id"].to_dict()), 200 + return create_rows_from_json(PUBLICSTEP, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/publications_endpoints.py b/src/resources/entities/publications_endpoints.py index 2079b940..825c3dea 100644 --- a/src/resources/entities/publications_endpoints.py +++ b/src/resources/entities/publications_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import PUBLICATION from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(PUBLICATION, request.json) - return get_row_by_id(PUBLICATION, request.json["id"].to_dict()), 200 + return create_rows_from_json(PUBLICATION, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/related_datafiles_endpoints.py b/src/resources/entities/related_datafiles_endpoints.py index 89db3031..47aac5fa 100644 --- a/src/resources/entities/related_datafiles_endpoints.py +++ b/src/resources/entities/related_datafiles_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import RELATEDDATAFILE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(RELATEDDATAFILE, request.json) - return get_row_by_id(RELATEDDATAFILE, request.json["id"].to_dict()), 200 + return create_rows_from_json(RELATEDDATAFILE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/rules_endpoints.py b/src/resources/entities/rules_endpoints.py index bcabdb59..c1d89e19 100644 --- a/src/resources/entities/rules_endpoints.py +++ b/src/resources/entities/rules_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import RULE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(RULE, request.json) - return get_row_by_id(RULE, request.json["id"].to_dict()), 200 + return create_rows_from_json(RULE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/sample_parameters_endpoints.py b/src/resources/entities/sample_parameters_endpoints.py index 2d6c1ce8..341b307f 100644 --- a/src/resources/entities/sample_parameters_endpoints.py +++ b/src/resources/entities/sample_parameters_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import SAMPLEPARAMETER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(SAMPLEPARAMETER, request.json) - return get_row_by_id(SAMPLEPARAMETER, request.json["id"].to_dict()), 200 + return create_rows_from_json(SAMPLEPARAMETER, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/sample_types_endpoints.py b/src/resources/entities/sample_types_endpoints.py index 0b1c0a19..916f904b 100644 --- a/src/resources/entities/sample_types_endpoints.py +++ b/src/resources/entities/sample_types_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import SAMPLETYPE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(SAMPLETYPE, request.json) - return get_row_by_id(SAMPLETYPE, request.json["id"].to_dict()), 200 + return create_rows_from_json(SAMPLETYPE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/samples_endpoints.py b/src/resources/entities/samples_endpoints.py index ac32465e..41769569 100644 --- a/src/resources/entities/samples_endpoints.py +++ b/src/resources/entities/samples_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import SAMPLE from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(SAMPLE, request.json) - return get_row_by_id(SAMPLE, request.json["id"].to_dict()), 200 + return create_rows_from_json(SAMPLE, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/shifts_endpoints.py b/src/resources/entities/shifts_endpoints.py index 86771697..9a3611df 100644 --- a/src/resources/entities/shifts_endpoints.py +++ b/src/resources/entities/shifts_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import SHIFT from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(SHIFT, request.json) - return get_row_by_id(SHIFT, request.json["id"].to_dict()), 200 + return create_rows_from_json(SHIFT, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/studies_endpoints.py b/src/resources/entities/studies_endpoints.py index 03eae006..78d74976 100644 --- a/src/resources/entities/studies_endpoints.py +++ b/src/resources/entities/studies_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import STUDY from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(STUDY, request.json) - return get_row_by_id(STUDY, request.json["id"].to_dict()), 200 + return create_rows_from_json(STUDY, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/study_investigations_endpoints.py b/src/resources/entities/study_investigations_endpoints.py index 0e385eb1..a12c8679 100644 --- a/src/resources/entities/study_investigations_endpoints.py +++ b/src/resources/entities/study_investigations_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import STUDYINVESTIGATION from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(STUDYINVESTIGATION, request.json) - return get_row_by_id(STUDYINVESTIGATION, request.json["id"].to_dict()), 200 + return create_rows_from_json(STUDYINVESTIGATION, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/user_groups_endpoints.py b/src/resources/entities/user_groups_endpoints.py index d553e50c..7030a90f 100644 --- a/src/resources/entities/user_groups_endpoints.py +++ b/src/resources/entities/user_groups_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import USERGROUP from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(USERGROUP, request.json) - return get_row_by_id(USERGROUP, request.json["id"].to_dict()), 200 + return create_rows_from_json(USERGROUP, request.json), 200 @requires_session_id @queries_records diff --git a/src/resources/entities/users_endpoints.py b/src/resources/entities/users_endpoints.py index 25ca655d..99359a81 100644 --- a/src/resources/entities/users_endpoints.py +++ b/src/resources/entities/users_endpoints.py @@ -2,7 +2,7 @@ from flask_restful import Resource from common.database_helpers import get_row_by_id, delete_row_by_id, update_row_from_id, get_rows_by_filter, \ - get_filtered_row_count, get_first_filtered_row, create_row_from_json, patch_entities + get_filtered_row_count, get_first_filtered_row, create_rows_from_json, patch_entities from common.helpers import requires_session_id, queries_records, get_filters_from_query_string from common.models.db_models import USER from src.swagger.swagger_generator import swagger_gen @@ -18,8 +18,7 @@ def get(self): @requires_session_id @queries_records def post(self): - create_row_from_json(USER, request.json) - return get_row_by_id(USER, request.json["id"].to_dict()), 200 + return create_rows_from_json(USER, request.json), 200 @requires_session_id @queries_records diff --git a/src/swagger/openapi.yaml b/src/swagger/openapi.yaml index 7acead22..995453c9 100644 --- a/src/swagger/openapi.yaml +++ b/src/swagger/openapi.yaml @@ -27,7 +27,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -198,7 +199,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -369,7 +371,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -540,7 +543,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -711,7 +715,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -882,7 +887,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1053,7 +1059,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1224,7 +1231,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1395,7 +1403,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1566,7 +1575,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1737,7 +1747,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -1908,7 +1919,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2079,7 +2091,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2250,7 +2263,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2421,7 +2435,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2592,7 +2607,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2763,7 +2779,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -2934,7 +2951,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3105,7 +3123,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3276,7 +3295,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3447,7 +3467,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3618,7 +3639,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3789,7 +3811,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -3960,7 +3983,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4131,7 +4155,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4302,7 +4327,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4473,7 +4499,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4644,7 +4671,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4815,7 +4843,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -4986,7 +5015,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -5157,7 +5187,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -5328,7 +5359,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -5499,7 +5531,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -5670,7 +5703,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -5841,7 +5875,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -6012,7 +6047,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false @@ -6183,7 +6219,8 @@ paths: - FIELD 1 - FIELD 2 type: object - - description: Given the names of related entities, include them in the results + - description: Given the names of related entities, include them in the results. + Only one include parameter is allowed in: query name: include required: false diff --git a/src/swagger/swagger_generator.py b/src/swagger/swagger_generator.py index ab9a33e1..c80c600e 100644 --- a/src/swagger/swagger_generator.py +++ b/src/swagger/swagger_generator.py @@ -31,8 +31,9 @@ class Entity(object): "query", False).parameter_as_dict ORDER_PARAMETER = Parameter("Given a field and direction, order the returned entities", "order", "string", "ID DESC", "query", False).parameter_as_dict - INCLUDE_PARAMETER = Parameter("Given the names of related entities, include them in the results", "include", - "object", {"Relation 1": ["Relation A", "Relation B"]}, "query", False).parameter_as_dict + INCLUDE_PARAMETER = Parameter( + "Given the names of related entities, include them in the results. Only one include parameter is allowed", + "include", "object", {"Relation 1": ["Relation A", "Relation B"]}, "query", False).parameter_as_dict DISTINCT_PARAMETER = Parameter("Return unique values for the fields requested", "distinct", "object", ["FIELD 1", "FIELD 2"], "query", False).parameter_as_dict PATH_PARAMETER = Parameter("The id of an entity", "id", "integer", 4, "path", True).parameter_as_dict @@ -262,7 +263,7 @@ def write_swagger_spec(self): swagger_spec.add_path(entity.entity_id_endpoint) swagger_spec.add_path(entity.entity_no_id_endpoint) swagger_dict = swagger_spec.get_spec_as_dict() - yaml.Dumper.ignore_aliases = lambda *args : True + yaml.Dumper.ignore_aliases = lambda *args: True with open(SwaggerGenerator.FILE_PATH, "w+") as target: target.write(yaml.dump(swagger_dict)) target.close() diff --git a/test/resources/__init__.py b/test/resources/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/resources/entities/__init__.py b/test/resources/entities/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/resources/entities/test_datafile.py b/test/resources/entities/test_datafile.py deleted file mode 100644 index 856472eb..00000000 --- a/test/resources/entities/test_datafile.py +++ /dev/null @@ -1,111 +0,0 @@ -import requests - -from common.database_helpers import insert_row_into_table, delete_row_by_id -from common.exceptions import MissingRecordError -from common.models.db_models import DATAFILE -from test.test_base.constants import GOOD_CREDENTIALS_HEADER, BAD_CREDENTIALS_HEADER -from test.test_base.base_rest_test import RestTestCase - -url_with_file_existing = "http://localhost:5000/datafiles/-50" -url_without_file_existing = "http://localhost:5000/datafiles/0" -good_data = {"NAME":"test"} -bad_data = '{"NAMEFf" : "test"}' - - -class TestDatafiles(RestTestCase): - - def setUp(self): - super().setUp() - insert_row_into_table(DATAFILE, DATAFILE(ID=-50, MOD_ID="modID", CREATE_ID="create_id", NAME="test_name", - MOD_TIME="2019-05-05 11:11:11", CREATE_TIME="2019-04-06 12:12:12", - DATASET_ID=1)) - - def tearDown(self): - super().tearDown() - try: # This catches the exception when we attempt to delete the file, that was deleted in the test - delete_row_by_id(DATAFILE, -50) - except MissingRecordError: - pass - - def test_get_with_id_with_credentials_and_file_exist(self): - response = requests.get(url_with_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(200, response) - self.expect_json_response(response) - # Add test to check the correct datafile is being returned - - def test_get_with_id_with_bad_credentials_and_file_exists(self): - response = requests.get(url_with_file_existing, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_get_with_id_with_no_credentials_and_file_exists(self): - response = requests.get(url_with_file_existing) - self.expect_status_code(403, response) - - def test_get_with_id_with_credentials_and_file_doesnt_exist(self): - response = requests.get(url_without_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(404, response) - - def test_get_with_id_with_bad_credentials_and_file_doesnt_exist(self): - response = requests.get(url_without_file_existing, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_get_with_id_with_no_credentials_and_file_doesnt_exist(self): - response = requests.get(url_without_file_existing, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_delete_with_credentials_and_file_exists(self): - response = requests.delete(url_with_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(204, response) - - def test_delete_with_bad_credentials_and_file_exists(self): - response = requests.delete(url_with_file_existing, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_delete_with_no_credentials_and_file_exists(self): - response = requests.delete(url_with_file_existing) - self.expect_status_code(403, response) - - def test_delete_with_credentials_and_file_doesnt_exists(self): - response = requests.delete(url_without_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(404, response) - - def test_delete_with_bad_credentials_and_file_doesnt_exists(self): - response = requests.delete(url_without_file_existing, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_delete_with_no_credentials_and_file_doesnt_exists(self): - response = requests.delete(url_without_file_existing) - self.expect_status_code(403, response) - - def test_patch_with_credentials_and_file_exists_with_valid_data(self): - response = requests.patch(url_with_file_existing, headers=GOOD_CREDENTIALS_HEADER, json=good_data) - self.expect_status_code(200, response) - self.expect_json_response(response) - - def test_patch_with_credentials_and_file_exists_with_invalid_data(self): - response = requests.patch(url_with_file_existing, headers=GOOD_CREDENTIALS_HEADER, json=bad_data) - self.expect_status_code(400, response) - - def test_patch_with_credentials_and_file_exists_with_no_data(self): - response = requests.patch(url_with_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(400, response) - - def test_patch_with_credentials_and_file_doesnt_exist_with_valid_data(self): - response = requests.patch(url_without_file_existing, headers=GOOD_CREDENTIALS_HEADER, json=good_data) - self.expect_status_code(404, response) - - def test_patch_with_credentials_and_file_doesnt_exist_with_invalid_data(self): - response = requests.patch(url_without_file_existing, headers=GOOD_CREDENTIALS_HEADER, json=bad_data) - self.expect_status_code(404, response) - - def test_patch_with_credentaisl_and_file_doesnt_exist_with_no_data(self): - response = requests.patch(url_without_file_existing, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(404, response) - - def test_patch_with_bad_credentials_and_file_exists_with_valid_data(self): - response = requests.patch(url_with_file_existing, headers=BAD_CREDENTIALS_HEADER, json=good_data ) - self.expect_status_code(403, response) - - def test_patch_with_no_credentials_and_file_exists_without_valid_data(self): - response = requests.patch(url_with_file_existing, json=bad_data) - self.expect_status_code(403, response) \ No newline at end of file diff --git a/test/resources/non_entities/__init__.py b/test/resources/non_entities/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/resources/non_entities/test_sessions.py b/test/resources/non_entities/test_sessions.py deleted file mode 100644 index 214450eb..00000000 --- a/test/resources/non_entities/test_sessions.py +++ /dev/null @@ -1,73 +0,0 @@ -import re - -import requests - -from test.test_base.base_rest_test import RestTestCase -from test.test_base.constants import GOOD_CREDENTIALS_HEADER, BAD_CREDENTIALS_HEADER - -uuid_pattern = re.compile("\\b[0-9a-f]{8}\\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\\b[0-9a-f]{12}\\b") -sessions_url = "http://localhost:5000/sessions" - - -def is_session_id_uuid(response): - if uuid_pattern.match(eval(response.text)["sessionID"]): - return True - return False - - -class TestSessions(RestTestCase): - - def test_post_generate_session_id_with_good_credentials(self): - response = requests.post(sessions_url, json={"username": "user", "password": "password"}) - self.assertTrue(is_session_id_uuid(response), "sessionID returned is not a uuid") - self.expect_status_code(201, response) - self.expect_json_response(response) - - def test_post_generate_session_id_with_bad_credentials(self): - response = requests.post(sessions_url, json={"username": "test", "password": "test"}) - self.expect_status_code(403, response) - - def test_post_generate_session_id_with_bad_json(self): - response = requests.post(sessions_url, json={"test": "test", "test": "test"}) - self.expect_status_code(400, response) - - def test_post_generate_session_id_with_no_credentials(self): - response = requests.post(sessions_url) - self.expect_status_code(400, response) - - def test_delete_remove_session_id_with_real_session_id(self): - response = requests.delete(sessions_url, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(200, response) - - def test_delete_remove_session_id_with_incorrect_session_id(self): - response = requests.delete(sessions_url, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_delete_remove_session_id_with_no_session_id(self): - response = requests.delete(sessions_url) - self.expect_status_code(403, response) - - def test_get_session_details_with_real_session_id(self): - response = requests.get(sessions_url, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(200, response) - self.expect_json_response(response) - - def test_get_session_details_with_incorrect_session_id(self): - response = requests.get(sessions_url, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_get_session_details_with_no_session_id(self): - response = requests.get(sessions_url) - self.expect_status_code(403, response) - - def test_put_refresh_session_with_real_session_id(self): # put is not currently not implemented properly - response = requests.put(sessions_url, headers=GOOD_CREDENTIALS_HEADER) - self.expect_status_code(200, response) - - def test_put_refresh_session_with_incorrect_session_id(self): # put is not currently implemented properly - response = requests.put(sessions_url, headers=BAD_CREDENTIALS_HEADER) - self.expect_status_code(403, response) - - def test_put_refresh_session_with_no_session_id(self): # put is not currently implemented properly - response = requests.put(sessions_url) - self.expect_status_code(403, response) diff --git a/test/test_base.py b/test/test_base.py new file mode 100644 index 00000000..61375e9e --- /dev/null +++ b/test/test_base.py @@ -0,0 +1,13 @@ +from unittest import TestCase + +from src.main import app + + +class FlaskAppTest(TestCase): + """ + The FlaskAppTest Base class sets up a test client to be used to mock requests + """ + + def setUp(self): + self.app = app.test_client() + self.app.testing = True diff --git a/test/test_base/__init__.py b/test/test_base/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/test_base/base_rest_test.py b/test/test_base/base_rest_test.py deleted file mode 100644 index 93fed57b..00000000 --- a/test/test_base/base_rest_test.py +++ /dev/null @@ -1,43 +0,0 @@ -from unittest import TestCase - -from common.database_helpers import insert_row_into_table, delete_row_by_id -from common.exceptions import MissingRecordError -from common.helpers import is_valid_json -from common.models.db_models import SESSION - - -class RestTestCase(TestCase): - """ - Parent class of endpoint test cases - """ - - def setUp(self): - """ - Inserts a session for testing into the user_sessions table - """ - insert_row_into_table(SESSION, SESSION(ID="TestSession")) - - def tearDown(self): - """ - Removes the inserted session from the user_sessions table - """ - try: - delete_row_by_id(SESSION, "TestSession") - except MissingRecordError: - pass - - def expect_status_code(self, expected_status_code, response): - """ - Asserts whether the returned status code is equal to the expected - :param expected_status_code: int: The status code that is expected - :param response: The response to be checked - """ - self.assertEqual(expected_status_code, response.status_code, "Incorrect status code, received: " + - str(response.status_code) + ". Expected " + str(expected_status_code)) - - def expect_json_response(self, response): - """ - Asserts whether the returned item is valid JSON - :param response: The response to be checked - """ - self.assertTrue(is_valid_json(response.text), "Response was not valid JSON") diff --git a/test/test_base/constants.py b/test/test_base/constants.py deleted file mode 100644 index bc7c8066..00000000 --- a/test/test_base/constants.py +++ /dev/null @@ -1,2 +0,0 @@ -GOOD_CREDENTIALS_HEADER = {"Authorization": "Bearer TestSession"} -BAD_CREDENTIALS_HEADER = {"Authorization": "Bearer SantaClaus"} \ No newline at end of file diff --git a/test/test_database_helpers.py b/test/test_database_helpers.py new file mode 100644 index 00000000..eae217c1 --- /dev/null +++ b/test/test_database_helpers.py @@ -0,0 +1,30 @@ +from unittest import TestCase + +from common.database_helpers import QueryFilterFactory, OrderFilter, LimitFilter, SkipFilter, WhereFilter, \ + IncludeFilter, DistinctFieldFilter + + +class TestQueryFilterFactory(TestCase): + def test_order_filter(self): + self.assertIs(OrderFilter, type(QueryFilterFactory.get_query_filter({"order": "ID DESC"}))) + + def test_limit_filter(self): + self.assertIs(LimitFilter, type(QueryFilterFactory.get_query_filter({"limit": 10}))) + + def test_skip_filter(self): + self.assertIs(SkipFilter, type(QueryFilterFactory.get_query_filter({"skip": 10}))) + + def test_where_filter(self): + self.assertIs(WhereFilter, type(QueryFilterFactory.get_query_filter({"where": {"ID": {"eq": "1"}}}))) + self.assertIs(WhereFilter, type(QueryFilterFactory.get_query_filter({"where": {"ID": {"lte": "1"}}}))) + self.assertIs(WhereFilter, type(QueryFilterFactory.get_query_filter({"where": {"ID": {"gte": "1"}}}))) + self.assertIs(WhereFilter, type(QueryFilterFactory.get_query_filter({"where": {"ID": {"like": "3"}}}))) + + def test_include_filter(self): + self.assertIs(IncludeFilter, type(QueryFilterFactory.get_query_filter({"include": "DATAFILE"}))) + self.assertIs(IncludeFilter, type(QueryFilterFactory.get_query_filter({"include": ["TEST"]}))) + self.assertIs(IncludeFilter, + type(QueryFilterFactory.get_query_filter({"include": {"Test": ["TEST1", "Test2"]}}))) + + def test_distinct_filter(self): + self.assertIs(DistinctFieldFilter, type(QueryFilterFactory.get_query_filter({"distinct": "TEST"}))) diff --git a/test/test_helpers.py b/test/test_helpers.py new file mode 100644 index 00000000..d5a8b53b --- /dev/null +++ b/test/test_helpers.py @@ -0,0 +1,183 @@ +from unittest import TestCase + +from sqlalchemy.exc import IntegrityError + +from common.database_helpers import delete_row_by_id, insert_row_into_table, LimitFilter, DistinctFieldFilter, \ + IncludeFilter, SkipFilter, WhereFilter, OrderFilter +from common.exceptions import MissingRecordError, BadFilterError, BadRequestError, MissingCredentialsError, \ + AuthenticationError +from common.helpers import is_valid_json, queries_records, get_session_id_from_auth_header, \ + get_filters_from_query_string +from common.models.db_models import SESSION +from test.test_base import FlaskAppTest + + +class TestIs_valid_json(TestCase): + def test_array(self): + self.assertTrue(is_valid_json("[]")) + + def test_null(self): + self.assertTrue("null") + + def test_valid_json(self): + self.assertTrue(is_valid_json('{"test":1}')) + + def test_single_quoted_json(self): + self.assertFalse(is_valid_json("{'test':1}")) + + def test_none(self): + self.assertFalse(is_valid_json(None)) + + def test_int(self): + self.assertFalse(is_valid_json(1)) + + def test_dict(self): + self.assertFalse(is_valid_json({"test": 1})) + + def test_list(self): + self.assertFalse(is_valid_json([])) + + +class TestRequires_session_id(FlaskAppTest): + def setUp(self): + super().setUp() + self.good_credentials_header = {"Authorization": "Bearer Test"} + self.bad_credentials_header = {"Authorization": "Test"} + session = SESSION() + session.ID = "Test" + insert_row_into_table(SESSION, session) + + def tearDown(self): + delete_row_by_id(SESSION, "Test") + + def test_missing_credentials(self): + self.assertEqual(401, self.app.get("/datafiles").status_code) + + def test_bad_credentials(self): + self.assertEqual(403, self.app.get("/datafiles", headers=self.bad_credentials_header).status_code) + + def test_good_credentials(self): + self.assertEqual(200, self.app.get("/datafiles?limit=0", headers=self.good_credentials_header).status_code) + + +class TestQueries_records(TestCase): + def test_missing_record_error(self): + @queries_records + def raise_missing_record(): + raise MissingRecordError() + + self.assertEqual(("No such record in table", 404), raise_missing_record()) + + def test_bad_filter_error(self): + @queries_records + def raise_bad_filter_error(): + raise BadFilterError() + + self.assertEqual(("Invalid filter requested", 400), raise_bad_filter_error()) + + def test_value_error(self): + @queries_records + def raise_value_error(): + raise ValueError() + + self.assertEqual(("Bad request", 400), raise_value_error()) + + def test_type_error(self): + @queries_records + def raise_type_error(): + raise TypeError() + + self.assertEqual(("Bad request", 400), raise_type_error()) + + def test_integrity_error(self): + @queries_records + def raise_integrity_error(): + raise IntegrityError() + + self.assertEqual(("Bad request", 400), raise_integrity_error()) + + def test_bad_request_error(self): + @queries_records + def raise_bad_request_error(): + raise BadRequestError() + + self.assertEqual(("Bad request", 400), raise_bad_request_error()) + + +class TestGet_session_id_from_auth_header(FlaskAppTest): + + def test_no_session_in_header(self): + with self.app: + self.app.get("/") + self.assertRaises(MissingCredentialsError, get_session_id_from_auth_header) + + def test_with_bad_header(self): + with self.app: + self.app.get("/", headers={"Authorization": "test"}) + self.assertRaises(AuthenticationError, get_session_id_from_auth_header) + + def test_with_good_header(self): + with self.app: + self.app.get("/", headers={"Authorization": "Bearer test"}) + self.assertEqual("test", get_session_id_from_auth_header()) + + +class TestGet_filters_from_query_string(FlaskAppTest): + def test_no_filters(self): + with self.app: + self.app.get("/") + self.assertEqual([], get_filters_from_query_string()) + + def test_bad_filter(self): + with self.app: + self.app.get("/?test=\"test\"") + self.assertRaises(BadFilterError, get_filters_from_query_string) + + def test_limit_filter(self): + with self.app: + self.app.get("/?limit=10") + filters = get_filters_from_query_string() + self.assertEqual(1, len(filters), msg="Returned incorrect number of filters") + self.assertIs(LimitFilter, type(filters[0]), msg="Incorrect type of filter") + + def test_order_filter(self): + with self.app: + self.app.get("/?order=\"ID DESC\"") + filters = get_filters_from_query_string() + self.assertEqual(1, len(filters), msg="Returned incorrect number of filters") + self.assertIs(OrderFilter, type(filters[0]), msg="Incorrect type of filter returned") + + def test_where_filter(self): + with self.app: + self.app.get('/?where={"ID":{"eq":3}}') + filters = get_filters_from_query_string() + self.assertEqual(1, len(filters), msg="Returned incorrect number of filters") + self.assertIs(WhereFilter, type(filters[0]), msg="Incorrect type of filter returned") + + def test_skip_filter(self): + with self.app: + self.app.get('/?skip=10') + filters = get_filters_from_query_string() + self.assertEqual(1, len(filters),msg="Returned incorrect number of filters") + self.assertIs(SkipFilter, type(filters[0]), msg="Incorrect type of filter returned") + + + def test_include_filter(self): + with self.app: + self.app.get("/?include=\"TEST\"") + filters =get_filters_from_query_string() + self.assertEqual(1, len(filters), msg="Incorrect number of filters returned") + self.assertIs(IncludeFilter, type(filters[0]), msg="Incorrect type of filter returned") + + def test_distinct_filter(self): + with self.app: + self.app.get("/?distinct=\"ID\"") + filters = get_filters_from_query_string() + self.assertEqual(1, len(filters), msg="Incorrect number of filters returned") + self.assertIs(DistinctFieldFilter, type(filters[0]), msg="Incorrect type of filter returned") + + def test_multiple_filters(self): + with self.app: + self.app.get("/?limit=10&skip=4") + filters = get_filters_from_query_string() + self.assertEqual(2, len(filters)) \ No newline at end of file diff --git a/test/test_swaggerGenerator.py b/test/test_swaggerGenerator.py new file mode 100644 index 00000000..93ab9a77 --- /dev/null +++ b/test/test_swaggerGenerator.py @@ -0,0 +1,9 @@ +from unittest import TestCase + +from src.swagger.swagger_generator import SwaggerGenerator + + +class TestSwaggerGenerator(TestCase): + def test_pascal_to_normal(self): + self.assertEqual(SwaggerGenerator.pascal_to_normal("TestCase"), "test case") + self.assertEqual(SwaggerGenerator.pascal_to_normal("testCase"), "test case") \ No newline at end of file