From 7746db3a22765d0cac1da0a2d6b1e5f3e846c7dc Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Mon, 29 Oct 2012 14:15:26 +0000
Subject: [PATCH] SP-348 / BIS-191: Metaprojects - fix
 GeneralInformationService.searchForXXXOnBehalfOfUser methods

SVN: 27397
---
 .../openbis/generic/server/CommonServer.java  |  29 +++-
 .../generic/server/CommonServerLogger.java    |   8 +
 .../api/v1/GeneralInformationService.java     |  70 ++++----
 .../server/dataaccess/IMetaprojectDAO.java    |   2 +-
 .../openbis/generic/shared/ICommonServer.java |  12 +-
 .../server/dataaccess/db/PersonDAOTest.java   |   2 +-
 .../api/v1/GeneralInformationServiceTest.java | 159 ++++++++++++++++++
 .../124/042=metaproject_assignments_all.tsv   |   4 +
 .../sql/postgresql/124/043=metaprojects.tsv   |   1 +
 .../sql/postgresql/124/044=persons.tsv        |   1 +
 .../postgresql/124/051=role_assignments.tsv   |   1 +
 11 files changed, 246 insertions(+), 43 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 160e643fbc5..57b89f1b15a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -43,8 +43,8 @@ import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.mail.MailClient;
 import ch.systemsx.cisd.common.properties.PropertyParametersUtil;
 import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperties;
-import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.dbmigration.DatabaseConfigurationContext;
+import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.server.authorization.AuthorizationServiceUtils;
 import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.AuthorizationGuard;
 import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.Capability;
@@ -1273,6 +1273,33 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return searchHelper.searchForDataSets(session.getUserName(), criteria);
     }
 
+    @Override
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_OBSERVER)
+    @Capability("SEARCH_ON_BEHALF_OF_USER")
+    public List<ExternalData> searchForDataSetsOnBehalfOfUser(String sessionToken,
+            DetailedSearchCriteria criteria, String userId)
+    {
+        final Session session = getSession(sessionToken);
+        SearchHelper searchHelper =
+                new SearchHelper(session, businessObjectFactory, getDAOFactory());
+        List<ExternalData> unfilteredDatasets = searchHelper.searchForDataSets(userId, criteria);
+
+        // Filter for user
+        final PersonPE person = getDAOFactory().getPersonDAO().tryFindPersonByUserId(userId);
+        final ExternalDataValidator validator = new ExternalDataValidator();
+        final ArrayList<ExternalData> datasets =
+                new ArrayList<ExternalData>(unfilteredDatasets.size());
+
+        for (ExternalData dataset : unfilteredDatasets)
+        {
+            if (validator.doValidation(person, dataset))
+            {
+                datasets.add(dataset);
+            }
+        }
+        return datasets;
+    }
+
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public ExternalData getDataSetInfo(String sessionToken,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index a33a1eb6efe..a729604eda6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -576,6 +576,14 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
+    @Override
+    public List<ExternalData> searchForDataSetsOnBehalfOfUser(String sessionToken,
+            DetailedSearchCriteria criteria, String userId)
+    {
+        logAccess(sessionToken, "search_for_datasets", "criteria(%s) user_id(%s)", criteria, userId);
+        return null;
+    }
+
     @Override
     public List<Sample> searchForSamples(String sessionToken, DetailedSearchCriteria criteria)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
index 9c0961b4fe9..f0684e3f5ed 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
@@ -310,18 +310,7 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
             EnumSet<SampleFetchOption> fetchOptions)
     {
         Session session = getSession(sessionToken);
-
-        EnumSet<SampleFetchOption> sampleFetchOptions =
-                (fetchOptions != null) ? fetchOptions : EnumSet.noneOf(SampleFetchOption.class);
-        DetailedSearchCriteria detailedSearchCriteria =
-                SearchCriteriaToDetailedSearchCriteriaTranslator.convert(
-                        SearchableEntityKind.SAMPLE, searchCriteria);
-        ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister sampleLister =
-                boFactory.createSampleLister(session);
-        Collection<Long> sampleIDs =
-                new SampleSearchManager(getDAOFactory().getHibernateSearchDAO(), sampleLister)
-                        .searchForSampleIDs(session.getUserName(), detailedSearchCriteria);
-        return createSampleLister(session.tryGetPerson()).getSamples(sampleIDs, sampleFetchOptions);
+        return searchForSamples(sessionToken, searchCriteria, fetchOptions, session.getUserName());
     }
 
     @Override
@@ -332,20 +321,26 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
             SearchCriteria searchCriteria, EnumSet<SampleFetchOption> fetchOptions, String userId)
     {
         final List<Sample> unfilteredSamples =
-                searchForSamples(sessionToken, searchCriteria, fetchOptions);
+                searchForSamples(sessionToken, searchCriteria, fetchOptions, userId);
+        return filterSamplesVisibleToUser(sessionToken, unfilteredSamples, userId);
+    }
 
-        // Filter for user
-        final PersonPE person = getDAOFactory().getPersonDAO().tryFindPersonByUserId(userId);
-        final SampleByIdentiferValidator validator = new SampleByIdentiferValidator();
-        final ArrayList<Sample> samples = new ArrayList<Sample>(unfilteredSamples.size());
-        for (Sample sample : unfilteredSamples)
-        {
-            if (validator.doValidation(person, sample))
-            {
-                samples.add(sample);
-            }
-        }
-        return samples;
+    private List<Sample> searchForSamples(String sessionToken, SearchCriteria searchCriteria,
+            EnumSet<SampleFetchOption> fetchOptions, String userId)
+    {
+        Session session = getSession(sessionToken);
+
+        EnumSet<SampleFetchOption> sampleFetchOptions =
+                (fetchOptions != null) ? fetchOptions : EnumSet.noneOf(SampleFetchOption.class);
+        DetailedSearchCriteria detailedSearchCriteria =
+                SearchCriteriaToDetailedSearchCriteriaTranslator.convert(
+                        SearchableEntityKind.SAMPLE, searchCriteria);
+        ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister sampleLister =
+                boFactory.createSampleLister(session);
+        Collection<Long> sampleIDs =
+                new SampleSearchManager(getDAOFactory().getHibernateSearchDAO(), sampleLister)
+                        .searchForSampleIDs(userId, detailedSearchCriteria);
+        return createSampleLister(session.tryGetPerson()).getSamples(sampleIDs, sampleFetchOptions);
     }
 
     @Override
@@ -859,20 +854,17 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
     public List<DataSet> searchForDataSetsOnBehalfOfUser(String sessionToken,
             SearchCriteria searchCriteria, String userId)
     {
-        final List<DataSet> unfilteredDatasets = searchForDataSets(sessionToken, searchCriteria);
-        // Filter for user
-        final PersonPE person = getDAOFactory().getPersonDAO().tryFindPersonByUserId(userId);
-        final DataSetByExperimentIdentifierValidator validator =
-                new DataSetByExperimentIdentifierValidator();
-        final ArrayList<DataSet> datasets = new ArrayList<DataSet>(unfilteredDatasets.size());
-        for (DataSet sample : unfilteredDatasets)
-        {
-            if (validator.doValidation(person, sample))
-            {
-                datasets.add(sample);
-            }
-        }
-        return datasets;
+        checkSession(sessionToken);
+
+        DetailedSearchCriteria detailedSearchCriteria =
+                SearchCriteriaToDetailedSearchCriteriaTranslator.convert(
+                        SearchableEntityKind.DATA_SET, searchCriteria);
+        List<ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData> privateDataSets =
+                commonServer.searchForDataSetsOnBehalfOfUser(sessionToken, detailedSearchCriteria,
+                        userId);
+
+        // The underlying search, as currently implemented, does not return any of the connections
+        return Translator.translate(privateDataSets, EnumSet.noneOf(Connections.class));
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
index 10194a5a49c..f3454e3ad28 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
@@ -31,7 +31,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 public interface IMetaprojectDAO extends IGenericDAO<MetaprojectPE>
 {
     /**
-     * Finds a metaproject by the specified owner id and metaproject name. Returns null is no
+     * Finds a metaproject by the specified owner id and metaproject name. Returns null if no
      * metaproject is found.
      */
     public MetaprojectPE tryFindByOwnerAndName(String ownerId, String metaprojectName);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index b810b57d5ec..e8da4b03115 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -564,11 +564,20 @@ public interface ICommonServer extends IServer
             String description, String leaderId, Collection<NewAttachment> attachments);
 
     /**
-     * Performs an <i>Hibernate Search</i> based on given parameters.
+     * Searches for samples that fulfill the specified search criteria.
      */
     @Transactional(readOnly = true)
     public List<ExternalData> searchForDataSets(String sessionToken, DetailedSearchCriteria criteria);
 
+    /**
+     * Searches for samples that fulfill the specified search criteria. The search is executed on
+     * behalf of a user identified by the userId (the returned results are exactly the same as if
+     * that user called the search method).
+     */
+    @Transactional(readOnly = true)
+    public List<ExternalData> searchForDataSetsOnBehalfOfUser(String sessionToken,
+            DetailedSearchCriteria criteria, String userId);
+
     /**
      * For given {@link TechId} returns the corresponding {@link ExternalData}.
      */
@@ -1389,4 +1398,5 @@ public interface ICommonServer extends IServer
     @Transactional
     public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             String name, String descriptionOrNull);
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/PersonDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/PersonDAOTest.java
index 35282473e51..48054a46530 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/PersonDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/PersonDAOTest.java
@@ -103,7 +103,7 @@ public final class PersonDAOTest extends AbstractDAOTest
         personDAO.createPerson(testPerson2);
         personDAO.createPerson(testPerson3);
         final List<PersonPE> persons = personDAO.listPersons();
-        assertEquals(9, persons.size());
+        assertEquals(10, persons.size());
         final PersonPE testPersonFromDB = personDAO.getPerson(testPerson.getId());
         assertEquals(testPerson, testPersonFromDB);
         final PersonPE testPersonFromDB2 = personDAO.getPerson(testPerson2.getId());
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index 341e7c91323..08303280734 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -157,6 +157,78 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertEntities("[]", samples);
     }
 
+    @Test
+    public void testSearchForSamplesOnBehalfOfUser()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "*TEST*"));
+
+        // executed by test
+        List<Sample> testResult =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria);
+        assertEntities(
+                "[/CISD/CP-TEST-1, /CISD/CP-TEST-2, /CISD/CP-TEST-3, /CISD/DYNA-TEST-1, /TEST-SPACE/EV-TEST, /TEST-SPACE/FV-TEST]",
+                testResult);
+
+        // executed by test on behalf of test_space
+        List<Sample> onBehalfOfTestSpaceResult =
+                generalInformationService.searchForSamplesOnBehalfOfUser(sessionToken,
+                        searchCriteria, EnumSet.of(SampleFetchOption.BASIC), "test_space");
+        assertEntities("[/TEST-SPACE/EV-TEST, /TEST-SPACE/FV-TEST]", onBehalfOfTestSpaceResult);
+
+        // executed by test_space
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_space", "password");
+
+        List<Sample> testSpaceResult =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria);
+        assertEntities("[/TEST-SPACE/EV-TEST, /TEST-SPACE/FV-TEST]", testSpaceResult);
+    }
+
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testSearchForSamplesOnBehalfOfUserExecutedByNotInstanceUser()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "SOME_CODE"));
+
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_role", "password");
+        generalInformationService.searchForSamplesOnBehalfOfUser(sessionToken, searchCriteria,
+                EnumSet.of(SampleFetchOption.BASIC), "admin");
+    }
+
+    @Test
+    public void testSearchForSamplesOnBehalfOfUserByMetaprojectName()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(
+                MatchClauseAttribute.METAPROJECT, "TEST_METAPROJECTS"));
+
+        // executed by test
+        List<Sample> testResult =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria);
+        assertEntities("[/TEST-SPACE/EV-TEST]", testResult);
+
+        // executed by test on behalf of test_space
+        List<Sample> onBehalfOfTestSpaceResult =
+                generalInformationService.searchForSamplesOnBehalfOfUser(sessionToken,
+                        searchCriteria, EnumSet.of(SampleFetchOption.BASIC), "test_space");
+        assertEntities("[/TEST-SPACE/EV-TEST, /TEST-SPACE/FV-TEST]", onBehalfOfTestSpaceResult);
+
+        // executed by test_space
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_space", "password");
+
+        List<Sample> testSpaceResult =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria);
+        assertEntities("[/TEST-SPACE/EV-TEST, /TEST-SPACE/FV-TEST]", testSpaceResult);
+    }
+
     @Test
     public void testSearchForSamplesByMetaprojectName()
     {
@@ -830,6 +902,84 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertEquals("[]", dataSets.toString());
     }
 
+    @Test
+    public void testSearchForDataSetsOnBehalfOfUser()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "*9000-2*"));
+
+        // executed by test
+        List<DataSet> dataSets =
+                generalInformationService.searchForDataSets(sessionToken, searchCriteria);
+        assertCollection(
+                "[20081105092259000-20, 20081105092259000-21, 20120619092259000-22, 20120628092259000-23, 20120628092259000-24, 20120628092259000-25]",
+                dataSets, new DataSetToCode());
+
+        // executed by test on behalf of test_space
+        List<DataSet> onBehalfOfTestSpaceResult =
+                generalInformationService.searchForDataSetsOnBehalfOfUser(sessionToken,
+                        searchCriteria, "test_space");
+        assertCollection(
+                "[20120619092259000-22, 20120628092259000-23, 20120628092259000-24, 20120628092259000-25]",
+                onBehalfOfTestSpaceResult, new DataSetToCode());
+
+        // executed by test_space
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_space", "password");
+
+        List<DataSet> testSpaceResult =
+                generalInformationService.searchForDataSets(sessionToken, searchCriteria);
+        assertCollection(
+                "[20120619092259000-22, 20120628092259000-23, 20120628092259000-24, 20120628092259000-25]",
+                testSpaceResult, new DataSetToCode());
+    }
+
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testSearchForDataSetsOnBehalfOfUserExecutedByNotInstanceUser()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "SOME_CODE"));
+
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_role", "password");
+        generalInformationService.searchForDataSetsOnBehalfOfUser(sessionToken, searchCriteria,
+                "admin");
+    }
+
+    @Test
+    public void testSearchForDataSetsOnBehalfOfUserByMetaprojectName()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(
+                MatchClauseAttribute.METAPROJECT, "TEST_METAPROJECTS"));
+
+        // executed by test
+        List<DataSet> dataSets =
+                generalInformationService.searchForDataSets(sessionToken, searchCriteria);
+        assertCollection("[20120619092259000-22]", dataSets, new DataSetToCode());
+
+        // executed by test on behalf of test_space
+        List<DataSet> onBehalfOfTestSpaceResult =
+                generalInformationService.searchForDataSetsOnBehalfOfUser(sessionToken,
+                        searchCriteria, "test_space");
+        assertCollection("[20120619092259000-22, 20120628092259000-23]", onBehalfOfTestSpaceResult,
+                new DataSetToCode());
+
+        // executed by test_space
+        generalInformationService.logout(sessionToken);
+        sessionToken =
+                generalInformationService.tryToAuthenticateForAllServices("test_space", "password");
+
+        List<DataSet> testSpaceResult =
+                generalInformationService.searchForDataSets(sessionToken, searchCriteria);
+        assertCollection("[20120619092259000-22, 20120628092259000-23]", testSpaceResult,
+                new DataSetToCode());
+    }
+
     @Test
     public void testSearchForDataSetsByMetaprojectName()
     {
@@ -1316,4 +1466,13 @@ public class GeneralInformationServiceTest extends SystemTestCase
         }
     }
 
+    private static class DataSetToCode implements IToStringDelegate<DataSet>
+    {
+        @Override
+        public String toString(DataSet t)
+        {
+            return t.getCode();
+        }
+    }
+
 }
diff --git a/openbis/sourceTest/sql/postgresql/124/042=metaproject_assignments_all.tsv b/openbis/sourceTest/sql/postgresql/124/042=metaproject_assignments_all.tsv
index ca14a3027cc..e85e9b35d1c 100644
--- a/openbis/sourceTest/sql/postgresql/124/042=metaproject_assignments_all.tsv
+++ b/openbis/sourceTest/sql/postgresql/124/042=metaproject_assignments_all.tsv
@@ -12,3 +12,7 @@
 12	1	\N	\N	2	\N	1	2012-09-05 10:18:10.581+02
 13	3	4	\N	\N	\N	\N	2012-09-05 10:18:10.581+02
 14	3	\N	979	\N	\N	\N	2012-09-05 10:18:10.581+02
+15	5	\N	1054	\N	\N	\N	2012-09-05 10:18:10.581+02
+16	5	\N	1055	\N	\N	\N	2012-09-05 10:18:10.581+02
+17	5	\N	\N	22	\N	\N	2012-09-05 10:18:10.581+02
+18	5	\N	\N	23	\N	\N	2012-09-05 10:18:10.581+02
diff --git a/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv b/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
index 23128b4687a..fa4e864e52f 100644
--- a/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
+++ b/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
@@ -2,3 +2,4 @@
 2	TEST_METAPROJECTS	Example metaproject no. 2	6	t	2012-09-05 10:18:10.581+02
 3	ANOTHER_TEST_METAPROJECTS	Another example metaproject	2	t	2012-09-05 10:18:10.581+02
 4	TEST_METAPROJECTS_2	Example metaproject no. 2	6	t	2012-09-05 10:18:10.581+02
+5	TEST_METAPROJECTS	Example metaproject no. 1	7	t	2012-09-05 10:18:10.581+02
\ No newline at end of file
diff --git a/openbis/sourceTest/sql/postgresql/124/044=persons.tsv b/openbis/sourceTest/sql/postgresql/124/044=persons.tsv
index d2417310823..0238e89db9b 100644
--- a/openbis/sourceTest/sql/postgresql/124/044=persons.tsv
+++ b/openbis/sourceTest/sql/postgresql/124/044=persons.tsv
@@ -4,3 +4,4 @@
 2	John	Doe	test	franz-josef.elmer@systemsx.ch	1	1	2008-11-05 09:18:10.581+01	\N	\\xaced00057372004163682e73797374656d73782e636973642e6f70656e6269732e67656e657269632e7368617265642e62617369632e64746f2e446973706c617953657474696e677300000000000000010200085a0029646973706c6179437573746f6d436f6c756d6e446562756767696e674572726f724d657373616765735a001575736557696c64636172645365617263684d6f64654c000e636f6c756d6e53657474696e677374000f4c6a6176612f7574696c2f4d61703b4c001064726f70446f776e53657474696e677371007e00014c001670616e656c436f6c6c617073656453657474696e677371007e00014c001170616e656c53697a6553657474696e677371007e00014c001d7265616c4e756d626572466f726d6174696e67506172616d65746572737400514c63682f73797374656d73782f636973642f6f70656e6269732f67656e657269632f7368617265642f62617369632f64746f2f5265616c4e756d626572466f726d6174696e67506172616d65746572733b4c000b74616253657474696e677371007e000178700001737200176a6176612e7574696c2e4c696e6b6564486173684d617034c04e5c106cc0fb0200015a000b6163636573734f72646572787200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000078007371007e00053f4000000000000c7708000000100000000174001e73616d706c652d747970656d61696e5f73616d706c655f62726f7773657274000a43454c4c5f504c415445787371007e00053f4000000000000c77080000001000000000787371007e00053f4000000000000c770800000010000000027400156c6566745f70616e656c5f43454c4c5f504c415445737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000078700000012c7400196c6566745f70616e656c5f44494c5554494f4e5f504c4154457371007e000d0000012c787372004f63682e73797374656d73782e636973642e6f70656e6269732e67656e657269632e7368617265642e62617369632e64746f2e5265616c4e756d626572466f726d6174696e67506172616d657465727300000000000000010200035a0010666f726d6174696e67456e61626c6564490009707265636973696f6e5a000a736369656e746966696378700100000004007371007e00053f4000000000000c7708000000100000000274002367656e657269635f73616d706c655f76696577657244494c5554494f4e5f504c415445740018636f6e7461696e65722d73616d706c652d73656374696f6e74001f67656e657269635f73616d706c655f76696577657243454c4c5f504c415445740016706172656e742d73616d706c65732d73656374696f6e78	t
 5	John	Inactive	inactive	inactive@in.active	1	1	2008-11-05 09:18:10.581+01	\N	\\xaced00057372004163682e73797374656d73782e636973642e6f70656e6269732e67656e657269632e7368617265642e62617369632e64746f2e446973706c617953657474696e677300000000000000010200035a001575736557696c64636172645365617263684d6f64654c000e636f6c756d6e53657474696e677374000f4c6a6176612f7574696c2f4d61703b4c000f73656374696f6e53657474696e677371007e0001787001737200176a6176612e7574696c2e4c696e6b6564486173684d617034c04e5c106cc0fb0200015a000b6163636573734f72646572787200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000078007371007e00043f4000000000000c7708000000100000000078	f
 6	John	Doe test role	test_role	inactive@in.active	1	1	2008-11-05 09:18:10.581+01	\N	\\xaced00057372004163682e73797374656d73782e636973642e6f70656e6269732e67656e657269632e7368617265642e62617369632e64746f2e446973706c617953657474696e677300000000000000010200035a001575736557696c64636172645365617263684d6f64654c000e636f6c756d6e53657474696e677374000f4c6a6176612f7574696c2f4d61703b4c000f73656374696f6e53657474696e677371007e0001787001737200176a6176612e7574696c2e4c696e6b6564486173684d617034c04e5c106cc0fb0200015a000b6163636573734f72646572787200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000078007371007e00043f4000000000000c7708000000100000000078	t
+7	John	Doe test space	test_space	inactive@in.active	1	3	2008-11-05 09:18:10.581+01	\N	\\xaced00057372004163682e73797374656d73782e636973642e6f70656e6269732e67656e657269632e7368617265642e62617369632e64746f2e446973706c617953657474696e677300000000000000010200035a001575736557696c64636172645365617263684d6f64654c000e636f6c756d6e53657474696e677374000f4c6a6176612f7574696c2f4d61703b4c000f73656374696f6e53657474696e677371007e0001787001737200176a6176612e7574696c2e4c696e6b6564486173684d617034c04e5c106cc0fb0200015a000b6163636573734f72646572787200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000078007371007e00043f4000000000000c7708000000100000000078	t
diff --git a/openbis/sourceTest/sql/postgresql/124/051=role_assignments.tsv b/openbis/sourceTest/sql/postgresql/124/051=role_assignments.tsv
index 4271bd48e2e..79b71915d4f 100644
--- a/openbis/sourceTest/sql/postgresql/124/051=role_assignments.tsv
+++ b/openbis/sourceTest/sql/postgresql/124/051=role_assignments.tsv
@@ -6,3 +6,4 @@
 6	OBSERVER	2	\N	3	2	2008-11-05 09:18:11.471+01	\N
 7	ETL_SERVER	\N	1	4	2	2008-11-05 09:18:11.471+01	\N
 8	POWER_USER	1	\N	6	2	2008-11-05 09:18:11.471+01	\N
+9	ADMIN	3	\N	7	2	2008-11-05 09:18:11.471+01	\N
-- 
GitLab