diff --git a/Makefile b/Makefile index d7de08b94..eca8232cc 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ SHELL := /bin/bash DIST_PATH ?= ./dist TEST_ARGS ?= --cov --cov-report=term-missing --cov-report=xml:$(DIST_PATH)/test-coverage.xml SMOKE_TEST_ARGS ?= -FEATURE_TEST_ARGS ?= ./tests/features --format progress2 +FEATURE_TEST_ARGS ?= ./tests/features TF_WORKSPACE_NAME ?= $(shell terraform -chdir=terraform/infrastructure workspace show) ENV ?= dev ACCOUNT ?= dev @@ -117,6 +117,7 @@ test-features-integration: check-warn ## Run the BDD feature tests in the integr --define="env=$(TF_WORKSPACE_NAME)" \ --define="account_name=$(ENV)" \ --define="use_shared_resources=${USE_SHARED_RESOURCES}" \ + -v --format progress2 \ $(FEATURE_TEST_ARGS) integration-test-with-custom_tag: diff --git a/layer/nrlf/core/decorators.py b/layer/nrlf/core/decorators.py index 79b01ae94..0e7476677 100644 --- a/layer/nrlf/core/decorators.py +++ b/layer/nrlf/core/decorators.py @@ -19,14 +19,13 @@ from nrlf.core.codes import SpineErrorConcept from nrlf.core.config import Config from nrlf.core.constants import ( - CLIENT_RP_DETAILS, - CONNECTION_METADATA, NHSD_CORRELATION_ID_HEADER, PERMISSION_ALLOW_ALL_POINTER_TYPES, X_CORRELATION_ID_HEADER, X_REQUEST_ID_HEADER, AccessControls, PointerTypes, + V2Headers, ) from nrlf.core.dynamodb.repository import DocumentPointerRepository from nrlf.core.errors import OperationOutcomeError, ParseError @@ -145,13 +144,20 @@ def wrapper(*args, **kwargs) -> Dict[str, Any]: RepositoryType = Union[Type[DocumentPointerRepository], None] -def _use_v2_permissions_model(headers: Dict[str, str]) -> bool: +def _use_v2_permissions_model(headers: Dict[str, str], path: str) -> bool: case_insensitive_headers = {key.lower(): value for key, value in headers.items()} - # if either or both headers are missing - return ( - CLIENT_RP_DETAILS not in case_insensitive_headers.keys() - or CONNECTION_METADATA not in case_insensitive_headers.keys() + + v2_headers_provided = ( + V2Headers.NHSD_END_USER_ORGANISATION_ODS in case_insensitive_headers.keys() + and V2Headers.NHSD_NRL_APP_ID in case_insensitive_headers.keys() ) + if not v2_headers_provided: + return False + + metadata = parse_headers(headers, use_v2_permissions=True) + v2_permissions_configured = get_pointer_permissions_v2(metadata, path) != {} + + return v2_permissions_configured def _load_v2_connection_metadata(headers: Dict[str, str], path: str): @@ -189,7 +195,7 @@ def _load_v2_connection_metadata(headers: Dict[str, str], path: str): def load_connection_metadata(headers: Dict[str, str], config: Config, path=""): logger.log(LogReference.HANDLER002, headers=headers) - if _use_v2_permissions_model(headers): + if _use_v2_permissions_model(headers, path): return _load_v2_connection_metadata(headers, path) metadata = parse_headers(headers, use_v2_permissions=False) diff --git a/layer/nrlf/core/tests/test_decorators.py b/layer/nrlf/core/tests/test_decorators.py index 4e23d5e92..bccde3265 100644 --- a/layer/nrlf/core/tests/test_decorators.py +++ b/layer/nrlf/core/tests/test_decorators.py @@ -807,45 +807,138 @@ def test_request_load_connection_metadata_with_no_permission_lookup_or_file(): assert expected_metadata.pointer_types == [] -missing_headers = [ - ["nhsd-connection-metadata"], - ["nhsd-connection-metadata", "nhsd-client-rp-details"], - ["nhsd-client-rp-details"], -] +def _create_v2_headers() -> dict: + """Create headers that trigger the v2 permissions model (missing nhsd-client-rp-details).""" + headers = create_headers( + additional_headers={ + V2Headers.NHSD_END_USER_ORGANISATION_ODS: "Y05868", + V2Headers.NHSD_NRL_APP_ID: "Y05868-TestApp-12345678", + } + ) + headers.pop("nhsd-client-rp-details") + return headers -@pytest.mark.parametrize("headers_missing_from_request", missing_headers) -def test_request_load_connection_with_missing_headers_gets_v2_permissions( - headers_missing_from_request, +def test_load_connection_metadata_v2_happy_path( + mocker, ): - headers = create_headers( + mocker.patch( + "nrlf.core.decorators.get_pointer_permissions_v2", + return_value={ + "types": [ + "http://snomed.info/sct|749001000000101", + "https://nicip.nhs.uk|MAULR", + ] + }, + ) + + metadata = load_connection_metadata( + headers=_create_v2_headers(), + config=Config(), + path="/producer/DocumentReference", + ) + + assert metadata.nrl_permissions_policy.types == [ + "http://snomed.info/sct|749001000000101", + "https://nicip.nhs.uk|MAULR", + ] + assert metadata.pointer_types == [] # no v1 permissions + assert metadata.ods_code == "Y05868" + assert metadata.nrl_app_id == "Y05868-TestApp-12345678" + + +def test_load_connection_metadata_gets_v2_permissions_when_v1_headers_also_provided( + mocker, +): + v1_permissions = [ + "http://snomed.info/sct|749001000000101", + "https://nicip.nhs.uk|MAULR", + ] + mocker.patch( + "nrlf.core.decorators.parse_permissions_file", + return_value=v1_permissions, + ) + v2_permissions = {"access_controls": [AccessControls.ALLOW_ALL_TYPES.value]} + mocker.patch( + "nrlf.core.decorators.get_pointer_permissions_v2", + return_value=v2_permissions, + ) + + v1_plus_v2_headers = create_headers( additional_headers={ V2Headers.NHSD_END_USER_ORGANISATION_ODS: "Y05868", V2Headers.NHSD_NRL_APP_ID: "Y05868-TestApp-12345678", } ) - for header_name in headers_missing_from_request: - headers.pop(header_name) - expected_metadata = load_connection_metadata( - headers=headers, config=Config(), path="/producer/DocumentReference" + metadata = load_connection_metadata( + headers=v1_plus_v2_headers, config=Config(), path="/producer/DocumentReference" ) - assert expected_metadata.pointer_types == [] - assert expected_metadata.ods_code == "Y05868" - assert expected_metadata.nrl_app_id == "Y05868-TestApp-12345678" + assert metadata.nrl_permissions_policy.types == PointerTypes.list() + assert metadata.pointer_types == [] # no v1 permissions -def _create_v2_headers() -> dict: - """Create headers that trigger the v2 permissions model (missing nhsd-client-rp-details).""" - headers = create_headers( +def test_load_connection_metadata_gets_v1_permissions_when_v2_permission_file_missing( + mocker, +): + v1_permissions = [ + "http://snomed.info/sct|749001000000101", + "https://nicip.nhs.uk|MAULR", + ] + mocker.patch( + "nrlf.core.decorators.parse_permissions_file", + return_value=v1_permissions, + ) + mocker.patch( + "nrlf.core.decorators.get_pointer_permissions_v2", + return_value={}, + ) + + v1_plus_v2_headers = create_headers( additional_headers={ V2Headers.NHSD_END_USER_ORGANISATION_ODS: "Y05868", V2Headers.NHSD_NRL_APP_ID: "Y05868-TestApp-12345678", } ) - headers.pop("nhsd-client-rp-details") - return headers + + metadata = load_connection_metadata( + headers=v1_plus_v2_headers, config=Config(), path="/producer/DocumentReference" + ) + + assert metadata.pointer_types == v1_permissions + assert metadata.nrl_permissions_policy == None # no v2 permissions + + +def test_load_connection_metadata_gets_v1_permissions_when_v2_headers_missing( + mocker, +): + v1_permissions = [ + "http://snomed.info/sct|749001000000101", + "https://nicip.nhs.uk|MAULR", + ] + mocker.patch( + "nrlf.core.decorators.parse_permissions_file", + return_value=v1_permissions, + ) + v2_permissions = {"access_controls": [AccessControls.ALLOW_ALL_TYPES.value]} + mocker.patch( + "nrlf.core.decorators.get_pointer_permissions_v2", + return_value=v2_permissions, + ) + + v1_headers_only = create_headers( + additional_headers={ + V2Headers.NHSD_END_USER_ORGANISATION_ODS: "Y05868", + } + ) + + metadata = load_connection_metadata( + headers=v1_headers_only, config=Config(), path="/producer/DocumentReference" + ) + + assert metadata.pointer_types == v1_permissions + assert metadata.nrl_permissions_policy == None # no v2 permissions def test_load_v2_connection_metadata_allow_all_types(mocker: MockerFixture): diff --git a/scripts/get_s3_permissions.py b/scripts/get_s3_permissions.py index 66f39c287..a7e64c5f4 100644 --- a/scripts/get_s3_permissions.py +++ b/scripts/get_s3_permissions.py @@ -55,6 +55,12 @@ def _write_permission_file(folder_path, ods_code, pointer_types, access_controls json.dump({"access_controls": access_controls or [], "types": pointer_types}, f) +def _write_v1_permission_file(folder_path, ods_code, pointer_types): + folder_path.mkdir(parents=True, exist_ok=True) + with open(folder_path / f"{ods_code}.json", "w") as f: + json.dump(pointer_types, f) + + def add_feature_test_files(local_path): """Bake in v2 permissions for the feature test application so that the v2 permissions model can be proven via feature tests without @@ -65,7 +71,7 @@ def add_feature_test_files(local_path): org_permissions = { "consumer": [ ( - "z00z-y11y-x22x", + "v2-z00z-y11y-x22x", "RX898", [PointerTypes.MENTAL_HEALTH_PLAN.value], [], @@ -77,7 +83,7 @@ def add_feature_test_files(local_path): [], ), ( - "z00z-y11y-x22x", + "v2-z00z-y11y-x22x", "4LLTYP35C", [], [AccessControls.ALLOW_ALL_TYPES.value], @@ -85,7 +91,7 @@ def add_feature_test_files(local_path): ], "producer": [ ( - "z00z-y11y-x22x", + "v2-z00z-y11y-x22x", "RX898", [PointerTypes.EOL_CARE_PLAN.value], [], @@ -97,7 +103,7 @@ def add_feature_test_files(local_path): [], ), ( - "z00z-y11y-x22x", + "v2-z00z-y11y-x22x", "4LLTYP35P", [], [ @@ -157,6 +163,24 @@ def add_feature_test_files(local_path): for app_id, pointer_types, access_controls in entries ] + print("Adding feature test v1 permissions to temporary directory...") + v1_permissions = [ + ( + "v2-z00z-y11y-x22x", + "V1ONLY0D5", + [PointerTypes.LLOYD_GEORGE_FOLDER.value], + [], + ), # http://snomed.info/sct|16521000000101 + ] + [ + _write_v1_permission_file( + Path.joinpath(local_path, app_id), + ods_code, + pointer_types, + ) + for app_id, ods_code, pointer_types, access_controls in v1_permissions + ] + def download_files(s3_client, bucket_name, local_path, file_names, folders): print(f"Downloading {len(file_names)} S3 files to temporary directory...") diff --git a/tests/features/consumer/readDocumentReference-failure.feature b/tests/features/consumer/readDocumentReference-failure.feature index dd37af613..f6ef1e0f4 100644 --- a/tests/features/consumer/readDocumentReference-failure.feature +++ b/tests/features/consumer/readDocumentReference-failure.feature @@ -6,7 +6,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' + When consumer 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' Then the response status code is 404 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -33,7 +33,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' reads a DocumentReference with ID 'X26`DROP TABLE 'pointers';--Something-000000000-000000000' + When consumer 'RX898' reads a DocumentReference with ID 'X26`DROP TABLE 'pointers';--Something-000000000-000000000' Then the response status code is 404 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -58,7 +58,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: | system | value | - When consumer v1 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' + When consumer 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' Then the response status code is 403 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -95,7 +95,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' reads a DocumentReference with ID '02V-1111111111-ReadDocRefNoAuthForType' + When consumer 'RX898' reads a DocumentReference with ID '02V-1111111111-ReadDocRefNoAuthForType' Then the response status code is 403 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -120,7 +120,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: | system | value | - When consumer v1 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' + When consumer 'RX898' reads a DocumentReference with ID 'X26-000000000-000000000' Then the response status code is 403 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -157,7 +157,7 @@ Feature: Consumer - readDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' reads a DocumentReference with ID '02V-1111111111-ReadDocRefNoAuthForTypeS3' + When consumer 'RX898' reads a DocumentReference with ID '02V-1111111111-ReadDocRefNoAuthForTypeS3' Then the response status code is 403 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: diff --git a/tests/features/consumer/readDocumentReference-success.feature b/tests/features/consumer/readDocumentReference-success.feature index 5de6b44cd..9a3c81d55 100644 --- a/tests/features/consumer/readDocumentReference-success.feature +++ b/tests/features/consumer/readDocumentReference-success.feature @@ -16,7 +16,7 @@ Feature: Consumer - readDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | RX898 | - When consumer v1 'RX898' reads a DocumentReference with ID 'RX898-9999999999-ReadDocRefSameCustodian' + When consumer 'RX898' reads a DocumentReference with ID 'RX898-9999999999-ReadDocRefSameCustodian' Then the response status code is 200 And the response is a DocumentReference with JSON value: """ @@ -133,7 +133,7 @@ Feature: Consumer - readDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | X26 | | author | RX898 | - When consumer v1 'RX898' reads a DocumentReference with ID 'X26-9999999999-ReadDocRefDiffCustodian' + When consumer 'RX898' reads a DocumentReference with ID 'X26-9999999999-ReadDocRefDiffCustodian' Then the response status code is 200 And the response is a DocumentReference with JSON value: """ @@ -250,5 +250,5 @@ Feature: Consumer - readDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898\|001 | | author | RX898 | - When consumer v1 'RX898' reads a DocumentReference with ID 'RX898%7C001-1234567890-ReadDocRefUrlEncoded' + When consumer 'RX898' reads a DocumentReference with ID 'RX898%7C001-1234567890-ReadDocRefUrlEncoded' Then the response status code is 200 diff --git a/tests/features/consumer/searchDocumentReference-failure.feature b/tests/features/consumer/searchDocumentReference-failure.feature index 48d0e7882..6113b714c 100644 --- a/tests/features/consumer/searchDocumentReference-failure.feature +++ b/tests/features/consumer/searchDocumentReference-failure.feature @@ -5,7 +5,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | extra | parameter | @@ -33,7 +33,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | Then the response status code is 400 And the response is an OperationOutcome with 1 issue @@ -59,7 +59,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | type | http://incorrect.info/sct\|736253002 | @@ -87,7 +87,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | type | http://snomed.info/sct\|887701000000100 | @@ -115,7 +115,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 123 | Then the response status code is 400 @@ -141,7 +141,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: | system | value | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | Then the response status code is 403 @@ -166,7 +166,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: | system | value | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000 | @@ -204,7 +204,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 8FW23 | | author | 8FW23 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|1102421000000108 | @@ -227,7 +227,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 8FW23 | | author | 8FW23 | - When consumer v1 'Z26' searches for DocumentReferences with parameters: + When consumer 'Z26' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | type | 736253002 | @@ -254,7 +254,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://incorrect.info/sct\|736253002 | @@ -282,7 +282,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000,http://snomed.info/sct\|invalid | diff --git a/tests/features/consumer/searchDocumentReference-success.feature b/tests/features/consumer/searchDocumentReference-success.feature index b3d9c4f7b..a35fa3273 100644 --- a/tests/features/consumer/searchDocumentReference-success.feature +++ b/tests/features/consumer/searchDocumentReference-success.feature @@ -16,7 +16,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | Then the response status code is 200 @@ -53,7 +53,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | custodian | 02V | | author | 02V | | identifier | 02V.123456789 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | Then the response status code is 200 @@ -90,7 +90,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | custodian | 02V | @@ -138,7 +138,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | DK94 | | author | DK94 | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | custodian | 02V | @@ -186,7 +186,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | custodian | 02V | @@ -245,7 +245,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | Then the response status code is 200 @@ -298,8 +298,8 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | DK94 | | author | N64 | - When producer v1 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' - And consumer v1 'RX898' searches for DocumentReferences with parameters: + When producer 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' + And consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | custodian | RX898 | @@ -348,7 +348,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000 | @@ -409,7 +409,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|1102421000000108 | @@ -450,7 +450,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | _summary | count | @@ -510,7 +510,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-4.pdf | | custodian | 02V | | author | 02V | - When consumer v1 'RX898' searches for DocumentReferences with parameters: + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000,http://snomed.info/sct\|823651000000106 | diff --git a/tests/features/consumer/searchPostDocumentReference-failure.feature b/tests/features/consumer/searchPostDocumentReference-failure.feature index 53fd41d39..2aa60a5b1 100644 --- a/tests/features/consumer/searchPostDocumentReference-failure.feature +++ b/tests/features/consumer/searchPostDocumentReference-failure.feature @@ -5,7 +5,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | extra | parameter | @@ -33,7 +33,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | Then the response status code is 400 And the response is an OperationOutcome with 1 issue @@ -59,7 +59,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | type | http://incorrect.info/sct\|736253002 | @@ -87,7 +87,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | type | http://snomed.info/sct\|887701000000100 | @@ -115,7 +115,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 123 | Then the response status code is 400 @@ -141,7 +141,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: | system | value | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 403 @@ -175,7 +175,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 8FW23 | | author | 8FW23 | - When consumer v1 'X26' searches for DocumentReferences using POST with request body: + When consumer 'X26' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | type | 736253002 | @@ -199,7 +199,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios Scenario: Search rejects request if the organisation has no registered pointer types Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 403 @@ -225,7 +225,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | category | http://incorrect.info/sct\|736253002 | @@ -253,7 +253,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios And the organisation 'RX898' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000,http://snomed.info/sct\|invalid | diff --git a/tests/features/consumer/searchPostDocumentReference-success.feature b/tests/features/consumer/searchPostDocumentReference-success.feature index af09f03d6..c8fcecaa5 100644 --- a/tests/features/consumer/searchPostDocumentReference-success.feature +++ b/tests/features/consumer/searchPostDocumentReference-success.feature @@ -16,7 +16,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | 8FW23 | | author | 8FW23 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 200 @@ -52,7 +52,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | RX898 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | custodian | RX898 | @@ -111,7 +111,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | X26 | | author | X26 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 200 @@ -180,7 +180,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | X26 | | author | X26 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 200 @@ -232,8 +232,8 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | DK94 | | author | N64 | - When producer v1 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' - And consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When producer 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' + And consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | custodian | RX898 | @@ -282,7 +282,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | x26 | | author | x26 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000 | @@ -353,7 +353,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | x26 | | author | x26 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | _summary | count | @@ -412,7 +412,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc-4.pdf | | custodian | X26 | | author | X26 | - When consumer v1 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | | category | http://snomed.info/sct\|734163000,http://snomed.info/sct\|823651000000106 | diff --git a/tests/features/consumer/v2-permissions-by-pointer-type.feature b/tests/features/consumer/v2-permissions-by-pointer-type.feature index 347d4ccec..a04ce9de0 100644 --- a/tests/features/consumer/v2-permissions-by-pointer-type.feature +++ b/tests/features/consumer/v2-permissions-by-pointer-type.feature @@ -5,7 +5,7 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios success scenarios. Background: - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API Scenario: V2 Permissions with access for pointer type - readDocumentReference Given a DocumentReference resource exists with values: @@ -19,7 +19,7 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | RX898 | - When consumer v2 'RX898' reads a DocumentReference with ID 'RX898-9999999999-ReadDocRefV2SameCustodian' + When consumer 'RX898' reads a DocumentReference with ID 'RX898-9999999999-ReadDocRefV2SameCustodian' Then the response status code is 200 And the response is a DocumentReference with JSON value: """ @@ -121,7 +121,7 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios """ Scenario: V2 permissions with access for pointer type retrieves expected document references - searchPostDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API And a DocumentReference resource exists with values: | property | value | | id | X26-1111111111-SearchMultipleRefTest1 | @@ -155,7 +155,7 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | X26 | | author | X26 | - When consumer v2 'RX898' searches for DocumentReferences using POST with request body: + When consumer 'RX898' searches for DocumentReferences using POST with request body: | key | value | | subject | 9278693472 | Then the response status code is 200 @@ -187,8 +187,8 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios And the Bundle does not contain a DocumentReference with ID 'X26-1111111111-SearchMultipleRefTestDifferentType' Scenario: V2 permissions with no access for pointer type - searchDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When consumer v2 'RX898' searches for DocumentReferences with parameters: + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API + When consumer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | | type | http://snomed.info/sct\|887701000000100 | @@ -211,8 +211,132 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios } """ + Scenario: No V2 Permissions for org gets v1 permissions - readDocumentReference + Given a DocumentReference resource exists with values: + | property | value | + | id | V1ONLY0D5-9999999999-ReadDocRefNoV2FindV1 | + | subject | 9999999999 | + | status | current | + | type | 16521000000101 | + | category | 419891008 | + | contentType | application/pdf | + | url | https://example.org/my-doc.pdf | + | custodian | V1ONLY0D5 | + | author | V1ONLY0D5 | + And a DocumentReference resource exists with values: + | property | value | + | id | RX898-9999999999-ReadDocRefNoV2PermsSoDontFindMe | + | subject | 9999999999 | + | status | current | + | type | 736253002 | + | category | 734163000 | + | contentType | application/pdf | + | url | https://example.org/my-doc.pdf | + | custodian | RX898 | + | author | RX898 | + When consumer 'V1ONLY0D5' reads a DocumentReference with ID 'V1ONLY0D5-9999999999-ReadDocRefNoV2FindV1' + Then the response status code is 200 + And the response is a DocumentReference with JSON value: + """ + { + "resourceType": "DocumentReference", + "id": "V1ONLY0D5-9999999999-ReadDocRefNoV2FindV1", + "status": "current", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "16521000000101", + "display": "Lloyd George record folder" + } + ] + }, + "category": [ + { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "419891008", + "display": "Record artifact" + } + ] + } + ], + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9999999999" + } + }, + "custodian": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "V1ONLY0D5" + } + }, + "author": [ + { + "identifier": { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "V1ONLY0D5" + } + } + ], + "content": [ + { + "attachment": { + "contentType": "application/pdf", + "url": "https://example.org/my-doc.pdf" + }, + "format": { + "system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode", + "code": "urn:nhs-ic:unstructured", + "display": "Unstructured Document" + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-ContentStability", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability", + "code": "static", + "display": "Static" + } + ] + } + }, + { + "url": "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-NRLRetrievalMechanism", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLRetrievalMechanism", + "code": "Direct", + "display": "Direct" + } + ] + } + } + ] + } + ], + "context": { + "practiceSetting": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "788007007", + "display": "General practice service" + } + ] + } + } + } + """ + Scenario: V2 permissions with access all pointer types retrieves expected document references - searchPostDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API And a DocumentReference resource exists with values: | property | value | | id | X26-5900056201-SearchMultipleType1 | @@ -246,7 +370,7 @@ Feature: Consumer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc-3.pdf | | custodian | X26 | | author | X26 | - When consumer v2 '4LLTYP35C' searches for DocumentReferences using POST with request body: + When consumer '4LLTYP35C' searches for DocumentReferences using POST with request body: | key | value | | subject | 9000000378 | Then the response status code is 200 diff --git a/tests/features/producer/createDocumentReference-failure.feature b/tests/features/producer/createDocumentReference-failure.feature index 905bea341..ff1d2bfda 100644 --- a/tests/features/producer/createDocumentReference-failure.feature +++ b/tests/features/producer/createDocumentReference-failure.feature @@ -16,7 +16,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -53,7 +53,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 1234567890 | | status | current | @@ -212,7 +212,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | N0TANGY | | author | HAR1 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -263,7 +263,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'ANGY1' is authorised to access pointer types: | system | value | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -298,7 +298,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' creates a DocumentReference with values: + When producer 'X26' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | type | 736253002 | @@ -335,7 +335,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -373,7 +373,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' creates a DocumentReference with values: + When producer 'X26' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -544,7 +544,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -581,7 +581,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -620,7 +620,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios | system | value | | https://nicip.nhs.uk | MAULR | | https://nicip.nhs.uk | MAXIB | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -665,7 +665,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' creates a DocumentReference with values: + When producer 'X26' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | @@ -814,7 +814,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9999999999 | | status | current | diff --git a/tests/features/producer/createDocumentReference-success.feature b/tests/features/producer/createDocumentReference-success.feature index 03f4f65c7..e7ea87d8c 100644 --- a/tests/features/producer/createDocumentReference-success.feature +++ b/tests/features/producer/createDocumentReference-success.feature @@ -5,7 +5,7 @@ Feature: Producer - createDocumentReference - Success Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -110,7 +110,7 @@ Feature: Producer - createDocumentReference - Success Scenarios | custodian | ANGY1 | | author | HAR1 | | practiceSetting | 788002001 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -161,7 +161,7 @@ Feature: Producer - createDocumentReference - Success Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -239,7 +239,7 @@ Feature: Producer - createDocumentReference - Success Scenarios | system | value | | https://nicip.nhs.uk | MAULR | | https://nicip.nhs.uk | MAXIB | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -282,7 +282,7 @@ Feature: Producer - createDocumentReference - Success Scenarios | author | HAR1 | | url | https://example.org/my-doc.pdf | | practiceSetting | 788002001 | - When producer v1 'ANGY1' creates a DocumentReference with values: + When producer 'ANGY1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -330,7 +330,7 @@ Feature: Producer - createDocumentReference - Success Scenarios And the organisation 'BARS1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 749001000000101 | - When producer v1 'BARS1' creates a DocumentReference with values: + When producer 'BARS1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | diff --git a/tests/features/producer/deleteDocumentReference-failure.feature b/tests/features/producer/deleteDocumentReference-failure.feature index 105398075..52fb6c3fc 100644 --- a/tests/features/producer/deleteDocumentReference-failure.feature +++ b/tests/features/producer/deleteDocumentReference-failure.feature @@ -19,7 +19,7 @@ Feature: Producer - deleteDocumentReference - Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | OC84 | | author | N64 | - When producer v1 'DK94' requests to delete DocumentReference with id 'OC84-111-DeleteTest-NotYourPointer' + When producer 'DK94' requests to delete DocumentReference with id 'OC84-111-DeleteTest-NotYourPointer' Then the response status code is 403 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: diff --git a/tests/features/producer/deleteDocumentReference-success.feature b/tests/features/producer/deleteDocumentReference-success.feature index f1543a8e5..440de277b 100644 --- a/tests/features/producer/deleteDocumentReference-success.feature +++ b/tests/features/producer/deleteDocumentReference-success.feature @@ -18,7 +18,7 @@ Feature: Producer - deleteDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | DK94 | | author | N64 | - When producer v1 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' + When producer 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1' Then the response status code is 200 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -47,7 +47,7 @@ Feature: Producer - deleteDocumentReference - Success Scenarios And the organisation 'DK94' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'DK94' requests to delete DocumentReference with id 'DK94-000-NoPointerHere' + When producer 'DK94' requests to delete DocumentReference with id 'DK94-000-NoPointerHere' Then the response status code is 200 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: diff --git a/tests/features/producer/searchDocumentReference-success.feature b/tests/features/producer/searchDocumentReference-success.feature index c8823bce5..2fe5e31df 100644 --- a/tests/features/producer/searchDocumentReference-success.feature +++ b/tests/features/producer/searchDocumentReference-success.feature @@ -27,7 +27,7 @@ Feature: Producer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | X26 | - When producer v1 'RX898' searches for DocumentReferences with parameters: + When producer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9278693472 | Then the response status code is 200 @@ -86,7 +86,7 @@ Feature: Producer - searchDocumentReference - Success Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | X26 | - When producer v1 'RX898' searches for DocumentReferences with parameters: + When producer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | pointer_type | 736253002 | | subject | 9999999999 | diff --git a/tests/features/producer/upsertDocumentReference-failure.feature b/tests/features/producer/upsertDocumentReference-failure.feature index fec9bd07e..192b6439a 100644 --- a/tests/features/producer/upsertDocumentReference-failure.feature +++ b/tests/features/producer/upsertDocumentReference-failure.feature @@ -6,7 +6,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' upserts a DocumentReference with values: + When producer 'X26' upserts a DocumentReference with values: | property | value | | id | X26-testid-upsert-0001-0001 | | subject | 9999999999 | @@ -45,7 +45,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' upserts a DocumentReference with values: + When producer 'X26' upserts a DocumentReference with values: | property | value | | subject | 9999999999 | | type | 736253002 | @@ -82,7 +82,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | X26-testid-upsert-0001-0001 | | subject | 9278693472 | @@ -120,7 +120,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | X26-testid-upsert-0001-0001 | | subject | 9999999999 | @@ -161,7 +161,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios | system | value | | http://snomed.info/sct | 1363501000000100 | | http://snomed.info/sct | 736253002 | - When producer v1 'X26' upserts a DocumentReference with values: + When producer 'X26' upserts a DocumentReference with values: | property | value | | id | X26-testid-upsert-0001-0001 | | subject | 9999999999 | @@ -200,7 +200,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios | system | value | | https://nicip.nhs.uk | MAULR | | https://nicip.nhs.uk | MAXIB | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | ANGY1-testid-upsert-0001-0001 | | subject | 9999999999 | @@ -335,7 +335,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | TSTCUS-sample-id-00003 | | subject | 9999999999 | diff --git a/tests/features/producer/upsertDocumentReference-success.feature b/tests/features/producer/upsertDocumentReference-success.feature index 2492ec602..9fefb7e66 100644 --- a/tests/features/producer/upsertDocumentReference-success.feature +++ b/tests/features/producer/upsertDocumentReference-success.feature @@ -8,7 +8,7 @@ Feature: Producer - upsertDocumentReference - Success Scenarios And the organisation 'ANGY1' is authorised to access pointer types: | system | value | | http://snomed.info/sct | 736253002 | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | ANGY1-testid-upsert-0001-0001 | | subject | 9278693472 | @@ -54,7 +54,7 @@ Feature: Producer - upsertDocumentReference - Success Scenarios | system | value | | https://nicip.nhs.uk | MAULR | | https://nicip.nhs.uk | MAXIB | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | ANGY1-testid-upsert-0001-0001 | | subject | 9278693472 | @@ -95,7 +95,7 @@ Feature: Producer - upsertDocumentReference - Success Scenarios | custodian | ANGY1 | | author | HAR1 | | url | https://example.org/my-doc.pdf | - When producer v1 'ANGY1' upserts a DocumentReference with values: + When producer 'ANGY1' upserts a DocumentReference with values: | property | value | | id | ANGY1-testid-upsert-0001-0002 | | subject | 9278693472 | diff --git a/tests/features/producer/v2-permissions-access-controls.feature b/tests/features/producer/v2-permissions-access-controls.feature index 3ca5246a1..3daec2282 100644 --- a/tests/features/producer/v2-permissions-access-controls.feature +++ b/tests/features/producer/v2-permissions-access-controls.feature @@ -1,8 +1,8 @@ Feature: Producer v2 access_control permissions - Success and Failure Scenarios Scenario: Successfully create a DocumentReference with a specified date with the ALLOW_OVERRIDE_CREATION_DATETIME permission - createDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When producer v2 '4LLTYP35P' creates a DocumentReference with values: + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API + When producer '4LLTYP35P' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -47,8 +47,8 @@ Feature: Producer v2 access_control permissions - Success and Failure Scenarios | date | 2024-06-01T12:00:00Z | Scenario: Create a DocumentReference with a specified date WITHOUT ALLOW_OVERRIDE_CREATION_DATETIME - date should be overridden by the server - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When producer v2 'RX898' creates a DocumentReference with values: + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API + When producer 'RX898' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -93,8 +93,8 @@ Feature: Producer v2 access_control permissions - Success and Failure Scenarios And the date of the resource in the Location header is not '2024-06-01T12:00:00Z' Scenario: Successfully supersede a DocumentReference with ALLOW_SUPERSEDE_WITH_DELETE_FAILURE - upsertDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When producer v2 '4LLTYP35P' upserts a DocumentReference with values: + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API + When producer '4LLTYP35P' upserts a DocumentReference with values: | property | value | | id | 4LLTYP35P-testid-upsert-0001-0002 | | subject | 9278693472 | @@ -126,8 +126,8 @@ Feature: Producer v2 access_control permissions - Success and Failure Scenarios """ Scenario: Supersede a DocumentReference fails without ALLOW_SUPERSEDE_WITH_DELETE_FAILURE - createDocumentReference - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API - When producer v2 'RX898' creates a DocumentReference with values: + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API + When producer 'RX898' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | diff --git a/tests/features/producer/v2-permissions-app-level.feature b/tests/features/producer/v2-permissions-app-level.feature index 1fcf7c6d3..37cf96c5f 100644 --- a/tests/features/producer/v2-permissions-app-level.feature +++ b/tests/features/producer/v2-permissions-app-level.feature @@ -6,7 +6,7 @@ Feature: Producer v2 APP-LEVEL permissions by pointer type - Success and Failure Scenario: HAPPY PATH V2 Permissions with access for pointer type - createDocumentReference Given the application 'ProducerTest001' (ID 'app-t001') is registered to access the API - When producer v2 'ORGA' creates a DocumentReference with values: + When producer 'ORGA' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -50,7 +50,7 @@ Feature: Producer v2 APP-LEVEL permissions by pointer type - Success and Failure Scenario: V2 Permissions with no producer access at all (but app level consumer access for specified type) Given the application 'ProducerTest002' (ID 'app-t002') is registered to access the API - When producer v2 'ORGA' creates a DocumentReference with values: + When producer 'ORGA' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -82,7 +82,7 @@ Feature: Producer v2 APP-LEVEL permissions by pointer type - Success and Failure Scenario: V2 Permissions with no access to specified type Given the application 'ProducerTest003' (ID 'app-t003') is registered to access the API - When producer v2 'ORGA' creates a DocumentReference with values: + When producer 'ORGA' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -117,7 +117,7 @@ Feature: Producer v2 APP-LEVEL permissions by pointer type - Success and Failure Scenario: V2 Permissions with org-level permissions for requested type but app level permissions for other types Given the application 'ProducerTest004' (ID 'app-t004') is registered to access the API - When producer v2 'ODS1' creates a DocumentReference with values: + When producer 'ODS1' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | diff --git a/tests/features/producer/v2-permissions-by-pointer-type.feature b/tests/features/producer/v2-permissions-by-pointer-type.feature index 83c429146..61694d0f9 100644 --- a/tests/features/producer/v2-permissions-by-pointer-type.feature +++ b/tests/features/producer/v2-permissions-by-pointer-type.feature @@ -5,10 +5,10 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios success scenarios. Background: - Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + Given the application 'DataShare' (ID 'v2-z00z-y11y-x22x') is registered to access the API Scenario: V2 Permissions with access for pointer type - createDocumentReference - When producer v2 'RX898' creates a DocumentReference with values: + When producer 'RX898' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -51,7 +51,7 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios | practiceSetting | 788002001 | Scenario: V2 Permissions with no access for pointer type - createDocumentReference - When producer v2 'RX898' creates a DocumentReference with values: + When producer 'RX898' creates a DocumentReference with values: | property | value | | subject | 9278693472 | | status | current | @@ -96,7 +96,7 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | RX898 | - When producer v2 'RX898' requests to delete DocumentReference with id 'RX898-111-DeleteDocRefTest1' + When producer 'RX898' requests to delete DocumentReference with id 'RX898-111-DeleteDocRefTest1' Then the response status code is 200 And the response is an OperationOutcome with 1 issue And the OperationOutcome contains the issue: @@ -141,7 +141,7 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | X26 | - When producer v2 'RX898' searches for DocumentReferences with parameters: + When producer 'RX898' searches for DocumentReferences with parameters: | parameter | value | | subject | 9999999999 | Then the response status code is 200 @@ -184,7 +184,7 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | 4LLTYP35P | | author | X26 | - When producer v2 '4LLTYP35P' searches for DocumentReferences with parameters: + When producer '4LLTYP35P' searches for DocumentReferences with parameters: | parameter | value | | subject | 9999999999 | Then the response status code is 200 @@ -226,7 +226,7 @@ Feature: Producer v2 permissions by pointer type - Success and Failure Scenarios | url | https://example.org/my-doc.pdf | | custodian | RX898 | | author | X26 | - When producer v2 'N00RG1' searches for DocumentReferences with parameters: + When producer 'N00RG1' searches for DocumentReferences with parameters: | parameter | value | | subject | 9999999999 | Then the response status code is 403 diff --git a/tests/features/steps/2_request.py b/tests/features/steps/2_request.py index 50f1b9848..4706fafa5 100644 --- a/tests/features/steps/2_request.py +++ b/tests/features/steps/2_request.py @@ -24,11 +24,9 @@ def consumer_count_document_references_step(context: Context, ods_code: str): context.response = client.count(items) -@when("consumer {version} '{ods_code}' searches for DocumentReferences with parameters") -def consumer_search_document_reference_step( - context: Context, version: str, ods_code: str -): - client = consumer_client_from_context(context, ods_code, v2=(version == "v2")) +@when("consumer '{ods_code}' searches for DocumentReferences with parameters") +def consumer_search_document_reference_step(context: Context, ods_code: str): + client = consumer_client_from_context(context, ods_code) if not context.table: raise ValueError("No search query table provided") @@ -48,12 +46,10 @@ def consumer_search_document_reference_step( @when( - "consumer {version} '{ods_code}' searches for DocumentReferences using POST with request body" + "consumer '{ods_code}' searches for DocumentReferences using POST with request body" ) -def consumer_search_post_document_reference_step( - context: Context, version: str, ods_code: str -): - client = consumer_client_from_context(context, ods_code, v2=(version == "v2")) +def consumer_search_post_document_reference_step(context: Context, ods_code: str): + client = consumer_client_from_context(context, ods_code) if not context.table: raise ValueError("No search query table provided") @@ -72,19 +68,17 @@ def consumer_search_post_document_reference_step( ) -@when( - "consumer {version} '{ods_code}' reads a DocumentReference with ID '{doc_ref_id}'" -) +@when("consumer '{ods_code}' reads a DocumentReference with ID '{doc_ref_id}'") def consumer_read_document_reference_step( - context: Context, version: str, ods_code: str, doc_ref_id: str + context: Context, ods_code: str, doc_ref_id: str ): - client = consumer_client_from_context(context, ods_code, v2=(version == "v2")) + client = consumer_client_from_context(context, ods_code) context.response = client.read(doc_ref_id) -@when("producer {version} '{ods_code}' creates a DocumentReference with values") -def create_post_document_reference_step(context: Context, version: str, ods_code: str): - client = producer_client_from_context(context, ods_code, v2=(version == "v2")) +@when("producer '{ods_code}' creates a DocumentReference with values") +def create_post_document_reference_step(context: Context, ods_code: str): + client = producer_client_from_context(context, ods_code) if not context.table: raise ValueError("No document reference data table provided") @@ -182,9 +176,9 @@ def update_post_body_step(context: Context, pointer_id: str): context.response = producer_client.update(doc_ref, pointer_id) -@when("producer {version} '{ods_code}' upserts a DocumentReference with values") -def create_put_document_reference_step(context: Context, ods_code: str, version: str): - client = producer_client_from_context(context, ods_code, v2=(version == "v2")) +@when("producer '{ods_code}' upserts a DocumentReference with values") +def create_put_document_reference_step(context: Context, ods_code: str): + client = producer_client_from_context(context, ods_code) if not context.table: raise ValueError("No document reference data table provided") @@ -221,12 +215,10 @@ def update_put_document_reference_step( @when( - "producer {version} '{ods_code}' requests to delete DocumentReference with id '{doc_ref_id}'" + "producer '{ods_code}' requests to delete DocumentReference with id '{doc_ref_id}'" ) -def delete_document_reference_step( - context: Context, version: str, ods_code: str, doc_ref_id: str -): - client = producer_client_from_context(context, ods_code, v2=(version == "v2")) +def delete_document_reference_step(context: Context, ods_code: str, doc_ref_id: str): + client = producer_client_from_context(context, ods_code) context.response = client.delete(doc_ref_id) @@ -238,11 +230,9 @@ def producer_read_document_reference_step( context.response = client.read(doc_ref_id) -@when("producer {version} '{ods_code}' searches for DocumentReferences with parameters") -def producer_search_document_reference_step( - context: Context, version: str, ods_code: str -): - client = producer_client_from_context(context, ods_code, v2=(version == "v2")) +@when("producer '{ods_code}' searches for DocumentReferences with parameters") +def producer_search_document_reference_step(context: Context, ods_code: str): + client = producer_client_from_context(context, ods_code) if not context.table: raise ValueError("No search query table provided") diff --git a/tests/features/utils/api_client.py b/tests/features/utils/api_client.py index 3b00c5938..4c8f8a8cc 100644 --- a/tests/features/utils/api_client.py +++ b/tests/features/utils/api_client.py @@ -33,11 +33,11 @@ def _config_from_context(context: Context, ods_code: str): ) -def consumer_client_from_context(context: Context, ods_code: str, v2: bool = False): +def consumer_client_from_context(context: Context, ods_code: str): client_config = _config_from_context(context, ods_code) - return ConsumerTestClient(config=client_config, use_v2=v2) + return ConsumerTestClient(config=client_config) -def producer_client_from_context(context: Context, ods_code: str, v2: bool = False): +def producer_client_from_context(context: Context, ods_code: str): client_config = _config_from_context(context, ods_code) - return ProducerTestClient(config=client_config, use_v2=v2) + return ProducerTestClient(config=client_config) diff --git a/tests/utilities/api_clients.py b/tests/utilities/api_clients.py index 5d0136519..7c6a1aacf 100644 --- a/tests/utilities/api_clients.py +++ b/tests/utilities/api_clients.py @@ -73,7 +73,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any: class ConsumerTestClient: - def __init__(self, config: ClientConfig, use_v2: bool = False): + def __init__(self, config: ClientConfig): self.config = config self.api_url = f"{self.config.base_url}consumer{self.config.api_path}" @@ -83,26 +83,19 @@ def __init__(self, config: ClientConfig, use_v2: bool = False): } if self.config.client_cert: - if use_v2: - self.request_headers.update( - { - V2Headers.NHSD_END_USER_ORGANISATION_ODS: self.config.connection_metadata.ods_code, - V2Headers.NHSD_NRL_APP_ID: self.config.connection_metadata.nrl_app_id, - NHSD_CORRELATION_ID_HEADER: "test-correlation-id", - } - ) - else: - connection_metadata = self.config.connection_metadata.model_dump( - by_alias=True - ) - client_rp_details = connection_metadata.pop("client_rp_details") - self.request_headers.update( - { - "NHSD-Connection-Metadata": json.dumps(connection_metadata), - "NHSD-Client-RP-Details": json.dumps(client_rp_details), - "NHSD-Correlation-Id": "test-correlation-id", - } - ) + connection_metadata = self.config.connection_metadata.model_dump( + by_alias=True + ) + client_rp_details = connection_metadata.pop("client_rp_details") + self.request_headers.update( + { + "NHSD-Connection-Metadata": json.dumps(connection_metadata), + "NHSD-Client-RP-Details": json.dumps(client_rp_details), + V2Headers.NHSD_END_USER_ORGANISATION_ODS: self.config.connection_metadata.ods_code, + V2Headers.NHSD_NRL_APP_ID: self.config.connection_metadata.nrl_app_id, + NHSD_CORRELATION_ID_HEADER: "test-correlation-id", + } + ) self.request_headers.update(self.config.custom_headers) @@ -224,7 +217,7 @@ def read_capability_statement(self) -> Response: class ProducerTestClient: - def __init__(self, config: ClientConfig, use_v2: bool = False): + def __init__(self, config: ClientConfig): self.config = config self.api_url = f"{self.config.base_url}producer{self.config.api_path}" @@ -234,26 +227,19 @@ def __init__(self, config: ClientConfig, use_v2: bool = False): } if self.config.client_cert: - if use_v2: - self.request_headers.update( - { - V2Headers.NHSD_END_USER_ORGANISATION_ODS: self.config.connection_metadata.ods_code, - V2Headers.NHSD_NRL_APP_ID: self.config.connection_metadata.nrl_app_id, - NHSD_CORRELATION_ID_HEADER: "test-correlation-id", - } - ) - else: - connection_metadata = self.config.connection_metadata.model_dump( - by_alias=True - ) - client_rp_details = connection_metadata.pop("client_rp_details") - self.request_headers.update( - { - "NHSD-Connection-Metadata": json.dumps(connection_metadata), - "NHSD-Client-RP-Details": json.dumps(client_rp_details), - "NHSD-Correlation-Id": "test-correlation-id", - } - ) + connection_metadata = self.config.connection_metadata.model_dump( + by_alias=True + ) + client_rp_details = connection_metadata.pop("client_rp_details") + self.request_headers.update( + { + "NHSD-Connection-Metadata": json.dumps(connection_metadata), + "NHSD-Client-RP-Details": json.dumps(client_rp_details), + V2Headers.NHSD_END_USER_ORGANISATION_ODS: self.config.connection_metadata.ods_code, + V2Headers.NHSD_NRL_APP_ID: self.config.connection_metadata.nrl_app_id, + NHSD_CORRELATION_ID_HEADER: "test-correlation-id", + } + ) self.request_headers.update(self.config.custom_headers)