use of org.sagebionetworks.bridge.models.apps.App in project BridgeServer2 by Sage-Bionetworks.
the class Exporter3ServiceTest method initExporter3.
@Test
public void initExporter3() throws Exception {
// App has no exporter3config.
app.setExporter3Configuration(null);
app.setExporter3Enabled(false);
// Mock SynapseHelper.
Team createdTeam = new Team();
createdTeam.setId(String.valueOf(DATA_ACCESS_TEAM_ID));
when(mockSynapseHelper.createTeamWithRetry(any())).thenReturn(createdTeam);
Project createdProject = new Project();
createdProject.setId(PROJECT_ID);
when(mockSynapseHelper.createEntityWithRetry(any(Project.class))).thenReturn(createdProject);
EntityView trackingView = new EntityView();
trackingView.setScopeIds(new ArrayList<>());
when(mockSynapseHelper.getEntityWithRetry(SYNAPSE_TRACKING_VIEW_ID, EntityView.class)).thenReturn(trackingView);
TableEntity createdTable = new TableEntity();
createdTable.setId(PARTICIPANT_VERSION_TABLE_ID);
when(mockSynapseHelper.createTableWithColumnsAndAcls(anyList(), anySet(), anySet(), anyString(), anyString())).thenReturn(PARTICIPANT_VERSION_TABLE_ID);
Folder createdFolder = new Folder();
createdFolder.setId(RAW_FOLDER_ID);
when(mockSynapseHelper.createEntityWithRetry(any(Folder.class))).thenReturn(createdFolder);
ExternalS3StorageLocationSetting createdStorageLocation = new ExternalS3StorageLocationSetting();
createdStorageLocation.setStorageLocationId(STORAGE_LOCATION_ID);
when(mockSynapseHelper.createStorageLocationForEntity(eq(RAW_FOLDER_ID), any(ExternalS3StorageLocationSetting.class))).thenReturn(createdStorageLocation);
// Execute and verify output.
Exporter3Configuration returnedEx3Config = exporter3Service.initExporter3(TestConstants.TEST_APP_ID);
assertEquals(returnedEx3Config.getDataAccessTeamId().longValue(), DATA_ACCESS_TEAM_ID);
assertEquals(returnedEx3Config.getParticipantVersionTableId(), PARTICIPANT_VERSION_TABLE_ID);
assertEquals(returnedEx3Config.getProjectId(), PROJECT_ID);
assertEquals(returnedEx3Config.getRawDataFolderId(), RAW_FOLDER_ID);
assertEquals(returnedEx3Config.getStorageLocationId().longValue(), STORAGE_LOCATION_ID);
// Verify created team.
ArgumentCaptor<Team> teamToCreateCaptor = ArgumentCaptor.forClass(Team.class);
verify(mockSynapseHelper).createTeamWithRetry(teamToCreateCaptor.capture());
Team teamToCreate = teamToCreateCaptor.getValue();
assertEquals(teamToCreate.getName(), EXPECTED_TEAM_NAME);
// Verify created project. Note that we call this method again later, which is why we verify it twice now.
ArgumentCaptor<Entity> entitiesToCreateCaptor = ArgumentCaptor.forClass(Project.class);
verify(mockSynapseHelper, times(2)).createEntityWithRetry(entitiesToCreateCaptor.capture());
List<Entity> entitiesToCreateList = entitiesToCreateCaptor.getAllValues();
Project projectToCreate = (Project) entitiesToCreateList.get(0);
assertEquals(projectToCreate.getName(), EXPECTED_PROJECT_NAME);
// Verify project ACLs.
verify(mockSynapseHelper).createAclWithRetry(PROJECT_ID, ADMIN_PRINCIPAL_ID_SET, READ_ONLY_PRINCIPAL_ID_SET);
// Verify project added to tracking view. For whatever reason, view scope IDs don't include the "syn" prefix.
ArgumentCaptor<EntityView> viewToUpdateCaptor = ArgumentCaptor.forClass(EntityView.class);
verify(mockSynapseHelper).updateEntityWithRetry(viewToUpdateCaptor.capture());
EntityView viewToUpdate = viewToUpdateCaptor.getValue();
assertTrue(viewToUpdate.getScopeIds().contains(PROJECT_ID_WITHOUT_PREFIX));
// Verify created participant version table.
verify(mockSynapseHelper).createTableWithColumnsAndAcls(Exporter3Service.PARTICIPANT_VERSION_COLUMN_MODELS, READ_ONLY_PRINCIPAL_ID_SET, ADMIN_PRINCIPAL_ID_SET, PROJECT_ID, Exporter3Service.TABLE_NAME_PARTICIPANT_VERSIONS);
// Verify created folder.
Folder folderToCreate = (Folder) entitiesToCreateList.get(1);
assertEquals(folderToCreate.getName(), Exporter3Service.FOLDER_NAME_BRIDGE_RAW_DATA);
assertEquals(folderToCreate.getParentId(), PROJECT_ID);
// Verify folder ACLs.
verify(mockSynapseHelper).createAclWithRetry(RAW_FOLDER_ID, ADMIN_PRINCIPAL_ID_SET, READ_ONLY_PRINCIPAL_ID_SET);
// Verify we write to S3 for the storage location.
verify(mockS3Helper).writeLinesToS3(RAW_HEALTH_DATA_BUCKET, TestConstants.TEST_APP_ID + "/owner.txt", ImmutableList.of(EXPORTER_SYNAPSE_USER));
// Verify created storage location.
ArgumentCaptor<ExternalS3StorageLocationSetting> storageLocationToCreateCaptor = ArgumentCaptor.forClass(ExternalS3StorageLocationSetting.class);
verify(mockSynapseHelper).createStorageLocationForEntity(eq(RAW_FOLDER_ID), storageLocationToCreateCaptor.capture());
ExternalS3StorageLocationSetting storageLocationToCreate = storageLocationToCreateCaptor.getValue();
assertEquals(storageLocationToCreate.getBaseKey(), TestConstants.TEST_APP_ID);
assertEquals(storageLocationToCreate.getBucket(), RAW_HEALTH_DATA_BUCKET);
assertTrue(storageLocationToCreate.getStsEnabled());
// Verify updated app.
ArgumentCaptor<App> appToUpdateCaptor = ArgumentCaptor.forClass(App.class);
verify(mockAppService).updateApp(appToUpdateCaptor.capture(), eq((true)));
App appToUpdate = appToUpdateCaptor.getValue();
assertTrue(appToUpdate.isExporter3Enabled());
Exporter3Configuration ex3ConfigToCreate = appToUpdate.getExporter3Configuration();
assertEquals(ex3ConfigToCreate, returnedEx3Config);
}
use of org.sagebionetworks.bridge.models.apps.App in project BridgeServer2 by Sage-Bionetworks.
the class UploadService method uploadComplete.
public void uploadComplete(String appId, UploadCompletionClient completedBy, Upload upload, boolean redrive) {
String uploadId = upload.getUploadId();
// We don't want to kick off upload validation on an upload that already has upload validation.
if (!upload.canBeValidated() && !redrive) {
logger.info(String.format("uploadComplete called for upload %s, which is already complete", uploadId));
return;
}
final String objectId = upload.getObjectId();
ObjectMetadata obj;
try {
Stopwatch stopwatch = Stopwatch.createStarted();
obj = s3Client.getObjectMetadata(uploadBucket, objectId);
logger.info("Finished getting S3 metadata for bucket " + uploadBucket + " key " + objectId + " in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms");
} catch (AmazonS3Exception ex) {
if (ex.getStatusCode() == 404) {
throw new NotFoundException(ex);
} else {
// Only S3 404s are mapped to 404s. Everything else is an internal server error.
throw new BridgeServiceException(ex);
}
}
String sse = obj.getSSEAlgorithm();
if (!AES_256_SERVER_SIDE_ENCRYPTION.equals(sse)) {
logger.error("Missing S3 server-side encryption (SSE) for presigned upload " + uploadId + ".");
}
try {
uploadDao.uploadComplete(completedBy, upload);
} catch (ConcurrentModificationException ex) {
// The old workflow is the app calls uploadComplete. The new workflow has an S3 trigger to call
// uploadComplete. During the transition, it's very likely that this will be called twice, sometimes
// concurrently. As such, we should log and squelch the ConcurrentModificationException.
logger.info("Concurrent modification of upload " + uploadId + " while marking upload complete");
// and duplicate records.
return;
}
// kick off upload validation
App app = appService.getApp(appId);
if (BridgeUtils.isExporter3Configured(app)) {
exporter3Service.completeUpload(app, upload);
}
// For backwards compatibility, always call Legacy Exporter 2.0. In the future, we may introduce a setting to
// disable this for new apps.
uploadValidationService.validateUpload(appId, upload);
}
use of org.sagebionetworks.bridge.models.apps.App in project BridgeServer2 by Sage-Bionetworks.
the class CRCController method updateParticipant.
@PostMapping("/v1/cuimc/participants/{userId}/laborders")
public StatusMessage updateParticipant(@PathVariable String userId) {
App app = httpBasicAuthentication();
AccountId accountId = parseAccountId(app.getIdentifier(), userId);
Account account = accountService.getAccount(accountId).orElseThrow(() -> new EntityNotFoundException(Account.class));
if (account == null) {
throw new EntityNotFoundException(Account.class);
}
updateState(account, SELECTED);
accountService.updateAccount(account);
return new StatusMessage("Participant updated.");
}
use of org.sagebionetworks.bridge.models.apps.App in project BridgeServer2 by Sage-Bionetworks.
the class CRCController method postProcedureRequest.
@PutMapping("/v1/cuimc/procedurerequests")
public ResponseEntity<StatusMessage> postProcedureRequest() {
App app = httpBasicAuthentication();
IParser parser = FHIR_CONTEXT.newJsonParser();
JsonNode data = parseJson(JsonNode.class);
ProcedureRequest procedure = parser.parseResource(ProcedureRequest.class, data.toString());
String userId = findUserId(procedure.getSubject());
int status = writeReportAndUpdateState(app, userId, data, PROCEDURE_REPORT, AccountStates.TESTS_COLLECTED, true);
if (status == 200) {
return ResponseEntity.ok(new StatusMessage("ProcedureRequest updated."));
}
return ResponseEntity.created(URI.create("/v1/cuimc/procedurerequests/" + userId)).body(new StatusMessage("ProcedureRequest created."));
}
use of org.sagebionetworks.bridge.models.apps.App in project BridgeServer2 by Sage-Bionetworks.
the class CRCController method httpBasicAuthentication.
/**
* This is bound to specific “machine” accounts that are enumerated in the controller. Authentication is
* session-less. The account itself has no administrative roles, so it can only execute these endpoints that
* specifically allows it, in the app to which it is bound.
*/
App httpBasicAuthentication() {
String value = request().getHeader(AUTHORIZATION);
if (value == null || value.length() < 5) {
throw new NotAuthenticatedException();
}
// Remove "Basic ";
value = value.substring(5).trim();
// Decode the credentials from base 64
value = new String(Base64.getDecoder().decode(value), Charset.defaultCharset());
// Split to username and password
String[] credentials = value.split(":");
if (credentials.length != 2) {
throw new NotAuthenticatedException();
}
String appId = ACCOUNTS.get(credentials[0]);
if (appId == null) {
throw new NotAuthenticatedException();
}
SignIn.Builder signInBuilder = new SignIn.Builder().withAppId(appId).withPassword(credentials[1]);
if (credentials[0].contains("@sagebase.org")) {
signInBuilder.withEmail(credentials[0]);
} else {
signInBuilder.withExternalId(credentials[0]);
}
App app = appService.getApp(appId);
// Verify the password
SignIn signIn = signInBuilder.build();
Account account = accountService.authenticate(app, signIn);
// This method of verification sidesteps RequestContext initialization
// through a session. Set up what is needed in the controller.
Set<String> studies = BridgeUtils.collectStudyIds(account);
RequestContext.Builder builder = new RequestContext.Builder().withCallerAppId(appId).withCallerRoles(account.getRoles()).withCallerUserId(account.getId()).withOrgSponsoredStudies(studies).withCallerOrgMembership(account.getOrgMembership());
RequestContext.set(builder.build());
return app;
}
Aggregations