Search in sources :

Example 1 with UploadValidationException

use of org.sagebionetworks.bridge.upload.UploadValidationException in project BridgeServer2 by Sage-Bionetworks.

the class HealthDataService method submitHealthData.

/* HEALTH DATA SUBMISSION */
/**
 * Synchronous health data API. Used to submit small health data payloads (such as survey responses) without
 * incurring the overhead of creating a bunch of small files to upload to S3.
 */
public HealthDataRecord submitHealthData(String appId, StudyParticipant participant, HealthDataSubmission healthDataSubmission) throws IOException, UploadValidationException {
    // validate health data submission
    if (healthDataSubmission == null) {
        throw new InvalidEntityException("Health data submission cannot be null");
    }
    Validate.entityThrowingException(HealthDataSubmissionValidator.INSTANCE, healthDataSubmission);
    // Generate a new uploadId.
    String uploadId = BridgeUtils.generateGuid();
    // construct health data record
    HealthDataRecord record = makeRecordFromSubmission(appId, participant, healthDataSubmission);
    // get schema
    UploadSchema schema = getSchemaForSubmission(appId, healthDataSubmission);
    if (schema != null) {
        // sanitize field names in the data node
        JsonNode sanitizedData = sanitizeFieldNames(healthDataSubmission.getData());
        // Filter data fields and attachments based on schema fields.
        filterAttachments(uploadId, schema, sanitizedData, record);
    }
    // Construct UploadValidationContext for the remaining upload handlers. We don't need all the fields, just the
    // ones that these handlers will be using.
    UploadValidationContext uploadValidationContext = new UploadValidationContext();
    uploadValidationContext.setHealthCode(participant.getHealthCode());
    uploadValidationContext.setHealthDataRecord(record);
    uploadValidationContext.setAppId(appId);
    // For back-compat reasons, we need to make a dummy upload to store the uploadId. This will never be persisted.
    // We just need a way to signal the Upload Validation pipeline to use this uploadId.
    Upload upload = Upload.create();
    upload.setUploadId(uploadId);
    uploadValidationContext.setUpload(upload);
    // Strict Validation Handler. If this throws, this is an invalid upload (400).
    try {
        strictValidationHandler.handle(uploadValidationContext);
    } catch (UploadValidationException ex) {
        throw new BadRequestException(ex);
    }
    // Transcribe Consent.
    transcribeConsentHandler.handle(uploadValidationContext);
    // Upload raw JSON as the raw data attachment. This is different from how the upload validation handles it.
    // Attachment ID is "[uploadId]-raw.json".
    String rawDataAttachmentId = uploadId + RAW_ATTACHMENT_SUFFIX;
    String rawDataValue = BridgeObjectMapper.get().writerWithDefaultPrettyPrinter().writeValueAsString(healthDataSubmission.getData());
    byte[] rawDataBytes = rawDataValue.getBytes(Charsets.UTF_8);
    uploadFileHelper.uploadBytesAsAttachment(rawDataAttachmentId, rawDataBytes);
    record.setRawDataAttachmentId(rawDataAttachmentId);
    // Upload Artifacts.
    uploadArtifactsHandler.handle(uploadValidationContext);
    // (depending on attachments). So we need to use the record ID to fetch the record again and return it.
    return getRecordById(uploadValidationContext.getRecordId());
}
Also used : UploadValidationException(org.sagebionetworks.bridge.upload.UploadValidationException) UploadValidationContext(org.sagebionetworks.bridge.upload.UploadValidationContext) HealthDataRecord(org.sagebionetworks.bridge.models.healthdata.HealthDataRecord) Upload(org.sagebionetworks.bridge.models.upload.Upload) BadRequestException(org.sagebionetworks.bridge.exceptions.BadRequestException) JsonNode(com.fasterxml.jackson.databind.JsonNode) UploadSchema(org.sagebionetworks.bridge.models.upload.UploadSchema) InvalidEntityException(org.sagebionetworks.bridge.exceptions.InvalidEntityException)

Example 2 with UploadValidationException

use of org.sagebionetworks.bridge.upload.UploadValidationException in project BridgeServer2 by Sage-Bionetworks.

the class SmsService method sendSmsMessage.

/**
 * Sends an SMS message using the given message provider. User ID is used to fetch the account, so we can get
 * health code and time zone and other relevant attributes to log and record as health data. If the recipient
 * doesn't have an account (for example, for Intent-to-Participate), this can be left null.
 */
public void sendSmsMessage(String userId, SmsMessageProvider provider) {
    checkNotNull(provider);
    App app = provider.getApp();
    Phone recipientPhone = provider.getPhone();
    String message = provider.getFormattedMessage();
    // Check max SMS length.
    if (message.getBytes(Charset.forName("US-ASCII")).length > SMS_CHARACTER_LIMIT) {
        throw new BridgeServiceException("SMS message cannot be longer than 600 UTF-8/ASCII characters.");
    }
    // Send SMS.
    String messageId;
    PublishResult result = snsClient.publish(provider.getSmsRequest());
    messageId = result.getMessageId();
    LOG.info("Sent SMS message, app=" + app.getIdentifier() + ", message ID=" + messageId + ", request ID=" + RequestContext.get().getId());
    // Log SMS message.
    DateTime sentOn = DateTime.now();
    SmsMessage smsMessage = SmsMessage.create();
    smsMessage.setPhoneNumber(recipientPhone.getNumber());
    smsMessage.setSentOn(sentOn.getMillis());
    smsMessage.setMessageBody(message);
    smsMessage.setMessageId(messageId);
    smsMessage.setSmsType(provider.getSmsTypeEnum());
    smsMessage.setAppId(app.getIdentifier());
    // Fetch participant, if it exists.
    StudyParticipant participant = null;
    if (userId != null) {
        participant = participantService.getParticipant(app, userId, false);
    }
    // Finish logging SMS message.
    if (participant != null) {
        smsMessage.setHealthCode(participant.getHealthCode());
    }
    Validate.entityThrowingException(SmsMessageValidator.INSTANCE, smsMessage);
    messageDao.logMessage(smsMessage);
    // If we have a participant, make a health data.
    if (participant != null) {
        initMessageLogSchema(app.getIdentifier());
        // Set sentOn w/ user's time zone, if it exists.
        DateTime sentOnWithTimeZone;
        if (participant.getTimeZone() != null) {
            sentOnWithTimeZone = sentOn.withZone(participant.getTimeZone());
        } else {
            sentOnWithTimeZone = sentOn.withZone(DateTimeZone.UTC);
        }
        // Create health data.
        ObjectNode healthDataNode = BridgeObjectMapper.get().createObjectNode();
        healthDataNode.put(FIELD_NAME_SENT_ON, sentOnWithTimeZone.toString());
        healthDataNode.put(FIELD_NAME_SMS_TYPE, provider.getSmsType());
        healthDataNode.put(FIELD_NAME_MESSAGE_BODY, message);
        // Health Data Service requires app version and phone info. However, this health data is submitted by
        // Bridge, not by the app, so fill those in with artificial values.
        HealthDataSubmission healthData = new HealthDataSubmission.Builder().withAppVersion(BRIDGE_SERVER_APP_VERSION).withPhoneInfo(BRIDGE_SERVER_PHONE_INFO).withCreatedOn(sentOnWithTimeZone).withSchemaId(MESSAGE_LOG_SCHEMA_ID).withSchemaRevision(MESSAGE_LOG_SCHEMA_REV).withData(healthDataNode).build();
        try {
            healthDataService.submitHealthData(app.getIdentifier(), participant, healthData);
        } catch (IOException | UploadValidationException ex) {
            throw new BridgeServiceException(ex);
        }
    }
}
Also used : App(org.sagebionetworks.bridge.models.apps.App) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) BridgeServiceException(org.sagebionetworks.bridge.exceptions.BridgeServiceException) StudyParticipant(org.sagebionetworks.bridge.models.accounts.StudyParticipant) IOException(java.io.IOException) DateTime(org.joda.time.DateTime) PublishResult(com.amazonaws.services.sns.model.PublishResult) SmsMessage(org.sagebionetworks.bridge.models.sms.SmsMessage) HealthDataSubmission(org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission) Phone(org.sagebionetworks.bridge.models.accounts.Phone) UploadValidationException(org.sagebionetworks.bridge.upload.UploadValidationException)

Example 3 with UploadValidationException

use of org.sagebionetworks.bridge.upload.UploadValidationException in project BridgeServer2 by Sage-Bionetworks.

the class CRCController method writeReportAndUpdateState.

private int writeReportAndUpdateState(App app, String userId, JsonNode data, String reportName, AccountStates state, boolean useCallerStudyIds) {
    String appId = RequestContext.get().getCallerAppId();
    AccountId accountId = AccountId.forId(appId, userId);
    Account account = accountService.getAccount(accountId).orElseThrow(() -> new EntityNotFoundException(Account.class));
    updateState(account, state);
    accountService.updateAccount(account);
    try {
        ObjectNode metadata = JsonNodeFactory.instance.objectNode();
        metadata.put("type", reportName);
        StudyParticipant participant = participantService.getParticipant(app, account, false);
        HealthDataSubmission healthData = new HealthDataSubmission.Builder().withAppVersion("v1").withCreatedOn(getTimestamp()).withMetadata(metadata).withData(data).withPhoneInfo(getUserAgent()).build();
        healthDataService.submitHealthData(appId, participant, healthData);
    } catch (IOException | UploadValidationException e) {
        throw new BridgeServiceException(e);
    }
    Set<String> callerStudyIds = useCallerStudyIds ? RequestContext.get().getOrgSponsoredStudies() : ImmutableSet.of();
    ReportData report = ReportData.create();
    report.setDate(JAN1.toString());
    report.setData(data);
    report.setStudyIds(callerStudyIds);
    DateRangeResourceList<? extends ReportData> results = reportService.getParticipantReport(appId, userId, reportName, account.getHealthCode(), JAN1, JAN2);
    int status = (results.getItems().isEmpty()) ? 201 : 200;
    reportService.saveParticipantReport(appId, userId, reportName, account.getHealthCode(), report);
    return status;
}
Also used : Account(org.sagebionetworks.bridge.models.accounts.Account) BridgeUtils.parseAccountId(org.sagebionetworks.bridge.BridgeUtils.parseAccountId) AccountId(org.sagebionetworks.bridge.models.accounts.AccountId) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) BridgeServiceException(org.sagebionetworks.bridge.exceptions.BridgeServiceException) EntityNotFoundException(org.sagebionetworks.bridge.exceptions.EntityNotFoundException) StudyParticipant(org.sagebionetworks.bridge.models.accounts.StudyParticipant) IOException(java.io.IOException) ContactPoint(org.hl7.fhir.dstu3.model.ContactPoint) HealthDataSubmission(org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission) UploadValidationException(org.sagebionetworks.bridge.upload.UploadValidationException) ReportData(org.sagebionetworks.bridge.models.reports.ReportData)

Aggregations

UploadValidationException (org.sagebionetworks.bridge.upload.UploadValidationException)3 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)2 IOException (java.io.IOException)2 BridgeServiceException (org.sagebionetworks.bridge.exceptions.BridgeServiceException)2 StudyParticipant (org.sagebionetworks.bridge.models.accounts.StudyParticipant)2 HealthDataSubmission (org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission)2 PublishResult (com.amazonaws.services.sns.model.PublishResult)1 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 ContactPoint (org.hl7.fhir.dstu3.model.ContactPoint)1 DateTime (org.joda.time.DateTime)1 BridgeUtils.parseAccountId (org.sagebionetworks.bridge.BridgeUtils.parseAccountId)1 BadRequestException (org.sagebionetworks.bridge.exceptions.BadRequestException)1 EntityNotFoundException (org.sagebionetworks.bridge.exceptions.EntityNotFoundException)1 InvalidEntityException (org.sagebionetworks.bridge.exceptions.InvalidEntityException)1 Account (org.sagebionetworks.bridge.models.accounts.Account)1 AccountId (org.sagebionetworks.bridge.models.accounts.AccountId)1 Phone (org.sagebionetworks.bridge.models.accounts.Phone)1 App (org.sagebionetworks.bridge.models.apps.App)1 HealthDataRecord (org.sagebionetworks.bridge.models.healthdata.HealthDataRecord)1 ReportData (org.sagebionetworks.bridge.models.reports.ReportData)1