diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java
index 76a08d3308a68caeca35502e64d4da4b492fd793..1dfc54d4a9ce6417203b5dc5c89ace8602e05a6d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java
@@ -76,7 +76,7 @@ public final class DefaultAccessController implements IAccessController
         PredicateExecutor.setDAOFactory(daoFactory);
     }
 
-    private final static List<RoleWithIdentifier> getUserRoles(final PersonPE person)
+    public final static List<RoleWithIdentifier> getUserRoles(final PersonPE person)
     {
         Set<RoleAssignmentPE> roleAssignments = person.getAllPersonRoles();
         return extractRolesWithIdentifiers(roleAssignments);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
index 2f85112b1063c676af542ea1592706e98ae26ad8..1b67c49f0fb2ba615ad1ae59f4eb6a9f4c984252 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
@@ -48,12 +48,14 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.QueryType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.QueryPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.plugin.query.shared.DatabaseDefinition;
 import ch.systemsx.cisd.openbis.plugin.query.shared.IQueryServer;
 import ch.systemsx.cisd.openbis.plugin.query.shared.ResourceNames;
 import ch.systemsx.cisd.openbis.plugin.query.shared.SimpleDatabaseConfigurationContext;
+import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.QueryAccessController;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.IQueryUpdates;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.NewQuery;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
@@ -147,6 +149,8 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
     public void registerQuery(String sessionToken, NewQuery expression)
     {
         Session session = getSession(sessionToken);
+        QueryAccessController.checkWriteAccess(session, expression.getQueryDatabase().getKey(),
+                "create");
 
         QueryPE query = new QueryPE();
         query.setName(expression.getName());
@@ -168,7 +172,7 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
 
     public void deleteQueries(String sessionToken, List<TechId> filterIds)
     {
-        checkSession(sessionToken);
+        Session session = getSession(sessionToken);
 
         IQueryDAO queryDAO = getDAOFactory().getQueryDAO();
         try
@@ -176,6 +180,8 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
             for (TechId techId : filterIds)
             {
                 QueryPE query = queryDAO.getByTechId(techId);
+                QueryAccessController.checkWriteAccess(session, query.getQueryDatabaseKey(),
+                        "delete");
                 queryDAO.delete(query);
             }
         } catch (DataAccessException ex)
@@ -186,7 +192,9 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
 
     public void updateQuery(String sessionToken, IQueryUpdates updates)
     {
-        checkSession(sessionToken);
+        Session session = getSession(sessionToken);
+        QueryAccessController.checkWriteAccess(session, updates.getQueryDatabase().getKey(),
+                "update");
 
         try
         {
@@ -211,9 +219,11 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
     public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings)
     {
-        checkSession(sessionToken);
+        Session session = getSession(sessionToken);
         try
         {
+            QueryAccessController
+                    .checkWriteAccess(session, database.getKey(), "create and perform");
             return queryDatabaseWithKey(database.getKey(), sqlQuery, bindings);
         } catch (DataAccessException ex)
         {
@@ -224,13 +234,14 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
     public TableModel queryDatabase(String sessionToken, TechId queryId,
             QueryParameterBindings bindings)
     {
-        checkSession(sessionToken);
+        Session session = getSession(sessionToken);
         try
         {
             IQueryDAO queryDAO = getDAOFactory().getQueryDAO();
             QueryPE query = queryDAO.getByTechId(queryId);
             String dbKey = query.getQueryDatabaseKey();
             String expression = StringEscapeUtils.unescapeHtml(query.getExpression());
+            QueryAccessController.checkReadAccess(session, dbKey);
             return queryDatabaseWithKey(dbKey, expression, bindings);
         } catch (DataAccessException ex)
         {
@@ -293,7 +304,7 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
             final String creatorMinimalRoleString =
                     PropertyUtils.getProperty(databaseProperties, CREATOR_MINIMAL_ROLE_KEY,
                             DEFAULT_CREATOR_MINIMAL_ROLE);
-            final String dataSpaceOrNull =
+            final String dataSpaceOrNullString =
                     PropertyUtils.getProperty(databaseProperties, DATA_SPACE_KEY);
 
             if (labels.contains(label))
@@ -303,11 +314,22 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
                                 + "' label is used more than once.");
             }
             labels.add(label);
-
+            GroupPE dataSpaceOrNull = null;
+            if (dataSpaceOrNullString != null)
+            {
+                dataSpaceOrNull =
+                        getDAOFactory().getGroupDAO().tryFindGroupByCodeAndDatabaseInstance(
+                                dataSpaceOrNullString, getDAOFactory().getHomeDatabaseInstance());
+                if (dataSpaceOrNull == null)
+                {
+                    throw new UnsupportedOperationException("Query database '" + databaseKey
+                            + "' is not defined properly. Space '" + dataSpaceOrNullString
+                            + "' doesn't exist.");
+                }
+            }
             try
             {
                 final RoleSet creatorMinimalRole = RoleSet.valueOf(creatorMinimalRoleString);
-                // TODO validate space
                 definitions.put(databaseKey, new DatabaseDefinition(configurationContext,
                         databaseKey, label, creatorMinimalRole, dataSpaceOrNull));
             } catch (IllegalArgumentException ex)
@@ -318,5 +340,7 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
             }
 
         }
+
+        QueryAccessController.initialize(definitions);
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/CopyOfIQueryServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/CopyOfIQueryServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..f64f7859e9322d45c62feb7e19d5d6b7c5c82911
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/CopyOfIQueryServer.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010 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.plugin.query.shared;
+
+import java.util.List;
+
+import org.springframework.transaction.annotation.Transactional;
+
+import ch.systemsx.cisd.openbis.generic.shared.DatabaseCreateOrDeleteModification;
+import ch.systemsx.cisd.openbis.generic.shared.DatabaseUpdateModification;
+import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.AuthorizationGuard;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnValueFilter;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.ExpressionValidator;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.DeleteQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.UpdateQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.IQueryUpdates;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.NewQuery;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+public interface CopyOfIQueryServer extends IServer
+{
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public int initDatabases(String sessionToken);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<QueryDatabase> listQueryDatabases(String sessionToken);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.POWER_USER)
+    public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
+            QueryParameterBindings bindings);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public TableModel queryDatabase(String sessionToken, TechId queryId,
+            QueryParameterBindings bindings);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    @ReturnValueFilter(validatorClass = ExpressionValidator.class)
+    public List<QueryExpression> listQueries(String sessionToken);
+
+    @Transactional
+    @RolesAllowed(RoleSet.OBSERVER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
+    public void registerQuery(String sessionToken, NewQuery expression);
+
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
+    public void deleteQueries(String sessionToken,
+            @AuthorizationGuard(guardClass = DeleteQueryPredicate.class) List<TechId> queryIds);
+
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseUpdateModification(value = ObjectKind.QUERY)
+    public void updateQuery(String sessionToken,
+            @AuthorizationGuard(guardClass = UpdateQueryPredicate.class) IQueryUpdates updates);
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/DatabaseDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/DatabaseDefinition.java
index 7b4332c073751493ed197a419a03eb0cab646383..2485bd2373f2b99bf0dbffa245594e3db9fca512 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/DatabaseDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/DatabaseDefinition.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.plugin.query.shared;
 
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 
 /**
  * @author Franz-Josef Elmer
@@ -27,14 +28,14 @@ public class DatabaseDefinition
 
     private final String label;
 
-    private final String dataSpaceOrNull;
+    private final GroupPE dataSpaceOrNull;
 
     private final RoleSet creatorMinimalRole;
 
     private final SimpleDatabaseConfigurationContext configurationContext;
 
     public DatabaseDefinition(SimpleDatabaseConfigurationContext configurationContext, String key,
-            String label, RoleSet creatorMinimalRole, String dataSpaceOrNull)
+            String label, RoleSet creatorMinimalRole, GroupPE dataSpaceOrNull)
     {
         assert key != null;
         assert label != null;
@@ -62,7 +63,7 @@ public class DatabaseDefinition
         return creatorMinimalRole;
     }
 
-    public String tryGetDataSpace()
+    public GroupPE tryGetDataSpace()
     {
         return dataSpaceOrNull;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
index fd7f3a9bd0621f376bb74c90e569551350d15816..2a163ca6ea21a519ca86a6cde640b31b5214f00a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
@@ -23,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional;
 import ch.systemsx.cisd.openbis.generic.shared.DatabaseCreateOrDeleteModification;
 import ch.systemsx.cisd.openbis.generic.shared.DatabaseUpdateModification;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.AuthorizationGuard;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnValueFilter;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
@@ -32,8 +31,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.QueryType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
-import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.DeleteQueryPredicate;
-import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.UpdateQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.QueryAccessController;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.IQueryUpdates;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.NewQuery;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
@@ -41,6 +39,7 @@ import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
 /**
+ * @see QueryAccessController for authorization
  * @author Franz-Josef Elmer
  */
 public interface IQueryServer extends IServer
@@ -55,7 +54,7 @@ public interface IQueryServer extends IServer
     public List<QueryDatabase> listQueryDatabases(String sessionToken);
 
     @Transactional(readOnly = true)
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings);
 
@@ -70,19 +69,17 @@ public interface IQueryServer extends IServer
     public List<QueryExpression> listQueries(String sessionToken, QueryType queryType);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
     public void registerQuery(String sessionToken, NewQuery expression);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
-    public void deleteQueries(String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteQueryPredicate.class) List<TechId> queryIds);
+    public void deleteQueries(String sessionToken, List<TechId> queryIds);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseUpdateModification(value = ObjectKind.QUERY)
-    public void updateQuery(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdateQueryPredicate.class) IQueryUpdates updates);
+    public void updateQuery(String sessionToken, IQueryUpdates updates);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/authorization/QueryAccessController.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/authorization/QueryAccessController.java
new file mode 100644
index 0000000000000000000000000000000000000000..fff4da3bb93d11e00818994bf895fbfc5c00a60c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/authorization/QueryAccessController.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2010 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.plugin.query.shared.authorization;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.openbis.generic.server.authorization.AuthorizationAdvisor;
+import ch.systemsx.cisd.openbis.generic.server.authorization.DefaultAccessController;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.Role;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.RoleWithIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.Role.RoleLevel;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+import ch.systemsx.cisd.openbis.plugin.query.shared.DatabaseDefinition;
+
+/**
+ * @author Piotr Buczek
+ */
+public class QueryAccessController
+{
+
+    private static final Logger authorizationLog =
+            LogFactory.getLogger(LogCategory.AUTH, AuthorizationAdvisor.class);
+
+    private static Map<String, DatabaseDefinition> definitionsByDbKey;
+
+    public static void initialize(Map<String, DatabaseDefinition> definitions)
+    {
+        definitionsByDbKey = definitions;
+    }
+
+    public static void checkWriteAccess(Session session, String dbKey, String operation)
+    {
+        DatabaseDefinition database = definitionsByDbKey.get(dbKey);
+        PersonPE person = session.tryGetPerson();
+        GroupPE dataSpaceOrNull = database.tryGetDataSpace();
+        RoleSet minimalRole = database.getCreatorMinimalRole();
+
+        if (isAuthorized(person, dataSpaceOrNull, minimalRole) == false)
+        {
+            String errorMsg =
+                    createErrorMessage(operation, session.getUserName(), dataSpaceOrNull,
+                            minimalRole, database.getLabel());
+            throw createAuthorizationError(session, operation, errorMsg);
+        }
+    }
+
+    public static void checkReadAccess(Session session, String dbKey)
+    {
+        DatabaseDefinition database = definitionsByDbKey.get(dbKey);
+        PersonPE person = session.tryGetPerson();
+        GroupPE dataSpaceOrNull = database.tryGetDataSpace();
+        RoleSet minimalRole = RoleSet.OBSERVER;
+
+        if (isAuthorized(person, dataSpaceOrNull, minimalRole) == false)
+        {
+            String errorMsg =
+                    createErrorMessage("perform", session.getUserName(), dataSpaceOrNull,
+                            minimalRole, database.getLabel());
+            throw createAuthorizationError(session, "perform", errorMsg);
+        }
+    }
+
+    private static boolean isAuthorized(PersonPE person, GroupPE dataSpaceOrNull,
+            RoleSet minimalRole)
+    {
+        final Set<Role> requiredRoles = minimalRole.getRoles();
+        if (person != null)
+        {
+            List<RoleWithIdentifier> userRoles = DefaultAccessController.getUserRoles(person);
+            userRoles.retainAll(requiredRoles);
+            if (userRoles.size() > 0)
+            {
+                if (dataSpaceOrNull == null)
+                {
+                    return true;
+                } else
+                {
+                    return isSpaceMatching(userRoles, dataSpaceOrNull);
+                }
+            } else
+            {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isSpaceMatching(List<RoleWithIdentifier> userRoles,
+            final GroupPE requiredSpace)
+    {
+
+        for (final RoleWithIdentifier role : userRoles)
+        {
+            final RoleLevel roleGroup = role.getRoleLevel();
+            if (roleGroup.equals(RoleLevel.SPACE) && role.getAssignedGroup().equals(requiredSpace))
+            {
+                return true;
+            } else if (roleGroup.equals(RoleLevel.INSTANCE)
+                    && role.getAssignedDatabaseInstance().equals(
+                            requiredSpace.getDatabaseInstance()))
+            {
+                // permissions on the database instance level allow to access all groups in this
+                // instance
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static String createErrorMessage(String operation, String userName,
+            GroupPE dataSpaceOrNull, RoleSet minimalRole, String database)
+    {
+        String minimalRoleDescription = minimalRole.name();
+        if (dataSpaceOrNull != null)
+        {
+            minimalRoleDescription += " in space " + dataSpaceOrNull.getCode();
+        }
+
+        return String.format("User '%s' does not have enough privileges to %s "
+                + "a query in database '%s'. One needs to be at least %s.", userName, operation,
+                database, minimalRoleDescription);
+    }
+
+    private static AuthorizationFailureException createAuthorizationError(Session session,
+            String operation, String errorMessage)
+    {
+        final String groupCode = session.tryGetHomeGroupCode();
+        authorizationLog
+                .info(String.format("[USER:'%s' SPACE:%s]: Authorization failure while "
+                        + "trying to %s a query: %s", session.getUserName(),
+                        groupCode == null ? "<UNDEFINED>" : "'" + groupCode + "'", operation,
+                        errorMessage));
+        return new AuthorizationFailureException(errorMessage);
+    }
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
index 9b5d16bcd8facd4f9dc04ccf2f33f2eea28c7ab7..529a9d6f83b5a6f1c68777c14b72d22b8e0acfdb 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
@@ -23,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional;
 import ch.systemsx.cisd.openbis.generic.shared.DatabaseCreateOrDeleteModification;
 import ch.systemsx.cisd.openbis.generic.shared.DatabaseUpdateModification;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.AuthorizationGuard;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnValueFilter;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
@@ -32,8 +31,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.QueryType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
-import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.DeleteQueryPredicate;
-import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.UpdateQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.QueryAccessController;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.IQueryUpdates;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.NewQuery;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
@@ -41,6 +39,7 @@ import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
 /**
+ * @see QueryAccessController for authorization
  * @author Franz-Josef Elmer
  */
 public interface IQueryServer extends IServer
@@ -55,7 +54,7 @@ public interface IQueryServer extends IServer
     public List<QueryDatabase> listQueryDatabases(String sessionToken);
 
     @Transactional(readOnly = true)
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings);
 
@@ -70,19 +69,17 @@ public interface IQueryServer extends IServer
     public List<QueryExpression> listQueries(String sessionToken, QueryType queryType);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
     public void registerQuery(String sessionToken, NewQuery expression);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.QUERY)
-    public void deleteQueries(String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteQueryPredicate.class) List<TechId> queryIds);
+    public void deleteQueries(String sessionToken, List<TechId> queryIds);
 
     @Transactional
-    @RolesAllowed(RoleSet.POWER_USER)
+    @RolesAllowed(RoleSet.OBSERVER)
     @DatabaseUpdateModification(value = ObjectKind.QUERY)
-    public void updateQuery(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdateQueryPredicate.class) IQueryUpdates updates);
+    public void updateQuery(String sessionToken, IQueryUpdates updates);
 }