From f06f137655cbfb6ce9077a41cff0caa578417a94 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Mon, 18 Dec 2017 12:04:23 +0000
Subject: [PATCH] SSDM-5721: Improve code after review by Piotr

SVN: 39051
---
 .../html/test/test-create.js                  |  2 +
 .../html/test/test-update.js                  |  4 +-
 .../executor/person/CreatePersonExecutor.java |  8 ++
 .../person/ISetPersonSpaceExecutor.java       | 31 ++++++++
 .../person/PersonAuthorizationExecutor.java   |  2 +-
 .../executor/person/SearchPersonExecutor.java | 37 +++++++++-
 .../person/SetPersonSpaceExecutor.java        | 73 +++++++++++++++++++
 .../executor/person/UpdatePersonExecutor.java | 10 ++-
 .../RoleAssignmentAuthorizationExecutor.java  |  2 +-
 .../v3/as/dto/person/create/PersonCreation.js |  7 ++
 .../v3/as/dto/person/update/PersonUpdate.js   | 18 ++---
 .../systemtest/asapi/v3/AbstractTest.java     |  4 +-
 .../systemtest/asapi/v3/CreatePersonTest.java |  4 +
 .../systemtest/asapi/v3/SearchPersonTest.java | 42 +++++++++++
 .../systemtest/asapi/v3/UpdatePersonTest.java | 34 +++++++--
 .../v3/dto/person/create/PersonCreation.java  | 15 +++-
 .../v3/dto/person/update/PersonUpdate.java    | 12 +--
 17 files changed, 274 insertions(+), 31 deletions(-)
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/ISetPersonSpaceExecutor.java
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SetPersonSpaceExecutor.java

diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
index ae1d9b9403e..3609f8ae1ea 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
@@ -623,6 +623,7 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 			var fCreate = function(facade) {
 				var personCreation = new c.PersonCreation();
 				personCreation.setUserId(userId);
+				personCreation.setHomeSpaceId(new c.SpacePermId("TEST"))
 				return facade.createPersons([ personCreation ]);
 			}
 			
@@ -630,6 +631,7 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 				c.assertEqual(person.getUserId(), userId, "User id");
 				c.assertEqual(person.getRegistrator().getUserId(), "openbis_test_js", "Registrator");
 				c.assertEqual(person.isActive(), true, "User active");
+				c.assertEqual(person.getSpace().getCode(), "TEST", "Home space");
 			}
 			
 			testCreate(c, fCreate, c.findPerson, fCheck);
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-update.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-update.js
index deb92f55b74..bdecac76987 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-update.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-update.js
@@ -845,7 +845,7 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 
 			var fUpdate = function(facade, permId) {
 				var update = new c.PersonUpdate();
-				update.setPersonId(permId);
+				update.setUserId(permId);
 				update.setHomeSpaceId(new c.SpacePermId("TEST"))
 				return facade.updatePersons([ update ]);
 			}
@@ -871,7 +871,7 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 			
 			var fUpdate = function(facade, permId) {
 				var update = new c.PersonUpdate();
-				update.setPersonId(permId);
+				update.setUserId(permId);
 				update.deactivate();
 				return facade.updatePersons([ update ]);
 			}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/CreatePersonExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/CreatePersonExecutor.java
index b10b93a6f0d..ccdc11c98d6 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/CreatePersonExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/CreatePersonExecutor.java
@@ -56,6 +56,9 @@ public class CreatePersonExecutor
 {
     @Autowired
     private IDAOFactory daoFactory;
+    
+    @Autowired
+    private ISetPersonSpaceExecutor setPersonSpaceExecutor;
 
     @Autowired
     private AuthenticationServiceHolder authenticationServiceHolder;
@@ -72,6 +75,10 @@ public class CreatePersonExecutor
     @Override
     protected void checkData(IOperationContext context, PersonCreation creation)
     {
+        if (StringUtils.isEmpty(creation.getUserId()))
+        {
+            throw new UserFailureException("Unspecified user id.");
+        }
     }
 
     @Override
@@ -152,6 +159,7 @@ public class CreatePersonExecutor
     @Override
     protected void updateBatch(IOperationContext context, MapBatch<PersonCreation, PersonPE> batch)
     {
+        setPersonSpaceExecutor.set(context, batch);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/ISetPersonSpaceExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/ISetPersonSpaceExecutor.java
new file mode 100644
index 00000000000..27ceecc0d55
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/ISetPersonSpaceExecutor.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.executor.person;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.create.PersonCreation;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.ISetEntityRelationsExecutor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface ISetPersonSpaceExecutor extends ISetEntityRelationsExecutor<PersonCreation, PersonPE>
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/PersonAuthorizationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/PersonAuthorizationExecutor.java
index 76c8ca4c334..03f88a20a19 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/PersonAuthorizationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/PersonAuthorizationExecutor.java
@@ -34,7 +34,7 @@ public class PersonAuthorizationExecutor implements IPersonAuthorizationExecutor
 {
 
     @Override
-    @RolesAllowed({ RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
+    @RolesAllowed({ RoleWithHierarchy.PROJECT_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
     @Capability("GET_PERSON")
     public void canGet(IOperationContext context)
     {
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SearchPersonExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SearchPersonExecutor.java
index b346ce66982..9f86e13898b 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SearchPersonExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SearchPersonExecutor.java
@@ -22,6 +22,9 @@ import java.util.List;
 import org.springframework.stereotype.Component;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.IdSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.id.Me;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.id.PersonPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.search.EmailSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.search.FirstNameSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.search.LastNameSearchCriteria;
@@ -52,7 +55,10 @@ public class SearchPersonExecutor extends AbstractSearchObjectManuallyExecutor<P
     @Override
     protected Matcher<PersonPE> getMatcher(ISearchCriteria criteria)
     {
-        if (criteria instanceof UserIdSearchCriteria)
+        if (criteria instanceof IdSearchCriteria<?>)
+        {
+            return new IdMatcher();
+        } else if (criteria instanceof UserIdSearchCriteria)
         {
             return new UserIdMatcher();
         } else if (criteria instanceof UserIdsSearchCriteria)
@@ -73,6 +79,35 @@ public class SearchPersonExecutor extends AbstractSearchObjectManuallyExecutor<P
         }
     }
     
+    private class IdMatcher extends SimpleFieldMatcher<PersonPE>
+    {
+
+        @Override
+        protected boolean isMatching(IOperationContext context, PersonPE object, ISearchCriteria criteria)
+        {
+            Object id = ((IdSearchCriteria<?>) criteria).getId();
+
+            if (id == null)
+            {
+                return true;
+            } else if (id instanceof PersonPermId)
+            {
+                return object.getUserId().equals(((PersonPermId) id).getPermId());
+            } else if (id instanceof Me)
+            {
+                PersonPE person = context.getSession().tryGetPerson();
+                if (person != null)
+                {
+                    return object.getUserId().equals(person.getUserId());
+                }
+                throw new IllegalArgumentException("Unspecified session user");
+            } else
+            {
+                throw new IllegalArgumentException("Unknown id: " + criteria.getClass());
+            }
+        }
+    }
+    
     private class UserIdMatcher extends StringFieldMatcher<PersonPE>
     {
         
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SetPersonSpaceExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SetPersonSpaceExecutor.java
new file mode 100644
index 00000000000..61730e511b1
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/SetPersonSpaceExecutor.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.executor.person;
+
+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.asapi.v3.dto.person.create.PersonCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.id.ISpaceId;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.IOperationContext;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.AbstractSetEntityToOneRelationExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.space.IMapSpaceByIdExecutor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class SetPersonSpaceExecutor
+        extends AbstractSetEntityToOneRelationExecutor<PersonCreation, PersonPE, ISpaceId, SpacePE>
+        implements ISetPersonSpaceExecutor
+{
+    @Autowired
+    private IMapSpaceByIdExecutor mapSpaceByIdExecutor;
+
+    @Override
+    protected String getRelationName()
+    {
+        return "person-space";
+    }
+
+    @Override
+    protected ISpaceId getRelatedId(PersonCreation creation)
+    {
+        return creation.getHomeSpaceId();
+    }
+
+    @Override
+    protected Map<ISpaceId, SpacePE> map(IOperationContext context, List<ISpaceId> relatedIds)
+    {
+        return mapSpaceByIdExecutor.map(context, relatedIds);
+    }
+
+    @Override
+    protected void check(IOperationContext context, PersonPE entity, ISpaceId relatedId, SpacePE related)
+    {
+    }
+
+    @Override
+    protected void set(IOperationContext context, PersonPE entity, SpacePE related)
+    {
+        entity.setHomeSpace(related);
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/UpdatePersonExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/UpdatePersonExecutor.java
index 9cbd10086c9..3ddb6d440bf 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/UpdatePersonExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/person/UpdatePersonExecutor.java
@@ -65,7 +65,7 @@ public class UpdatePersonExecutor
     @Override
     protected IPersonId getId(PersonUpdate update)
     {
-        return update.getPersonId();
+        return update.getUserId();
     }
 
     @Override
@@ -77,13 +77,13 @@ public class UpdatePersonExecutor
     @Override
     protected void checkData(IOperationContext context, PersonUpdate update)
     {
-        IPersonId personId = update.getPersonId();
+        IPersonId personId = update.getUserId();
         if (personId == null || personId instanceof Me)
         {
             PersonPE person = context.getSession().tryGetPerson();
             if (person != null)
             {
-                update.setPersonId(new PersonPermId(person.getUserId()));
+                update.setUserId(new PersonPermId(person.getUserId()));
             } else
             {
                 throw new UserFailureException("Person to be updated not specified.");
@@ -119,6 +119,10 @@ public class UpdatePersonExecutor
     private void deactivate(IOperationContext context, PersonPE person)
     {
         authorizationExecutor.canDeactivate(context);
+        if (person.equals(context.getSession().tryGetPerson()))
+        {
+            throw new UserFailureException("You can not deactivate yourself. Ask another instance admin to do that for you.");
+        }
         IRoleAssignmentDAO roleAssignmenDAO = daoFactory.getRoleAssignmentDAO();
         person.setActive(false);
         person.clearAuthorizationGroups();
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/roleassignment/RoleAssignmentAuthorizationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/roleassignment/RoleAssignmentAuthorizationExecutor.java
index 275df382141..0e2c1f9aa6d 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/roleassignment/RoleAssignmentAuthorizationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/roleassignment/RoleAssignmentAuthorizationExecutor.java
@@ -38,7 +38,7 @@ public class RoleAssignmentAuthorizationExecutor implements IRoleAssignmentAutho
 {
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_ADMIN)
     @Capability("GET_ROLE_ASSIGNMENT")
     public void canGet(IOperationContext context)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/create/PersonCreation.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/create/PersonCreation.js
index 54456fb149a..3f265a01577 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/create/PersonCreation.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/create/PersonCreation.js
@@ -5,6 +5,7 @@ define([ "stjs" ], function(stjs) {
 		prototype['@type'] = 'as.dto.person.create.PersonCreation';
 		constructor.serialVersionUID = 1;
 		prototype.userId = null;
+		prototype.homeSpaceId = null;
 
 		prototype.getUserId = function() {
 			return this.userId;
@@ -12,6 +13,12 @@ define([ "stjs" ], function(stjs) {
 		prototype.setUserId = function(userId) {
 			this.userId = userId;
 		};
+		prototype.getHomeSpaceId = function() {
+			return this.homeSpaceId;
+		};
+		prototype.setHomeSpaceId = function(spaceId) {
+			this.homeSpaceId = spaceId;
+		};
 	}, {
 	});
 	return PersonCreation;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/update/PersonUpdate.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/update/PersonUpdate.js
index ea71be43cf5..bb4fc30f72b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/update/PersonUpdate.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/person/update/PersonUpdate.js
@@ -5,21 +5,21 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/
 	stjs.extend(PersonUpdate, null, [], function(constructor, prototype) {
 		prototype['@type'] = 'as.dto.person.update.PersonUpdate';
 		constructor.serialVersionUID = 1;
-		prototype.personId = null;
+		prototype.userId = null;
 		prototype.homeSpaceId = null;
 		prototype.active = true;
 
 		prototype.getObjectId = function() {
-			return this.getPersonId();
+			return this.getUserId();
 		};
-		prototype.getPersonId = function() {
-			return this.personId;
+		prototype.getUserId = function() {
+			return this.userId;
 		};
-		prototype.setPersonId = function(personId) {
-			this.personId = personId;
+		prototype.setUserId = function(userId) {
+			this.userId = userId;
 		};
 		prototype.getHomeSpaceId = function() {
-			return this.spaceId;
+			return this.homeSpaceId;
 		};
 		prototype.setHomeSpaceId = function(spaceId) {
 			this.homeSpaceId.setValue(spaceId);
@@ -31,8 +31,8 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/
 			this.active = false;
 		};
 	}, {
-		PersonId : "IPersonId",
-		spaceId : {
+		userId : "IPersonId",
+		homeSpaceId : {
 			name : "FieldUpdateValue",
 			arguments : [ "ISpaceId" ]
 		}
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractTest.java
index dc12ebbc2bd..f1ddfb168d0 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractTest.java
@@ -1250,7 +1250,9 @@ public class AbstractTest extends SystemTestCase
         List<String> renderedAssignments = new ArrayList<>();
         for (RoleAssignment roleAssignment : roleAssignments)
         {
-            renderedAssignments.add(roleAssignment.getRoleLevel() + "_" + roleAssignment.getRole() + " " + roleAssignment.getSpace());
+            Space space = roleAssignment.getSpace();
+            renderedAssignments.add(roleAssignment.getRoleLevel() + "_" + roleAssignment.getRole() + 
+                    (space == null ? "" : " " + space));
         }
         Collections.sort(renderedAssignments);
         return renderedAssignments.toString();
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePersonTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePersonTest.java
index e660cc130eb..15343e8befa 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePersonTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePersonTest.java
@@ -28,6 +28,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.create.PersonCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.fetchoptions.PersonFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.id.PersonPermId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.id.SpacePermId;
 import ch.systemsx.cisd.common.action.IDelegatedAction;
 
 /**
@@ -44,6 +45,7 @@ public class CreatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_USER, PASSWORD);
         PersonCreation personCreation = new PersonCreation();
         personCreation.setUserId("user-" + System.currentTimeMillis());
+        personCreation.setHomeSpaceId(new SpacePermId("CISD"));
         
         // When
         List<PersonPermId> persons = v3api.createPersons(sessionToken, Arrays.asList(personCreation));
@@ -52,9 +54,11 @@ public class CreatePersonTest extends AbstractTest
         assertEquals(persons.toString(), "[" + personCreation.getUserId() + "]");
         PersonFetchOptions fetchOptions = new PersonFetchOptions();
         fetchOptions.withRegistrator();
+        fetchOptions.withSpace();
         Person person = v3api.getPersons(sessionToken, persons, fetchOptions).get(persons.get(0));
         assertEquals(person.getUserId(), personCreation.getUserId());
         assertEquals(person.getRegistrator().getUserId(), TEST_USER);
+        assertEquals(person.getSpace().getCode(), "CISD");
     }
     
     @Test(dataProvider = "usersNotAllowedToCreatePersons")
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPersonTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPersonTest.java
index 7de4b00cde2..1d809a0a90b 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPersonTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPersonTest.java
@@ -24,6 +24,8 @@ import org.testng.annotations.Test;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.fetchoptions.PersonFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.id.Me;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.id.PersonPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.search.PersonSearchCriteria;
 
 /**
@@ -57,4 +59,44 @@ public class SearchPersonTest extends AbstractTest
                 + "observer_cisd, home space:CISD, [SPACE_ADMIN Space TESTGROUP, SPACE_OBSERVER Space CISD]\n"
                 + "test_role, home space:CISD, [SPACE_POWER_USER Space CISD], registrator: test\n");
     }
+    
+    @Test
+    public void testSearchPersonById()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PersonSearchCriteria searchCriteria = new PersonSearchCriteria();
+        searchCriteria.withId().thatEquals(new PersonPermId(TEST_GROUP_OBSERVER));
+        PersonFetchOptions fetchOptions = new PersonFetchOptions();
+        fetchOptions.withSpace();
+        fetchOptions.withRoleAssignments().withSpace();
+        fetchOptions.withRegistrator();
+        
+        // Then
+        List<Person> persons = v3api.searchPersons(sessionToken, searchCriteria, fetchOptions).getObjects();
+        
+        // When
+        assertEquals(renderPersons(persons), "observer, home space:CISD, [SPACE_OBSERVER Space TESTGROUP]\n");
+    }
+    
+    @Test
+    public void testSearchPersonByMe()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PersonSearchCriteria searchCriteria = new PersonSearchCriteria();
+        searchCriteria.withId().thatEquals(new Me());
+        PersonFetchOptions fetchOptions = new PersonFetchOptions();
+        fetchOptions.withSpace();
+        fetchOptions.withRoleAssignments().withSpace();
+        fetchOptions.withRegistrator();
+        
+        // Then
+        List<Person> persons = v3api.searchPersons(sessionToken, searchCriteria, fetchOptions).getObjects();
+        
+        // When
+        assertEquals(renderPersons(persons), "test, home space:CISD, [INSTANCE_ADMIN, INSTANCE_ETL_SERVER, "
+                + "SPACE_ADMIN Space CISD, SPACE_ADMIN Space TESTGROUP, SPACE_ETL_SERVER Space CISD], "
+                + "registrator: system\n");
+    }
 }
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/UpdatePersonTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/UpdatePersonTest.java
index 14010d8e902..30682e9a949 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/UpdatePersonTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/UpdatePersonTest.java
@@ -46,7 +46,7 @@ public class UpdatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_USER, PASSWORD);
         PersonUpdate personUpdate = new PersonUpdate();
         PersonPermId personId = new PersonPermId("homeless");
-        personUpdate.setPersonId(personId);
+        personUpdate.setUserId(personId);
         personUpdate.setHomeSpaceId(new SpacePermId("TEST-SPACE"));
         
         assertUserFailureException(new IDelegatedAction()
@@ -68,7 +68,7 @@ public class UpdatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_OBSERVER_CISD, PASSWORD);
         PersonUpdate personUpdate = new PersonUpdate();
         PersonPermId personId = new PersonPermId("homeless");
-        personUpdate.setPersonId(personId);
+        personUpdate.setUserId(personId);
         personUpdate.setHomeSpaceId(new SpacePermId("TESTGROUP"));
         
         // When
@@ -89,7 +89,7 @@ public class UpdatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_OBSERVER_CISD, PASSWORD);
         PersonUpdate personUpdate = new PersonUpdate();
         PersonPermId personId = new PersonPermId("homeless");
-        personUpdate.setPersonId(personId);
+        personUpdate.setUserId(personId);
         personUpdate.setHomeSpaceId(new SpacePermId("CISD"));
         
         assertAuthorizationFailureException(new IDelegatedAction()
@@ -130,7 +130,7 @@ public class UpdatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_GROUP_OBSERVER, PASSWORD);
         PersonUpdate personUpdate = new PersonUpdate();
         IPersonId personId = new Me();
-        personUpdate.setPersonId(personId);
+        personUpdate.setUserId(personId);
         personUpdate.setHomeSpaceId(new SpacePermId("TESTGROUP"));
         
         // When
@@ -151,7 +151,7 @@ public class UpdatePersonTest extends AbstractTest
         String sessionToken = v3api.login(TEST_USER, PASSWORD);
         PersonUpdate personUpdate = new PersonUpdate();
         PersonPermId personId = new PersonPermId(TEST_GROUP_OBSERVER);
-        personUpdate.setPersonId(personId);
+        personUpdate.setUserId(personId);
         personUpdate.deactivate();
         
         // When
@@ -165,6 +165,28 @@ public class UpdatePersonTest extends AbstractTest
         assertEquals(person.isActive(), Boolean.FALSE);
     }
     
+    @Test
+    public void testDeactivateYourself()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PersonUpdate personUpdate = new PersonUpdate();
+        PersonPermId personId = new PersonPermId(TEST_USER);
+        personUpdate.setUserId(personId);
+        personUpdate.deactivate();
+        
+        assertUserFailureException(new IDelegatedAction()
+        {
+            @Override
+            public void execute()
+            {
+                // When
+                v3api.updatePersons(sessionToken, Arrays.asList(personUpdate));
+            }
+            // Then
+        }, "You can not deactivate yourself. Ask another instance admin to do that for you.");
+    }
+    
     @Test(dataProvider = "usersNotAllowedToDeactivateUsers")
     public void testDeactivateUserWithUserCausingAuthorizationFailure(final String user)
     {
@@ -176,7 +198,7 @@ public class UpdatePersonTest extends AbstractTest
                     // Given
                     String sessionToken = v3api.login(user, PASSWORD);
                     PersonUpdate personUpdate = new PersonUpdate();
-                    personUpdate.setPersonId(new PersonPermId(TEST_GROUP_OBSERVER));
+                    personUpdate.setUserId(new PersonPermId(TEST_GROUP_OBSERVER));
                     personUpdate.deactivate();
                     
                     // When
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/create/PersonCreation.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/create/PersonCreation.java
index c2cce127b0b..9417df0aa59 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/create/PersonCreation.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/create/PersonCreation.java
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.ICreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.IObjectCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.id.ISpaceId;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
@@ -34,6 +35,9 @@ public class PersonCreation implements ICreation, IObjectCreation
 
     @JsonProperty
     private String userId;
+    
+    @JsonProperty
+    private ISpaceId homeSpaceId;
 
     public String getUserId()
     {
@@ -44,6 +48,15 @@ public class PersonCreation implements ICreation, IObjectCreation
     {
         this.userId = userId;
     }
-    
+
+    public ISpaceId getHomeSpaceId()
+    {
+        return homeSpaceId;
+    }
+
+    public void setHomeSpaceId(ISpaceId homeSpaceId)
+    {
+        this.homeSpaceId = homeSpaceId;
+    }
     
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/update/PersonUpdate.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/update/PersonUpdate.java
index b8b1d7cb9a7..80c5e0af1f4 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/update/PersonUpdate.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/person/update/PersonUpdate.java
@@ -38,7 +38,7 @@ public class PersonUpdate implements IUpdate, IObjectUpdate<IPersonId>
     private static final long serialVersionUID = 1L;
     
     @JsonProperty
-    private IPersonId personId;
+    private IPersonId userId;
 
     @JsonProperty
     private FieldUpdateValue<ISpaceId> homeSpaceId = new FieldUpdateValue<ISpaceId>();
@@ -46,21 +46,21 @@ public class PersonUpdate implements IUpdate, IObjectUpdate<IPersonId>
     @JsonProperty
     private boolean active = true;
     
-    public IPersonId getPersonId()
+    public IPersonId getUserId()
     {
-        return personId;
+        return userId;
     }
 
-    public void setPersonId(IPersonId personId)
+    public void setUserId(IPersonId personId)
     {
-        this.personId = personId;
+        this.userId = personId;
     }
 
     @Override
     @JsonIgnore
     public IPersonId getObjectId()
     {
-        return getPersonId();
+        return getUserId();
     }
 
     @JsonIgnore
-- 
GitLab