Skip to content
10 changes: 8 additions & 2 deletions layer/nrlf/core/authoriser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ def get_pointer_permissions_v2(
ods_code = connection_metadata.ods_code
app_id = connection_metadata.nrl_app_id

key = f"{producer_or_consumer}/{app_id}/{ods_code}.json"
logger.log(LogReference.V2PERMISSIONS011, key=key)
# check for app-wide permissions
app_wide_key = f"{producer_or_consumer}/{app_id}.json"
if path.isfile(f"/opt/python/nrlf_permissions/{app_wide_key}"):
logger.log(LogReference.V2PERMISSIONS011, key=app_wide_key)
key = app_wide_key
else:
key = f"{producer_or_consumer}/{app_id}/{ods_code}.json"
logger.log(LogReference.V2PERMISSIONS011, key=key)

file_path = f"/opt/python/nrlf_permissions/{key}"

Expand Down
31 changes: 30 additions & 1 deletion layer/nrlf/core/tests/test_authoriser.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_authoriser_parse_permission_file_with_permission_file():
new_callable=mock_open,
read_data='{"types": ["http://snomed.info/sct|736253001"]}',
)
def test_authoriser_get_v2_permissions_with_pointer_types(mock_file, mocker):
def test_authoriser_get_v2_permissions_with_org_pointer_types(mock_file, mocker):
spy = mocker.spy(logger, "log")

expected_lookup_key = "producer/ODS123-app-id/ODS123.json"
Expand All @@ -47,6 +47,35 @@ def test_authoriser_get_v2_permissions_with_pointer_types(mock_file, mocker):
spy.assert_called_with(LogReference.V2PERMISSIONS011, key=expected_lookup_key)


@patch(
"builtins.open",
new_callable=mock_open,
read_data='{"types": ["http://snomed.info/sct|736253001"]}',
)
@patch("os.path.isfile")
def test_authoriser_get_v2_permissions_with_app_pointer_types(
mock_isfile, mock_file, mocker
):
spy = mocker.spy(logger, "log")
mock_isfile.return_value = True

expected_lookup_key = "producer/ODS123-app-id.json"
connection_metadata = parse_headers(
create_headers(ods_code="ODS123", nrl_app_id="ODS123-app-id")
)
result = get_pointer_permissions_v2(
connection_metadata=connection_metadata,
request_path="/producer/DocumentReference/_search",
)

mock_file.assert_called_once_with(
f"/opt/python/nrlf_permissions/{expected_lookup_key}"
)
assert result.get("types") == ["http://snomed.info/sct|736253001"]

spy.assert_called_with(LogReference.V2PERMISSIONS011, key=expected_lookup_key)


def test_authoriser_parse_v2_permission_file_with_no_permission_file(mocker):
spy = mocker.spy(logger, "log")
expected_lookup_key = "consumer/NotAnApp/NotFound.json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ Feature: Consumer - searchDocumentReference - Success Scenarios
| url | https://example.org/my-doc.pdf |
| custodian | DK94 |
| author | N64 |
When producer 'DK94' requests to delete DocumentReference with id 'DK94-111-DeleteDocRefTest1'
When producer v1 '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 |
Expand Down
94 changes: 82 additions & 12 deletions tests/features/producer/createDocumentReference-failure.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 1234567890 |
| status | current |
Expand Down Expand Up @@ -212,7 +212,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios
| url | https://example.org/my-doc.pdf |
| custodian | N0TANGY |
| author | HAR1 |
When producer 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9278693472 |
| status | current |
Expand Down Expand Up @@ -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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -292,13 +292,83 @@ Feature: Producer - createDocumentReference - Failure Scenarios
}
"""

# Credentials - type not allowed at application level (v2 permissions)
Scenario: Producer lacks permissions to create specified type at the application level
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
And the application has 'producer' permissions for pointer types:
| system | value |
| http://snomed.info/sct | 736253002 |
When producer v2 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
| type | 887701000000100 |
| category | 734163000 |
| custodian | ANGY1 |
| author | HAR1 |
| url | https://example.org/my-doc.pdf |
Then the response status code is 403
And the response is an OperationOutcome with 1 issue
And the OperationOutcome contains the issue:
"""
{
"severity": "error",
"code": "forbidden",
"details": {
"coding": [
{
"system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode",
"code": "ACCESS DENIED",
"display": "Access has been denied to process this request"
}
]
},
"diagnostics": "Your organisation 'ANGY1' does not have permission to access this resource. Contact the onboarding team."
}
"""

# Credentials - type not allowed at org level (v2 permissions)
Scenario: Producer lacks permissions to create specified type at the org level
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
And the organisation 'ANGY1' is authorised as a Producer for pointer types:
| system | value |
| http://snomed.info/sct | 736253002 |
When producer v2 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
| type | 887701000000100 |
| category | 734163000 |
| custodian | ANGY1 |
| author | HAR1 |
| url | https://example.org/my-doc.pdf |
Then the response status code is 403
And the response is an OperationOutcome with 1 issue
And the OperationOutcome contains the issue:
"""
{
"severity": "error",
"code": "forbidden",
"details": {
"coding": [
{
"system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode",
"code": "ACCESS DENIED",
"display": "Access has been denied to process this request"
}
]
},
"diagnostics": "Your organisation 'ANGY1' does not have permission to access this resource. Contact the onboarding team."
}
"""

Scenario: Invalid status
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
And the organisation 'X26' is authorised to access pointer types:
| system | value |
| http://snomed.info/sct | 1363501000000100 |
| http://snomed.info/sct | 736253002 |
When producer 'X26' creates a DocumentReference with values:
When producer v1 'X26' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| type | 736253002 |
Expand Down Expand Up @@ -335,7 +405,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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -373,7 +443,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios
| system | value |
| http://snomed.info/sct | 1363501000000100 |
| http://snomed.info/sct | 736253002 |
When producer 'X26' creates a DocumentReference with values:
When producer v1 'X26' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -544,7 +614,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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9278693472 |
| status | current |
Expand Down Expand Up @@ -581,7 +651,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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -620,7 +690,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios
| system | value |
| https://nicip.nhs.uk | MAULR |
| https://nicip.nhs.uk | MAXIB |
When producer 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -665,7 +735,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios
| system | value |
| http://snomed.info/sct | 1363501000000100 |
| http://snomed.info/sct | 736253002 |
When producer 'X26' creates a DocumentReference with values:
When producer v1 'X26' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down Expand Up @@ -814,7 +884,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 'ANGY1' creates a DocumentReference with values:
When producer v1 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9999999999 |
| status | current |
Expand Down
Loading
Loading