use of org.sagebionetworks.repo.model.Team 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.repo.model.Team in project BridgeServer2 by Sage-Bionetworks.
the class Exporter3Service method initExporter3.
/**
* Initializes configs and Synapse resources for Exporter 3.0. Note that if any config already exists, this API
* will simply ignore them. This allows for two notable scenarios
* (a) Advanced users can use existing projects or data access teams for Exporter 3.0.
* (b) If in the future, we add something new (like a notification queue, or a default view), we can re-run this
* API to create the new stuff without affecting the old stuff.
*/
public Exporter3Configuration initExporter3(String appId) throws BridgeSynapseException, IOException, SynapseException {
boolean isAppModified = false;
App app = appService.getApp(appId);
// Init the Exporter3Config object.
Exporter3Configuration ex3Config = app.getExporter3Configuration();
if (ex3Config == null) {
ex3Config = new Exporter3Configuration();
app.setExporter3Configuration(ex3Config);
isAppModified = true;
}
// Name in Synapse are globally unique, so we add a random token to the name to ensure it
// doesn't conflict with an existing name. Also, Synapse names can only contain a certain
// subset of characters. We've verified this name is acceptable for this transformation.
String synapseName = BridgeUtils.toSynapseFriendlyName(app.getName());
String nameScopingToken = getNameScopingToken();
// Create data access team.
Long dataAccessTeamId = ex3Config.getDataAccessTeamId();
if (dataAccessTeamId == null) {
Team team = new Team();
team.setName(synapseName + " Access Team " + nameScopingToken);
team = synapseHelper.createTeamWithRetry(team);
dataAccessTeamId = Long.parseLong(team.getId());
LOG.info("Created Synapse team " + dataAccessTeamId);
ex3Config.setDataAccessTeamId(dataAccessTeamId);
isAppModified = true;
}
Set<Long> adminPrincipalIds = ImmutableSet.of(exporterSynapseId, bridgeAdminTeamId);
Set<Long> readOnlyPrincipalIds = ImmutableSet.of(bridgeStaffTeamId, dataAccessTeamId);
// Create project.
String projectId = ex3Config.getProjectId();
if (projectId == null) {
Project project = new Project();
project.setName(synapseName + " Project " + nameScopingToken);
project = synapseHelper.createEntityWithRetry(project);
projectId = project.getId();
LOG.info("Created Synapse project " + projectId);
// Create ACLs for project.
synapseHelper.createAclWithRetry(projectId, adminPrincipalIds, readOnlyPrincipalIds);
ex3Config.setProjectId(projectId);
isAppModified = true;
// We also need to add this project to the tracking view.
if (StringUtils.isNotBlank(synapseTrackingViewId)) {
try {
EntityView view = synapseHelper.getEntityWithRetry(synapseTrackingViewId, EntityView.class);
if (view != null) {
// For whatever reason, view.getScopes() doesn't include the "syn" prefix.
view.getScopeIds().add(projectId.substring(3));
synapseHelper.updateEntityWithRetry(view);
}
} catch (SynapseException ex) {
LOG.error("Error adding new project " + projectId + " to tracking view " + synapseTrackingViewId + ": " + ex.getMessage(), ex);
}
}
}
// Create Participant Version Table.
String participantVersionTableId = ex3Config.getParticipantVersionTableId();
if (participantVersionTableId == null) {
participantVersionTableId = synapseHelper.createTableWithColumnsAndAcls(PARTICIPANT_VERSION_COLUMN_MODELS, readOnlyPrincipalIds, adminPrincipalIds, projectId, TABLE_NAME_PARTICIPANT_VERSIONS);
LOG.info("Created Synapse table " + participantVersionTableId);
ex3Config.setParticipantVersionTableId(participantVersionTableId);
isAppModified = true;
}
// Create Folder for raw data.
String rawDataFolderId = ex3Config.getRawDataFolderId();
if (rawDataFolderId == null) {
Folder folder = new Folder();
folder.setName(FOLDER_NAME_BRIDGE_RAW_DATA);
folder.setParentId(projectId);
folder = synapseHelper.createEntityWithRetry(folder);
rawDataFolderId = folder.getId();
LOG.info("Created Synapse folder " + rawDataFolderId);
// Create ACLs for folder. This is a separate ACL because we don't want to allow people to modify the
// raw data.
synapseHelper.createAclWithRetry(rawDataFolderId, adminPrincipalIds, readOnlyPrincipalIds);
ex3Config.setRawDataFolderId(rawDataFolderId);
isAppModified = true;
}
// Create storage location.
Long storageLocationId = ex3Config.getStorageLocationId();
if (storageLocationId == null) {
// Create owner.txt so that we can create the storage location.
s3Helper.writeLinesToS3(rawHealthDataBucket, appId + "/owner.txt", ImmutableList.of(exporterSynapseUser));
// Create storage location.
ExternalS3StorageLocationSetting storageLocation = new ExternalS3StorageLocationSetting();
storageLocation.setBaseKey(appId);
storageLocation.setBucket(rawHealthDataBucket);
storageLocation.setStsEnabled(true);
storageLocation = synapseHelper.createStorageLocationForEntity(rawDataFolderId, storageLocation);
storageLocationId = storageLocation.getStorageLocationId();
LOG.info("Created Synapse storage location " + storageLocationId);
ex3Config.setStorageLocationId(storageLocationId);
isAppModified = true;
}
// Finally, enable Exporter 3.0 if it's not already enabled.
if (!app.isExporter3Enabled()) {
app.setExporter3Enabled(true);
isAppModified = true;
}
// exporter3config and exporter3enabled.
if (isAppModified) {
appService.updateApp(app, true);
}
return ex3Config;
}
use of org.sagebionetworks.repo.model.Team in project BridgeServer2 by Sage-Bionetworks.
the class AppService method createSynapseProjectTeam.
protected App createSynapseProjectTeam(List<String> synapseUserIds, List<String> userIds, App app) throws SynapseException {
// first check if app already has project and team ids
if (app.getSynapseDataAccessTeamId() != null) {
throw new EntityAlreadyExistsException(App.class, "App already has a team ID.", new ImmutableMap.Builder<String, Object>().put(IDENTIFIER_PROPERTY, app.getIdentifier()).put("synapseDataAccessTeamId", app.getSynapseDataAccessTeamId()).build());
}
if (app.getSynapseProjectId() != null) {
throw new EntityAlreadyExistsException(App.class, "App already has a project ID.", new ImmutableMap.Builder<String, Object>().put(IDENTIFIER_PROPERTY, app.getIdentifier()).put("synapseProjectId", app.getSynapseProjectId()).build());
}
// Name in Synapse are globally unique, so we add a random token to the name to ensure it
// doesn't conflict with an existing name. Also, Synapse names can only contain a certain
// subset of characters. We've verified this name is acceptable for this transformation.
String synapseName = BridgeUtils.toSynapseFriendlyName(app.getName());
String nameScopingToken = getNameScopingToken();
// create synapse project and team
Team team = new Team();
team.setName(synapseName + " Access Team " + nameScopingToken);
Team newTeam = synapseClient.createTeam(team);
String newTeamId = newTeam.getId();
Project project = new Project();
project.setName(synapseName + " Project " + nameScopingToken);
Project newProject = synapseClient.createEntity(project);
String newProjectId = newProject.getId();
// Add the exporter, bridge admin team, and individuals as admins
AccessControlList projectACL = synapseClient.getACL(newProjectId);
// add exporter as admin
addAdminToACL(projectACL, EXPORTER_SYNAPSE_USER_ID);
addAdminToACL(projectACL, bridgeAdminTeamId);
for (String synapseUserId : synapseUserIds) {
addAdminToACL(projectACL, synapseUserId);
}
// Add the data access team and bridge staff team as a read/download team
addToACL(projectACL, bridgeStaffTeamId, READ_DOWNLOAD_ACCESS);
addToACL(projectACL, newTeamId, READ_DOWNLOAD_ACCESS);
synapseClient.updateACL(projectACL);
addProjectToTrackingView(newProjectId);
// Users added afterwards will have read/download rights through the access team.
for (String synapseUserId : synapseUserIds) {
MembershipInvitation teamMemberInvitation = new MembershipInvitation();
teamMemberInvitation.setInviteeId(synapseUserId);
teamMemberInvitation.setTeamId(newTeamId);
synapseClient.createMembershipInvitation(teamMemberInvitation, null, null);
synapseClient.setTeamMemberPermissions(newTeamId, synapseUserId, true);
}
// Add users as non-admin members of the team
for (String userId : userIds) {
MembershipInvitation teamMemberInvitation = new MembershipInvitation();
teamMemberInvitation.setInviteeId(userId);
teamMemberInvitation.setTeamId(newTeamId);
synapseClient.createMembershipInvitation(teamMemberInvitation, null, null);
synapseClient.setTeamMemberPermissions(newTeamId, userId, false);
}
// finally, update app
app.setSynapseProjectId(newProjectId);
app.setSynapseDataAccessTeamId(Long.parseLong(newTeamId));
updateApp(app, false);
return app;
}
use of org.sagebionetworks.repo.model.Team in project BridgeServer2 by Sage-Bionetworks.
the class AppServiceTest method before.
@BeforeMethod
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
// Mock config.
when(mockBridgeConfig.get(AppService.CONFIG_KEY_SUPPORT_EMAIL_PLAIN)).thenReturn(SUPPORT_EMAIL);
when(mockBridgeConfig.get(AppService.CONFIG_KEY_TEAM_BRIDGE_ADMIN)).thenReturn(String.valueOf(BRIDGE_ADMIN_TEAM_ID));
when(mockBridgeConfig.get(AppService.CONFIG_KEY_TEAM_BRIDGE_STAFF)).thenReturn(String.valueOf(BRIDGE_STAFF_TEAM_ID));
when(mockBridgeConfig.getPropertyAsList(AppService.CONFIG_APP_WHITELIST)).thenReturn(ImmutableList.of(API_APP_ID));
when(mockBridgeConfig.get(AppService.CONFIG_KEY_SYNAPSE_TRACKING_VIEW)).thenReturn(SYNAPSE_TRACKING_VIEW_ID);
// this has to be set again after being mocked
service.setBridgeConfig(mockBridgeConfig);
// Mock templates
service.setAppEmailVerificationTemplateSubject(mockTemplateAsSpringResource("Verify your app email"));
service.setAppEmailVerificationTemplate(mockTemplateAsSpringResource("Click here ${appEmailVerificationUrl} ${appEmailVerificationExpirationPeriod}" + " ${studyEmailVerificationUrl} ${studyEmailVerificationExpirationPeriod}"));
service.setValidator(new AppValidator());
AppAndUsersValidator appAndUsersValidator = new AppAndUsersValidator();
appAndUsersValidator.setSynapseClient(mockSynapseClient);
service.setAppAndUsersValidator(appAndUsersValidator);
when(service.getNameScopingToken()).thenReturn(TEST_NAME_SCOPING_TOKEN);
app = getTestApp();
app.setIdentifier(TEST_APP_ID);
when(mockAppDao.getApp(TEST_APP_ID)).thenReturn(app);
GuidVersionHolder keys = new GuidVersionHolder("guid", 1L);
when(mockTemplateService.createTemplate(any(), any())).thenReturn(keys);
when(mockAppDao.createApp(any())).thenAnswer(invocation -> {
// Return the same app, except set version to 1.
App app = invocation.getArgument(0);
app.setVersion(1L);
return app;
});
when(mockAppDao.updateApp(any())).thenAnswer(invocation -> {
// Return the same app, except we increment the version.
App app = invocation.getArgument(0);
Long oldVersion = app.getVersion();
app.setVersion(oldVersion != null ? oldVersion + 1 : 1);
return app;
});
// Spy AppService.createTimeLimitedToken() to create a known token instead of a random one. This makes our
// tests easier.
doReturn(VERIFICATION_TOKEN).when(service).createTimeLimitedToken();
// setup project and team
team = new Team();
project = new Project();
project.setId(TEST_PROJECT_ID);
team.setId(TEST_TEAM_ID);
teamMemberInvitation = new MembershipInvitation();
teamMemberInvitation.setInviteeId(TEST_USER_ID.toString());
teamMemberInvitation.setTeamId(TEST_TEAM_ID);
}
Aggregations