Search in sources :

Example 1 with UnclassifiedServerFailureException

use of ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException in project gpconnect-demonstrator by nhsconnect.

the class AppointmentResourceProvider method updateAppointment.

@Update
public MethodOutcome updateAppointment(@IdParam IdType appointmentId, @ResourceParam Appointment appointment) {
    MethodOutcome methodOutcome = new MethodOutcome();
    OperationOutcome operationalOutcome = new OperationOutcome();
    AppointmentDetail appointmentDetail = appointmentResourceConverterToAppointmentDetail(appointment);
    // URL ID and Resource ID must be the same
    if (!Objects.equals(appointmentId.getIdPartAsLong(), appointmentDetail.getId())) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("Id in URL (" + appointmentId.getIdPart() + ") should match Id in Resource (" + appointmentDetail.getId() + ")");
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    // Make sure there is an existing appointment to be amended
    AppointmentDetail oldAppointmentDetail = appointmentSearch.findAppointmentByID(appointmentId.getIdPartAsLong());
    if (oldAppointmentDetail == null) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("No appointment details found for ID: " + appointmentId.getIdPart());
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    String oldAppointmentVersionId = String.valueOf(oldAppointmentDetail.getLastUpdated().getTime());
    String newAppointmentVersionId = appointmentId.getVersionIdPart();
    if (newAppointmentVersionId != null && !newAppointmentVersionId.equalsIgnoreCase(oldAppointmentVersionId)) {
        throw new ResourceVersionConflictException("The specified version (" + newAppointmentVersionId + ") did not match the current resource version (" + oldAppointmentVersionId + ")");
    }
    // Determin if it is a cancel or an amend
    if (appointmentDetail.getCancellationReason() != null) {
        if (appointmentDetail.getCancellationReason().isEmpty()) {
            operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("The cancellation reason can not be blank");
            methodOutcome.setOperationOutcome(operationalOutcome);
            return methodOutcome;
        }
        // This is a Cancellation - so copy across fields which can be
        // altered
        boolean cancelComparisonResult = compareAppointmentsForInvalidPropertyCancel(oldAppointmentDetail, appointmentDetail);
        if (cancelComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Invalid Appointment property has been amended (cancellation)"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        oldAppointmentDetail.setCancellationReason(appointmentDetail.getCancellationReason());
        String oldStatus = oldAppointmentDetail.getStatus();
        appointmentDetail = oldAppointmentDetail;
        appointmentDetail.setStatus("cancelled");
        if (!"cancelled".equalsIgnoreCase(oldStatus)) {
            for (Long slotId : appointmentDetail.getSlotIds()) {
                SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
                // slotDetail.setAppointmentId(null);
                slotDetail.setFreeBusyType("FREE");
                slotDetail.setLastUpdated(new Date());
                slotStore.saveSlot(slotDetail);
            }
        }
    } else {
        if (appointment.getStatus().equals("cancelled")) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Appointment has been cancelled and cannot be amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        boolean amendComparisonResult = compareAppointmentsForInvalidPropertyAmend(appointmentDetail, oldAppointmentDetail);
        if (amendComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(403, "Invalid Appointment property has been amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        // This is an Amend
        oldAppointmentDetail.setComment(appointmentDetail.getComment());
        oldAppointmentDetail.setReasonCode(appointmentDetail.getReasonCode());
        oldAppointmentDetail.setDescription(appointmentDetail.getDescription());
        oldAppointmentDetail.setReasonDisplay(appointmentDetail.getReasonDisplay());
        oldAppointmentDetail.setTypeCode(appointmentDetail.getTypeCode());
        oldAppointmentDetail.setTypeDisplay(appointmentDetail.getTypeDisplay());
        appointmentDetail = oldAppointmentDetail;
    }
    List<SlotDetail> slots = new ArrayList<>();
    for (Long slotId : appointmentDetail.getSlotIds()) {
        SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
        if (slotDetail == null) {
            throw new UnprocessableEntityException("Slot resource reference is not a valid resource");
        }
        slots.add(slotDetail);
    }
    // Update version and
    appointmentDetail.setLastUpdated(new Date());
    // lastUpdated timestamp
    appointmentDetail = appointmentStore.saveAppointment(appointmentDetail, slots);
    methodOutcome.setId(new IdDt("Appointment", appointmentDetail.getId()));
    methodOutcome.setResource(appointmentDetailToAppointmentResourceConverter(appointmentDetail));
    return methodOutcome;
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) AppointmentDetail(uk.gov.hscic.model.appointment.AppointmentDetail) ArrayList(java.util.ArrayList) IdDt(ca.uhn.fhir.model.primitive.IdDt) ResourceVersionConflictException(ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException) MethodOutcome(ca.uhn.fhir.rest.api.MethodOutcome) Date(java.util.Date) UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) OperationOutcome(org.hl7.fhir.dstu3.model.OperationOutcome) SlotDetail(uk.gov.hscic.model.appointment.SlotDetail) Update(ca.uhn.fhir.rest.annotation.Update)

Example 2 with UnclassifiedServerFailureException

use of ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException in project gpconnect-demonstrator by nhsconnect.

the class CertificateValidator method validateRequest.

public void validateRequest(HttpServletRequest request) {
    try {
        if (request.isSecure() && !HttpMethod.OPTIONS.name().equals(request.getMethod()) && (env.getProperty("clientAuth") == null || !env.getProperty("clientAuth").equals("false"))) {
            X509Certificate[] certificates = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
            if (certificates == null) {
                throw new CertificateException("No certificate found!", 496);
            }
            X509Certificate certificate = certificates[0];
            if (logCertsToConsole) {
                System.out.println("Known Certs: ");
                for (X509Certificate knownCert : storeCertificates) {
                    System.out.println(knownCert.toString());
                }
                System.out.println("Recieved Cert: ");
                System.out.println(certificate.toString());
            }
            if (!storeCertificates.contains(certificate)) {
                String message = getCertificateError(certificate);
                throw new CertificateException(message, 495);
            }
        }
    } catch (CertificateException certificateException) {
        StringBuilder requestURL = new StringBuilder(request.getRequestURL());
        String queryString = request.getQueryString();
        if (null != queryString) {
            requestURL.append('?').append(queryString);
        }
        String warningMsg = "Bad signature detected for " + request.getMethod() + " to " + requestURL + ": " + certificateException.getMessage();
        throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(certificateException.getStatusCode(), warningMsg), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
    } catch (InvalidNameException ex) {
        java.util.logging.Logger.getLogger(CertificateValidator.class.getName()).log(Level.SEVERE, null, ex);
    }
}
Also used : UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) InvalidNameException(javax.naming.InvalidNameException) X509Certificate(java.security.cert.X509Certificate)

Example 3 with UnclassifiedServerFailureException

use of ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException in project gpconnect-demonstrator by nhsconnect.

the class PatientResourceProvider method registerPatient.

@Operation(name = REGISTER_PATIENT_OPERATION_NAME)
public Bundle registerPatient(@ResourceParam Parameters params) {
    Patient registeredPatient = null;
    validateParameterNames(params, registerPatientParams);
    Patient unregisteredPatient = params.getParameter().stream().filter(param -> "registerPatient".equalsIgnoreCase(param.getName())).map(ParametersParameterComponent::getResource).map(Patient.class::cast).findFirst().orElse(null);
    String nnn = nhsNumber.fromPatientResource(unregisteredPatient);
    // if its patient 14 spoof not on PDS and return the required error
    if (nnn.equals(patientNotOnSpine)) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) not present on PDS", nnn)), SystemCode.INVALID_PATIENT_DEMOGRAPHICS, IssueType.INVALID);
    } else if (nnn.equals(patientSuperseded)) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) is superseded", nnn)), SystemCode.INVALID_NHS_NUMBER, IssueType.INVALID);
    }
    if (unregisteredPatient != null) {
        validatePatient(unregisteredPatient);
        // check if the patient already exists
        PatientDetails patientDetails = patientSearch.findPatient(nhsNumber.fromPatientResource(unregisteredPatient));
        if (patientDetails == null || IsInactiveTemporaryPatient(patientDetails)) {
            if (patientDetails == null) {
                patientDetails = registerPatientResourceConverterToPatientDetail(unregisteredPatient);
                patientStore.create(patientDetails);
            } else {
                // reactivate inactive non temporary patient
                patientDetails.setRegistrationStatus(ACTIVE_REGISTRATION_STATUS);
                updateAddressAndTelecom(unregisteredPatient, patientDetails);
                patientStore.update(patientDetails);
            }
            try {
                registeredPatient = patientDetailsToRegisterPatientResourceConverter(patientSearch.findPatient(unregisteredPatient.getIdentifierFirstRep().getValue()));
                addPreferredBranchSurgeryExtension(registeredPatient);
            } catch (FHIRException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (patientDetails.isDeceased() || patientDetails.isSensitive()) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) has invalid demographics", nnn)), SystemCode.INVALID_PATIENT_DEMOGRAPHICS, IssueType.INVALID);
        } else {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(409, String.format("Patient (NHS number - %s) already exists", nnn)), SystemCode.DUPLICATE_REJECTED, IssueType.INVALID);
        }
    } else {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException("Patient record not found"), SystemCode.INVALID_PARAMETER, IssueType.INVALID);
    }
    Bundle bundle = new Bundle().setType(BundleType.SEARCHSET);
    bundle.getMeta().addProfile(SystemURL.SD_GPC_SRCHSET_BUNDLE);
    bundle.addEntry().setResource(registeredPatient);
    return bundle;
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) PatientDetails(uk.gov.hscic.model.patient.PatientDetails) PopulateMedicationBundle(uk.gov.hscic.medications.PopulateMedicationBundle) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) FHIRException(org.hl7.fhir.exceptions.FHIRException)

Example 4 with UnclassifiedServerFailureException

use of ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException in project gpconnect-demonstrator by nhsconnect.

the class WebTokenFactory method getWebToken.

/**
 * @param requestDetails Hapi Fhir object describing request
 * @param futureRequestLeeway JWT time leeway in seconds
 * @return populated WebToken object
 */
WebToken getWebToken(RequestDetails requestDetails, int futureRequestLeeway) {
    WebToken webToken = null;
    String authorizationHeader = requestDetails.getHeader(HttpHeaders.AUTHORIZATION);
    if (null == authorizationHeader) {
        throwInvalidRequest400_BadRequestException(HttpHeaders.AUTHORIZATION + " header missing");
    }
    String[] authorizationHeaderComponents = authorizationHeader.split(" ");
    if (authorizationHeaderComponents.length != 2 || !"Bearer".equalsIgnoreCase(authorizationHeaderComponents[0])) {
        throwInvalidRequest400_BadRequestException(HttpHeaders.AUTHORIZATION + " header invalid");
    }
    String contentType = requestDetails.getHeader(HttpHeaders.CONTENT_TYPE);
    if (contentType == null) {
        if (Arrays.asList(RequestTypeEnum.POST, RequestTypeEnum.PUT).contains(requestDetails.getRequestType())) {
            // NB Issue type is Incomplete not Invalid
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "No content media type set"), SystemCode.BAD_REQUEST, IssueType.INCOMPLETE);
        }
    } else if (!CONTENT_TYPES.contains(contentType.split(";")[0])) {
        throwUnsupportedMedia415_BadRequestException("Unsupported content media type");
    }
    String[] formatParam = requestDetails.getParameters().get("_format");
    String acceptHeader = null == formatParam ? requestDetails.getHeader(HttpHeaders.ACCEPT) : formatParam[0];
    // If it's still null, use the Content-Type header value
    if (null == acceptHeader) {
        acceptHeader = contentType;
    }
    if (acceptHeader == null || !CONTENT_TYPES.contains(acceptHeader.split(";")[0])) {
        throwUnsupportedMedia415_BadRequestException("Unsupported accept media type");
    }
    try {
        if (authorizationHeaderComponents[1].contains("==") || authorizationHeaderComponents[1].contains("/") || authorizationHeaderComponents[1].contains("+")) {
            throwInvalidRequest400_BadRequestException("JWT must be encoded using Base64URL. Padding is not allowed");
        }
        String[] jWTParts = authorizationHeaderComponents[1].split("\\.");
        if (jWTParts.length == 2) {
            String headerJsonString = new String(Base64.getUrlDecoder().decode(jWTParts[0]));
            validateJWTHeader(headerJsonString);
            String claimsJsonString = new String(Base64.getUrlDecoder().decode(jWTParts[1]));
            // This magically populates the WebToken data object
            webToken = new ObjectMapper().readValue(claimsJsonString, WebToken.class);
            jwtParseResourcesValidation(claimsJsonString);
        } else {
            throwInvalidRequest400_BadRequestException("Invalid number of JWT base 64 blocks " + jWTParts.length);
        }
    } catch (IllegalArgumentException iae) {
        throwInvalidRequest400_BadRequestException("JWT is not Base 64");
    } catch (JsonParseException ex) {
        throwInvalidRequest400_BadRequestException(String.format("Invalid WebToken: JSON is not valid - %s", ex.getMessage()));
    } catch (IOException ex) {
        throwInvalidRequest400_BadRequestException("Invalid WebToken");
    }
    WebTokenValidator.validateWebToken(webToken, futureRequestLeeway);
    return webToken;
}
Also used : UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) IOException(java.io.IOException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) WebToken(uk.gov.hscic.common.filters.model.WebToken)

Aggregations

UnclassifiedServerFailureException (ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException)4 UnprocessableEntityException (ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException)2 IdDt (ca.uhn.fhir.model.primitive.IdDt)1 Update (ca.uhn.fhir.rest.annotation.Update)1 MethodOutcome (ca.uhn.fhir.rest.api.MethodOutcome)1 InvalidRequestException (ca.uhn.fhir.rest.server.exceptions.InvalidRequestException)1 ResourceVersionConflictException (ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException)1 JsonParseException (com.fasterxml.jackson.core.JsonParseException)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 IOException (java.io.IOException)1 X509Certificate (java.security.cert.X509Certificate)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 InvalidNameException (javax.naming.InvalidNameException)1 OperationOutcome (org.hl7.fhir.dstu3.model.OperationOutcome)1 FHIRException (org.hl7.fhir.exceptions.FHIRException)1 WebToken (uk.gov.hscic.common.filters.model.WebToken)1 PopulateMedicationBundle (uk.gov.hscic.medications.PopulateMedicationBundle)1 AppointmentDetail (uk.gov.hscic.model.appointment.AppointmentDetail)1 SlotDetail (uk.gov.hscic.model.appointment.SlotDetail)1