diff --git a/datagateway_api/src/main.py b/datagateway_api/src/main.py index 47ab71f1..7670b22f 100644 --- a/datagateway_api/src/main.py +++ b/datagateway_api/src/main.py @@ -19,14 +19,12 @@ get_id_endpoint, ) from datagateway_api.src.resources.entities.entity_map import endpoints -from datagateway_api.src.resources.non_entities.sessions_endpoints import ( - session_endpoints, -) +from datagateway_api.src.resources.non_entities.sessions_endpoints import Sessions from datagateway_api.src.resources.table_endpoints.table_endpoints import ( - count_instrument_facility_cycles_endpoint, - count_instrument_investigation_endpoint, - instrument_facility_cycles_endpoint, - instrument_investigation_endpoint, + InstrumentsFacilityCycles, + InstrumentsFacilityCyclesCount, + InstrumentsFacilityCyclesInvestigations, + InstrumentsFacilityCyclesInvestigationsCount, ) from datagateway_api.src.swagger.apispec_flask_restful import RestfulPlugin from datagateway_api.src.swagger.initialise_spec import initialise_spec @@ -103,42 +101,32 @@ def create_api_endpoints(flask_app, api, spec): spec.path(resource=get_find_one_endpoint_resource, api=api) # Session endpoint - session_endpoint_resource = session_endpoints(backend) - api.add_resource(session_endpoint_resource, "/sessions") - # spec.path(resource=session_endpoint_resource, api=api) + api.add_resource(Sessions, "/sessions") + spec.path(resource=Sessions, api=api) # Table specific endpoints - instrument_facility_cycle_resource = instrument_facility_cycles_endpoint(backend) api.add_resource( - instrument_facility_cycle_resource, "/instruments//facilitycycles", + InstrumentsFacilityCycles, "/instruments//facilitycycles", ) - # spec.path(resource=instrument_facility_cycle_resource, api=api) + spec.path(resource=InstrumentsFacilityCycles, api=api) - count_instrument_facility_cycle_res = count_instrument_facility_cycles_endpoint( - backend, - ) api.add_resource( - count_instrument_facility_cycle_res, - "/instruments//facilitycycles/count", + InstrumentsFacilityCyclesCount, "/instruments//facilitycycles/count", ) - # spec.path(resource=count_instrument_facility_cycle_resource, api=api) + spec.path(resource=InstrumentsFacilityCyclesCount, api=api) - instrument_investigation_resource = instrument_investigation_endpoint(backend) api.add_resource( - instrument_investigation_resource, + InstrumentsFacilityCyclesInvestigations, "/instruments//facilitycycles//investigations", ) - # spec.path(resource=instrument_investigation_resource, api=api) + spec.path(resource=InstrumentsFacilityCyclesInvestigations, api=api) - count_instrument_investigation_resource = count_instrument_investigation_endpoint( - backend, - ) api.add_resource( - count_instrument_investigation_resource, + InstrumentsFacilityCyclesInvestigationsCount, "/instruments//facilitycycles//investigations" "/count", ) - # spec.path(resource=count_instrument_investigation_resource, api=api) + spec.path(resource=InstrumentsFacilityCyclesInvestigationsCount, api=api) def openapi_config(spec): diff --git a/datagateway_api/src/resources/non_entities/sessions_endpoints.py b/datagateway_api/src/resources/non_entities/sessions_endpoints.py index 28af931a..6049afab 100644 --- a/datagateway_api/src/resources/non_entities/sessions_endpoints.py +++ b/datagateway_api/src/resources/non_entities/sessions_endpoints.py @@ -3,163 +3,152 @@ from flask import request from flask_restful import Resource +from datagateway_api.common.config import config from datagateway_api.common.exceptions import AuthenticationError from datagateway_api.common.helpers import get_session_id_from_auth_header log = logging.getLogger() +backend = config.get_backend_type() -def session_endpoints(backend): - """ - Generate a flask_restful Resource class using the configured backend. In main.py - these generated classes are registered with the api e.g. - `api.add_resource(get_endpoint("Datafiles", DATAFILE), "/datafiles")` - :param backend: The backend instance used for processing requests - :type backend: :class:`DatabaseBackend` or :class:`PythonICATBackend` - :return: The generated session endpoint class - """ +class Sessions(Resource): + def post(self): + """ + Generates a sessionID if the user has correct credentials + :return: String - SessionID - 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 + --- + 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 content: - application/json: + application/json: schema: - 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) + 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 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 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 - return Sessions + 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 diff --git a/datagateway_api/src/resources/table_endpoints/table_endpoints.py b/datagateway_api/src/resources/table_endpoints/table_endpoints.py index ad923ced..88637bcf 100644 --- a/datagateway_api/src/resources/table_endpoints/table_endpoints.py +++ b/datagateway_api/src/resources/table_endpoints/table_endpoints.py @@ -1,272 +1,214 @@ from flask_restful import Resource +from datagateway_api.common.config import config from datagateway_api.common.helpers import ( get_filters_from_query_string, get_session_id_from_auth_header, ) - -def instrument_facility_cycles_endpoint(backend): - """ - Generate a flask_restful Resource class using the configured backend. In main.py - these generated classes are registered with the api e.g. - `api.add_resource(get_endpoint("Datafiles", DATAFILE), "/datafiles")` - - :param backend: The backend instance used for processing requests - :type backend: :class:`DatabaseBackend` or :class:`PythonICATBackend` - :return: The generated endpoint class - """ - 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): - """ - Generate a flask_restful Resource class using the configured backend. In main.py - these generated classes are registered with the api e.g. - `api.add_resource(get_endpoint("Datafiles", DATAFILE), "/datafiles")` - - :param backend: The backend instance used for processing requests - :type backend: :class:`DatabaseBackend` or :class:`PythonICATBackend` - :return: The generated endpoint class - """ - 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): - """ - Generate a flask_restful Resource class using the configured backend. In main.py - these generated classes are registered with the api e.g. - `api.add_resource(get_endpoint("Datafiles", DATAFILE), "/datafiles")` - - :param backend: The backend instance used for processing requests - :type backend: :class:`DatabaseBackend` or :class:`PythonICATBackend` - :return: The generated endpoint class - """ - 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_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): - """ - Generate a flask_restful Resource class using the configured backend. In main.py - these generated classes are registered with the api e.g. - `api.add_resource(get_endpoint("Datafiles", DATAFILE), "/datafiles")` - - :param backend: The backend instance used for processing requests - :type backend: :class:`DatabaseBackend` or :class:`PythonICATBackend` - :return: The generated endpoint class - """ - 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_instrument_facility_cycle_with_filters( - get_session_id_from_auth_header(), - instrument_id, - cycle_id, - get_filters_from_query_string(), - ), - 200, - ) - - return InstrumentsFacilityCyclesInvestigationsCount +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_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_instrument_facility_cycle_with_filters( + get_session_id_from_auth_header(), + instrument_id, + cycle_id, + get_filters_from_query_string(), + ), + 200, + )