diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectIdentifierExistingSpacePredicateSystemTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectIdentifierExistingSpacePredicateSystemTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..26bea8a629321c95bc10d1a29c1962aad36f9d80
--- /dev/null
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectIdentifierExistingSpacePredicateSystemTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 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.systemsx.cisd.openbis.datastoreserver.systemtests.authorization.predicate.project;
+
+import java.util.List;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.datastoreserver.systemtests.authorization.predicate.CommonPredicateSystemTest;
+import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSessionProvider;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.systemtest.authorization.predicate.project.ProjectPredicateTestService;
+
+/**
+ * @author pkupczyk
+ */
+public class ProjectIdentifierExistingSpacePredicateSystemTest extends CommonPredicateSystemTest<ProjectIdentifier>
+{
+
+    @Override
+    protected ProjectIdentifier createNonexistentObject()
+    {
+        return new ProjectIdentifier("IDONTEXIST", "IDONTEXIST");
+    }
+
+    @Override
+    protected ProjectIdentifier createObject(SpacePE spacePE, ProjectPE projectPE)
+    {
+        return new ProjectIdentifier(spacePE.getCode(), projectPE.getCode());
+    }
+
+    @Override
+    protected void evaluateObjects(IAuthSessionProvider sessionProvider, List<ProjectIdentifier> objects)
+    {
+        getBean(ProjectPredicateTestService.class).testProjectIdentifierExistingSpacePredicate(sessionProvider, objects.get(0));
+    }
+
+    @Override
+    protected void assertWithNull(PersonPE person, Throwable t)
+    {
+        assertException(t, UserFailureException.class, "No project specified.");
+    }
+
+    @Override
+    protected void assertWithNonexistentObject(PersonPE person, Throwable t)
+    {
+        assertNoException(t);
+    }
+
+}
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectPermIdStringPredicateSystemTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectPermIdStringPredicateSystemTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6f45bb60b5d13b4762d17ff32645aa8ff69ed16
--- /dev/null
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/authorization/predicate/project/ProjectPermIdStringPredicateSystemTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 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.systemsx.cisd.openbis.datastoreserver.systemtests.authorization.predicate.project;
+
+import java.util.List;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.datastoreserver.systemtests.authorization.predicate.CommonPredicateSystemTest;
+import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSessionProvider;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+import ch.systemsx.cisd.openbis.systemtest.authorization.predicate.project.ProjectPredicateTestService;
+
+/**
+ * @author pkupczyk
+ */
+public class ProjectPermIdStringPredicateSystemTest extends CommonPredicateSystemTest<String>
+{
+
+    @Override
+    protected String createNonexistentObject()
+    {
+        return "IDONTEXIST";
+    }
+
+    @Override
+    protected String createObject(SpacePE spacePE, ProjectPE projectPE)
+    {
+        return projectPE.getPermId();
+    }
+
+    @Override
+    protected void evaluateObjects(IAuthSessionProvider sessionProvider, List<String> objects)
+    {
+        getBean(ProjectPredicateTestService.class).testProjectPermIdStringPredicate(sessionProvider, objects.get(0));
+    }
+
+    @Override
+    protected void assertWithNull(PersonPE person, Throwable t)
+    {
+        assertException(t, UserFailureException.class, "No project perm id specified.");
+    }
+
+    @Override
+    protected void assertWithNonexistentObject(PersonPE person, Throwable t)
+    {
+        assertNoException(t);
+    }
+
+}
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 ebd142efa8a738ba72edf05343e4d495f4f123be..543d9531fb08d78503bf4c25af6ea9d697757324 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
@@ -70,6 +70,7 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DeletionT
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ExperimentUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ListSampleCriteriaPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierPredicate;
+import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPermIdStringPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.RevertDeletionPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleTechIdCollectionPredicate;
@@ -921,7 +922,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_OBSERVER)
     public List<Experiment> listMetaprojectExperiments(final String sessionToken,
             IMetaprojectId metaprojectId)
     {
@@ -958,10 +959,10 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_OBSERVER)
     public List<Experiment> listExperiments(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier)
+            @AuthorizationGuard(guardClass = ProjectIdentifierPredicate.class) ProjectIdentifier projectIdentifier)
     {
         List<ProjectIdentifier> projectIdentifiers = projectIdentifier != null ? Collections.singletonList(projectIdentifier) : null;
         return listExperiments(sessionToken, experimentType, null, projectIdentifiers, false, false);
@@ -2246,9 +2247,10 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_USER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_USER)
     @Capability("WRITE_EXPERIMENT_ATTACHMENT")
-    public void updateExperimentAttachments(String sessionToken, TechId experimentId,
+    public void updateExperimentAttachments(String sessionToken,
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId,
             Attachment attachment)
     {
         Session session = getSession(sessionToken);
@@ -2260,9 +2262,9 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_USER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_USER)
     @Capability("WRITE_EXPERIMENT_ATTACHMENT")
-    public void addExperimentAttachment(String sessionToken, TechId experimentId,
+    public void addExperimentAttachment(String sessionToken, @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId,
             NewAttachment attachment)
     {
         Session session = getSession(sessionToken);
@@ -2530,7 +2532,8 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
 
     @Override
     @RolesAllowed(RoleWithHierarchy.PROJECT_OBSERVER)
-    public IIdHolder getProjectIdHolder(String sessionToken, String projectPermId)
+    public IIdHolder getProjectIdHolder(String sessionToken,
+            @AuthorizationGuard(guardClass = ProjectPermIdStringPredicate.class) String projectPermId)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
@@ -2946,7 +2949,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed({ RoleWithHierarchy.SPACE_POWER_USER, RoleWithHierarchy.PROJECT_ADMIN })
     @Capability("WRITE_PROJECT_ATTACHMENT")
-    public void updateProjectAttachments(String sessionToken, TechId projectId,
+    public void updateProjectAttachments(String sessionToken, @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId,
             Attachment attachment)
     {
         Session session = getSession(sessionToken);
@@ -2960,7 +2963,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed({ RoleWithHierarchy.SPACE_POWER_USER, RoleWithHierarchy.PROJECT_ADMIN })
     @Capability("WRITE_PROJECT_ATTACHMENT")
-    public void addProjectAttachments(String sessionToken, TechId projectId,
+    public void addProjectAttachments(String sessionToken, @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId,
             NewAttachment attachment)
     {
         Session session = getSession(sessionToken);
@@ -3588,7 +3591,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_USER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_USER)
     public void updateManagedPropertyOnExperiment(String sessionToken, TechId experimentId,
             IManagedProperty managedProperty, IManagedUiAction updateAction)
     {
@@ -4248,7 +4251,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_OBSERVER)
     public void addToMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToAdd)
     {
@@ -4341,7 +4344,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     }
 
     @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @RolesAllowed(RoleWithHierarchy.PROJECT_OBSERVER)
     public Metaproject registerMetaproject(String sessionToken,
             IMetaprojectRegistration registration)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java
index 79b5b605584eb655d552ac7cfb11427b5fe30806..43fe0ade2edcb985dcae9935ae1dfefec4a5075c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java
@@ -86,6 +86,8 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ListSampl
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.NewExperimentPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.NewSamplePredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.NewSamplesWithTypePredicate;
+import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierExistingSpacePredicate;
+import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPermIdPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleOwnerIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SamplePermIdPredicate;
@@ -553,7 +555,7 @@ public class ServiceForDataStoreServer extends AbstractCommonServer<IServiceForD
     @Override
     @RolesAllowed({ RoleWithHierarchy.PROJECT_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
     public List<Experiment> listExperimentsForProjects(String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) List<ProjectIdentifier> projectIdentifiers,
+            @AuthorizationGuard(guardClass = ProjectIdentifierPredicate.class) List<ProjectIdentifier> projectIdentifiers,
             ExperimentFetchOptions experimentFetchOptions)
     {
         if (sessionToken == null)
@@ -953,7 +955,7 @@ public class ServiceForDataStoreServer extends AbstractCommonServer<IServiceForD
         Set<SamplePropertyPE> properties = top.getProperties();
         HibernateUtils.initialize(properties);
         return EntityPropertyTranslator.translate(properties.toArray(new SamplePropertyPE[0]),
-                new HashMap<MaterialTypePE, MaterialType>(), new HashMap<PropertyTypePE, PropertyType>(), 
+                new HashMap<MaterialTypePE, MaterialType>(), new HashMap<PropertyTypePE, PropertyType>(),
                 managedPropertyEvaluatorFactory);
     }
 
@@ -976,7 +978,7 @@ public class ServiceForDataStoreServer extends AbstractCommonServer<IServiceForD
         Set<SamplePropertyPE> properties = sample.getProperties();
         HibernateUtils.initialize(properties);
         return EntityPropertyTranslator.translate(properties.toArray(new SamplePropertyPE[0]),
-                new HashMap<MaterialTypePE, MaterialType>(), new HashMap<PropertyTypePE, PropertyType>(), 
+                new HashMap<MaterialTypePE, MaterialType>(), new HashMap<PropertyTypePE, PropertyType>(),
                 managedPropertyEvaluatorFactory);
     }
 
@@ -1694,7 +1696,7 @@ public class ServiceForDataStoreServer extends AbstractCommonServer<IServiceForD
     @Override
     @RolesAllowed({ RoleWithHierarchy.PROJECT_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
     public Project tryGetProject(String sessionToken,
-            @AuthorizationGuard(guardClass = ExistingSpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier)
+            @AuthorizationGuard(guardClass = ProjectIdentifierExistingSpacePredicate.class) ProjectIdentifier projectIdentifier)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierExistingSpacePredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierExistingSpacePredicate.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5b6b1f48da2330da8c4f4e4f23eb9588bdd36d8
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierExistingSpacePredicate.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017 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.systemsx.cisd.openbis.generic.server.authorization.predicate;
+
+/**
+ * @author pkupczyk
+ */
+public class ProjectIdentifierExistingSpacePredicate extends ProjectIdentifierPredicate
+{
+
+    public ProjectIdentifierExistingSpacePredicate()
+    {
+        super(true);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierPredicate.java
index 9a248129740698686cf8b548b2cda7d04a2209d1..ea8a708580072dbe78a2d8f02a48a4adaa87cfed 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectIdentifierPredicate.java
@@ -34,9 +34,15 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
  */
 public class ProjectIdentifierPredicate extends DelegatedPredicate<SpaceIdentifier, ProjectIdentifier>
 {
+
     public ProjectIdentifierPredicate()
     {
-        super(new SpaceIdentifierPredicate(false));
+        this(false);
+    }
+
+    public ProjectIdentifierPredicate(boolean okForNonExistentSpaces)
+    {
+        super(new SpaceIdentifierPredicate(okForNonExistentSpaces));
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectPermIdStringPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectPermIdStringPredicate.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9edfe57fe93c9dde94b88af0a6753dfef0dbfb6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/predicate/ProjectPermIdStringPredicate.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 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.systemsx.cisd.openbis.generic.server.authorization.predicate;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.PermId;
+
+/**
+ * @author pkupczyk
+ */
+public class ProjectPermIdStringPredicate extends DelegatedPredicate<PermId, String>
+{
+    public ProjectPermIdStringPredicate()
+    {
+        super(new ProjectPermIdPredicate());
+    }
+
+    @Override
+    public PermId tryConvert(String value)
+    {
+        return value != null ? new PermId(value) : null;
+    }
+
+    @Override
+    public String getCandidateDescription()
+    {
+        return "project perm id";
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServerTest.java
index ff3d92efa33f39a6f90441e228506ab71750d61d..f2f934604992c64bdafac6471ab13824928b8354 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServerTest.java
@@ -16,18 +16,30 @@
 
 package ch.systemsx.cisd.openbis.generic.server;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import junit.framework.Assert;
-
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentFetchOptions;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PermId;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.systemtest.SystemTestCase;
+import ch.systemsx.cisd.openbis.systemtest.authorization.ProjectAuthorizationUser;
+
+import junit.framework.Assert;
 
 /**
  * @author pkupczyk
@@ -83,4 +95,149 @@ public class ServiceForDataStoreServerTest extends SystemTestCase
         Assert.assertEquals(Long.valueOf(123L), updatedDataSets.get(0).getSize());
     }
 
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListExperimentsForProjectsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+        ExperimentFetchOptions fetchOptions = new ExperimentFetchOptions();
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments =
+                    etlService.listExperimentsForProjects(session.getSessionToken(), Arrays.asList(projectIdentifier), fetchOptions);
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                etlService.listExperimentsForProjects(session.getSessionToken(), Arrays.asList(projectIdentifier), fetchOptions);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListProjectsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        List<Project> projects = etlService.listProjects(session.getSessionToken());
+
+        if (user.isTestSpaceUser())
+        {
+            assertEntities("[/TEST-SPACE/NOE, /TEST-SPACE/PROJECT-TO-DELETE, /TEST-SPACE/TEST-PROJECT]", projects);
+        } else if (user.isTestGroupUser())
+        {
+            assertEntities("[/TESTGROUP/TESTPROJ]", projects);
+        } else if (user.isTestProjectUser() && user.hasPAEnabled())
+        {
+            assertEntities("[/TEST-SPACE/PROJECT-TO-DELETE, /TEST-SPACE/TEST-PROJECT]", projects);
+        } else
+        {
+            assertEntities("[]", projects);
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testTryGetProjectWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            Project project = etlService.tryGetProject(session.getSessionToken(), projectIdentifier);
+            assertEquals(project.getIdentifier(), "/TEST-SPACE/TEST-PROJECT");
+        } else
+        {
+            try
+            {
+                etlService.tryGetProject(session.getSessionToken(), projectIdentifier);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testTryGetProjectByPermIdWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        PermId projectPermId = new PermId("20120814110011738-105"); // /TEST-SPACE/TEST-PROJECT
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            Project project = etlService.tryGetProjectByPermId(session.getSessionToken(), projectPermId);
+            assertEquals(project.getIdentifier(), "/TEST-SPACE/TEST-PROJECT");
+        } else
+        {
+            try
+            {
+                etlService.tryGetProjectByPermId(session.getSessionToken(), projectPermId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testTryGetExperimentByPermIdWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        PermId experimentPermId = new PermId("201206190940555-1032"); // /TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            Experiment experiment = etlService.tryGetExperimentByPermId(session.getSessionToken(), experimentPermId);
+            assertEquals(experiment.getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                etlService.tryGetExperimentByPermId(session.getSessionToken(), experimentPermId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListDataSetsByExperimentIDWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = etlService.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId experimentId = new TechId(23L); // /TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<AbstractExternalData> dataSets = etlService.listDataSetsByExperimentID(session.getSessionToken(), experimentId);
+            assertEquals(dataSets.size(), 9);
+        } else
+        {
+            try
+            {
+                etlService.listDataSetsByExperimentID(session.getSessionToken(), experimentId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CommonServerTest.java
index 43b3986932adc4a1ee07524d8767fce9630f3e86..16afe36d91e24ebfb2834870e82e9b342ccbb776 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CommonServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CommonServerTest.java
@@ -31,7 +31,7 @@ import java.util.Map;
 
 import javax.sql.DataSource;
 
-import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.log4j.Logger;
 import org.springframework.transaction.annotation.Propagation;
@@ -44,6 +44,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
@@ -52,15 +53,22 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ContainerDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentUpdateResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsIds;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
@@ -68,7 +76,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.displaysettings.IDisplaySettingsUpdate;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.id.experiment.ExperimentIdentifierId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.id.metaproject.MetaprojectIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
@@ -108,7 +119,7 @@ public class CommonServerTest extends SystemTestCase
 
     private AuthorizationGroup findAuthorizationGroup(List<AuthorizationGroup> spaces, final String spaceCode)
     {
-        return CollectionUtils.find(spaces, new Predicate<AuthorizationGroup>()
+        return IterableUtils.find(spaces, new Predicate<AuthorizationGroup>()
             {
                 @Override
                 public boolean evaluate(AuthorizationGroup object)
@@ -247,6 +258,81 @@ public class CommonServerTest extends SystemTestCase
 
     }
 
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testGetProjectInfoByTechIdWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId projectId = new TechId(5L); // /TEST-SPACE/TEST-PROJECT
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            Project project = commonServer.getProjectInfo(session.getSessionToken(), projectId);
+            assertNotNull(project);
+            assertEquals(project.getIdentifier(), "/TEST-SPACE/TEST-PROJECT");
+        } else
+        {
+            try
+            {
+                commonServer.getProjectInfo(session.getSessionToken(), projectId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testGetProjectInfoByIdentifierWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            Project project = commonServer.getProjectInfo(session.getSessionToken(), projectIdentifier);
+            assertNotNull(project);
+            assertEquals(project.getIdentifier(), "/TEST-SPACE/TEST-PROJECT");
+        } else
+        {
+            try
+            {
+                commonServer.getProjectInfo(session.getSessionToken(), projectIdentifier);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testGetProjectIdHolderWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        String projectPermId = "20120814110011738-105"; // /TEST-SPACE/TEST-PROJECT
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            IIdHolder project = commonServer.getProjectIdHolder(session.getSessionToken(), projectPermId);
+            assertNotNull(project);
+            assertEquals(project.getId(), Long.valueOf(5));
+        } else
+        {
+            try
+            {
+                commonServer.getProjectIdHolder(session.getSessionToken(), projectPermId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
     @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
     public void testUpdateProjectWithProjectAuthorization(ProjectAuthorizationUser user)
     {
@@ -276,7 +362,80 @@ public class CommonServerTest extends SystemTestCase
     }
 
     @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
-    public void testDeleteProjectWithProjectAuthorization(ProjectAuthorizationUser user)
+    public void testUpdateProjectAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId projectId = new TechId(5L); // /TEST-SPACE/TEST-PROJECT
+
+        Attachment attachment = new Attachment();
+        attachment.setFileName("testProject.txt");
+        attachment.setTitle("new title");
+        attachment.setVersion(1);
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            commonServer.updateProjectAttachments(session.getSessionToken(), projectId, attachment);
+
+            List<Attachment> attachments = commonServer.listProjectAttachments(session.getSessionToken(), projectId);
+            assertEquals(attachments.size(), 1);
+            assertEquals(attachments.get(0).getTitle(), attachment.getTitle());
+        } else
+        {
+            try
+            {
+                commonServer.updateProjectAttachments(session.getSessionToken(), projectId, attachment);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testDeleteProjectAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO testSession = commonServer.tryAuthenticate(TEST_USER, PASSWORD);
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId projectId = new TechId(5L); // /TEST-SPACE/TEST-PROJECT
+        String fileName = "testProject.txt";
+        String reason = "testReason";
+        Integer version = 1;
+
+        AttachmentWithContent before = genericServer.getProjectFileAttachment(testSession.getSessionToken(), projectId, fileName, version);
+
+        assertNotNull(before);
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            commonServer.deleteProjectAttachments(session.getSessionToken(), projectId, Arrays.asList(fileName), reason);
+
+            try
+            {
+                genericServer.getProjectFileAttachment(testSession.getSessionToken(), projectId, fileName, version);
+                fail();
+            } catch (UserFailureException e)
+            {
+                assertEquals(e.getMessage(),
+                        "Attachment 'testProject.txt' (version '1') not found in project '/TEST-SPACE/TEST-PROJECT'.");
+            }
+        } else
+        {
+            try
+            {
+                commonServer.deleteProjectAttachments(session.getSessionToken(), projectId, Arrays.asList(fileName), reason);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testDeleteProjectsWithProjectAuthorization(ProjectAuthorizationUser user)
     {
         SessionContextDTO testSession = commonServer.tryAuthenticate(TEST_USER, PASSWORD);
         SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
@@ -331,6 +490,91 @@ public class CommonServerTest extends SystemTestCase
         }
     }
 
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListProjectAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId projectId = new TechId(5L); // /TEST-SPACE/TEST-PROJECT
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Attachment> attachments = commonServer.listProjectAttachments(session.getSessionToken(), projectId);
+            assertEquals(attachments.size(), 1);
+            assertEquals(attachments.get(0).getFileName(), "testProject.txt");
+        } else
+        {
+            try
+            {
+                commonServer.listProjectAttachments(session.getSessionToken(), projectId);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testRegisterProjectWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "PA_TEST");
+
+        if (user.isTestSpaceUser())
+        {
+            commonServer.registerProject(session.getSessionToken(), projectIdentifier, "testDescription", user.getUserId(),
+                    Arrays.<NewAttachment> asList());
+
+            Project projectInfo = commonServer.getProjectInfo(session.getSessionToken(), projectIdentifier);
+            assertEquals(projectInfo.getIdentifier(), projectIdentifier.toString());
+        } else
+        {
+            try
+            {
+                commonServer.registerProject(session.getSessionToken(), projectIdentifier, "testDescription", user.getUserId(),
+                        Arrays.<NewAttachment> asList());
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testAddProjectAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId projectId = new TechId(5L); // /TEST-SPACE/TEST-PROJECT
+
+        NewAttachment attachment = new NewAttachment();
+        attachment.setFilePath("testProject2.txt");
+        attachment.setContent("testContent2".getBytes());
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            commonServer.addProjectAttachments(session.getSessionToken(), projectId, attachment);
+
+            List<Attachment> attachments = commonServer.listProjectAttachments(session.getSessionToken(), projectId);
+            assertEquals(attachments.size(), 2);
+            assertEquals(attachments.get(0).getFileName(), "testProject.txt");
+            assertEquals(attachments.get(1).getFileName(), "testProject2.txt");
+        } else
+        {
+            try
+            {
+                commonServer.addProjectAttachments(session.getSessionToken(), projectId, attachment);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
     @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
     public void testDeleteExperimentsWithProjectAuthorization(ProjectAuthorizationUser user)
     {
@@ -423,6 +667,244 @@ public class CommonServerTest extends SystemTestCase
         }
     }
 
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListExperimentsByExperimentTypeAndProjectIdentifierWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ExperimentType experimentType = new ExperimentType();
+        experimentType.setCode("SIRNA_HCS");
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments = commonServer.listExperiments(session.getSessionToken(), experimentType, projectIdentifier);
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                commonServer.listExperiments(session.getSessionToken(), experimentType, projectIdentifier);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListExperimentsByExperimentTypeAndProjectIdentifiersWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ExperimentType experimentType = new ExperimentType();
+        experimentType.setCode("SIRNA_HCS");
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments = commonServer.listExperiments(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                commonServer.listExperiments(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListExperimentsHavingSamplesWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ExperimentType experimentType = new ExperimentType();
+        experimentType.setCode("SIRNA_HCS");
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments =
+                    commonServer.listExperimentsHavingSamples(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                commonServer.listExperimentsHavingSamples(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListExperimentsHavingDataSetsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ExperimentType experimentType = new ExperimentType();
+        experimentType.setCode("SIRNA_HCS");
+
+        ProjectIdentifier projectIdentifier = new ProjectIdentifier("TEST-SPACE", "TEST-PROJECT");
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments =
+                    commonServer.listExperimentsHavingDataSets(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            try
+            {
+                commonServer.listExperimentsHavingDataSets(session.getSessionToken(), experimentType, Arrays.asList(projectIdentifier));
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testListMetaprojectExperimentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        Metaproject metaproject = new Metaproject();
+        metaproject.setName("TEST_LIST_METAPROJECT_EXPERIMENTS");
+        metaproject = commonServer.registerMetaproject(session.getSessionToken(), metaproject);
+
+        MetaprojectAssignmentsIds assignments = new MetaprojectAssignmentsIds();
+        assignments.addExperiment(new ExperimentIdentifierId("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST"));
+
+        commonServer.addToMetaproject(session.getSessionToken(), new MetaprojectIdentifierId(metaproject.getIdentifier()), assignments);
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments =
+                    commonServer.listMetaprojectExperiments(session.getSessionToken(), new MetaprojectIdentifierId(metaproject.getIdentifier()));
+
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).isStub(), false);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            List<Experiment> experiments =
+                    commonServer.listMetaprojectExperiments(session.getSessionToken(), new MetaprojectIdentifierId(metaproject.getIdentifier()));
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).isStub(), true);
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testSearchForExperimentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        ExperimentType experimentType = new ExperimentType();
+        experimentType.setCode("SIRNA_HCS");
+
+        DetailedSearchCriterion criterion = new DetailedSearchCriterion();
+        criterion.setField(DetailedSearchField.createAttributeField(ExperimentAttributeSearchFieldKind.PROJECT));
+        criterion.setValue("TEST-PROJECT");
+
+        DetailedSearchCriteria criteria = new DetailedSearchCriteria();
+        criteria.setCriteria(Arrays.asList(criterion));
+        criteria.setConnection(SearchCriteriaConnection.MATCH_ANY);
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            List<Experiment> experiments =
+                    commonServer.searchForExperiments(session.getSessionToken(), criteria);
+            assertEquals(experiments.size(), 1);
+            assertEquals(experiments.get(0).getIdentifier(), "/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
+        } else
+        {
+            List<Experiment> experiments = commonServer.searchForExperiments(session.getSessionToken(), criteria);
+            assertEquals(experiments.size(), 0);
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testUpdateExperimentAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId experimentId = new TechId(23L); // /TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST
+
+        Attachment attachment = new Attachment();
+        attachment.setFileName("testExperiment.txt");
+        attachment.setTitle("new title");
+        attachment.setVersion(1);
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            commonServer.updateExperimentAttachments(session.getSessionToken(), experimentId, attachment);
+
+            List<Attachment> attachments = commonServer.listExperimentAttachments(session.getSessionToken(), experimentId);
+            assertEquals(attachments.size(), 1);
+            assertEquals(attachments.get(0).getTitle(), attachment.getTitle());
+        } else
+        {
+            try
+            {
+                commonServer.updateExperimentAttachments(session.getSessionToken(), experimentId, attachment);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
+    @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
+    public void testAddExperimentAttachmentWithProjectAuthorization(ProjectAuthorizationUser user)
+    {
+        SessionContextDTO session = commonServer.tryAuthenticate(user.getUserId(), PASSWORD);
+
+        TechId experimentId = new TechId(23L); // /TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST
+
+        NewAttachment attachment = new NewAttachment();
+        attachment.setFilePath("testExperiment2.txt");
+        attachment.setContent("testContent2".getBytes());
+
+        if (user.isTestSpaceUser() || (user.isTestProjectUser() && user.hasPAEnabled()))
+        {
+            commonServer.addExperimentAttachment(session.getSessionToken(), experimentId, attachment);
+
+            List<Attachment> attachments = commonServer.listExperimentAttachments(session.getSessionToken(), experimentId);
+            assertEquals(attachments.size(), 2);
+            assertEquals(attachments.get(0).getFileName(), "testExperiment.txt");
+            assertEquals(attachments.get(1).getFileName(), "testExperiment2.txt");
+        } else
+        {
+            try
+            {
+                commonServer.addExperimentAttachment(session.getSessionToken(), experimentId, attachment);
+                fail();
+            } catch (AuthorizationFailureException e)
+            {
+                // expected
+            }
+        }
+    }
+
     @Test(dataProviderClass = ProjectAuthorizationUser.class, dataProvider = ProjectAuthorizationUser.PROVIDER)
     public void testListExperimentAttachmentsWithProjectAuthorization(ProjectAuthorizationUser user)
     {
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/authorization/predicate/project/ProjectPredicateTestService.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/authorization/predicate/project/ProjectPredicateTestService.java
index e18aa488bc19a1f5c6d1c79f479d7a275d7fb21d..96a9327057d50837c93a11af275825fe3a766d3f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/authorization/predicate/project/ProjectPredicateTestService.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/authorization/predicate/project/ProjectPredicateTestService.java
@@ -28,9 +28,11 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.AbstractT
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.NewProjectPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectAugmentedCodePredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdPredicate;
+import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierExistingSpacePredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPEPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPermIdPredicate;
+import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPermIdStringPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
@@ -113,6 +115,13 @@ public class ProjectPredicateTestService
     {
     }
 
+    @Transactional
+    @RolesAllowed(value = { RoleWithHierarchy.PROJECT_OBSERVER })
+    public void testProjectPermIdStringPredicate(IAuthSessionProvider sessionProvider,
+            @AuthorizationGuard(guardClass = ProjectPermIdStringPredicate.class) String projectPermIdString)
+    {
+    }
+
     @Transactional
     @RolesAllowed(value = { RoleWithHierarchy.PROJECT_OBSERVER })
     public void testProjectTechIdCollectionPredicate(IAuthSessionProvider sessionProvider,
@@ -120,4 +129,11 @@ public class ProjectPredicateTestService
     {
     }
 
+    @Transactional
+    @RolesAllowed(value = { RoleWithHierarchy.PROJECT_OBSERVER })
+    public void testProjectIdentifierExistingSpacePredicate(IAuthSessionProvider sessionProvider,
+            @AuthorizationGuard(guardClass = ProjectIdentifierExistingSpacePredicate.class) ProjectIdentifier projectIdentifier)
+    {
+    }
+
 }
diff --git a/openbis/sourceTest/sql/postgresql/162/001=attachment_contents.tsv b/openbis/sourceTest/sql/postgresql/162/001=attachment_contents.tsv
index 21d30d1f9f9902a866dad03bcf84eb3469061374..3efe93aad0018b264134acec60f0f1cf777a5849 100644
--- a/openbis/sourceTest/sql/postgresql/162/001=attachment_contents.tsv
+++ b/openbis/sourceTest/sql/postgresql/162/001=attachment_contents.tsv
@@ -8,3 +8,4 @@
 8	\\x33564350310a33564350320a3356435033
 9	\\x33564350310a33564350320a3356435033
 10	\\x33564350310a33564350320a3356435033
+11	\\x33564350310a33564350320a3356435033
diff --git a/openbis/sourceTest/sql/postgresql/162/002=attachments.tsv b/openbis/sourceTest/sql/postgresql/162/002=attachments.tsv
index bb74bf9187f681c79ca0a83dfb4cc42093323eb2..212ce5bbf36e1453e1eb5ff14299e4292fb3ab4a 100644
--- a/openbis/sourceTest/sql/postgresql/162/002=attachments.tsv
+++ b/openbis/sourceTest/sql/postgresql/162/002=attachments.tsv
@@ -8,3 +8,4 @@
 8	22	cellPlates.txt	2008-12-10 13:51:10.050748+01	1	2	8	\N	\N	\N	\N
 9	\N	projectDescription.txt	2012-01-03 08:27:57.123+01	1	2	9	\N	3	The Project	All about it.
 10	23	testExperiment.txt	2012-01-03 08:27:57.123+01	1	2	10	\N	\N	\N	\N
+11	\N	testProject.txt	2012-01-03 08:27:57.123+01	1	2	11	\N	5	\N	\N
diff --git a/openbis/sourceTest/sql/postgresql/162/025=experiment_properties.tsv b/openbis/sourceTest/sql/postgresql/162/025=experiment_properties.tsv
index 558e852c60b6612640d37bcca78e2eb3144319a5..5ff0034fe7fa1510f2e7c0f6ea849964ef5b6b69 100644
--- a/openbis/sourceTest/sql/postgresql/162/025=experiment_properties.tsv
+++ b/openbis/sourceTest/sql/postgresql/162/025=experiment_properties.tsv
@@ -15,3 +15,4 @@
 20	22	1	A simple experiment	\N	2	2008-11-05 09:22:37.246+01	2009-03-18 10:50:19.475958+01	\N	1
 21	24	3	2009-02-10 01:00:00 +0200	\N	2	2009-02-09 12:17:55.058768+01	2009-03-18 10:50:19.475958+01	\N	1
 22	22	8	\N	\N	2	2008-11-05 09:22:37.246+01	2009-03-18 10:50:19.475958+01	35	1
+23	23	1	A test experiment	\N	2	2008-11-05 09:22:37.246+01	2009-03-18 10:50:19.475958+01	\N	1