use of org.sagebionetworks.bridge.exceptions.BadRequestException in project BridgeServer2 by Sage-Bionetworks.
the class ParticipantService method sendInstallLinkMessage.
/**
* Send a message by either email or SMS, depending on the configuration of the account.
* IMPORTANT: the email and phone are considered to be verified; pass null for these arguments
* if the values are not verified. We do it this way so the IntentService can provide values
* even before an account exists.
*/
public void sendInstallLinkMessage(App app, SmsType type, String healthCode, String email, Phone phone, String osName) {
if (email == null && phone == null) {
throw new BadRequestException(ACCOUNT_UNABLE_TO_BE_CONTACTED_ERROR);
}
if (app.getInstallLinks().isEmpty()) {
throw new BadRequestException(NO_INSTALL_LINKS_ERROR);
}
String url = getInstallLink(osName, app.getInstallLinks());
if (phone != null) {
TemplateRevision revision = templateService.getRevisionForUser(app, SMS_APP_INSTALL_LINK);
SmsMessageProvider.Builder builder = new SmsMessageProvider.Builder().withApp(app).withTemplateRevision(revision).withPromotionType().withPhone(phone).withToken(APP_INSTALL_URL_KEY, url);
if (type == SmsType.PROMOTIONAL) {
builder.withPromotionType();
} else {
builder.withTransactionType();
}
// Account hasn't been created yet, so there is no ID yet. Pass in null user ID to
// SMS Service.
smsService.sendSmsMessage(null, builder.build());
} else {
TemplateRevision revision = templateService.getRevisionForUser(app, EMAIL_APP_INSTALL_LINK);
BasicEmailProvider provider = new BasicEmailProvider.Builder().withApp(app).withTemplateRevision(revision).withRecipientEmail(email).withType(EmailType.APP_INSTALL).withToken(APP_INSTALL_URL_KEY, url).build();
sendMailService.sendEmail(provider);
}
// exists yet. We only publish it when this template is triggered for an existing account.
if (healthCode != null) {
activityEventService.publishInstallLinkSent(app, healthCode, getInstallDateTime());
}
}
use of org.sagebionetworks.bridge.exceptions.BadRequestException in project BridgeServer2 by Sage-Bionetworks.
the class ParticipantService method resendVerification.
public void resendVerification(App app, ChannelType type, String userId) {
checkNotNull(app);
checkArgument(isNotBlank(userId));
StudyParticipant participant = getParticipant(app, userId, false);
if (type == ChannelType.EMAIL) {
if (participant.getEmail() == null) {
throw new BadRequestException("Email address has not been set.");
}
AccountId accountId = AccountId.forEmail(app.getIdentifier(), participant.getEmail());
accountWorkflowService.resendVerificationToken(type, accountId);
} else if (type == ChannelType.PHONE) {
if (participant.getPhone() == null) {
throw new BadRequestException("Phone number has not been set.");
}
AccountId accountId = AccountId.forPhone(app.getIdentifier(), participant.getPhone());
accountWorkflowService.resendVerificationToken(type, accountId);
} else {
throw new UnsupportedOperationException("Channel type not implemented");
}
}
use of org.sagebionetworks.bridge.exceptions.BadRequestException in project BridgeServer2 by Sage-Bionetworks.
the class ParticipantService method createSmsRegistration.
/**
* This is a researcher API to backfill SMS notification registrations for a user. We generally prefer the app
* register notifications, but sometimes the work can't be done on time, so we want study developers to have the
* option of backfilling these.
*/
public void createSmsRegistration(App app, String userId) {
checkNotNull(app);
checkNotNull(userId);
// Account must have a verified phone number.
Account account = getAccountThrowingException(app.getIdentifier(), userId);
if (!TRUE.equals(account.getPhoneVerified())) {
throw new BadRequestException("Can't create SMS notification registration for user " + userId + ": user has no verified phone number");
}
// We need the account's request info to build the criteria context.
RequestInfo requestInfo = requestInfoService.getRequestInfo(userId);
if (requestInfo == null) {
throw new BadRequestException("Can't create SMS notification registration for user " + userId + ": user has no request info");
}
Set<String> studyIds = BridgeUtils.collectStudyIds(account);
CriteriaContext criteriaContext = new CriteriaContext.Builder().withAppId(app.getIdentifier()).withUserId(userId).withHealthCode(account.getHealthCode()).withClientInfo(requestInfo.getClientInfo()).withLanguages(requestInfo.getLanguages()).withUserDataGroups(account.getDataGroups()).withUserStudyIds(studyIds).build();
// Participant must be consented.
StudyParticipant participant = getParticipant(app, account, false);
if (!TRUE.equals(participant.isConsented())) {
throw new BadRequestException("Can't create SMS notification registration for user " + userId + ": user is not consented");
}
// Create registration.
NotificationRegistration registration = NotificationRegistration.create();
registration.setHealthCode(account.getHealthCode());
registration.setProtocol(NotificationProtocol.SMS);
registration.setEndpoint(account.getPhone().getNumber());
// Create registration.
notificationsService.createRegistration(app.getIdentifier(), criteriaContext, registration);
}
use of org.sagebionetworks.bridge.exceptions.BadRequestException in project BridgeServer2 by Sage-Bionetworks.
the class OAuthProviderService method oauthSignIn.
/**
* Authenticate a Bridge user via an external OAuth server that supports Open Connect ID (identified by the supplied
* vendor ID; currently the only supported external authentication server is Synapse, but the same requirements are
* fulfilled by Google, Facebook, etc.). This is the second contact of the OAuth server, after a client has sent a
* user to authenticate on the OAuth server's web site and the OAuth server has redirected back to the Bridge client
* with an authentication code. We now exchange it for an authentication token as well as the additional OCID
* information to verify the identity of the caller (currently we ask for the user's Synapse ID from Synapse, but we
* could also use email or phone number).
*
* @param authToken
* that was passed from the OAuth server back to the authenticating client
* @return accountId if the exchange is successful, the accountId will contain an identifying credential that should
* be usable to retrieve an account
*
* @throws BadRequestException
*/
public AccountId oauthSignIn(OAuthAuthorizationToken authToken) {
checkNotNull(authToken);
if (authToken.getVendorId() == null) {
throw new BadRequestException("Vendor ID required");
}
if (authToken.getAppId() == null) {
throw new BadRequestException("App ID required");
}
if (authToken.getAuthToken() == null) {
throw new BadRequestException("Authorization token required");
}
OAuthProvider provider = null;
if (SYNAPSE_OAUTH_VENDOR_ID.equals(authToken.getVendorId())) {
// Synapse configuration is globally available and not stored in providers table.
provider = new OAuthProvider(this.synapseClientID, this.synapseClientSecret, this.synapseOauthURL, authToken.getCallbackUrl(), null);
} else {
// Is this vendor ID mapped to another provider for this app?
App app = appService.getApp(authToken.getAppId());
provider = app.getOAuthProviders().get(authToken.getVendorId());
}
if (provider == null) {
throw new BadRequestException("Vendor not supported: " + authToken.getVendorId());
}
HttpPost client = createOAuthProviderPost(provider, provider.getEndpoint());
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair(GRANT_TYPE_PROP_NAME, AUTHORIZATION_CODE_VALUE));
pairs.add(new BasicNameValuePair(CODE_PROP_NAME, authToken.getAuthToken()));
pairs.add(new BasicNameValuePair(REDIRECT_URI_PROP_NAME, authToken.getCallbackUrl()));
client.setEntity(formEntity(pairs));
Response response = executeGrantRequest(client);
if (response.getStatusCode() < 200 || response.getStatusCode() > 299) {
throw new BadRequestException(response.getBody().get(SYNAPSE_ERROR_KEY).textValue());
}
JwtParser parser = getJwtParser();
parser.setSigningKey(getRSAPublicKey());
parser.setAllowedClockSkewSeconds(5);
String idTokenBlock = response.getBody().get(SYNAPSE_ID_TOKEN_KEY).textValue();
Jws<Claims> jwt = parser.parseClaimsJws(idTokenBlock);
String synapseUserId = jwt.getBody().get(SYNAPSE_USERID_KEY, String.class);
if (synapseUserId != null) {
return AccountId.forSynapseUserId(authToken.getAppId(), synapseUserId);
}
return null;
}
use of org.sagebionetworks.bridge.exceptions.BadRequestException in project BridgeServer2 by Sage-Bionetworks.
the class ReportService method getStudyReportV4.
/**
* Return set of study report records based on the provided datetime range. Study memberships are enforced.
*/
public ForwardCursorPagedResourceList<ReportData> getStudyReportV4(final String appId, final String identifier, final DateTime startTime, final DateTime endTime, final String offsetKey, final int pageSize) {
if (pageSize < API_MINIMUM_PAGE_SIZE || pageSize > API_MAXIMUM_PAGE_SIZE) {
throw new BadRequestException(BridgeConstants.PAGE_SIZE_ERROR);
}
RangeTuple<DateTime> finalTimes = validateDateTimeRange(startTime, endTime);
ReportDataKey key = new ReportDataKey.Builder().withReportType(ReportType.STUDY).withIdentifier(identifier).withAppId(appId).build();
Validate.entityThrowingException(ReportDataKeyValidator.INSTANCE, key);
ReportIndex index = reportIndexDao.getIndex(key);
checkStudyReportAccess(index);
return reportDataDao.getReportDataV4(key, finalTimes.getStart(), finalTimes.getEnd(), offsetKey, pageSize);
}
Aggregations