From a872f4abfd53cd17b9a1a6d1fca2623a1c863268 Mon Sep 17 00:00:00 2001 From: Jack Wainwright Date: Mon, 14 Mar 2022 11:15:47 +0000 Subject: [PATCH 1/7] [ERSSUP-60919]-[RG/AD]-[Added additional requirements to ReferralRequest]-[JW] --- .../responses/WithAdditionalRequirements.json | 198 ++++++++++++++++++ sandbox/src/services/mockResponseProvider.js | 5 + .../schemas/eRS-ReferralRequest.yaml | 21 +- .../Extension-eRS-AdditionalRequirement.yaml | 38 ++++ .../retrieveReferralRequest/200Response.yaml | 4 + specification/e-referrals-service-api.yaml | 14 +- 6 files changed, 266 insertions(+), 14 deletions(-) create mode 100644 sandbox/src/mocks/retrieveReferralRequest/responses/WithAdditionalRequirements.json create mode 100644 specification/components/schemas/extensions/Extension-eRS-AdditionalRequirement.yaml diff --git a/sandbox/src/mocks/retrieveReferralRequest/responses/WithAdditionalRequirements.json b/sandbox/src/mocks/retrieveReferralRequest/responses/WithAdditionalRequirements.json new file mode 100644 index 000000000..f92b6288a --- /dev/null +++ b/sandbox/src/mocks/retrieveReferralRequest/responses/WithAdditionalRequirements.json @@ -0,0 +1,198 @@ +{ + "id": "000000070011", + "meta": { + "versionId": "5", + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-ReferralRequest-1" + ] + }, + "resourceType": "ReferralRequest", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-ClinicalInfoFirstSubmitted-1", + "valueDateTime": "2021-06-11T12:09:08.667Z" + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-ReferralPriority-1", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-Priority-1", + "code": "ROUTINE", + "display": "Routine" + } + ] + } + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-ReferralShortlist-1", + "valueReference": { + "reference": "#shortlist" + } + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-Commissioning-Rule-Org-1", + "valueIdentifier": { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "R69" + } + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-PatientAdditionalRequirement-1", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-AdditionalRequirementType-1", + "code": "ADVOCACY", + "display": "Advocacy" + } + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-PatientAdditionalRequirement-1", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-AdditionalRequirementType-1", + "code": "INTERPRETER", + "display": "Interpreter" + } + }, + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-PatientAdditionalRequirement-1", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-AdditionalRequirementType-1", + "code": "TRANSPORT", + "display": "Transport" + } + } + ], + "contained": [ + { + "id": "serviceSearchCriteria", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-ServiceSearchCriteria-Parameters-1" + ] + }, + "resourceType": "Parameters", + "parameter": [ + { + "name": "priority", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-Priority-1", + "code": "ROUTINE" + } + }, + { + "name": "specialty", + "valueCoding": { + "system": "_baseUrl_/STU3/CodeSystem/SPECIALTY", + "code": "CARDIOLOGY" + } + }, + { + "name": "clinicType", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-ClinicType-1", + "code": "HEART_FAILURE" + } + }, + { + "name": "postcode", + "valueString": "LS1 2TW" + }, + { + "name": "distanceLimit", + "valueUnsignedInt": 123 + }, + { + "name": "ageAndGenderAppropriate", + "valueBoolean": true + } + ] + }, + { + "id": "shortlist", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-Shortlist-List-1" + ] + }, + "resourceType": "List", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-Shortlist-SearchCriteria-1", + "valueReference": { + "reference": "#serviceSearchCriteria" + } + } + ], + "status": "current", + "mode": "snapshot", + "entry": [ + { + "item": { + "identifier": { + "system": "http://fhir.nhs.net/Id/ers-service", + "value": "11002" + }, + "display": "Good Cardiology Business Service" + } + } + ] + }, + { + "id": "DocumentReference-80000", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-DocumentReference-1" + ] + }, + "resourceType": "DocumentReference", + "type": { + "coding": [ + { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-AttachmentType-1", + "code": "REFERRER", + "display": "Referrer" + } + ] + }, + "status": "current", + "indexed": "2021-06-11T12:09:09.459Z", + "description": "referralletter pdf", + "content": [ + { + "attachment": { + "id": "80000", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-AttachedBy-1", + "valueReference": { + "identifier": { + "system": "http://fhir.nhs.net/Id/sds-user-id", + "value": "021600556514" + } + } + } + ], + "contentType": "application/pdf", + "url": "Binary/att-70000-80000", + "size": 6, + "title": "referralletter.pdf", + "creation": "2021-06-11" + } + } + ] + } + ], + "status": "active", + "subject": { + "identifier": { + "system": "http://fhir.nhs.net/Id/nhs-number", + "value": "9912003888" + } + }, + "supportingInfo": [ + { + "reference": "#DocumentReference-80000" + } + ], + "intent": "plan" +} diff --git a/sandbox/src/services/mockResponseProvider.js b/sandbox/src/services/mockResponseProvider.js index 76a773483..574f1ff1a 100644 --- a/sandbox/src/services/mockResponseProvider.js +++ b/sandbox/src/services/mockResponseProvider.js @@ -209,6 +209,11 @@ module.exports = { return { responsePath: 'retrieveReferralRequest/responses/WithRelatedReferral.json', responseCode: 200 } } + // Scenario 7 - ReferralRequest with additional requirements + if (ubrn === '000000070011' && (!version || version === '5')) { + return { responsePath: 'retrieveReferralRequest/responses/WithAdditionalRequirements.json', responseCode: 200 } + } + return {} }, diff --git a/specification/components/schemas/eRS-ReferralRequest.yaml b/specification/components/schemas/eRS-ReferralRequest.yaml index 88fb3ddaa..dae58540c 100644 --- a/specification/components/schemas/eRS-ReferralRequest.yaml +++ b/specification/components/schemas/eRS-ReferralRequest.yaml @@ -55,16 +55,16 @@ properties: type: array nullable: true description: | - | Field | Cardinality | Notes | - | ------------------------------------------ | ----------- | ------------------------------------------ | - | `Extension-eRS-ReferralShortlist` | `1..1` | | - | `Extension-eRS-Commissioning-Rule-Org` | `1..1` | | - | `Extension-eRS-ReferralPriority` | `1..1` | | - | `Extension-eRS-ReferralState` | `1..1` | | - | `Extension-eRS-Appointment` | `0..1` | | - | `Extension-eRS-ClinicalInfoFirstSubmitted` | `0..1` | | - | `Extension-eRS-ClinicalInfoLastUpdated` | `0..1` | | - | `Extension-eRS-Appointment-Reference` | `0..1` | | + | Field | Cardinality | Notes | + | ------------------------------------------ | ----------- | ----------------------------------------------------------------------- | + | `Extension-eRS-ReferralShortlist` | `1..1` | | + | `Extension-eRS-Commissioning-Rule-Org` | `1..1` | | + | `Extension-eRS-ReferralPriority` | `1..1` | | + | `Extension-eRS-Appointment` | `0..1` | | + | `Extension-eRS-ClinicalInfoFirstSubmitted` | `0..1` | | + | `Extension-eRS-ClinicalInfoLastUpdated` | `0..1` | | + | `Extension-eRS-Appointment-Reference` | `0..1` | | + | `Extension-eRS-AdditionalRequirement` | `0..3` | Outlines that this `ReferralRequest` requires an additional requirement | items: anyOf: - $ref: 'extensions/Extension-eRS-ReferralShortlist.yaml' @@ -75,6 +75,7 @@ properties: - $ref: 'extensions/Extension-eRS-ClinicalInfoFirstSubmitted.yaml' - $ref: 'extensions/Extension-eRS-ClinicalInfoLastUpdated.yaml' - $ref: 'extensions/Extension-eRS-Appointment-Reference.yaml' + - $ref: 'extensions/Extension-eRS-AdditionalRequirement.yaml' status: type: string enum: diff --git a/specification/components/schemas/extensions/Extension-eRS-AdditionalRequirement.yaml b/specification/components/schemas/extensions/Extension-eRS-AdditionalRequirement.yaml new file mode 100644 index 000000000..e9bd6358a --- /dev/null +++ b/specification/components/schemas/extensions/Extension-eRS-AdditionalRequirement.yaml @@ -0,0 +1,38 @@ +title: Extension-eRS-AdditionalRequirement +description: Indicates a patient's additional needs that they require when requesting an appointment. This e-RS feature, including the management of additional requirements and booking them, is not currently supported. +type: object +required: + - url + - valueCoding +properties: + url: + type: string + enum: + - 'https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-PatientAdditionalRequirement-1' + example: 'https://fhir.nhs.uk/STU3/StructureDefinition/Extension-eRS-PatientAdditionalRequirement-1' + valueCoding: + type: object + required: + - system + - code + - display + properties: + system: + type: string + enum: + - 'https://fhir.nhs.uk/STU3/CodeSystem/eRS-AdditionalRequirementType-1' + example: 'https://fhir.nhs.uk/STU3/CodeSystem/eRS-AdditionalRequirementType-1' + code: + type: string + enum: + - 'ADVOCACY' + - 'INTERPRETER' + - 'TRANSPORT' + example: 'ADVOCACY' + display: + type: string + enum: + - 'Advocacy' + - 'Interpreter' + - 'Transport' + example: 'Advocacy' diff --git a/specification/components/schemas/responses/retrieveReferralRequest/200Response.yaml b/specification/components/schemas/responses/retrieveReferralRequest/200Response.yaml index ecb0dfeef..817d1b618 100644 --- a/specification/components/schemas/responses/retrieveReferralRequest/200Response.yaml +++ b/specification/components/schemas/responses/retrieveReferralRequest/200Response.yaml @@ -37,3 +37,7 @@ content: summary: `ReferralRequest` with related ReferralRequest value: $ref: '../../../examples/retrieveReferralRequest/responses/WithRelatedReferral.json' + with-additional-requirements: + summary: `ReferralRequest` with additional requirements + value: + $ref: '../../../examples/retrieveReferralRequest/responses/WithAdditionalRequirements.json' diff --git a/specification/e-referrals-service-api.yaml b/specification/e-referrals-service-api.yaml index c7ae48e44..095167000 100644 --- a/specification/e-referrals-service-api.yaml +++ b/specification/e-referrals-service-api.yaml @@ -1093,6 +1093,7 @@ paths: | `ReferralRequest` deferred to service provider for booking | `ubrn`=`000000070003` | | `ReferralRequest` that was converted from an Advice and Guidance Request | `ubrn`=`000000070004` | | `ReferralRequest` with related `ReferralRequest` | `ubrn`=`000000070005` | + | `ReferralRequest` with additional requirements listed | `ubrn`=`000000070011` | summary: A005 - Retrieve referral request operationId: a005-retrieve-referral-request @@ -1160,6 +1161,7 @@ paths: | `ReferralRequest` deferred to service provider for booking | `ubrn`=`000000070003`, `version`=`5` | | `ReferralRequest` that was converted from an Advice and Guidance Request | `ubrn`=`000000070004`, `version`=`5` | | `ReferralRequest` with related `ReferralRequest` | `ubrn`=`000000070005`, `version`=`5` | + | `ReferralRequest` with additional requirements listed | `ubrn`=`000000070011`, `version`=`5` | summary: A005 - Retrieve referral request (versioned) operationId: a005-retrieve-referral-request-versioned @@ -2863,13 +2865,15 @@ paths: A patient can request assistance at a service (e.g. a translator, transport or advocacy) when a shortlist is created within the e-RS web application, meaning that all services shortlisted would support the patient's additional requirements to attend. - The e-RS APIs do not currently support patients' additional requirements so you can neither specify services that support patients' additional requirements, view existing additional requirements for a patient, nor arrange additional requirements for a patient. + The e-RS APIs do not currently support patients' additional requirements so you can neither specify services that support patients' additional requirements, arrange additional requirements for a patient, or view comments associated with the request for additional requirements. + + You must consider if you are fully meeting the patient's additional requirement needs if there are additional requirements associated with the referral. If you do not know whether the patient has an existing additional requirement need and the referral may have been shortlisted within the e-RS web application, be mindful that if you chose to amend the shortlist via changing the services, you could remove this patient need. If you are changing services to send the patient to a triage service, the triaging service will not support additional requirements but will need to consider if the patient has any additional requirements as part of their decision for future care. - You can view additional requirements on a referral via the e-RS web application. + You can view additional requirements on a referral via the e-RS web application or by fetching [[HYPERLINK_A005]]. ## Supported security patterns - Healthcare worker, user-restricted access @@ -2962,13 +2966,15 @@ paths: A patient can request assistance at a service (e.g. a translator, transport or advocacy) when a shortlist is created within the e-RS web application, meaning that all services shortlisted would support the patient's additional requirements to attend. - The e-RS APIs do not currently support patients' additional requirements so you can neither specify services that support patients' additional requirements, view existing additional requirements for a patient, nor arrange additional requirements for a patient. + The e-RS APIs do not currently support patients' additional requirements so you can neither specify services that support patients' additional requirements, arrange additional requirements for a patient, or view comments associated with the request for additional requirements. + + You must consider if you are fully meeting the patient's additional requirement needs if there are additional requirements associated with the referral. If you do not know whether the patient has an existing additional requirement need and the referral may have been shortlisted within the e-RS web application, be mindful that if you chose to amend the shortlist via changing the services, you could remove this patient need. If you are changing services to send the patient to a triage service, the triaging service will not support additional requirements but will need to consider if the patient has any additional requirements as part of their decision for future care. - You can view additional requirements on a referral via the e-RS web application. + You can view additional requirements on a referral via the e-RS web application or by fetching [[HYPERLINK_A005]]. ## Supported security patterns - Healthcare worker, user-restricted access From f5cc7f3ae9613df77a339a4359179ae1b4868979 Mon Sep 17 00:00:00 2001 From: Francisco Videira Date: Wed, 13 Apr 2022 10:40:32 +0000 Subject: [PATCH 2/7] [ERSSUP-61354]-[RG]-[Remove support for HTML and HTM uploads via A020]-[FV] --- .../src/routes/uploadFileToDocumentStore.js | 2 +- ...aml => FileContentTypeSchemaDownload.yaml} | 0 .../file/FileContentTypeSchemaUpload.yaml | 43 +++++++++++++++++++ ...yaml => ContentTypeAttachmentsUpload.yaml} | 1 - ...ml => ContentTypeAttachmentsDownload.yaml} | 0 .../retrieveAttachment/200Response.yaml | 6 +-- specification/e-referrals-service-api.yaml | 5 +-- 7 files changed, 48 insertions(+), 9 deletions(-) rename specification/components/schemas/file/{FileContentTypeSchema.yaml => FileContentTypeSchemaDownload.yaml} (100%) create mode 100644 specification/components/schemas/file/FileContentTypeSchemaUpload.yaml rename specification/components/schemas/headers/request/{ContentTypeFileUpload.yaml => ContentTypeAttachmentsUpload.yaml} (96%) rename specification/components/schemas/headers/response/{ContentTypeFileUpload.yaml => ContentTypeAttachmentsDownload.yaml} (100%) diff --git a/sandbox/src/routes/uploadFileToDocumentStore.js b/sandbox/src/routes/uploadFileToDocumentStore.js index c9b2552fc..7d5250b45 100644 --- a/sandbox/src/routes/uploadFileToDocumentStore.js +++ b/sandbox/src/routes/uploadFileToDocumentStore.js @@ -12,7 +12,7 @@ module.exports = [ maxBytes: 5242880, //5MB parse: false, // https://nhsd-jira.digital.nhs.uk/browse/ERSSUP-9016 lists currently supported file types - allow: ['text/plain', 'text/html', 'application/pdf', 'text/xml', 'text/rtf', + allow: ['text/plain', 'application/pdf', 'text/xml', 'text/rtf', 'audio/basic', 'audio/mpeg', 'image/png', 'image/gif', 'image/jpeg', 'image/tiff', 'video/mpeg', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/dicom'] diff --git a/specification/components/schemas/file/FileContentTypeSchema.yaml b/specification/components/schemas/file/FileContentTypeSchemaDownload.yaml similarity index 100% rename from specification/components/schemas/file/FileContentTypeSchema.yaml rename to specification/components/schemas/file/FileContentTypeSchemaDownload.yaml diff --git a/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml b/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml new file mode 100644 index 000000000..ae314062a --- /dev/null +++ b/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml @@ -0,0 +1,43 @@ +text/plain: + schema: + $ref: 'StringBinarySchema.yaml' + example: 'This is some example text.' +application/pdf: + schema: + $ref: 'StringBinarySchema.yaml' +text/xml: + schema: + $ref: 'StringBinarySchema.yaml' +text/rtf: + schema: + $ref: 'StringBinarySchema.yaml' +audio/basic: + schema: + $ref: 'StringBinarySchema.yaml' +audio/mpeg: + schema: + $ref: 'StringBinarySchema.yaml' +image/png: + schema: + $ref: 'StringBinarySchema.yaml' +image/gif: + schema: + $ref: 'StringBinarySchema.yaml' +image/jpeg: + schema: + $ref: 'StringBinarySchema.yaml' +image/tiff: + schema: + $ref: 'StringBinarySchema.yaml' +video/mpeg: + schema: + $ref: 'StringBinarySchema.yaml' +application/msword: + schema: + $ref: 'StringBinarySchema.yaml' +application/vnd.openxmlformats-officedocument.wordprocessingml.document: + schema: + $ref: 'StringBinarySchema.yaml' +application/dicom: + schema: + $ref: 'StringBinarySchema.yaml' diff --git a/specification/components/schemas/headers/request/ContentTypeFileUpload.yaml b/specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml similarity index 96% rename from specification/components/schemas/headers/request/ContentTypeFileUpload.yaml rename to specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml index 7282436af..8186f1dd0 100644 --- a/specification/components/schemas/headers/request/ContentTypeFileUpload.yaml +++ b/specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml @@ -7,7 +7,6 @@ schema: type: string enum: - 'text/plain' - - 'text/html' - 'application/pdf' - 'text/xml' - 'text/rtf' diff --git a/specification/components/schemas/headers/response/ContentTypeFileUpload.yaml b/specification/components/schemas/headers/response/ContentTypeAttachmentsDownload.yaml similarity index 100% rename from specification/components/schemas/headers/response/ContentTypeFileUpload.yaml rename to specification/components/schemas/headers/response/ContentTypeAttachmentsDownload.yaml diff --git a/specification/components/schemas/responses/retrieveAttachment/200Response.yaml b/specification/components/schemas/responses/retrieveAttachment/200Response.yaml index 6c0e336f5..19386c1e2 100644 --- a/specification/components/schemas/responses/retrieveAttachment/200Response.yaml +++ b/specification/components/schemas/responses/retrieveAttachment/200Response.yaml @@ -9,8 +9,6 @@ headers: Content-Length: $ref: '../../headers/response/ContentLength.yaml' Content-Type: - $ref: '../../headers/response/ContentTypeFileUpload.yaml' + $ref: '../../headers/response/ContentTypeAttachmentsDownload.yaml' content: - $ref: '../../file/FileContentTypeSchema.yaml' - - \ No newline at end of file + $ref: '../../file/FileContentTypeSchemaDownload.yaml' diff --git a/specification/e-referrals-service-api.yaml b/specification/e-referrals-service-api.yaml index 095167000..f94c3e0d0 100644 --- a/specification/e-referrals-service-api.yaml +++ b/specification/e-referrals-service-api.yaml @@ -808,7 +808,6 @@ paths: | File type | File extension(s) | | ------------------ | --------------------------- | | Plain Text | `.txt` | - | HTML Text | `.html,` `.htm` | | PDF | `.pdf` | | XML Text | `.xml` | | RTF Text | `.rtf`, `.rtx` | @@ -845,7 +844,7 @@ paths: summary: A020 - Upload file to document store operationId: a020-upload-file-to-document-store parameters: - - $ref: 'components/schemas/headers/request/ContentTypeFileUpload.yaml' + - $ref: 'components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml' - $ref: 'components/schemas/headers/request/BearerAuthorization.yaml' - $ref: 'components/schemas/headers/request/OdsCode.yaml' - $ref: 'components/schemas/headers/request/BusinessFunction.yaml' @@ -856,7 +855,7 @@ paths: requestBody: required: true content: - $ref: 'components/schemas/file/FileContentTypeSchema.yaml' + $ref: 'components/schemas/file/FileContentTypeSchemaUpload.yaml' responses: '201': $ref: 'components/schemas/responses/uploadFileToDocumentStore/201Response.yaml' From 906def0b9e1249d7f704606d19a2f1f02e86c36d Mon Sep 17 00:00:00 2001 From: Francisco Videira Date: Thu, 5 May 2022 15:20:05 +0000 Subject: [PATCH 3/7] [ERSSUP-61927]-[RG]-[Revert ERSSUP-61354 Remove support for HTML and HTM uploads via A020]-[FV] This reverts commit f5cc7f3ae9613df77a339a4359179ae1b4868979. --- .../src/routes/uploadFileToDocumentStore.js | 2 +- ...wnload.yaml => FileContentTypeSchema.yaml} | 0 .../file/FileContentTypeSchemaUpload.yaml | 43 ------------------- ...Upload.yaml => ContentTypeFileUpload.yaml} | 1 + ...wnload.yaml => ContentTypeFileUpload.yaml} | 0 .../retrieveAttachment/200Response.yaml | 6 ++- specification/e-referrals-service-api.yaml | 5 ++- 7 files changed, 9 insertions(+), 48 deletions(-) rename specification/components/schemas/file/{FileContentTypeSchemaDownload.yaml => FileContentTypeSchema.yaml} (100%) delete mode 100644 specification/components/schemas/file/FileContentTypeSchemaUpload.yaml rename specification/components/schemas/headers/request/{ContentTypeAttachmentsUpload.yaml => ContentTypeFileUpload.yaml} (96%) rename specification/components/schemas/headers/response/{ContentTypeAttachmentsDownload.yaml => ContentTypeFileUpload.yaml} (100%) diff --git a/sandbox/src/routes/uploadFileToDocumentStore.js b/sandbox/src/routes/uploadFileToDocumentStore.js index 7d5250b45..c9b2552fc 100644 --- a/sandbox/src/routes/uploadFileToDocumentStore.js +++ b/sandbox/src/routes/uploadFileToDocumentStore.js @@ -12,7 +12,7 @@ module.exports = [ maxBytes: 5242880, //5MB parse: false, // https://nhsd-jira.digital.nhs.uk/browse/ERSSUP-9016 lists currently supported file types - allow: ['text/plain', 'application/pdf', 'text/xml', 'text/rtf', + allow: ['text/plain', 'text/html', 'application/pdf', 'text/xml', 'text/rtf', 'audio/basic', 'audio/mpeg', 'image/png', 'image/gif', 'image/jpeg', 'image/tiff', 'video/mpeg', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/dicom'] diff --git a/specification/components/schemas/file/FileContentTypeSchemaDownload.yaml b/specification/components/schemas/file/FileContentTypeSchema.yaml similarity index 100% rename from specification/components/schemas/file/FileContentTypeSchemaDownload.yaml rename to specification/components/schemas/file/FileContentTypeSchema.yaml diff --git a/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml b/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml deleted file mode 100644 index ae314062a..000000000 --- a/specification/components/schemas/file/FileContentTypeSchemaUpload.yaml +++ /dev/null @@ -1,43 +0,0 @@ -text/plain: - schema: - $ref: 'StringBinarySchema.yaml' - example: 'This is some example text.' -application/pdf: - schema: - $ref: 'StringBinarySchema.yaml' -text/xml: - schema: - $ref: 'StringBinarySchema.yaml' -text/rtf: - schema: - $ref: 'StringBinarySchema.yaml' -audio/basic: - schema: - $ref: 'StringBinarySchema.yaml' -audio/mpeg: - schema: - $ref: 'StringBinarySchema.yaml' -image/png: - schema: - $ref: 'StringBinarySchema.yaml' -image/gif: - schema: - $ref: 'StringBinarySchema.yaml' -image/jpeg: - schema: - $ref: 'StringBinarySchema.yaml' -image/tiff: - schema: - $ref: 'StringBinarySchema.yaml' -video/mpeg: - schema: - $ref: 'StringBinarySchema.yaml' -application/msword: - schema: - $ref: 'StringBinarySchema.yaml' -application/vnd.openxmlformats-officedocument.wordprocessingml.document: - schema: - $ref: 'StringBinarySchema.yaml' -application/dicom: - schema: - $ref: 'StringBinarySchema.yaml' diff --git a/specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml b/specification/components/schemas/headers/request/ContentTypeFileUpload.yaml similarity index 96% rename from specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml rename to specification/components/schemas/headers/request/ContentTypeFileUpload.yaml index 8186f1dd0..7282436af 100644 --- a/specification/components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml +++ b/specification/components/schemas/headers/request/ContentTypeFileUpload.yaml @@ -7,6 +7,7 @@ schema: type: string enum: - 'text/plain' + - 'text/html' - 'application/pdf' - 'text/xml' - 'text/rtf' diff --git a/specification/components/schemas/headers/response/ContentTypeAttachmentsDownload.yaml b/specification/components/schemas/headers/response/ContentTypeFileUpload.yaml similarity index 100% rename from specification/components/schemas/headers/response/ContentTypeAttachmentsDownload.yaml rename to specification/components/schemas/headers/response/ContentTypeFileUpload.yaml diff --git a/specification/components/schemas/responses/retrieveAttachment/200Response.yaml b/specification/components/schemas/responses/retrieveAttachment/200Response.yaml index 19386c1e2..6c0e336f5 100644 --- a/specification/components/schemas/responses/retrieveAttachment/200Response.yaml +++ b/specification/components/schemas/responses/retrieveAttachment/200Response.yaml @@ -9,6 +9,8 @@ headers: Content-Length: $ref: '../../headers/response/ContentLength.yaml' Content-Type: - $ref: '../../headers/response/ContentTypeAttachmentsDownload.yaml' + $ref: '../../headers/response/ContentTypeFileUpload.yaml' content: - $ref: '../../file/FileContentTypeSchemaDownload.yaml' + $ref: '../../file/FileContentTypeSchema.yaml' + + \ No newline at end of file diff --git a/specification/e-referrals-service-api.yaml b/specification/e-referrals-service-api.yaml index f94c3e0d0..095167000 100644 --- a/specification/e-referrals-service-api.yaml +++ b/specification/e-referrals-service-api.yaml @@ -808,6 +808,7 @@ paths: | File type | File extension(s) | | ------------------ | --------------------------- | | Plain Text | `.txt` | + | HTML Text | `.html,` `.htm` | | PDF | `.pdf` | | XML Text | `.xml` | | RTF Text | `.rtf`, `.rtx` | @@ -844,7 +845,7 @@ paths: summary: A020 - Upload file to document store operationId: a020-upload-file-to-document-store parameters: - - $ref: 'components/schemas/headers/request/ContentTypeAttachmentsUpload.yaml' + - $ref: 'components/schemas/headers/request/ContentTypeFileUpload.yaml' - $ref: 'components/schemas/headers/request/BearerAuthorization.yaml' - $ref: 'components/schemas/headers/request/OdsCode.yaml' - $ref: 'components/schemas/headers/request/BusinessFunction.yaml' @@ -855,7 +856,7 @@ paths: requestBody: required: true content: - $ref: 'components/schemas/file/FileContentTypeSchemaUpload.yaml' + $ref: 'components/schemas/file/FileContentTypeSchema.yaml' responses: '201': $ref: 'components/schemas/responses/uploadFileToDocumentStore/201Response.yaml' From 781e72cfadbca6b45162765f428783c51527784b Mon Sep 17 00:00:00 2001 From: nhsd-hubert-raich Date: Tue, 10 Aug 2021 14:43:50 +0000 Subject: [PATCH 4/7] [ERSSUP-56595]-[]-[Discovery APIGEE configuration for ERSSUP-56026 APIM Client makes an Application-restricted Open API call to a read-only e-RS Endpoint]-[HR] --- .../AssignMessage.AddIssuerHeader.xml | 9 -- ....Remove.x-ers-business-function-header.xml | 10 ++ ...gnMessage.Remove.x-ers-ods-code-header.xml | 10 ++ ...usiness-function-header-app-restricted.xml | 9 ++ ...hsd-ers-ods-code-header-app-restricted.xml | 9 ++ ...et.x-ers-user-id-header-app-restricted.xml | 9 ++ ....x-ers-user-id-header-user-restricted.xml} | 11 +-- ...er.xml => AssignMessage.SetAsidHeader.xml} | 12 +-- .../policies/OAuthV2.VerifyAccessToken.xml | 3 +- proxies/live/apiproxy/targets/ers-target.xml | 95 ++++++++++++++++++- .../AssignMessage.AddIssuerHeader.xml | 9 -- .../AssignMessage.AddUserIdHeader.xml | 9 -- 12 files changed, 147 insertions(+), 48 deletions(-) delete mode 100644 proxies/live/apiproxy/policies/AssignMessage.AddIssuerHeader.xml create mode 100644 proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml create mode 100644 proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml create mode 100644 proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml create mode 100644 proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml create mode 100644 proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml rename proxies/live/apiproxy/policies/{AssignMessage.RemoveAndAddUserIdHeader.xml => AssignMessage.Set.x-ers-user-id-header-user-restricted.xml} (64%) rename proxies/live/apiproxy/policies/{AssignMessage.RemoveAndAddAsidHeader.xml => AssignMessage.SetAsidHeader.xml} (56%) delete mode 100644 proxies/sandbox/apiproxy/policies/AssignMessage.AddIssuerHeader.xml delete mode 100644 proxies/sandbox/apiproxy/policies/AssignMessage.AddUserIdHeader.xml diff --git a/proxies/live/apiproxy/policies/AssignMessage.AddIssuerHeader.xml b/proxies/live/apiproxy/policies/AssignMessage.AddIssuerHeader.xml deleted file mode 100644 index f85399509..000000000 --- a/proxies/live/apiproxy/policies/AssignMessage.AddIssuerHeader.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - -
{accesstoken.id_token-issuer}
-
-
- false - -
diff --git a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml new file mode 100644 index 000000000..7290b1816 --- /dev/null +++ b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml @@ -0,0 +1,10 @@ + + + + +
+ + + true + + diff --git a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml new file mode 100644 index 000000000..90be5ba64 --- /dev/null +++ b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml @@ -0,0 +1,10 @@ + + + + +
+ + + true + + diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml new file mode 100644 index 000000000..0f7962bf9 --- /dev/null +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml @@ -0,0 +1,9 @@ + + + +
AUTHORISED_APPLICATION
+
+
+ false + +
diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml new file mode 100644 index 000000000..ea200911a --- /dev/null +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml @@ -0,0 +1,9 @@ + + + +
{app.app-restricted-ods-code}
+
+
+ false + +
diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml new file mode 100644 index 000000000..0e7766bde --- /dev/null +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml @@ -0,0 +1,9 @@ + + + +
{app.app-restricted-user-id}
+
+
+ false + +
diff --git a/proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddUserIdHeader.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-user-restricted.xml similarity index 64% rename from proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddUserIdHeader.xml rename to proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-user-restricted.xml index 9a2af2905..7a8ebc1f1 100644 --- a/proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddUserIdHeader.xml +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-user-restricted.xml @@ -1,14 +1,9 @@ - - - -
- - - + +
{accesstoken.id_token-subject}
-
+ false diff --git a/proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddAsidHeader.xml b/proxies/live/apiproxy/policies/AssignMessage.SetAsidHeader.xml similarity index 56% rename from proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddAsidHeader.xml rename to proxies/live/apiproxy/policies/AssignMessage.SetAsidHeader.xml index 87ed3b097..03ef30ec6 100644 --- a/proxies/live/apiproxy/policies/AssignMessage.RemoveAndAddAsidHeader.xml +++ b/proxies/live/apiproxy/policies/AssignMessage.SetAsidHeader.xml @@ -1,15 +1,9 @@ - - - - -
- - - + +
{private.apigee.NHSD-ASID}
-
+ false diff --git a/proxies/live/apiproxy/policies/OAuthV2.VerifyAccessToken.xml b/proxies/live/apiproxy/policies/OAuthV2.VerifyAccessToken.xml index 3ffc12e3d..bfe7f192c 100644 --- a/proxies/live/apiproxy/policies/OAuthV2.VerifyAccessToken.xml +++ b/proxies/live/apiproxy/policies/OAuthV2.VerifyAccessToken.xml @@ -1,5 +1,4 @@ VerifyAccessToken - - urn:nhsd:apim:user-nhs-id:aal3:e-referrals-service-api + urn:nhsd:apim:app:level3:e-referrals-service-api urn:nhsd:apim:user-nhs-id:aal3:e-referrals-service-api diff --git a/proxies/live/apiproxy/targets/ers-target.xml b/proxies/live/apiproxy/targets/ers-target.xml index 0d60f77cf..29a838b7c 100644 --- a/proxies/live/apiproxy/targets/ers-target.xml +++ b/proxies/live/apiproxy/targets/ers-target.xml @@ -59,7 +59,8 @@ (accesstoken.auth_type == "user") - + + RaiseFault.403Forbidden (request.header.nhsd-ers-business-function == "AUTHORISED_APPLICATION") @@ -94,6 +95,9 @@ + + + (accesstoken.auth_type == "app") @@ -103,6 +107,92 @@ +======= + + + + RaiseFault.403Forbidden + (request.header.nhsd-ers-business-function == "AUTHORISED_APPLICATION") + + + AssignMessage.Swap.NHSD-eRS-On-Behalf-Of-User-ID + (request.header.NHSD-eRS-On-Behalf-Of-User-ID ~~ ".+") + + + AssignMessage.Swap.nhsd-end-user-organisation-ods + (request.header.nhsd-end-user-organisation-ods ~~ ".+") + + + AssignMessage.Swap.nhsd-ers-business-function + (request.header.nhsd-ers-business-function ~~ ".+") + + + AssignMessage.Swap.nhsd-ers-comm-rule-org + (request.header.nhsd-ers-comm-rule-org ~~ ".+") + + + AssignMessage.Swap.nhsd-ers-file-name + (request.header.nhsd-ers-file-name ~~ ".+") + + + AssignMessage.Swap.nhsd-ers-referral-id + (request.header.nhsd-ers-referral-id ~~ ".+") + + + AssignMessage.Remove.x-request-id-header + + {% if ALLOW_ECHO_TARGET | default(false) == true %} + AssignMessage.SetEchoTarget + (request.header.echo) + {% endif %} + + + AssignMessage.Swap.CorrelationHeader + + + + + + (accesstoken.auth_type == "app") + + + + RaiseFault.400BadRequest + (request.header.nhsd-ers-ods-code != null) + + + RaiseFault.400BadRequest + (request.header.nhsd-ers-business-function != null) + + + AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted + + + AssignMessage.Set.nhsd-ers-business-function-header-app-restricted + + + AssignMessage.Set.x-ers-user-id-header-app-restricted + + + AssignMessage.Swap.nhsd-end-user-organisation-ods + (request.header.nhsd-end-user-organisation-ods ~~ ".+") + + + AssignMessage.Swap.nhsd-ers-business-function + (request.header.nhsd-ers-business-function ~~ ".+") + + + AssignMessage.Remove.x-request-id-header + + + + AssignMessage.Swap.CorrelationHeader + + + @@ -115,7 +205,8 @@ - {% if '--ft-' in (ERS_TARGET_SERVER | default('e-referrals-service-api')) %} ref://e-referral-service-ca {% endif %} true + {% if '--ft-' in (ERS_TARGET_SERVER | default('e-referrals-service-api')) %} ref://e-referral-service-ca {% endif %} true + diff --git a/proxies/sandbox/apiproxy/policies/AssignMessage.AddIssuerHeader.xml b/proxies/sandbox/apiproxy/policies/AssignMessage.AddIssuerHeader.xml deleted file mode 100644 index 47c397344..000000000 --- a/proxies/sandbox/apiproxy/policies/AssignMessage.AddIssuerHeader.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - -
{jwt.DecodeJWT.FromJWTHeader.claim.issuer}
-
-
- false - -
diff --git a/proxies/sandbox/apiproxy/policies/AssignMessage.AddUserIdHeader.xml b/proxies/sandbox/apiproxy/policies/AssignMessage.AddUserIdHeader.xml deleted file mode 100644 index 699a07bd9..000000000 --- a/proxies/sandbox/apiproxy/policies/AssignMessage.AddUserIdHeader.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - -
{jwt.DecodeJWT.FromJWTHeader.claim.subject}
-
-
- false - -
From c622b5066ad49705a0eaf483be037a4d51573dab Mon Sep 17 00:00:00 2001 From: Jamie Green Date: Thu, 16 Dec 2021 09:03:05 +0000 Subject: [PATCH 5/7] [ERSSUP-58836]-[JW]-[Add app-restricted product]-[JG] --- manifest_template.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/manifest_template.yml b/manifest_template.yml index 377dc41d6..f08c78a2e 100644 --- a/manifest_template.yml +++ b/manifest_template.yml @@ -48,7 +48,12 @@ ACCESS_MODES: scopes: ['urn:nhsd:apim:user-nhs-id:aal3:e-referrals-service-api'] requireCallbackUrl: true description: User restricted - + - name: application-restricted + nameSuffix: -application-restricted + displayName: Application Restricted + scopes: ['urn:nhsd:apim:app:level3:e-referrals-service-api'] + requireCallbackUrl: false + description: Application Restricted --- From 9d76b8ba5b0c973e2796f5a3c229df0904191a1b Mon Sep 17 00:00:00 2001 From: Jamie Green Date: Thu, 14 Apr 2022 14:40:56 +0000 Subject: [PATCH 6/7] [ERSSUP-60546]-[AC]-[Allow App restricted. Includes updates for App restricted headers and ITs]-[JG] --- azure/templates/ers-integration-tests.yml | 3 +- azure/templates/run-tests.yml | 3 +- ....Remove.x-ers-business-function-header.xml | 10 -- ...gnMessage.Remove.x-ers-ods-code-header.xml | 10 -- ...usiness-function-header-app-restricted.xml | 14 +- ...hsd-ers-ods-code-header-app-restricted.xml | 14 +- ...et.x-ers-user-id-header-app-restricted.xml | 14 +- proxies/live/apiproxy/targets/ers-target.xml | 116 +++--------- tests/asserts.py | 48 +++++ tests/conftest.py | 168 +++++++++++++++--- tests/data.py | 2 - tests/integration/test_app_restricted.py | 166 ++++++++++++++--- tests/integration/test_headers.py | 134 +++++++------- tests/sandbox/test_create_referral.py | 2 +- tests/sandbox/test_get_codesystem.py | 2 +- 15 files changed, 447 insertions(+), 259 deletions(-) delete mode 100644 proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml delete mode 100644 proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml diff --git a/azure/templates/ers-integration-tests.yml b/azure/templates/ers-integration-tests.yml index 2bacf644d..6e40a5907 100644 --- a/azure/templates/ers-integration-tests.yml +++ b/azure/templates/ers-integration-tests.yml @@ -5,7 +5,8 @@ steps: export ERS_TEST_ASID="$(ers-testing-asid)" export OAUTH_PROXY="oauth2-mock" export OAUTH_BASE_URI="https://$(ENVIRONMENT).api.service.nhs.uk" - + export JWT_PRIVATE_KEY_ABSOLUTE_PATH="$(Pipeline.Workspace)/secrets/$(JWT_TESTING_PRIVATE_KEY)" + poetry run pytest -v tests/integration --junitxml=tests/ers-test-integration-report.xml displayName: Run eRS integration tests workingDirectory: "$(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME)" diff --git a/azure/templates/run-tests.yml b/azure/templates/run-tests.yml index d360a913c..8d7fc5830 100644 --- a/azure/templates/run-tests.yml +++ b/azure/templates/run-tests.yml @@ -25,7 +25,8 @@ steps: - template: "azure/components/get-aws-secrets-and-ssm-params.yml@common" parameters: - secret_file_ids: [] + secret_file_ids: + - ptl/app-credentials/jwt_testing/non-prod/JWT_TESTING_PRIVATE_KEY config_ids: [] secret_ids: - ptl/api-deployment/e-referrals-service/ers-testing-asid diff --git a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml deleted file mode 100644 index 7290b1816..000000000 --- a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-business-function-header.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -
- - - true - - diff --git a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml b/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml deleted file mode 100644 index 90be5ba64..000000000 --- a/proxies/live/apiproxy/policies/AssignMessage.Remove.x-ers-ods-code-header.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -
- - - true - - diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml index 0f7962bf9..f21e92509 100644 --- a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-business-function-header-app-restricted.xml @@ -1,9 +1,9 @@ - - -
AUTHORISED_APPLICATION
-
-
- false - + + +
AUTHORISED_APPLICATION
+
+
+ false +
diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml index ea200911a..0f91d0854 100644 --- a/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted.xml @@ -1,9 +1,9 @@ - - -
{app.app-restricted-ods-code}
-
-
- false - + + +
{app.app-restricted-ods-code}
+
+
+ false +
diff --git a/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml index 0e7766bde..16b2654ce 100644 --- a/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml +++ b/proxies/live/apiproxy/policies/AssignMessage.Set.x-ers-user-id-header-app-restricted.xml @@ -1,9 +1,9 @@ - - -
{app.app-restricted-user-id}
-
-
- false - + + +
{app.app-restricted-user-id}
+
+
+ false +
diff --git a/proxies/live/apiproxy/targets/ers-target.xml b/proxies/live/apiproxy/targets/ers-target.xml index 29a838b7c..350b167cc 100644 --- a/proxies/live/apiproxy/targets/ers-target.xml +++ b/proxies/live/apiproxy/targets/ers-target.xml @@ -34,7 +34,7 @@ AssignMessage.PopulateAsidFromApp - AssignMessage.RemoveAndAddAsidHeader + AssignMessage.SetAsidHeader AssignMessage.AddBaseUrlHeader @@ -59,12 +59,11 @@ (accesstoken.auth_type == "user") - - + RaiseFault.403Forbidden (request.header.nhsd-ers-business-function == "AUTHORISED_APPLICATION") - AssignMessage.RemoveAndAddUserIdHeader + AssignMessage.Set.x-ers-user-id-header-user-restricted AssignMessage.Swap.NHSD-eRS-On-Behalf-Of-User-ID (request.header.NHSD-eRS-On-Behalf-Of-User-ID ~~ ".+") @@ -90,109 +89,39 @@ (request.header.echo) {% endif %} + The Swapping of the Request Headers converts X-Correlation-ID to NHSD-Correlation-ID before sending to backend. --> AssignMessage.Swap.CorrelationHeader - - - - (accesstoken.auth_type == "app") - - + RaiseFault.403Forbidden - - - -======= - - - + (request.header.x-ers-ods-code) + RaiseFault.403Forbidden - (request.header.nhsd-ers-business-function == "AUTHORISED_APPLICATION") - - - AssignMessage.Swap.NHSD-eRS-On-Behalf-Of-User-ID - (request.header.NHSD-eRS-On-Behalf-Of-User-ID ~~ ".+") - - - AssignMessage.Swap.nhsd-end-user-organisation-ods - (request.header.nhsd-end-user-organisation-ods ~~ ".+") - - - AssignMessage.Swap.nhsd-ers-business-function - (request.header.nhsd-ers-business-function ~~ ".+") - - - AssignMessage.Swap.nhsd-ers-comm-rule-org - (request.header.nhsd-ers-comm-rule-org ~~ ".+") - - - AssignMessage.Swap.nhsd-ers-file-name - (request.header.nhsd-ers-file-name ~~ ".+") - - - AssignMessage.Swap.nhsd-ers-referral-id - (request.header.nhsd-ers-referral-id ~~ ".+") - - - AssignMessage.Remove.x-request-id-header - - {% if ALLOW_ECHO_TARGET | default(false) == true %} - AssignMessage.SetEchoTarget - (request.header.echo) - {% endif %} - - - AssignMessage.Swap.CorrelationHeader - - - - - - (accesstoken.auth_type == "app") - - - - RaiseFault.400BadRequest - (request.header.nhsd-ers-ods-code != null) - - - RaiseFault.400BadRequest - (request.header.nhsd-ers-business-function != null) - - + (request.header.x-ers-business-function) + + RaiseFault.403Forbidden + (request.header.x-ers-user-id) + AssignMessage.Set.nhsd-ers-ods-code-header-app-restricted - - + AssignMessage.Set.nhsd-ers-business-function-header-app-restricted - - + AssignMessage.Set.x-ers-user-id-header-app-restricted - - - AssignMessage.Swap.nhsd-end-user-organisation-ods - (request.header.nhsd-end-user-organisation-ods ~~ ".+") - - - AssignMessage.Swap.nhsd-ers-business-function - (request.header.nhsd-ers-business-function ~~ ".+") - - + AssignMessage.Remove.x-request-id-header - - + {% if ALLOW_ECHO_TARGET | default(false) == true %} + AssignMessage.SetEchoTarget + (request.header.echo) + {% endif %} AssignMessage.Swap.CorrelationHeader - - - + + @@ -205,8 +134,7 @@ - {% if '--ft-' in (ERS_TARGET_SERVER | default('e-referrals-service-api')) %} ref://e-referral-service-ca {% endif %} true - + {% if '--ft-' in (ERS_TARGET_SERVER | default('e-referrals-service-api')) %} ref://e-referral-service-ca {% endif %} true diff --git a/tests/asserts.py b/tests/asserts.py index 684568a19..ff3219056 100644 --- a/tests/asserts.py +++ b/tests/asserts.py @@ -2,6 +2,7 @@ from typing import Dict from pytest_check import check from requests import Response +from data import RenamedHeader # Headers which are expected for all requests _generic_headers = { @@ -24,6 +25,9 @@ # Headers which should be excluded from validation entirely. _excluded_headers = ["Keep-Alive"] +_HEADER_REQUEST_ID = "x-request-id" +_HEADER_ERS_TRANSACTION_ID = "X_ERS_TRANSACTION_ID" + def assert_status_code(expected: int, actual: int): """Assert that supplied status code is as expected""" @@ -85,3 +89,47 @@ def _filter_header(header: str) -> bool: def _lower_keys(dict: Dict[str, str]) -> Dict[str, str]: return {key.lower(): value for key, value in dict.items()} + + +def assert_ok_response(response: Response, expected_correlation_id: int): + # Verify the status + assert ( + response.status_code == 200 + ), "Expected a 200 when accesing the api but got " + (str)(response.status_code) + + # Verify the response headers + client_response_headers = response.headers + assert ( + client_response_headers[RenamedHeader.CORRELATION_ID.original] + == expected_correlation_id + ) + assert len(client_response_headers[_HEADER_REQUEST_ID]) > 10 + assert _HEADER_ERS_TRANSACTION_ID not in client_response_headers + + for renamed_header in RenamedHeader: + assert renamed_header.renamed not in client_response_headers + + +def assert_error_response( + response: Response, expected_correlation_id: int, expected_status_code: int +): + # Verify the status + assert response.status_code == expected_status_code, ( + "Expected a " + + expected_status_code + + " when accesing the api but got " + + (str)(response.status_code) + ) + + assert len(response.content) == 0 + + # Verify the response headers + client_response_headers = response.headers + + assert ( + client_response_headers[RenamedHeader.CORRELATION_ID.original] + == expected_correlation_id + ) + + for renamed_header in RenamedHeader: + assert renamed_header.renamed not in client_response_headers diff --git a/tests/conftest.py b/tests/conftest.py index 26c356208..85bf63209 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,10 +1,15 @@ import os +from uuid import uuid4 +from time import time + import pytest from api_test_utils.apigee_api_apps import ApigeeApiDeveloperApps from api_test_utils.apigee_api_products import ApigeeApiProducts from api_test_utils.oauth_helper import OauthHelper +__JWKS_RESOURCE_URL = "https://raw.githubusercontent.com/NHSDigital/identity-service-jwks/main/jwks/internal-dev/9baed6f4-1361-4a8e-8531-1f8426e3aba8.json" + def get_env(variable_name: str) -> str: """Returns an environment variable""" @@ -64,56 +69,167 @@ def asid(): return get_env("ERS_TEST_ASID") -@pytest.fixture -async def product(environment, service_name): - # Setup - product = ApigeeApiProducts() - await product.create_new_product() +@pytest.fixture(scope="session") +def token_url(): + oauth_proxy = get_env("OAUTH_PROXY") + oauth_base_uri = get_env("OAUTH_BASE_URI") + return f"{oauth_base_uri}/{oauth_proxy}/token" - print(f"CREATED PRODUCT NAME: {product.name}") - # Update products allowed paths - proxies = [f"identity-service-mock-{environment}"] +@pytest.fixture(scope="session") +def app_restricted_ods_code(): + return "RCD" - if service_name is not None: - proxies.append(service_name) - await product.update_proxies(proxies) - await product.update_scopes( - scopes=["urn:nhsd:apim:user-nhs-id:aal3:e-referrals-service-api"] +@pytest.fixture(scope="session") +def app_restricted_user_id(): + return "555032000100" + + +@pytest.fixture +async def user_restricted_product(make_product): + # Setup + product = await make_product( + ["urn:nhsd:apim:user-nhs-id:aal3:e-referrals-service-api"] ) yield product # Teardown - print("Cleanup product") + print(f"Cleanup product: {product.name}") await product.destroy_product() @pytest.fixture -async def app(product, asid): +def make_product(environment, service_name): + async def _make_product(product_scopes): + # Setup + product = ApigeeApiProducts() + await product.create_new_product() + + print(f"CREATED PRODUCT NAME: {product.name}") + + # Update products allowed paths + proxies = [f"identity-service-mock-{environment}"] + + if service_name is not None: + proxies.append(service_name) + + await product.update_proxies(proxies) + await product.update_scopes(scopes=product_scopes) + return product + + return _make_product + + +@pytest.fixture +async def user_restricted_app(make_app, user_restricted_product, asid): # Setup - app = ApigeeApiDeveloperApps() - await app.create_new_app() + app = await make_app(user_restricted_product, {"asid": asid}) + + yield app + + # Teardown + print(f"Cleanup app: {app.name}") + await app.destroy_app() - print(f"CREATED APP NAME: {app.name}") - # Set ASID - await app.set_custom_attributes({"asid": asid}) +@pytest.fixture +def make_app(): + async def _make_app(product, custom_attributes): + # Setup + app = ApigeeApiDeveloperApps() + await app.create_new_app() - # Assign the new app to the product - await app.add_api_product([product.name]) + print(f"CREATED APP NAME: {app.name}") - app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url) + # Set ASID + await app.set_custom_attributes(custom_attributes) + + # Assign the new app to the product + await app.add_api_product([product.name]) + + app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url) + return app + + return _make_app + + +@pytest.fixture +async def user_restricted_access_code(user_restricted_app, actor): + token_resp = user_restricted_app.oauth.get_authenticated_with_mock_auth( + actor.user_id + ) + print(f"user restricted resp: {token_resp}") + return token_resp["access_token"] + + +@pytest.fixture +async def app_restricted_product(make_product): + # Setup + product = await make_product(["urn:nhsd:apim:app:level3:e-referrals-service-api"]) + + yield product + + # Teardown + print(f"Cleanup product: {product.name}") + await product.destroy_product() + + +@pytest.fixture +async def app_restricted_app( + make_app, + app_restricted_product, + asid, + app_restricted_ods_code, + app_restricted_user_id, +): + # Setup + app = await make_app( + app_restricted_product, + { + "asid": asid, + "app-restricted-ods-code": app_restricted_ods_code, + "app-restricted-user-id": app_restricted_user_id, + "jwks-resource-url": __JWKS_RESOURCE_URL, + }, + ) yield app # Teardown - print("Cleanup app") + print(f"Cleanup app: {app.name}") await app.destroy_app() @pytest.fixture -async def access_code(app, actor): - token_resp = app.oauth.get_authenticated_with_mock_auth(actor.user_id) +async def app_restricted_access_code(app_restricted_app, token_url): + jwt = app_restricted_app.oauth.create_jwt( + **{ + "kid": "test-1", + "claims": { + "sub": app_restricted_app.client_id, + "iss": app_restricted_app.client_id, + "jti": str(uuid4()), + "aud": token_url, + "exp": int(time()) + 60, + }, + } + ) + resp = await app_restricted_app.oauth.get_token_response( + grant_type="client_credentials", _jwt=jwt + ) + if resp["status_code"] != 200: + message = "unable to get token" + raise RuntimeError( + f"\n{'*' * len(message)}\n" + f"MESSAGE: {message}\n" + f"URL: {resp.get('url')}\n" + f"STATUS CODE: {resp.get('status_code')}\n" + f"RESPONSE: {resp.get('body')}\n" + f"HEADERS: {resp.get('headers')}\n" + f"{'*' * len(message)}\n" + ) + token_resp = resp["body"] + print(f"app restricted resp: {token_resp}") return token_resp["access_token"] diff --git a/tests/data.py b/tests/data.py index 642d2954b..e5ac327cf 100644 --- a/tests/data.py +++ b/tests/data.py @@ -7,8 +7,6 @@ class Actor(Enum): RCA = ("555031998104", "D82106", "REFERRING_CLINICIAN_ADMIN") SPC = ("555032006106", "RCD", "SERVICE_PROVIDER_CLINICIAN") SPCA = ("555031998104", "RCD", "SERVICE_PROVIDER_CLINICIAN_ADMIN", "555031999105") - # AUTHORISED_APPLICATION isn't valid for user-restricted access and should only be used for application-restricted access - AA = ("555031998104", "RCD", "AUTHORISED_APPLICATION") @property def user_id(self): diff --git a/tests/integration/test_app_restricted.py b/tests/integration/test_app_restricted.py index 5f4d597a2..e5265a339 100644 --- a/tests/integration/test_app_restricted.py +++ b/tests/integration/test_app_restricted.py @@ -1,49 +1,175 @@ import pytest import requests from data import Actor, RenamedHeader +from asserts import assert_ok_response, assert_error_response -HEADER_AUTHORIZATION = "Authorization" -HEADER_REQUEST_ID = "x-request-id" +_HEADER_AUTHORIZATION = "Authorization" +_HEADER_ECHO = "echo" # enable echo target +_HEADER_BASE_URL = "x-ers-network-baseurl" +_HEADER_USER_ID = "x-ers-user-id" +_HEADER_REQUEST_ID = "x-request-id" +_HEADER_ASID = "xapi_asid" +_HEADER_ERS_TRANSACTION_ID = "X_ERS_TRANSACTION_ID" -EXPECTED_CORRELATION_ID = "123123-123123-123123-123123" -EXPECTED_ACTOR = Actor.AA +_EXPECTED_CORRELATION_ID = "123123-123123-123123-123123" +_EXPECTED_ACTOR = Actor.RC -SPECIALTY_REF_DATA_URL = "/FHIR/STU3/CodeSystem/SPECIALTY" +_SPECIALTY_REF_DATA_URL = "/FHIR/STU3/CodeSystem/SPECIALTY" +_AUTHORISED_APPLICATION = "AUTHORISED_APPLICATION" +_EXPECTED_ASID = "280477200122" @pytest.mark.integration_test class TestAppRestricted: - @pytest.mark.parametrize("actor", [(EXPECTED_ACTOR)]) - def test_authorised_application_not_supported( - self, access_code, service_url, actor + @pytest.mark.parametrize("actor", [(_EXPECTED_ACTOR)]) + def test_authorised_application_not_supported_for_user_restricted( + self, user_restricted_access_code, service_url, actor ): + # attempt to use AUTHORISED_APPLICATION with an RC client_request_headers = { - HEADER_AUTHORIZATION: "Bearer " + access_code, - RenamedHeader.CORRELATION_ID.original: EXPECTED_CORRELATION_ID, - RenamedHeader.BUSINESS_FUNCTION.original: actor.business_function, + _HEADER_AUTHORIZATION: "Bearer " + user_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + RenamedHeader.BUSINESS_FUNCTION.original: _AUTHORISED_APPLICATION, RenamedHeader.ODS_CODE.original: actor.org_code, - HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters + _HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters } # Make the API call response = requests.get( - f"{service_url}{SPECIALTY_REF_DATA_URL}", headers=client_request_headers + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers ) - # Verify the status - assert ( - response.status_code == 403 - ), "Expected a 403 when accesing the api but got " + (str)(response.status_code) + assert_error_response(response, _EXPECTED_CORRELATION_ID, 403) - assert len(response.content) == 0 + def test_authorised_application_supported_for_app_restricted( + self, app_restricted_access_code, service_url + ): + client_request_headers = { + _HEADER_AUTHORIZATION: "Bearer " + app_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + _HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters + } + + # Make the API call + response = requests.get( + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers + ) + + assert_ok_response(response, _EXPECTED_CORRELATION_ID) + + @pytest.mark.parametrize( + "header,value", + [ + (RenamedHeader.ODS_CODE.renamed, "ABC"), + (RenamedHeader.BUSINESS_FUNCTION.renamed, _AUTHORISED_APPLICATION), + (_HEADER_USER_ID, "1"), + ], + ) + def test_authorised_application_header_rejected( + self, app_restricted_access_code, service_url, header, value + ): + client_request_headers = { + _HEADER_AUTHORIZATION: "Bearer " + app_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + header: value, + _HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters + } + + # Make the API call + response = requests.get( + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers + ) + + assert_error_response(response, _EXPECTED_CORRELATION_ID, 403) + + def test_headers_on_echo_target( + self, + app_restricted_access_code, + service_url, + asid, + app_restricted_ods_code, + app_restricted_user_id, + ): + client_request_headers = { + _HEADER_ECHO: "", # enable echo target + _HEADER_AUTHORIZATION: "Bearer " + app_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + _HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters + } + + # Make the API call + response = requests.get(service_url, headers=client_request_headers) + assert ( + response.status_code == 200 + ), "Expected a 200 when accesing the api but got " + (str)(response.status_code) # Verify the response headers client_response_headers = response.headers - + assert _HEADER_REQUEST_ID not in client_response_headers assert ( client_response_headers[RenamedHeader.CORRELATION_ID.original] - == EXPECTED_CORRELATION_ID + == _EXPECTED_CORRELATION_ID ) for renamed_header in RenamedHeader: assert renamed_header.renamed not in client_response_headers + + # Verify the received headers by the target + json_response = response.json() + target_request_headers = json_response["headers"] + + expected_app_restricted_renamed_headers = [ + RenamedHeader.CORRELATION_ID, + RenamedHeader.BUSINESS_FUNCTION, + RenamedHeader.ODS_CODE, + ] + not_expected_renamed_headers = [] + for renamed_header in RenamedHeader: + if renamed_header not in expected_app_restricted_renamed_headers: + not_expected_renamed_headers.append(renamed_header) + + for renamed_header in RenamedHeader: + assert renamed_header.original not in target_request_headers, ( + "Should not have any original headers in " + target_request_headers + ) + assert _HEADER_REQUEST_ID not in target_request_headers, ( + "Should not have " + + _HEADER_REQUEST_ID + + " header in " + + target_request_headers + ) + + for renamed_header in not_expected_renamed_headers: + assert renamed_header.renamed not in target_request_headers, ( + "Should not have " + + not_expected_renamed_headers + + " renamed headers in " + + target_request_headers + ) + + for renamed_header in expected_app_restricted_renamed_headers: + assert renamed_header.renamed in target_request_headers, ( + "Should have " + + expected_app_restricted_renamed_headers + + " headers in " + + target_request_headers + ) + assert _HEADER_USER_ID in target_request_headers, ( + "Should have " + _HEADER_USER_ID + " header in " + target_request_headers + ) + + # Verify the header values + assert target_request_headers[RenamedHeader.CORRELATION_ID.renamed].startswith( + _EXPECTED_CORRELATION_ID + ) + assert ( + target_request_headers[RenamedHeader.BUSINESS_FUNCTION.renamed] + == _AUTHORISED_APPLICATION + ) + assert ( + target_request_headers[RenamedHeader.ODS_CODE.renamed] + == app_restricted_ods_code + ) + assert target_request_headers[_HEADER_ASID] == asid + assert target_request_headers[_HEADER_USER_ID] == app_restricted_user_id + assert target_request_headers[_HEADER_BASE_URL] == service_url diff --git a/tests/integration/test_headers.py b/tests/integration/test_headers.py index 72a175ebe..332b3944a 100644 --- a/tests/integration/test_headers.py +++ b/tests/integration/test_headers.py @@ -1,41 +1,44 @@ import pytest import requests from data import Actor, RenamedHeader +from asserts import assert_ok_response -HEADER_AUTHORIZATION = "Authorization" -HEADER_ECHO = "echo" # enable echo target -HEADER_BASE_URL = "x-ers-network-baseurl" -HEADER_USER_ID = "x-ers-user-id" -HEADER_REQUEST_ID = "x-request-id" -HEADER_ASID = "xapi_asid" -HEADER_ERS_TRANSACTION_ID = "X_ERS_TRANSACTION_ID" +_HEADER_AUTHORIZATION = "Authorization" +_HEADER_ECHO = "echo" # enable echo target +_HEADER_BASE_URL = "x-ers-network-baseurl" +_HEADER_USER_ID = "x-ers-user-id" +_HEADER_REQUEST_ID = "x-request-id" +_HEADER_ASID = "xapi_asid" +_HEADER_ERS_TRANSACTION_ID = "X_ERS_TRANSACTION_ID" -EXPECTED_REFERRAL_ID = "000000040032" -EXPECTED_CORRELATION_ID = "123123-123123-123123-123123" -EXPECTED_FILENAME = "mysuperfilename.txt" -EXPECTED_ASID = "280477200122" -EXPECTED_COMM_RULE_ORG = "R100" -EXPECTED_ACTOR = Actor.RC -EXPECTED_OBO_USER_ID = "0123456789000" +_EXPECTED_REFERRAL_ID = "000000040032" +_EXPECTED_CORRELATION_ID = "123123-123123-123123-123123" +_EXPECTED_FILENAME = "mysuperfilename.txt" +_EXPECTED_ASID = "280477200122" +_EXPECTED_COMM_RULE_ORG = "R100" +_EXPECTED_ACTOR = Actor.RC +_EXPECTED_OBO_USER_ID = "0123456789000" -SPECIALTY_REF_DATA_URL = "/FHIR/STU3/CodeSystem/SPECIALTY" +_SPECIALTY_REF_DATA_URL = "/FHIR/STU3/CodeSystem/SPECIALTY" @pytest.mark.integration_test class TestHeaders: - @pytest.mark.parametrize("actor,asid", [(EXPECTED_ACTOR, EXPECTED_ASID)]) - def test_headers_on_echo_target(self, access_code, service_url, actor): + @pytest.mark.parametrize("actor,asid", [(_EXPECTED_ACTOR, _EXPECTED_ASID)]) + def test_headers_on_echo_target( + self, user_restricted_access_code, service_url, actor + ): client_request_headers = { - HEADER_ECHO: "", # enable echo target - HEADER_AUTHORIZATION: "Bearer " + access_code, - HEADER_REQUEST_ID: "DUMMY-VALUE", - RenamedHeader.REFERRAL_ID.original: EXPECTED_REFERRAL_ID, - RenamedHeader.CORRELATION_ID.original: EXPECTED_CORRELATION_ID, + _HEADER_ECHO: "", # enable echo target + _HEADER_AUTHORIZATION: "Bearer " + user_restricted_access_code, + _HEADER_REQUEST_ID: "DUMMY-VALUE", + RenamedHeader.REFERRAL_ID.original: _EXPECTED_REFERRAL_ID, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, RenamedHeader.BUSINESS_FUNCTION.original: actor.business_function, RenamedHeader.ODS_CODE.original: actor.org_code, - RenamedHeader.FILENAME.original: EXPECTED_FILENAME, - RenamedHeader.COMM_RULE_ORG.original: EXPECTED_COMM_RULE_ORG, - RenamedHeader.OBO_USER_ID.original: EXPECTED_OBO_USER_ID, + RenamedHeader.FILENAME.original: _EXPECTED_FILENAME, + RenamedHeader.COMM_RULE_ORG.original: _EXPECTED_COMM_RULE_ORG, + RenamedHeader.OBO_USER_ID.original: _EXPECTED_OBO_USER_ID, } # Make the API call @@ -46,10 +49,10 @@ def test_headers_on_echo_target(self, access_code, service_url, actor): # Verify the response headers client_response_headers = response.headers - assert HEADER_REQUEST_ID not in client_response_headers + assert _HEADER_REQUEST_ID not in client_response_headers assert ( client_response_headers[RenamedHeader.CORRELATION_ID.original] - == EXPECTED_CORRELATION_ID + == _EXPECTED_CORRELATION_ID ) for renamed_header in RenamedHeader: @@ -64,15 +67,15 @@ def test_headers_on_echo_target(self, access_code, service_url, actor): assert renamed_header.original not in target_request_headers assert renamed_header.renamed in target_request_headers - assert HEADER_REQUEST_ID not in target_request_headers + assert _HEADER_REQUEST_ID not in target_request_headers # Verify the header values assert ( target_request_headers[RenamedHeader.REFERRAL_ID.renamed] - == EXPECTED_REFERRAL_ID + == _EXPECTED_REFERRAL_ID ) assert target_request_headers[RenamedHeader.CORRELATION_ID.renamed].startswith( - EXPECTED_CORRELATION_ID + _EXPECTED_CORRELATION_ID ) assert ( target_request_headers[RenamedHeader.BUSINESS_FUNCTION.renamed] @@ -80,52 +83,39 @@ def test_headers_on_echo_target(self, access_code, service_url, actor): ) assert target_request_headers[RenamedHeader.ODS_CODE.renamed] == actor.org_code assert ( - target_request_headers[RenamedHeader.FILENAME.renamed] == EXPECTED_FILENAME + target_request_headers[RenamedHeader.FILENAME.renamed] == _EXPECTED_FILENAME ) assert ( target_request_headers[RenamedHeader.COMM_RULE_ORG.renamed] - == EXPECTED_COMM_RULE_ORG + == _EXPECTED_COMM_RULE_ORG ) assert ( target_request_headers[RenamedHeader.OBO_USER_ID.renamed] - == EXPECTED_OBO_USER_ID + == _EXPECTED_OBO_USER_ID ) - assert target_request_headers[HEADER_ASID] == EXPECTED_ASID - assert target_request_headers[HEADER_USER_ID] == actor.user_id - assert target_request_headers[HEADER_BASE_URL] == service_url + assert target_request_headers[_HEADER_ASID] == _EXPECTED_ASID + assert target_request_headers[_HEADER_USER_ID] == actor.user_id + assert target_request_headers[_HEADER_BASE_URL] == service_url - @pytest.mark.parametrize("actor", [(EXPECTED_ACTOR)]) - def test_headers_on_refdata_response(self, access_code, service_url, actor): + @pytest.mark.parametrize("actor", [(_EXPECTED_ACTOR)]) + def test_headers_on_refdata_response( + self, user_restricted_access_code, service_url, actor + ): client_request_headers = { - HEADER_AUTHORIZATION: "Bearer " + access_code, - RenamedHeader.CORRELATION_ID.original: EXPECTED_CORRELATION_ID, + _HEADER_AUTHORIZATION: "Bearer " + user_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, RenamedHeader.BUSINESS_FUNCTION.original: actor.business_function, RenamedHeader.ODS_CODE.original: actor.org_code, - HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters + _HEADER_REQUEST_ID: "DUMMY", # this must be less than 10 characters } # Make the API call response = requests.get( - f"{service_url}{SPECIALTY_REF_DATA_URL}", headers=client_request_headers + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers ) - # Verify the status - assert ( - response.status_code == 200 - ), "Expected a 200 when accesing the api but got " + (str)(response.status_code) - - # Verify the response headers - client_response_headers = response.headers - assert ( - client_response_headers[RenamedHeader.CORRELATION_ID.original] - == EXPECTED_CORRELATION_ID - ) - assert len(client_response_headers[HEADER_REQUEST_ID]) > 10 - assert HEADER_ERS_TRANSACTION_ID not in client_response_headers - - for renamed_header in RenamedHeader: - assert renamed_header.renamed not in client_response_headers + assert_ok_response(response, _EXPECTED_CORRELATION_ID) @pytest.mark.parametrize( "auth_header", @@ -133,16 +123,16 @@ def test_headers_on_refdata_response(self, access_code, service_url, actor): ) def test_unknown_access_code(self, service_url, auth_header): client_request_headers = { - RenamedHeader.CORRELATION_ID.original: EXPECTED_CORRELATION_ID, - HEADER_REQUEST_ID: "DUMMY", + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + _HEADER_REQUEST_ID: "DUMMY", } if auth_header is not None: - client_request_headers[HEADER_AUTHORIZATION] = auth_header + client_request_headers[_HEADER_AUTHORIZATION] = auth_header # Make the API call response = requests.get( - f"{service_url}{SPECIALTY_REF_DATA_URL}", headers=client_request_headers + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers ) # Verify the status @@ -155,27 +145,27 @@ def test_unknown_access_code(self, service_url, auth_header): # Verify the response headers client_response_headers = response.headers assert 'error="invalid_token"' in client_response_headers["WWW-Authenticate"] - assert client_response_headers[HEADER_REQUEST_ID] == "DUMMY" + assert client_response_headers[_HEADER_REQUEST_ID] == "DUMMY" assert ( client_response_headers[RenamedHeader.CORRELATION_ID.original] - == EXPECTED_CORRELATION_ID + == _EXPECTED_CORRELATION_ID ) for renamed_header in RenamedHeader: assert renamed_header.renamed not in client_response_headers - @pytest.mark.parametrize("service_name,actor", [(None, EXPECTED_ACTOR)]) - def test_access_code_not_supported(self, access_code, service_url): + @pytest.mark.parametrize("service_name,actor", [(None, _EXPECTED_ACTOR)]) + def test_access_code_not_supported(self, user_restricted_access_code, service_url): client_request_headers = { - HEADER_AUTHORIZATION: "Bearer " + access_code, - RenamedHeader.CORRELATION_ID.original: EXPECTED_CORRELATION_ID, - HEADER_REQUEST_ID: "DUMMY", + _HEADER_AUTHORIZATION: "Bearer " + user_restricted_access_code, + RenamedHeader.CORRELATION_ID.original: _EXPECTED_CORRELATION_ID, + _HEADER_REQUEST_ID: "DUMMY", } # Make the API call response = requests.get( - f"{service_url}{SPECIALTY_REF_DATA_URL}", headers=client_request_headers + f"{service_url}{_SPECIALTY_REF_DATA_URL}", headers=client_request_headers ) # Verify the status @@ -187,7 +177,7 @@ def test_access_code_not_supported(self, access_code, service_url): # Verify the response headers client_response_headers = response.headers - assert client_response_headers[HEADER_REQUEST_ID] == "DUMMY" + assert client_response_headers[_HEADER_REQUEST_ID] == "DUMMY" assert 'error="invalid_token"' in client_response_headers["WWW-Authenticate"] assert ( "Invalid API call as no apiproduct match found" @@ -196,7 +186,7 @@ def test_access_code_not_supported(self, access_code, service_url): assert ( client_response_headers[RenamedHeader.CORRELATION_ID.original] - == EXPECTED_CORRELATION_ID + == _EXPECTED_CORRELATION_ID ) for renamed_header in RenamedHeader: diff --git a/tests/sandbox/test_create_referral.py b/tests/sandbox/test_create_referral.py index c704c0126..2abe074fa 100644 --- a/tests/sandbox/test_create_referral.py +++ b/tests/sandbox/test_create_referral.py @@ -13,7 +13,7 @@ class TestCreateReferral(SandboxTest): @pytest.fixture def unauthorised_actors(self) -> Iterable[Actor]: - return [Actor.SPC, Actor.SPCA, Actor.AA] + return [Actor.SPC, Actor.SPCA] @pytest.fixture def call_endpoint( diff --git a/tests/sandbox/test_get_codesystem.py b/tests/sandbox/test_get_codesystem.py index 6a353f08a..8e59acc1e 100644 --- a/tests/sandbox/test_get_codesystem.py +++ b/tests/sandbox/test_get_codesystem.py @@ -17,7 +17,7 @@ def unauthorised_actors(self) -> Iterable[Actor]: return self.unauthorised_actors_list() def unauthorised_actors_list(self) -> List[Actor]: - return [Actor.AA] + return [] @pytest.fixture def authorised_actors(self) -> Iterable[Actor]: From 0af7f67413923aea31a0754093fc62f1e85d5639 Mon Sep 17 00:00:00 2001 From: Raja Govindharaj Date: Fri, 20 May 2022 10:04:46 +0000 Subject: [PATCH 7/7] +minor