diff --git a/datagateway_api/src/main.py b/datagateway_api/src/main.py index e43090c6..3224ac09 100644 --- a/datagateway_api/src/main.py +++ b/datagateway_api/src/main.py @@ -19,12 +19,14 @@ get_id_endpoint, ) from datagateway_api.src.resources.entities.entity_map import endpoints -from datagateway_api.src.resources.non_entities.sessions_endpoints import Sessions +from datagateway_api.src.resources.non_entities.sessions_endpoints import ( + session_endpoints, +) from datagateway_api.src.resources.table_endpoints.table_endpoints import ( - InstrumentsFacilityCycles, - InstrumentsFacilityCyclesCount, - InstrumentsFacilityCyclesInvestigations, - InstrumentsFacilityCyclesInvestigationsCount, + count_instrument_facility_cycles_endpoint, + instrument_facility_cycles_endpoint, + instrument_investigation_endpoint, + count_instrument_investigation_endpoint, ) from datagateway_api.src.swagger.apispec_flask_restful import RestfulPlugin from datagateway_api.src.swagger.initialise_spec import initialise_spec @@ -68,56 +70,79 @@ def handle_error(e): def create_api_endpoints(app, api, spec): try: backend_type = app.config["TEST_BACKEND"] + print(f"test backend: {backend_type}") except KeyError: backend_type = config.get_backend_type() + print(f"config backend: {backend_type}") + # TODO - Add :param backend: to the endpoint functions backend = create_backend(backend_type) + print(f"Backend: {backend}, Type: {type(backend)}") for entity_name in endpoints: - get_endpoint_resource = get_endpoint(entity_name, endpoints[entity_name]) + get_endpoint_resource = get_endpoint( + entity_name, endpoints[entity_name], backend + ) api.add_resource(get_endpoint_resource, f"/{entity_name.lower()}") spec.path(resource=get_endpoint_resource, api=api) - get_id_endpoint_resource = get_id_endpoint(entity_name, endpoints[entity_name]) + get_id_endpoint_resource = get_id_endpoint( + entity_name, endpoints[entity_name], backend + ) api.add_resource(get_id_endpoint_resource, f"/{entity_name.lower()}/") spec.path(resource=get_id_endpoint_resource, api=api) get_count_endpoint_resource = get_count_endpoint( - entity_name, endpoints[entity_name], + entity_name, endpoints[entity_name], backend, ) api.add_resource(get_count_endpoint_resource, f"/{entity_name.lower()}/count") spec.path(resource=get_count_endpoint_resource, api=api) get_find_one_endpoint_resource = get_find_one_endpoint( - entity_name, endpoints[entity_name], + entity_name, endpoints[entity_name], backend, ) api.add_resource( - get_find_one_endpoint_resource, f"/{entity_name.lower()}/findone" + get_find_one_endpoint_resource, f"/{entity_name.lower()}/findone", ) spec.path(resource=get_find_one_endpoint_resource, api=api) # Session endpoint - api.add_resource(Sessions, "/sessions") - spec.path(resource=Sessions, api=api) + session_endpoint_resource = session_endpoints(backend) + api.add_resource(session_endpoint_resource, "/sessions") + # spec.path(resource=session_endpoint_resource, api=api) # Table specific endpoints - api.add_resource(InstrumentsFacilityCycles, "/instruments//facilitycycles") - spec.path(resource=InstrumentsFacilityCycles, api=api) + instrument_facility_cycle_resource = instrument_facility_cycles_endpoint(backend) + api.add_resource( + instrument_facility_cycle_resource, "/instruments//facilitycycles" + ) + # spec.path(resource=instrument_facility_cycle_resource, api=api) + + count_instrument_facility_cycle_resource = count_instrument_facility_cycles_endpoint( + backend + ) api.add_resource( - InstrumentsFacilityCyclesCount, "/instruments//facilitycycles/count", + count_instrument_facility_cycle_resource, + "/instruments//facilitycycles/count", ) - spec.path(resource=InstrumentsFacilityCyclesCount, api=api) + # spec.path(resource=count_instrument_facility_cycle_resource, api=api) + + instrument_investigation_resource = instrument_investigation_endpoint(backend) api.add_resource( - InstrumentsFacilityCyclesInvestigations, + instrument_investigation_resource, "/instruments//facilitycycles//investigations", ) - spec.path(resource=InstrumentsFacilityCyclesInvestigations, api=api) + # spec.path(resource=instrument_investigation_resource, api=api) + + count_instrument_investigation_resource = count_instrument_investigation_endpoint( + backend + ) api.add_resource( - InstrumentsFacilityCyclesInvestigationsCount, + count_instrument_investigation_resource, "/instruments//facilitycycles//investigations" "/count", ) - spec.path(resource=InstrumentsFacilityCyclesInvestigationsCount, api=api) + # spec.path(resource=count_instrument_investigation_resource, api=api) def openapi_config(spec): @@ -141,7 +166,7 @@ def specs(): if __name__ == "__main__": - api, spec = create_app_infrastructure() + api, spec = create_app_infrastructure(app) create_api_endpoints(app, api, spec) openapi_config(spec) app.run( diff --git a/datagateway_api/src/resources/entities/entity_endpoint.py b/datagateway_api/src/resources/entities/entity_endpoint.py index 568508b6..3446913d 100644 --- a/datagateway_api/src/resources/entities/entity_endpoint.py +++ b/datagateway_api/src/resources/entities/entity_endpoint.py @@ -8,10 +8,10 @@ get_session_id_from_auth_header, ) -backend = create_backend(config.get_backend_type()) +# backend = create_backend(config.get_backend_type()) -def get_endpoint(name, entity_type): +def get_endpoint(name, entity_type, backend): """ Given an entity name generate a flask_restful Resource class. In main.py these generated classes are registered with the api e.g @@ -159,7 +159,7 @@ def patch(self): return Endpoint -def get_id_endpoint(name, entity_type): +def get_id_endpoint(name, entity_type, backend): """ Given an entity name generate a flask_restful Resource class. In main.py these generated classes are registered with the api e.g @@ -289,7 +289,7 @@ def patch(self, id_): return EndpointWithID -def get_count_endpoint(name, entity_type): +def get_count_endpoint(name, entity_type, backend): """ Given an entity name generate a flask_restful Resource class. In main.py these generated classes are registered with the api e.g @@ -342,7 +342,7 @@ def get(self): return CountEndpoint -def get_find_one_endpoint(name, entity_type): +def get_find_one_endpoint(name, entity_type, backend): """ Given an entity name generate a flask_restful Resource class. In main.py these generated classes are registered with the api e.g diff --git a/datagateway_api/src/resources/non_entities/sessions_endpoints.py b/datagateway_api/src/resources/non_entities/sessions_endpoints.py index bfb253d7..36a33922 100644 --- a/datagateway_api/src/resources/non_entities/sessions_endpoints.py +++ b/datagateway_api/src/resources/non_entities/sessions_endpoints.py @@ -11,145 +11,154 @@ log = logging.getLogger() -backend = create_backend(config.get_backend_type()) +# backend = create_backend(config.get_backend_type()) -class Sessions(Resource): - def post(self): - """ - Generates a sessionID if the user has correct credentials - :return: String - SessionID +def session_endpoints(backend): + """ + TODO - Add docstring + """ + log.info("test") - --- - summary: Login - description: Generates a sessionID if the user has correct credentials - tags: - - Sessions - security: [] - requestBody: - description: User credentials to login with - required: true - content: - application/json: - schema: - type: object - properties: - username: - type: string - password: - type: string - mechanism: - type: string - responses: - 201: - description: Success - returns a session ID + class Sessions(Resource): + def post(self): + """ + Generates a sessionID if the user has correct credentials + :return: String - SessionID + --- + summary: Login + description: Generates a sessionID if the user has correct credentials + tags: + - Sessions + security: [] + requestBody: + description: User credentials to login with + required: true content: - application/json: + application/json: schema: - type: object - properties: - sessionID: - type: string - description: Session ID - example: xxxxxx-yyyyyyy-zzzzzz - 400: - description: Bad request. User credentials not provided in request body - 403: - description: Forbidden. User credentials were invalid - """ - if not ( - request.data and "username" in request.json and "password" in request.json - ): - return "Bad request", 400 - # If no mechanism is present in request body, default to simple - if not ("mechanism" in request.json): - request.json["mechanism"] = "simple" - try: - return {"sessionID": backend.login(request.json)}, 201 - except AuthenticationError: - return "Forbidden", 403 + type: object + properties: + username: + type: string + password: + type: string + mechanism: + type: string + responses: + 201: + description: Success - returns a session ID + content: + application/json: + schema: + type: object + properties: + sessionID: + type: string + description: Session ID + example: xxxxxx-yyyyyyy-zzzzzz + 400: + description: Bad request. User credentials not provided in request body + 403: + description: Forbidden. User credentials were invalid + """ + if not ( + request.data + and "username" in request.json + and "password" in request.json + ): + return "Bad request", 400 + # If no mechanism is present in request body, default to simple + if not ("mechanism" in request.json): + request.json["mechanism"] = "simple" + try: + return ({"sessionID": backend.login(request.json)}, 201) + except AuthenticationError: + return ("Forbidden", 403) - def delete(self): - """ - Deletes a users sessionID when they logout - :return: Blank response, 200 - --- - summary: Delete session - description: Deletes a users sessionID when they logout - tags: - - Sessions - responses: - 200: - description: Success - User's session was successfully deleted - 400: - description: Bad request - something was wrong with the request - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - 404: - description: Not Found - Unable to find session ID - """ - backend.logout(get_session_id_from_auth_header()) - return "", 200 + def delete(self): + """ + Deletes a users sessionID when they logout + :return: Blank response, 200 + --- + summary: Delete session + description: Deletes a users sessionID when they logout + tags: + - Sessions + responses: + 200: + description: Success - User's session was successfully deleted + 400: + description: Bad request - something was wrong with the request + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + 404: + description: Not Found - Unable to find session ID + """ + backend.logout(get_session_id_from_auth_header()) + return ("", 200) - def get(self): - """ - Gives details of a users session - :return: String: Details of the session, 200 - --- - summary: Get session details - description: Gives details of a user's session - tags: - - Sessions - responses: - 200: - description: Success - a user's session details - content: - application/json: - schema: - type: object - properties: - ID: - type: string - description: The session ID - example: xxxxxx-yyyyyyy-zzzzzz - EXPIREDATETIME: - type: string - format: datetime - description: When this session expires - example: "2017-07-21T17:32:28Z" - USERNAME: - type: string - description: Username associated with this session - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - """ - return backend.get_session_details(get_session_id_from_auth_header()), 200 + def get(self): + """ + Gives details of a users session + :return: String: Details of the session, 200 + --- + summary: Get session details + description: Gives details of a user's session + tags: + - Sessions + responses: + 200: + description: Success - a user's session details + content: + application/json: + schema: + type: object + properties: + ID: + type: string + description: The session ID + example: xxxxxx-yyyyyyy-zzzzzz + EXPIREDATETIME: + type: string + format: datetime + description: When this session expires + example: "2017-07-21T17:32:28Z" + USERNAME: + type: string + description: Username associated with this session + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + """ + return (backend.get_session_details(get_session_id_from_auth_header()), 200) - def put(self): - """ - Refreshes a users session - :return: String: The session ID that has been refreshed, 200 - --- - summary: Refresh session - description: Refreshes a users session - tags: - - Sessions - responses: - 200: - description: Success - the user's session ID that has been refreshed - content: - application/json: - schema: - type: string - description: Session ID - example: xxxxxx-yyyyyyy-zzzzzz - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - """ - return backend.refresh(get_session_id_from_auth_header()), 200 + def put(self): + """ + Refreshes a users session + :return: String: The session ID that has been refreshed, 200 + --- + summary: Refresh session + description: Refreshes a users session + tags: + - Sessions + responses: + 200: + description: Success - the user's session ID that has been refreshed + content: + application/json: + schema: + type: string + description: Session ID + example: xxxxxx-yyyyyyy-zzzzzz + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + """ + return (backend.refresh(get_session_id_from_auth_header()), 200) + + return Sessions diff --git a/datagateway_api/src/resources/table_endpoints/table_endpoints.py b/datagateway_api/src/resources/table_endpoints/table_endpoints.py index ee539462..507d3295 100644 --- a/datagateway_api/src/resources/table_endpoints/table_endpoints.py +++ b/datagateway_api/src/resources/table_endpoints/table_endpoints.py @@ -10,206 +10,243 @@ backend = create_backend(config.get_backend_type()) -class InstrumentsFacilityCycles(Resource): - def get(self, id_): - """ - --- - summary: Get an Instrument's FacilityCycles - description: Given an Instrument id get facility cycles where the instrument has - investigations that occur within that cycle, subject to the given filters - tags: - - FacilityCycles - parameters: - - in: path - required: true - name: id - description: The id of the instrument to retrieve the facility cycles of - schema: - type: integer - - WHERE_FILTER - - ORDER_FILTER - - LIMIT_FILTER - - SKIP_FILTER - - DISTINCT_FILTER - - INCLUDE_FILTER - responses: - 200: - description: Success - returns a list of the instrument's facility - cycles that satisfy the filters - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/FACILITYCYCLE' - 400: - description: Bad request - Something was wrong with the request - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - 404: - description: No such record - Unable to find a record in ICAT - """ - return ( - backend.get_facility_cycles_for_instrument_with_filters( - get_session_id_from_auth_header(), id_, get_filters_from_query_string(), - ), - 200, - ) - - -class InstrumentsFacilityCyclesCount(Resource): - def get(self, id_): - """ - --- - summary: Count an Instrument's FacilityCycles - description: Return the count of the Facility Cycles that have investigations - that occur within that cycle on the specified instrument that would be - retrieved given the filters provided - tags: - - FacilityCycles - parameters: - - in: path - required: true - name: id - description: The id of the instrument to count the facility cycles of - schema: - type: integer - - WHERE_FILTER - - DISTINCT_FILTER - responses: - 200: - description: Success - The count of the instrument's facility cycles - that satisfy the filters - content: - application/json: - schema: - type: integer - 400: - description: Bad request - Something was wrong with the request - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - 404: - description: No such record - Unable to find a record in ICAT - """ - return ( - backend.get_facility_cycles_for_instrument_count_with_filters( - get_session_id_from_auth_header(), id_, get_filters_from_query_string(), - ), - 200, - ) - - -class InstrumentsFacilityCyclesInvestigations(Resource): - def get(self, instrument_id, cycle_id): - """ - --- - summary: Get the investigations for a given Facility Cycle & Instrument - description: Given an Instrument id and Facility Cycle id, get the - investigations that occur within that cycle on that instrument, subject to - the given filters - tags: - - Investigations - parameters: - - in: path - required: true - name: instrument_id - description: The id of the instrument to retrieve the investigations of - schema: - type: integer - - in: path - required: true - name: cycle_id - description: The id of the facility cycle to retrieve the investigations - schema: - type: integer - - WHERE_FILTER - - ORDER_FILTER - - LIMIT_FILTER - - SKIP_FILTER - - DISTINCT_FILTER - - INCLUDE_FILTER - responses: - 200: - description: Success - returns a list of the investigations for the - given instrument and facility cycle that satisfy the filters - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/INVESTIGATION' - 400: - description: Bad request - Something was wrong with the request - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - 404: - description: No such record - Unable to find a record in ICAT - """ - return ( - backend.get_investigations_for_instrument_in_facility_cycle_with_filters( - get_session_id_from_auth_header(), - instrument_id, - cycle_id, - get_filters_from_query_string(), - ), - 200, - ) - - -class InstrumentsFacilityCyclesInvestigationsCount(Resource): - def get(self, instrument_id, cycle_id): - """ - --- - summary: Count investigations for a given Facility Cycle & Instrument - description: Given an Instrument id and Facility Cycle id, get the number of - investigations that occur within that cycle on that instrument, subject to - the given filters - tags: - - Investigations - parameters: - - in: path - required: true - name: instrument_id - description: The id of the instrument to retrieve the investigations of - schema: - type: integer - - in: path - required: true - name: cycle_id - description: The id of the facility cycle to retrieve the investigations - schema: - type: integer - - WHERE_FILTER - - DISTINCT_FILTER - responses: - 200: - description: Success - The count of the investigations for the given - instrument and facility cycle that satisfy the filters - content: - application/json: - schema: - type: integer - 400: - description: Bad request - Something was wrong with the request - 401: - description: Unauthorized - No session ID found in HTTP Auth. header - 403: - description: Forbidden - The session ID provided is invalid - 404: - description: No such record - Unable to find a record in ICAT - """ - return ( - backend.get_investigation_count_for_instrument_facility_cycle_with_filters( - get_session_id_from_auth_header(), - instrument_id, - cycle_id, - get_filters_from_query_string(), - ), - 200, - ) +def instrument_facility_cycles_endpoint(backend): + """ + TODO - Add docstring + """ + pass + + class InstrumentsFacilityCycles(Resource): + def get(self, id_): + """ + --- + summary: Get an Instrument's FacilityCycles + description: Given an Instrument id get facility cycles where the instrument + has investigations that occur within that cycle, subject to the given + filters + tags: + - FacilityCycles + parameters: + - in: path + required: true + name: id + description: The id of the instrument to retrieve the facility cycles of + schema: + type: integer + - WHERE_FILTER + - ORDER_FILTER + - LIMIT_FILTER + - SKIP_FILTER + - DISTINCT_FILTER + - INCLUDE_FILTER + responses: + 200: + description: Success - returns a list of the instrument's facility + cycles that satisfy the filters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FACILITYCYCLE' + 400: + description: Bad request - Something was wrong with the request + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + 404: + description: No such record - Unable to find a record in ICAT + """ + return ( + backend.get_facility_cycles_for_instrument_with_filters( + get_session_id_from_auth_header(), + id_, + get_filters_from_query_string(), + ), + 200, + ) + + return InstrumentsFacilityCycles + + +def count_instrument_facility_cycles_endpoint(backend): + """ + TODO - Add docstring + """ + pass + + class InstrumentsFacilityCyclesCount(Resource): + def get(self, id_): + """ + --- + summary: Count an Instrument's FacilityCycles + description: Return the count of the Facility Cycles that have + investigations that occur within that cycle on the specified instrument + that would be retrieved given the filters provided + tags: + - FacilityCycles + parameters: + - in: path + required: true + name: id + description: The id of the instrument to count the facility cycles of + schema: + type: integer + - WHERE_FILTER + - DISTINCT_FILTER + responses: + 200: + description: Success - The count of the instrument's facility cycles + that satisfy the filters + content: + application/json: + schema: + type: integer + 400: + description: Bad request - Something was wrong with the request + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + 404: + description: No such record - Unable to find a record in ICAT + """ + return ( + backend.get_facility_cycles_for_instrument_count_with_filters( + get_session_id_from_auth_header(), + id_, + get_filters_from_query_string(), + ), + 200, + ) + + return InstrumentsFacilityCyclesCount + + +def instrument_investigation_endpoint(backend): + """ + TODO - Add docstring + """ + pass + + class InstrumentsFacilityCyclesInvestigations(Resource): + def get(self, instrument_id, cycle_id): + """ + --- + summary: Get the investigations for a given Facility Cycle & Instrument + description: Given an Instrument id and Facility Cycle id, get the + investigations that occur within that cycle on that instrument, subject + to the given filters + tags: + - Investigations + parameters: + - in: path + required: true + name: instrument_id + description: The id of the instrument to retrieve the investigations of + schema: + type: integer + - in: path + required: true + name: cycle_id + description: The id of the facility cycle to retrieve the investigations + schema: + type: integer + - WHERE_FILTER + - ORDER_FILTER + - LIMIT_FILTER + - SKIP_FILTER + - DISTINCT_FILTER + - INCLUDE_FILTER + responses: + 200: + description: Success - returns a list of the investigations for the + given instrument and facility cycle that satisfy the filters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/INVESTIGATION' + 400: + description: Bad request - Something was wrong with the request + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + 404: + description: No such record - Unable to find a record in ICAT + """ + return ( + backend.get_investigations_for_instrument_in_facility_cycle_with_filters( + get_session_id_from_auth_header(), + instrument_id, + cycle_id, + get_filters_from_query_string(), + ), + 200, + ) + + return InstrumentsFacilityCyclesInvestigations + + +def count_instrument_investigation_endpoint(backend): + """ + TODO - Add docstring + """ + pass + + class InstrumentsFacilityCyclesInvestigationsCount(Resource): + def get(self, instrument_id, cycle_id): + """ + --- + summary: Count investigations for a given Facility Cycle & Instrument + description: Given an Instrument id and Facility Cycle id, get the number of + investigations that occur within that cycle on that instrument, subject + to the given filters + tags: + - Investigations + parameters: + - in: path + required: true + name: instrument_id + description: The id of the instrument to retrieve the investigations of + schema: + type: integer + - in: path + required: true + name: cycle_id + description: The id of the facility cycle to retrieve the investigations + schema: + type: integer + - WHERE_FILTER + - DISTINCT_FILTER + responses: + 200: + description: Success - The count of the investigations for the given + instrument and facility cycle that satisfy the filters + content: + application/json: + schema: + type: integer + 400: + description: Bad request - Something was wrong with the request + 401: + description: Unauthorized - No session ID found in HTTP Auth. header + 403: + description: Forbidden - The session ID provided is invalid + 404: + description: No such record - Unable to find a record in ICAT + """ + return ( + backend.get_investigation_count_for_instrument_facility_cycle_with_filters( + get_session_id_from_auth_header(), + instrument_id, + cycle_id, + get_filters_from_query_string(), + ), + 200, + ) + + return InstrumentsFacilityCyclesInvestigationsCount diff --git a/test/icat/endpoints/test_endpoint_rules.py b/test/icat/endpoints/test_endpoint_rules.py index b92d8ff8..5259fec7 100644 --- a/test/icat/endpoints/test_endpoint_rules.py +++ b/test/icat/endpoints/test_endpoint_rules.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.main import api +from datagateway_api.src.main import app from datagateway_api.src.resources.entities.entity_map import endpoints @@ -22,7 +22,7 @@ def test_entity_endpoints(self, endpoint_ending, expected_methods): for endpoint_entity in endpoints.keys(): endpoint_found = False - for rule in api.app.url_map.iter_rules(): + for rule in app.url_map.iter_rules(): if f"/{endpoint_entity.lower()}{endpoint_ending}" == rule.rule: endpoint_found = True @@ -64,7 +64,7 @@ def test_entity_endpoints(self, endpoint_ending, expected_methods): def test_non_entity_endpoints(self, endpoint_name, expected_methods): endpoint_found = False - for rule in api.app.url_map.iter_rules(): + for rule in app.url_map.iter_rules(): if endpoint_name == rule.rule: endpoint_found = True