public async Task <Resource> Get <T>(FhirRequest request) where T : Resource { ValidateResource(request.StrResourceType); request.ProfileUri = _resourceProfile; return(await _fhirSearch.Get <T>(request)); }
public async Task <Resource> Get(FhirRequest request) { ValidateResource(request.StrResourceType); request.ProfileUri = _resourceProfile; return(await _fhirSearch.Get <Organization>(request)); }
/// <summary> /// Get a DocumentReference by id /// </summary> /// <remarks> /// Get a single DocumentReference using the DocRef logical id /// </remarks> public async Task <Resource> Get(FhirRequest request) { ValidateResource(request.StrResourceType); request.ProfileUri = _resourceProfile; var result = await _fhirSearch.Get <DocumentReference>(request); return(result); }
public async SystemTasks.Task <Resource> ValidateConditionalUpdate(FhirRequest request) { if (!request.Resource.ResourceType.Equals(ResourceType.DocumentReference)) { return(OperationOutcomeFactory.CreateInvalidResource("relatesTo")); } var document = request.Resource as DocumentReference; var relatesTo = _fhirValidation.GetValidRelatesTo(document.RelatesTo); if (document.RelatesTo.Count == 0) { //skip checks, request is just a standard create return(null); } else if (relatesTo.element == null) { return(OperationOutcomeFactory.CreateInvalidResource(relatesTo.issue)); } //Subject already validated during ValidateCreate //relatesTo Reference/Identifier already validated during ValidateCreate => validPointer var isRelatesToReference = !string.IsNullOrWhiteSpace(relatesTo.element.Target.Reference); FhirRequest pointerRequest = null; DocumentReference oldDocument = null; if (isRelatesToReference) { var pointerId = _fhirValidation.GetReferenceId(relatesTo.element.Target); pointerRequest = NrlsPointerHelper.CreateReferenceSearch(request, pointerId); oldDocument = await _fhirSearch.Get <DocumentReference>(pointerRequest); } else { var subjectNhsNumber = _fhirValidation.GetSubjectReferenceId(document.Subject); pointerRequest = NrlsPointerHelper.CreateMasterIdentifierSearch(request, relatesTo.element.Target.Identifier, subjectNhsNumber); var pointers = await _fhirSearch.Find <DocumentReference>(pointerRequest); //There should only ever be zero or one oldDocument = pointers.Entry.FirstOrDefault()?.Resource as DocumentReference; } if (oldDocument == null) { //Cant find related document return(OperationOutcomeFactory.CreateInvalidResource("relatesTo.target", "Referenced DocumentReference does not exist.")); } //related document does not have same patient if (string.IsNullOrEmpty(oldDocument.Subject.Reference) || oldDocument.Subject.Reference != document.Subject.Reference) { return(OperationOutcomeFactory.CreateInvalidResource("relatesTo.target", "Resolved DocumentReference is not associated with the same patient.")); } //Reference type checks if (isRelatesToReference) { //related document does not have masterIdentifier or masterIdentifier does not match new var docRelatesToIdentifier = document.RelatesTo.First().Target.Identifier; if (docRelatesToIdentifier != null) { var oldDocRelatesToIdentifier = oldDocument.MasterIdentifier; if (oldDocRelatesToIdentifier == null) { return(OperationOutcomeFactory.CreateInvalidResource("relatesTo.target", "Resolved DocumentReference does not have an MasterIdentifier.")); } if (string.IsNullOrWhiteSpace(docRelatesToIdentifier.System) || string.IsNullOrWhiteSpace(docRelatesToIdentifier.Value) || docRelatesToIdentifier.Value != oldDocRelatesToIdentifier.Value || docRelatesToIdentifier.System != oldDocRelatesToIdentifier.System) { return(OperationOutcomeFactory.CreateInvalidResource("relatesTo.target", "Resolved DocumentReference does not have a matching MasterIdentifier.")); } } } //Custodian already validated against incoming ASID during ValidateCreate var custodianOdsCode = _fhirValidation.GetOrganizationReferenceId(document.Custodian); if (oldDocument.Custodian == null || string.IsNullOrEmpty(oldDocument.Custodian.Reference) || oldDocument.Custodian.Reference != $"{FhirConstants.SystemODS}{custodianOdsCode}") { //related document does not have same custodian return(OperationOutcomeFactory.CreateInvalidResource("relatesTo.target", $"Resolved DocumentReference is not associated with custodian {custodianOdsCode}")); } if (oldDocument.Status != DocumentReferenceStatus.Current) { //Only allowed to transition to superseded from current return(OperationOutcomeFactory.CreateInactiveDocumentReference()); } return(oldDocument); }
/// <summary> /// Delete a DocumentReference using the id value found in the request _id query parameter /// </summary> /// <remarks> /// First we do a search to get the document, then we check the incoming ASID associated OrgCode against the custodian on the document. /// If valid we can delete. /// We use the FhirMaintain service and FhirSearch service to facilitate this /// </remarks> public async SystemTasks.Task <OperationOutcome> Delete <T>(FhirRequest request) where T : Resource { ValidateResource(request.StrResourceType); request.ProfileUri = _resourceProfile; // NRLS Layers of validation before Fhir Delete Call var id = request.IdParameter; var identifier = request.IdentifierParameter; var subject = request.SubjectParameter; if (string.IsNullOrEmpty(id) && _fhirValidation.ValidateIdentifierParameter("identifier", identifier) != null && _fhirValidation.ValidatePatientParameter(subject) != null) { throw new HttpFhirException("Missing or Invalid _id parameter", OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter: _id"), HttpStatusCode.BadRequest); } if (string.IsNullOrEmpty(id) && _fhirValidation.ValidateIdentifierParameter("identifier", identifier) == null && _fhirValidation.ValidatePatientParameter(subject) != null) { throw new HttpFhirException("Missing or Invalid subject parameter", OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter: subject"), HttpStatusCode.BadRequest); } if (string.IsNullOrEmpty(id) && _fhirValidation.ValidateIdentifierParameter("identifier", identifier) != null && _fhirValidation.ValidatePatientParameter(subject) == null) { throw new HttpFhirException("Missing or Invalid identifier parameter", OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter: identifier"), HttpStatusCode.BadRequest); } request.Id = id; Resource document; if (!string.IsNullOrEmpty(id)) { ObjectId mongoId; if (!ObjectId.TryParse(id, out mongoId)) { throw new HttpFhirException("Invalid _id parameter", OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter", $"The Logical ID format does not apply to the given Logical ID - {id}"), HttpStatusCode.BadRequest); } document = await _fhirSearch.Get <T>(request); } else { document = await _fhirSearch.GetByMasterId <T>(request); } var documentResponse = ParseRead(document, id); if (documentResponse.ResourceType == ResourceType.Bundle) { var result = documentResponse as Bundle; if (!result.Total.HasValue || result.Total.Value < 1 || result.Entry.FirstOrDefault() == null) { return(OperationOutcomeFactory.CreateNotFound(id)); } var orgDocument = result.Entry.FirstOrDefault().Resource as DocumentReference; var orgCode = _fhirValidation.GetOrganizationReferenceId(orgDocument.Custodian); var invalidAsid = InvalidAsid(orgCode, request.RequestingAsid, false); if (invalidAsid != null) { return(invalidAsid); } } else { return(documentResponse as OperationOutcome); } bool deleted; if (!string.IsNullOrEmpty(id)) { deleted = await _fhirMaintain.Delete <T>(request); } else { //Add identifier on the fly as it is not a standard search parameter request.AllowedParameters = request.AllowedParameters.Concat(new[] { "identifier" }).ToArray(); deleted = await _fhirMaintain.DeleteConditional <T>(request); } if (!deleted) { return(OperationOutcomeFactory.CreateNotFound(request.Id)); } return(OperationOutcomeFactory.CreateDelete(request.RequestUrl?.AbsoluteUri, request.AuditId)); }
/// <summary> /// Search for Documents or Get one by _id /// </summary> /// <remarks> /// As the NRLS is implemented with just a search and not read, to read a document the _id parameter is supplied /// </remarks> public async Task<Resource> Find<T>(FhirRequest request) where T : Resource { ValidateResource(request.StrResourceType); request.ProfileUri = _resourceProfile; var id = request.IdParameter; //We are going to be strict hear for search and only proceed if we have valid parameters if(request.InvalidParameters.Count() > 0) { throw new HttpFhirException("Invalid parameters", OperationOutcomeFactory.CreateInvalidParameter($"Invalid parameter: {string.Join(", ", request.InvalidParameters)}"), HttpStatusCode.BadRequest); } //If we have an _id param it should be the only param so check for that here. if (request.HasIdParameter) { ObjectId mongoId; if (!ObjectId.TryParse(id, out mongoId)) { return OperationOutcomeFactory.CreateNotFound(""); } if (request.QueryParameters.Count() > 1) { throw new HttpFhirException("Invalid _id parameter", OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter: _id"), HttpStatusCode.BadRequest); } request.Id = id; var results = await _fhirSearch.Get<T>(request); var response = ParseRead(results, id); return response; } //If we are here then it is a standard search query var patient = request.QueryParameters.FirstOrDefault(x => x.Item1 == "subject"); if (patient != null) { var invalidPatient = _fhirValidation.ValidatePatientParameter(patient.Item2); if (invalidPatient != null) { throw new HttpFhirException("Missing or Invalid patient parameter", invalidPatient, HttpStatusCode.BadRequest); } } else { throw new HttpFhirException("Missing or Invalid patient parameter", OperationOutcomeFactory.CreateInvalidParameter("Missing parameter: subject"), HttpStatusCode.BadRequest); } var custodian = request.QueryParameters.FirstOrDefault(x => x.Item1 == "custodian"); var useCustodianIdentifierValidation = false; if (custodian == null) { //temporarily also support the incorrectly spec'd custodian.identifier parameter //custodian is a reference type and should not be used in this way custodian = request.QueryParameters.FirstOrDefault(x => x.Item1 == "custodian.identifier"); useCustodianIdentifierValidation = custodian != null; } if (custodian != null) { //temporarily also support the incorrectly spec'd custodian.identifier parameter var invalidCustodian = useCustodianIdentifierValidation ? _fhirValidation.ValidateCustodianIdentifierParameter(custodian.Item2) : _fhirValidation.ValidateCustodianParameter(custodian.Item2); if (invalidCustodian != null) { throw new HttpFhirException("Missing or Invalid custodian parameter", invalidCustodian, HttpStatusCode.BadRequest); } var custodianOrgCode = useCustodianIdentifierValidation? _fhirValidation.GetOrganizationParameterIdentifierId(custodian.Item2) : _fhirValidation.GetOrganizationParameterId(custodian.Item2); var custodianRequest = NrlsPointerHelper.CreateOrgSearch(request, custodianOrgCode); var custodians = await _fhirSearch.Find<Organization>(custodianRequest) as Bundle; if (custodians.Entry.Count == 0) { var invalidOrg = OperationOutcomeFactory.CreateOrganizationNotFound(custodianOrgCode); throw new HttpFhirException("Missing or Invalid custodian parameter", invalidOrg, HttpStatusCode.NotFound); } var invalidOrgInteraction = ValidateOrganisationInteraction(request.RequestingAsid, custodianOrgCode, true); if (invalidOrgInteraction != null) { throw new HttpFhirException("Invalid Provider Request Exception", invalidOrgInteraction, HttpStatusCode.Unauthorized); } } var type = request.QueryParameters.FirstOrDefault(x => x.Item1 == "type.coding"); if (type != null) { var invalidType = _fhirValidation.ValidTypeParameter(type.Item2); if (invalidType != null) { throw new HttpFhirException("Missing or Invalid type parameter", invalidType, HttpStatusCode.BadRequest); } } var summary = request.QueryParameters.FirstOrDefault(x => x.Item1 == "_summary"); if (summary != null) { var validSummaryParams = new string[] { "subject", "_format", "_summary" }; var invalidSummaryParams = request.QueryParameters.Where(x => !validSummaryParams.Contains(x.Item1)); OperationOutcome invalidSummary = null; if (invalidSummaryParams.Any()) { var invalidSummaryParamsList = string.Join(", ", invalidSummaryParams.Select(x => $"{x.Item1}={x.Item2}")); invalidSummary = OperationOutcomeFactory.CreateInvalidParameter("Invalid parameter", $"Unsupported search parameter - {invalidSummaryParamsList}"); throw new HttpFhirException("Missing or Invalid type parameter", invalidSummary, HttpStatusCode.BadRequest); } invalidSummary = _fhirValidation.ValidSummaryParameter(summary.Item2); if (invalidSummary != null) { throw new HttpFhirException("Missing or Invalid type parameter", invalidSummary, HttpStatusCode.BadRequest); } request.IsSummary = true; } return await _fhirSearch.Find<T>(request); }