From 2b31c6ae67a86637c651ea3d826dcefbea87129f Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Tue, 3 Nov 2015 13:35:57 +0000
Subject: [PATCH] SSDM-2706 : V3 AS API - create data sets (only metadata) -
 make it work with loginAs instead of registratorId + more tests

SVN: 34980
---
 .../server/api/v3/ApplicationServerApi.java   |   1 -
 .../dataset/CreateDataSetExecutor.java        |   7 +-
 .../ISetDataSetRegistratorExecutor.java       |  33 ---
 .../SetDataSetRegistratorExecutor.java        |  78 --------
 .../method/AbstractMethodExecutor.java        |   5 +
 .../method/CreateDataSetMethodExecutor.java   |  26 +++
 .../generic/server/dataaccess/IDataDAO.java   |   2 +-
 .../generic/server/dataaccess/db/DataDAO.java |  12 +-
 .../systemtest/api/v3/CreateDataSetTest.java  | 189 +++++++++++++-----
 .../dto/entity/dataset/DataSetCreation.java   |  13 --
 10 files changed, 177 insertions(+), 189 deletions(-)
 delete mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/ISetDataSetRegistratorExecutor.java
 delete mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/SetDataSetRegistratorExecutor.java

diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java
index 8033e0275f2..cd0184e24fa 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java
@@ -306,7 +306,6 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
 
     @Override
     @Transactional
-    @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
     @Capability("CREATE_DATASET")
     @DatabaseCreateOrDeleteModification(value = ObjectKind.DATA_SET)
     public List<DataSetPermId> createDataSets(String sessionToken, List<DataSetCreation> creations)
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/CreateDataSetExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/CreateDataSetExecutor.java
index 633ebf48ca2..ebe7382de60 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/CreateDataSetExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/CreateDataSetExecutor.java
@@ -85,9 +85,6 @@ public class CreateDataSetExecutor extends AbstractCreateEntityExecutor<DataSetC
     @Autowired
     private ISetDataSetRelatedDataSetsExecutor setDataSetRelatedDataSetsExecutor;
 
-    @Autowired
-    private ISetDataSetRegistratorExecutor setDataSetRegistratorExecutor;
-
     @Autowired
     private IUpdateEntityPropertyExecutor updateEntityPropertyExecutor;
 
@@ -156,6 +153,7 @@ public class CreateDataSetExecutor extends AbstractCreateEntityExecutor<DataSetC
             dataSet.setCode(creation.getCode());
             dataSet.setDataSetType(type);
             dataSet.setDerived(false == creation.isMeasured());
+            dataSet.setRegistrator(context.getSession().tryGetPerson());
             RelationshipUtils.updateModificationDateAndModifier(dataSet, context.getSession().tryGetPerson());
 
             dataSets.add(dataSet);
@@ -193,7 +191,6 @@ public class CreateDataSetExecutor extends AbstractCreateEntityExecutor<DataSetC
         setDataSetDataStoreExecutor.set(context, entitiesMap);
         setDataSetSampleExecutor.set(context, entitiesMap);
         setDataSetExperimentExecutor.set(context, entitiesMap);
-        setDataSetRegistratorExecutor.set(context, entitiesMap);
 
         Map<IEntityPropertiesHolder, Map<String, String>> propertyMap = new HashMap<IEntityPropertiesHolder, Map<String, String>>();
         for (Map.Entry<DataSetCreation, DataPE> entry : entitiesMap.entrySet())
@@ -228,7 +225,7 @@ public class CreateDataSetExecutor extends AbstractCreateEntityExecutor<DataSetC
     @Override
     protected void save(IOperationContext context, List<DataPE> entities, boolean clearCache)
     {
-        daoFactory.getDataDAO().createDataSets(entities);
+        daoFactory.getDataDAO().createDataSets(entities, context.getSession().tryGetPerson());
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/ISetDataSetRegistratorExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/ISetDataSetRegistratorExecutor.java
deleted file mode 100644
index 22900f3a7bd..00000000000
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/ISetDataSetRegistratorExecutor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2015 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.ethz.sis.openbis.generic.server.api.v3.executor.dataset;
-
-import java.util.Map;
-
-import ch.ethz.sis.openbis.generic.server.api.v3.executor.IOperationContext;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetCreation;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
-
-/**
- * @author pkupczyk
- */
-public interface ISetDataSetRegistratorExecutor
-{
-
-    void set(IOperationContext context, Map<DataSetCreation, DataPE> entitiesMap);
-
-}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/SetDataSetRegistratorExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/SetDataSetRegistratorExecutor.java
deleted file mode 100644
index 9ad0b4eeeb4..00000000000
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/dataset/SetDataSetRegistratorExecutor.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2015 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.ethz.sis.openbis.generic.server.api.v3.executor.dataset;
-
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.sis.openbis.generic.server.api.v3.executor.IOperationContext;
-import ch.ethz.sis.openbis.generic.server.api.v3.executor.entity.AbstractSetEntityToOneRelationExecutor;
-import ch.ethz.sis.openbis.generic.server.api.v3.executor.person.IMapPersonByIdExecutor;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetCreation;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.person.IPersonId;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
-
-/**
- * @author pkupczyk
- */
-@Component
-public class SetDataSetRegistratorExecutor extends AbstractSetEntityToOneRelationExecutor<DataSetCreation, DataPE, IPersonId, PersonPE> implements
-        ISetDataSetRegistratorExecutor
-{
-
-    @Autowired
-    private IMapPersonByIdExecutor mapPersonByIdExecutor;
-
-    @Override
-    protected IPersonId getRelatedId(DataSetCreation creation)
-    {
-        return creation.getRegistratorId();
-    }
-
-    @Override
-    protected Map<IPersonId, PersonPE> map(IOperationContext context, List<IPersonId> relatedIds)
-    {
-        return mapPersonByIdExecutor.map(context, relatedIds);
-    }
-
-    @Override
-    protected void check(IOperationContext context, DataPE entity, IPersonId relatedId, PersonPE related)
-    {
-    }
-
-    @Override
-    protected void set(IOperationContext context, DataPE entity, PersonPE related)
-    {
-        PersonPE person = null;
-
-        if (related == null)
-        {
-            person = context.getSession().tryGetPerson();
-        } else
-        {
-            person = related;
-        }
-
-        entity.setRegistrator(person);
-        entity.setModifier(person);
-    }
-
-}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractMethodExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractMethodExecutor.java
index 02582577ec1..0154363cfce 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractMethodExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractMethodExecutor.java
@@ -46,6 +46,7 @@ public class AbstractMethodExecutor
 
         try
         {
+            checkSession(session);
             T result = action.execute(context);
             flushCurrentSession();
             return result;
@@ -73,6 +74,10 @@ public class AbstractMethodExecutor
         return sessionManager.getSession(sessionToken);
     }
 
+    protected void checkSession(Session session)
+    {
+    }
+
     public interface IMethodAction<T>
     {
 
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/CreateDataSetMethodExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/CreateDataSetMethodExecutor.java
index 76b39b03a3c..b0e0516ac3c 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/CreateDataSetMethodExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/CreateDataSetMethodExecutor.java
@@ -16,6 +16,8 @@
 
 package ch.ethz.sis.openbis.generic.server.api.v3.executor.method;
 
+import java.util.Set;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -23,6 +25,10 @@ import ch.ethz.sis.openbis.generic.server.api.v3.executor.dataset.ICreateDataSet
 import ch.ethz.sis.openbis.generic.server.api.v3.executor.entity.ICreateEntityExecutor;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetCreation;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.DataSetPermId;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
 /**
  * @author pkupczyk
@@ -35,6 +41,26 @@ public class CreateDataSetMethodExecutor extends AbstractCreateMethodExecutor<Da
     @Autowired
     private ICreateDataSetExecutor createExecutor;
 
+    @Override
+    protected void checkSession(Session session)
+    {
+        // We are checking the creator of the session here instead of the actual user. The creator of the session has to always be ETL_SERVER. The
+        // actual user does not have to be ETL_SERVER. This will happen when data store executes the registration on behalf of a different user for
+        // the user to become the registrator.
+
+        Set<RoleAssignmentPE> roles = session.tryGetCreatorPerson().getAllPersonRoles();
+
+        for (RoleAssignmentPE role : roles)
+        {
+            if (RoleCode.ETL_SERVER.equals(role.getRole()))
+            {
+                return;
+            }
+        }
+
+        throw new UserFailureException("Data set creation can be only executed by a user with " + RoleCode.ETL_SERVER + " role.");
+    }
+
     @Override
     protected ICreateEntityExecutor<DataSetCreation, DataSetPermId> getCreateExecutor()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
index 6dd563f0719..15cf9326070 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
@@ -135,7 +135,7 @@ public interface IDataDAO extends IGenericDAO<DataPE>
     /**
      * Persists the specified data sets.
      */
-    public void createDataSets(List<DataPE> dataSets);
+    public void createDataSets(List<DataPE> dataSets, PersonPE modifier);
 
     /**
      * Updates the specified data set.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
index c86968ba43c..2d4d36e41d6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
@@ -741,19 +741,17 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple
     @Override
     public void createDataSet(DataPE dataset, PersonPE modifier)
     {
-        dataset.setModifier(modifier);
-        dataset.setRegistrator(modifier);
-        createDataSets(Collections.singletonList(dataset));
+        createDataSets(Collections.singletonList(dataset), modifier);
     }
 
     @Override
-    public void createDataSets(final List<DataPE> dataSets) throws DataAccessException
+    public void createDataSets(final List<DataPE> dataSets, PersonPE modifier) throws DataAccessException
     {
         assert dataSets != null && dataSets.size() > 0 : "Unspecified or empty dataSets.";
 
         for (final DataPE dataPE : dataSets)
         {
-            internalCreateOrUpdateDataSet(dataPE);
+            internalCreateOrUpdateDataSet(dataPE, modifier);
         }
 
         if (operationLog.isInfoEnabled())
@@ -765,11 +763,13 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple
         scheduleDynamicPropertiesEvaluation(dataSets);
     }
 
-    private void internalCreateOrUpdateDataSet(DataPE dataset)
+    private void internalCreateOrUpdateDataSet(DataPE dataset, PersonPE modifier)
     {
         assert dataset != null : "Unspecified data set.";
 
         dataset.setCode(CodeConverter.tryToDatabase(dataset.getCode()));
+        dataset.setModifier(modifier);
+        dataset.setRegistrator(modifier);
         validatePE(dataset);
 
         lockRelatedEntities(dataset);
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/CreateDataSetTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/CreateDataSetTest.java
index e8232d21745..8384e4180b5 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/CreateDataSetTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/CreateDataSetTest.java
@@ -40,18 +40,19 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.FileFormatTypePe
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.LocatorTypePermId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.datastore.DataStorePermId;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.datastore.IDataStoreId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.entitytype.EntityTypePermId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.entitytype.IEntityTypeId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentIdentifier;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentPermId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.externaldms.ExternalDmsPermId;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.person.PersonPermId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.project.ProjectIdentifier;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.ISampleId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SamplePermId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.space.SpacePermId;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.tag.TagCode;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.vocabulary.VocabularyTermCode;
 import ch.systemsx.cisd.common.action.IDelegatedAction;
 
@@ -206,6 +207,103 @@ public class CreateDataSetTest extends AbstractDataSetTest
             }, "Value of mandatory property 'COMMENT' not specified");
     }
 
+    @Test
+    public void testCreateWithDataStoreNull()
+    {
+        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+
+        final DataSetCreation creation = dataSetCreation();
+        creation.setDataStoreId(null);
+
+        assertUserFailureException(new IDelegatedAction()
+            {
+                @Override
+                public void execute()
+                {
+                    v3api.createDataSets(sessionToken, Arrays.asList(creation));
+                }
+            }, "Data store id cannot be null.");
+    }
+
+    @Test
+    public void testCreateWithDataStoreNonexistent()
+    {
+        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+
+        final IDataStoreId dataStoreId = new DataStorePermId("IDONTEXIST");
+        final DataSetCreation creation = dataSetCreation();
+        creation.setDataStoreId(dataStoreId);
+
+        assertObjectNotFoundException(new IDelegatedAction()
+            {
+                @Override
+                public void execute()
+                {
+                    v3api.createDataSets(sessionToken, Arrays.asList(creation));
+                }
+            }, dataStoreId);
+    }
+
+    @Test
+    public void testCreateWithMeasuredTrue()
+    {
+        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+
+        final DataSetCreation creation = dataSetCreation();
+        creation.setMeasured(true);
+
+        DataSet dataSet = createDataSet(sessionToken, creation, new DataSetFetchOptions());
+        assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
+        assertEquals(dataSet.isMeasured(), Boolean.TRUE);
+    }
+
+    @Test
+    public void testCreateWithMeasuredFalse()
+    {
+        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+
+        final DataSetCreation creation = dataSetCreation();
+        creation.setMeasured(false);
+
+        DataSet dataSet = createDataSet(sessionToken, creation, new DataSetFetchOptions());
+        assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
+        assertEquals(dataSet.isMeasured(), Boolean.FALSE);
+    }
+
+    @Test
+    public void testCreateWithTagsExisting()
+    {
+        final String sessionToken = v3api.loginAs(TEST_USER, PASSWORD, TEST_SPACE_USER);
+
+        final DataSetCreation creation = dataSetCreation();
+        creation.setExperimentId(new ExperimentIdentifier("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST"));
+        creation.setTagIds(Arrays.asList(new TagCode("TEST_METAPROJECTS")));
+
+        DataSetFetchOptions fo = new DataSetFetchOptions();
+        fo.withTags();
+
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
+        assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
+        assertTags(dataSet.getTags(), "/test_space/TEST_METAPROJECTS");
+    }
+
+    @Test
+    public void testCreateWithTagsNonexistent()
+    {
+        final String sessionToken = v3api.loginAs(TEST_USER, PASSWORD, TEST_SPACE_USER);
+
+        final DataSetCreation creation = dataSetCreation();
+        creation.setExperimentId(new ExperimentIdentifier("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST"));
+        creation.setTagIds(Arrays.asList(new TagCode("IDONTEXIST")));
+
+        DataSetFetchOptions fo = new DataSetFetchOptions();
+        fo.withTags();
+
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
+        assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
+        assertTags(dataSet.getTags(), "/test_space/IDONTEXIST");
+    }
+
     @Test
     public void testCreateWithExperimentNullAndSampleNull()
     {
@@ -238,10 +336,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fo.withExperiment();
         fo.withSample();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment().getIdentifier().getIdentifier(), "/CISD/NEMO/EXP1");
         assertEquals(dataSet.getSample(), null);
@@ -260,10 +355,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fo.withExperiment();
         fo.withSample();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment().getIdentifier().getIdentifier(), "/CISD/NEMO/EXP-TEST-1");
         assertEquals(dataSet.getSample().getIdentifier().getIdentifier(), "/CISD/CP-TEST-1");
@@ -283,10 +375,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fo.withExperiment();
         fo.withSample();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment(), null);
         assertEquals(dataSet.getSample().getIdentifier().getIdentifier(), "/CISD/3V-125");
@@ -347,10 +436,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fo.withExperiment();
         fo.withSample();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment().getIdentifier().getIdentifier(), "/CISD/NEMO/EXP-TEST-1");
         assertEquals(dataSet.getSample().getIdentifier().getIdentifier(), "/CISD/CP-TEST-1");
@@ -404,13 +490,12 @@ public class CreateDataSetTest extends AbstractDataSetTest
     @Test
     public void testCreateWithExperimentUnauthorized()
     {
-        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        final String sessionToken = v3api.loginAs(TEST_USER, PASSWORD, TEST_SPACE_USER);
 
         final IExperimentId experimentId = new ExperimentIdentifier("/CISD/NEMO/EXP1");
         final DataSetCreation creation = dataSetCreation();
         creation.setExperimentId(experimentId);
         creation.setSampleId(null);
-        creation.setRegistratorId(new PersonPermId(TEST_SPACE_USER));
 
         assertUnauthorizedObjectAccessException(new IDelegatedAction()
             {
@@ -419,7 +504,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
                 {
                     v3api.createDataSets(sessionToken, Arrays.asList(creation));
                 }
-            }, new DataSetPermId(creation.getCode()));
+            }, experimentId);
     }
 
     @Test
@@ -449,13 +534,12 @@ public class CreateDataSetTest extends AbstractDataSetTest
     @Test
     public void testCreateWithSampleUnauthorized()
     {
-        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        final String sessionToken = v3api.loginAs(TEST_USER, PASSWORD, TEST_SPACE_USER);
 
         final ISampleId sampleId = new SampleIdentifier("/CISD/CP-TEST-1");
         final DataSetCreation creation = dataSetCreation();
         creation.setExperimentId(null);
         creation.setSampleId(sampleId);
-        creation.setRegistratorId(new PersonPermId(TEST_SPACE_USER));
 
         assertUnauthorizedObjectAccessException(new IDelegatedAction()
             {
@@ -464,7 +548,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
                 {
                     v3api.createDataSets(sessionToken, Arrays.asList(creation));
                 }
-            }, new DataSetPermId(creation.getCode()));
+            }, sampleId);
     }
 
     @Test
@@ -487,12 +571,26 @@ public class CreateDataSetTest extends AbstractDataSetTest
     }
 
     @Test
-    public void testCreateWithRegistratorNull()
+    public void testCreateWithUserNonEtlServer()
+    {
+        final String sessionToken = v3api.login(TEST_SPACE_USER, PASSWORD);
+
+        assertUserFailureException(new IDelegatedAction()
+            {
+                @Override
+                public void execute()
+                {
+                    createDataSet(sessionToken, dataSetCreation(), new DataSetFetchOptions());
+                }
+            }, "Data set creation can be only executed by a user with ETL_SERVER role.");
+    }
+
+    @Test
+    public void testCreateWithUserEtlServer()
     {
         final String sessionToken = v3api.login(TEST_USER, PASSWORD);
 
         final DataSetCreation creation = dataSetCreation();
-        creation.setTypeId(new EntityTypePermId("UNKNOWN"));
         creation.setExperimentId(new ExperimentIdentifier("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST"));
 
         DataSetFetchOptions fo = new DataSetFetchOptions();
@@ -500,10 +598,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fo.withSample();
         fo.withRegistrator();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment().getIdentifier().getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
         assertEquals(dataSet.getSample(), null);
@@ -511,24 +606,19 @@ public class CreateDataSetTest extends AbstractDataSetTest
     }
 
     @Test
-    public void testCreateWithRegistratorNotNull()
+    public void testCreateWithUserEtlServerOnBehalfOtherUser()
     {
-        final String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        final String sessionToken = v3api.loginAs(TEST_USER, PASSWORD, TEST_SPACE_USER);
 
         final DataSetCreation creation = dataSetCreation();
-        creation.setTypeId(new EntityTypePermId("UNKNOWN"));
         creation.setExperimentId(new ExperimentIdentifier("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST"));
-        creation.setRegistratorId(new PersonPermId(TEST_SPACE_USER));
 
         DataSetFetchOptions fo = new DataSetFetchOptions();
         fo.withExperiment();
         fo.withSample();
         fo.withRegistrator();
 
-        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
-        DataSet dataSet = dataSets.values().iterator().next();
-
+        DataSet dataSet = createDataSet(sessionToken, creation, fo);
         assertEquals(dataSet.getCode(), creation.getCode().toUpperCase());
         assertEquals(dataSet.getExperiment().getIdentifier().getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
         assertEquals(dataSet.getSample(), null);
@@ -553,8 +643,6 @@ public class CreateDataSetTest extends AbstractDataSetTest
         creation.setDataStoreId(new DataStorePermId("STANDARD"));
         creation.setPhysicalData(physicalCreation);
 
-        List<DataSetPermId> ids = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-
         DataSetFetchOptions fetchOptions = new DataSetFetchOptions();
         fetchOptions.withType();
         fetchOptions.withExperiment();
@@ -564,9 +652,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fetchOptions.withPhysicalData().withStorageFormat();
         fetchOptions.withLinkedData();
 
-        Map<IDataSetId, DataSet> map = v3api.mapDataSets(sessionToken, ids, fetchOptions);
-
-        DataSet dataSet = map.get(ids.get(0));
+        DataSet dataSet = createDataSet(sessionToken, creation, fetchOptions);
         assertEquals(dataSet.getCode(), "TEST_PHYSICAL_DATASET");
         assertEquals(dataSet.getType().getCode(), "UNKNOWN");
         assertEquals(dataSet.getExperiment().getPermId().getPermId(), "200811050951882-1028");
@@ -590,8 +676,6 @@ public class CreateDataSetTest extends AbstractDataSetTest
         creation.setDataStoreId(new DataStorePermId("STANDARD"));
         creation.setContainedIds(Arrays.asList(new DataSetPermId("20081105092159188-3")));
 
-        List<DataSetPermId> ids = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-
         DataSetFetchOptions fetchOptions = new DataSetFetchOptions();
         fetchOptions.withType();
         fetchOptions.withExperiment();
@@ -600,9 +684,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fetchOptions.withLinkedData();
         fetchOptions.withContained();
 
-        Map<IDataSetId, DataSet> map = v3api.mapDataSets(sessionToken, ids, fetchOptions);
-
-        DataSet dataSet = map.get(ids.get(0));
+        DataSet dataSet = createDataSet(sessionToken, creation, fetchOptions);
         assertEquals(dataSet.getCode(), "TEST_CONTAINER_DATASET");
         assertEquals(dataSet.getType().getCode(), "CONTAINER_TYPE");
         assertEquals(dataSet.getExperiment().getPermId().getPermId(), "200811050951882-1028");
@@ -629,8 +711,6 @@ public class CreateDataSetTest extends AbstractDataSetTest
         creation.setDataStoreId(new DataStorePermId("STANDARD"));
         creation.setLinkedData(linkedCreation);
 
-        List<DataSetPermId> ids = v3api.createDataSets(sessionToken, Arrays.asList(creation));
-
         DataSetFetchOptions fetchOptions = new DataSetFetchOptions();
         fetchOptions.withType();
         fetchOptions.withExperiment();
@@ -638,9 +718,7 @@ public class CreateDataSetTest extends AbstractDataSetTest
         fetchOptions.withPhysicalData();
         fetchOptions.withLinkedData().withExternalDms();
 
-        Map<IDataSetId, DataSet> map = v3api.mapDataSets(sessionToken, ids, fetchOptions);
-
-        DataSet dataSet = map.get(ids.get(0));
+        DataSet dataSet = createDataSet(sessionToken, creation, fetchOptions);
         assertEquals(dataSet.getCode(), "TEST_LINK_DATASET");
         assertEquals(dataSet.getType().getCode(), "LINK_TYPE");
         assertEquals(dataSet.getExperiment().getPermId().getPermId(), "200811050951882-1028");
@@ -687,4 +765,11 @@ public class CreateDataSetTest extends AbstractDataSetTest
         return creation;
     }
 
+    private DataSet createDataSet(String sessionToken, DataSetCreation creation, DataSetFetchOptions fo)
+    {
+        List<DataSetPermId> permIds = v3api.createDataSets(sessionToken, Arrays.asList(creation));
+        Map<IDataSetId, DataSet> dataSets = v3api.mapDataSets(sessionToken, permIds, fo);
+        return dataSets.values().iterator().next();
+    }
+
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSetCreation.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSetCreation.java
index 60d60a4eebd..6af6cf91521 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSetCreation.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSetCreation.java
@@ -27,7 +27,6 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.datastore.IDataStoreId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.entitytype.IEntityTypeId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.person.IPersonId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.ISampleId;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.tag.ITagId;
 import ch.systemsx.cisd.base.annotation.JsonObject;
@@ -68,8 +67,6 @@ public class DataSetCreation implements Serializable, ICreationIdHolder
 
     private List<? extends IDataSetId> childIds;
 
-    private IPersonId registratorId;
-
     private CreationId creationId;
 
     public IEntityTypeId getTypeId()
@@ -213,16 +210,6 @@ public class DataSetCreation implements Serializable, ICreationIdHolder
         return properties;
     }
 
-    public IPersonId getRegistratorId()
-    {
-        return registratorId;
-    }
-
-    public void setRegistratorId(IPersonId registratorId)
-    {
-        this.registratorId = registratorId;
-    }
-
     @Override
     public CreationId getCreationId()
     {
-- 
GitLab