diff --git a/datastore_server/dist/etc/service.properties b/datastore_server/dist/etc/service.properties index 9ae459fbbbae4ba948e74137ab2db4d4245473f1..2920c6361cc180769d08457d41c6a6212a157d51 100644 --- a/datastore_server/dist/etc/service.properties +++ b/datastore_server/dist/etc/service.properties @@ -51,6 +51,19 @@ username = etlserver # The password to use when contacting the openBIS server password = etlserver +# +# CIFEX configuration: Only needed if data export should work without the user having to type in +# his password. Note that in in order for this to work the CIFEX server needs to be configured to +# allow calling setSessionUser() from the IP address of this data store server, see configuration +# option allowed-ips-for-set-session-user in CIFEX's service.properties +# + +# The admin username to use when contacting the CIFEX server +cifex-admin-username = + +# The admin password to use when contacting the CIFEX server +cifex-admin-password = + # The base URL for Web client access. download-url = https://localhost:8444 diff --git a/datastore_server/etc/service.properties b/datastore_server/etc/service.properties index 5469b6a909557393210b9664bec457e6442d6a14..2850b10bac7b8fd0f3c39cf41c46df78a393608a 100644 --- a/datastore_server/etc/service.properties +++ b/datastore_server/etc/service.properties @@ -50,6 +50,19 @@ username = etlserver # The password to use when contacting the openBIS server password = doesnotmatter +# +# CIFEX configuration: Only needed if data export should work without the user having to type in +# his password. Note that in in order for this to work the CIFEX server needs to be configured to +# allow calling setSessionUser() from the IP address of this data store server, see configuration +# option allowed-ips-for-set-session-user in CIFEX's service.properties +# + +# The admin username to use when contacting the CIFEX server +cifex-admin-username = + +# The admin password to use when contacting the CIFEX server +cifex-admin-password = + # The base URL for Web client access. download-url = http://localhost:8889 diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataSetCommandExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataSetCommandExecutor.java index 80de33d4baf988d09d11c7240a9eb8701c27ff7a..c474a29f0ce3d63a5d3c0bc84504a15bf81fb731 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataSetCommandExecutor.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataSetCommandExecutor.java @@ -114,10 +114,11 @@ class DataSetCommandExecutor implements IDataSetCommandExecutor public void scheduleUploadingDataSetsToCIFEX(ICIFEXRPCServiceFactory cifexServiceFactory, MailClientParameters mailClientParameters, List<ExternalData> dataSets, - DataSetUploadContext uploadContext) + DataSetUploadContext uploadContext, String cifexAdminUserOrNull, + String cifexAdminPasswordOrNull) { scheduleCommand(new UploadingCommand(cifexServiceFactory, mailClientParameters, dataSets, - uploadContext)); + uploadContext, cifexAdminUserOrNull, cifexAdminPasswordOrNull)); } public void scheduleProcessDatasets(IProcessingPluginTask task, diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java index f5963124aa195da7a798eab7fd387407911b9258..a13cc30aa2e1d4f301a8ac50cf269762dcb20539 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java @@ -57,12 +57,16 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic private final PluginTaskProviders pluginTaskParameters; + private String cifexAdminUserOrNull; + + private String cifexAdminPasswordOrNull; + private File storeRoot; private File commandQueueDirOrNull; private IDataSetCommandExecutor commandExecuter; - + public DataStoreService(SessionTokenManager sessionTokenManager, MailClientParameters mailClientParameters, PluginTaskProviders pluginTaskParameters) { @@ -101,6 +105,16 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic } } + public void setCifexAdminUserOrNull(String cifexAdminUserOrNull) + { + this.cifexAdminUserOrNull = cifexAdminUserOrNull; + } + + public void setCifexAdminPasswordOrNull(String cifexAdminPasswordOrNull) + { + this.cifexAdminPasswordOrNull = cifexAdminPasswordOrNull; + } + public void afterPropertiesSet() { String prefix = "Property 'storeRoot' "; @@ -185,7 +199,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic throw new InvalidSessionException("User couldn't be authenticated at CIFEX."); } commandExecuter.scheduleUploadingDataSetsToCIFEX(serviceFactory, mailClientParameters, - dataSets, context); + dataSets, context, cifexAdminUserOrNull, cifexAdminPasswordOrNull); } protected ICIFEXRPCServiceFactory createCIFEXRPCServiceFactory(String cifexURL) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java index c3ca8e82aa1f717b040ef95696270875b492dd79..edfe6dda88bb503f4b9e1762f96446c922c894f7 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java @@ -48,10 +48,15 @@ interface IDataSetCommandExecutor * @param cifexServiceFactory Factory for creating CIFEX upload service. * @param mailClientParameters Parameters needed for sending an e-mail to the user if uploading * failed. + * @param cifexAdminUserOrNull The name of the CIFEX admin user, or <code>null</code>, if no + * connection as admin should be used. + * @param cifexAdminPasswordOrNull The password of the CIFEX admin user, or <code>null</code>, + * if no connection as admin should be used. */ void scheduleUploadingDataSetsToCIFEX(ICIFEXRPCServiceFactory cifexServiceFactory, MailClientParameters mailClientParameters, List<ExternalData> dataSets, - DataSetUploadContext uploadContext); + DataSetUploadContext uploadContext, String cifexAdminUserOrNull, + String cifexAdminPasswordOrNull); /** * Schedules the specified processing task for provided datasets. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommand.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommand.java index 1baa30a7990730ce9bc23cb1d552601db1ca78fe..745af2257fb3121a12639ef2548016dcd56dfbd7 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommand.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommand.java @@ -265,6 +265,12 @@ class UploadingCommand implements IDataSetCommand private final String userEMail; + private final boolean userAuthenticated; + + private final String cifexAdminUserOrNull; + + private final String cifexAdminPasswordOrNull; + private final MailClientParameters mailClientParameters; private final TokenGenerator tokenGenerator; @@ -274,13 +280,17 @@ class UploadingCommand implements IDataSetCommand UploadingCommand(ICIFEXRPCServiceFactory cifexServiceFactory, MailClientParameters mailClientParameters, List<ExternalData> dataSets, - DataSetUploadContext context) + DataSetUploadContext context, String cifexAdminUserOrNull, + String cifexAdminPasswordOrNull) { this.cifexServiceFactory = cifexServiceFactory; this.mailClientParameters = mailClientParameters; this.dataSets = dataSets; this.userID = context.getUserID(); this.password = context.getPassword(); + this.userAuthenticated = context.isUserAuthenticated(); + this.cifexAdminUserOrNull = cifexAdminUserOrNull; + this.cifexAdminPasswordOrNull = cifexAdminPasswordOrNull; fileName = context.getFileName(); userEMail = context.getUserEMail(); this.comment = context.getComment(); @@ -301,7 +311,7 @@ class UploadingCommand implements IDataSetCommand + " data sets has been successfully created."); } ICIFEXComponent cifex = cifexServiceFactory.createCIFEXComponent(); - String sessionToken = cifex.login(userID, password); + String sessionToken = getCIFEXSession(cifex); ICIFEXUploader uploader = cifex.createUploader(sessionToken); uploader.addProgressListener(new ProgressListener(zipFile)); uploader.upload(Arrays.asList(zipFile), Constants.USER_ID_PREFIX + userID, comment); @@ -315,6 +325,21 @@ class UploadingCommand implements IDataSetCommand } } + private String getCIFEXSession(ICIFEXComponent cifex) + { + if (userAuthenticated && StringUtils.isBlank(password) + && StringUtils.isNotBlank(cifexAdminUserOrNull) + && StringUtils.isNotBlank(cifexAdminPasswordOrNull)) + { + final String token = cifex.login(cifexAdminUserOrNull, cifexAdminPasswordOrNull); + cifex.setSessionUser(token, userID); + return token; + } else + { + return cifex.login(userID, password); + } + } + private String createFileName() { if (StringUtils.isBlank(fileName)) diff --git a/datastore_server/source/java/dssApplicationContext.xml b/datastore_server/source/java/dssApplicationContext.xml index 2436745d1e842d7775630d8a0a930354b711ec83..c0115c2acd41fc769148c995a905fef011c784df 100644 --- a/datastore_server/source/java/dssApplicationContext.xml +++ b/datastore_server/source/java/dssApplicationContext.xml @@ -46,6 +46,8 @@ </bean> </constructor-arg> <constructor-arg ref="plugin-tasks" /> + <property name="cifexAdminUserOrNull" value="${cifex-admin-username}" /> + <property name="cifexAdminPasswordOrNull" value="${cifex-admin-password}" /> <property name="storeRoot" value="${storeroot-dir}"/> <property name="commandQueueDir" value="${commandqueue-dir}"/> </bean> diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java index d462158141e05fa56abb46ce38bc14cadfdf7310..9710e18a78694dfe983987a884c548bd676405bc 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java @@ -269,7 +269,7 @@ public class DataStoreServiceTest extends AssertJUnit will(returnValue("token")); one(commandExecutor).scheduleUploadingDataSetsToCIFEX(cifexServiceFactory, - mailClientParameters, dataSets, uploadContext); + mailClientParameters, dataSets, uploadContext, null, null); } }); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommandTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommandTest.java index 5375dd763763ad66e5025f5ca8d81ac13dff604c..d424d19cc85f5b250b78f088a95c9ec1c371231d 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommandTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/UploadingCommandTest.java @@ -45,6 +45,7 @@ import ch.systemsx.cisd.base.utilities.OSUtilities; import ch.systemsx.cisd.cifex.rpc.client.ICIFEXComponent; import ch.systemsx.cisd.cifex.rpc.client.ICIFEXUploader; import ch.systemsx.cisd.cifex.rpc.client.gui.IProgressListener; +import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; import ch.systemsx.cisd.common.filesystem.FileUtilities; import ch.systemsx.cisd.common.logging.BufferedAppender; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; @@ -105,8 +106,18 @@ public class UploadingCommandTest extends AssertJUnit private DataSetUploadContext uploadContext; + private DataSetUploadContext uploadContextNoPasswordAuthenticated; + + private DataSetUploadContext uploadContextNoPasswordNotAuthenticated; + + private List<ExternalData> dataSets; + private UploadingCommand command; + private UploadingCommand commandAdminSession; + + private UploadingCommand commandAdminSessionNotAuthenticated; + private File ds2; @BeforeMethod @@ -128,6 +139,20 @@ public class UploadingCommandTest extends AssertJUnit uploadContext.setPassword("pwd"); uploadContext.setUserEMail("user@bc.de"); uploadContext.setFileName(ZIP_FILENAME); + uploadContextNoPasswordAuthenticated = new DataSetUploadContext(); + uploadContextNoPasswordAuthenticated.setCifexURL("cifexURL"); + uploadContextNoPasswordAuthenticated.setUserID("user"); + uploadContextNoPasswordAuthenticated.setPassword(""); + uploadContextNoPasswordAuthenticated.setSessionUserID("user"); + uploadContextNoPasswordAuthenticated.setUserEMail("user@bc.de"); + uploadContextNoPasswordAuthenticated.setFileName(ZIP_FILENAME); + uploadContextNoPasswordNotAuthenticated = new DataSetUploadContext(); + uploadContextNoPasswordNotAuthenticated.setCifexURL("cifexURL"); + uploadContextNoPasswordNotAuthenticated.setUserID("user"); + uploadContextNoPasswordNotAuthenticated.setPassword(""); + uploadContextNoPasswordNotAuthenticated.setSessionUserID("anotherUser"); + uploadContextNoPasswordNotAuthenticated.setUserEMail("user@bc.de"); + uploadContextNoPasswordNotAuthenticated.setFileName(ZIP_FILENAME); createTestData(LOCATION1); ds2 = createTestData(LOCATION2); ExternalData dataSet1 = @@ -137,9 +162,19 @@ public class UploadingCommandTest extends AssertJUnit ExternalData dataSet2 = ExternalDataTranslator.translate(createDataSet("2", LOCATION2), "?", "?", ExperimentTranslator.LoadableFields.PROPERTIES); - List<ExternalData> dataSets = Arrays.<ExternalData> asList(dataSet1, dataSet2); - command = new UploadingCommand(factory, mailClientParameters, dataSets, uploadContext); + dataSets = Arrays.<ExternalData> asList(dataSet1, dataSet2); + command = + new UploadingCommand(factory, mailClientParameters, dataSets, uploadContext, null, + null); + commandAdminSession = + new UploadingCommand(factory, mailClientParameters, dataSets, + uploadContextNoPasswordAuthenticated, "admin", "admpwd"); + commandAdminSessionNotAuthenticated = + new UploadingCommand(factory, mailClientParameters, dataSets, + uploadContextNoPasswordNotAuthenticated, "admin", "admpwd"); command.deleteAfterUploading = false; + commandAdminSession.deleteAfterUploading = false; + commandAdminSessionNotAuthenticated.deleteAfterUploading = false; } private ExternalDataPE createDataSet(String code, String location) @@ -234,6 +269,7 @@ public class UploadingCommandTest extends AssertJUnit @Test public void testExecute() throws Exception { + uploadContext.setPassword("pwd"); context.checking(new Expectations() { { @@ -285,9 +321,92 @@ public class UploadingCommandTest extends AssertJUnit context.assertIsSatisfied(); } + @Test + public void testExecuteAdminSession() throws Exception + { + context.checking(new Expectations() + { + { + one(factory).createCIFEXComponent(); + will(returnValue(cifex)); + + one(cifex).login("admin", "admpwd"); + will(returnValue(SESSION_TOKEN)); + + one(cifex).setSessionUser(SESSION_TOKEN, + uploadContextNoPasswordAuthenticated.getUserID()); + + one(cifex).createUploader(SESSION_TOKEN); + will(returnValue(uploader)); + + final IProgressListener[] listener = new IProgressListener[1]; + one(uploader).addProgressListener(with(any(IProgressListener.class))); + will(new CustomAction("store listener") + { + public Object invoke(Invocation invocation) throws Throwable + { + listener[0] = (IProgressListener) invocation.getParameter(0); + return null; + } + }); + + one(uploader).upload( + Collections.singletonList(new File(TMP, ZIP_FILENAME + ".zip")), + "id:user", null); + will(new CustomAction("report 'finish' to listener") + { + public Object invoke(Invocation invocation) throws Throwable + { + listener[0].finished(true, Collections.<String> emptyList(), + Collections.<Throwable> emptyList()); + return null; + } + }); + } + }); + + logRecorder.resetLogContent(); + commandAdminSession.execute(STORE); + + assertEquals("no emails expected", false, EMAILS.exists()); + assertEquals(1, TMP.listFiles().length); + checkZipFileContent(TMP.listFiles()[0]); + assertEquals(INFO_UPLOAD_PREFIX + + "Zip file <zipfile> with 2 data sets has been successfully created." + + OSUtilities.LINE_SEPARATOR + INFO_UPLOAD_PREFIX + + "Zip file <zipfile> has been successfully uploaded.", getNormalizedLogContent()); + context.assertIsSatisfied(); + } + + @Test(expectedExceptions = AuthorizationFailureException.class) + public void testExecuteAdminSessionNotAuthenticated() throws Exception + { + try + { + context.checking(new Expectations() + { + { + one(factory).createCIFEXComponent(); + will(returnValue(cifex)); + + one(cifex).login(uploadContextNoPasswordNotAuthenticated.getUserID(), + uploadContextNoPasswordNotAuthenticated.getPassword()); + will(throwException(new AuthorizationFailureException("forget it!"))); + } + }); + + logRecorder.resetLogContent(); + commandAdminSessionNotAuthenticated.execute(STORE); + } finally + { + context.assertIsSatisfied(); + } + } + @Test public void testExecuteWithFailedZipFileCreation() { + uploadContext.setPassword("pwd"); FileUtilities.deleteRecursively(ds2); command.execute(STORE); @@ -302,6 +421,7 @@ public class UploadingCommandTest extends AssertJUnit @Test public void testExecuteWithFailedUpload() { + uploadContext.setPassword("pwd"); context.checking(new Expectations() { { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java index ecf8a447b24a2a9b6b0da9723eadbe084810f9b1..25ad884fb57c5937f8c1a67ccec6f213f337d3e3 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java @@ -217,6 +217,7 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject Map<DataStorePE, List<ExternalDataPE>> map = groupDataSetsByDataStores(); assertDataSetsAreKnown(map); uploadContext.setUserEMail(session.getPrincipal().getEmail()); + uploadContext.setSessionUserID(session.getUserName()); if (StringUtils.isBlank(uploadContext.getComment())) { uploadContext.setComment(createUploadComment(externalData)); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetUploadContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetUploadContext.java index fe5ec637894636a353202e1da5a9698fbcfae306..366816604528beb4b2873398d12913bb94db68f5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetUploadContext.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetUploadContext.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.shared.dto; import java.io.Serializable; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; @@ -45,7 +46,9 @@ public class DataSetUploadContext implements Serializable private String comment; private String email; - + + private String sessionUserID; + public final String getFileName() { return fileName; @@ -106,6 +109,16 @@ public class DataSetUploadContext implements Serializable this.email = email; } + public final boolean isUserAuthenticated() + { + return ObjectUtils.equals(userID, sessionUserID); + } + + public final void setSessionUserID(String sessionUserID) + { + this.sessionUserID = sessionUserID; + } + @Override public boolean equals(final Object obj) {