server/querier.py
changeset 5423 e15abfdcce38
parent 5177 395e1ff018ae
parent 5421 8167de96c523
child 5426 0d4853a6e5ee
--- a/server/querier.py	Mon Apr 26 18:45:03 2010 +0200
+++ b/server/querier.py	Wed Apr 28 12:14:22 2010 +0200
@@ -1,10 +1,23 @@
+# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Helper classes to execute RQL queries on a set of sources, performing
 security checking and data aggregation.
 
-:organization: Logilab
-:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
-:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 from __future__ import with_statement
 
@@ -48,7 +61,16 @@
         if 'Password' in solution.itervalues():
             raise Unauthorized('Password selection is not allowed')
 
-def check_read_access(schema, user, rqlst, solution):
+def term_etype(session, term, solution, args):
+    """return the entity type for the given term (a VariableRef or a Constant
+    node)
+    """
+    try:
+        return solution[term.name]
+    except AttributeError:
+        return session.describe(term.eval(args))[0]
+
+def check_read_access(session, rqlst, solution, args):
     """check that the given user has credentials to access data read the
     query
 
@@ -56,6 +78,10 @@
     in the schema), keys are variable names and values associated rql expression
     for the associated variable with the given solution
     """
+    # use `term_etype` since we've to deal with rewritten constants here,
+    # when used as an external source by another repository.
+    # XXX what about local read security w/ those rewritten constants...
+    schema = session.repo.schema
     if rqlst.where is not None:
         for rel in rqlst.where.iget_nodes(Relation):
             # XXX has_text may have specific perm ?
@@ -63,12 +89,15 @@
                 continue
             rschema = schema.rschema(rel.r_type)
             if rschema.final:
-                eschema = schema.eschema(solution[rel.children[0].name])
+                eschema = schema.eschema(term_etype(session, rel.children[0],
+                                                    solution, args))
                 rdef = eschema.rdef(rschema)
             else:
-                rdef = rschema.rdef(solution[rel.children[0].name],
-                                    solution[rel.children[1].children[0].name])
-            if not user.matching_groups(rdef.get_groups('read')):
+                rdef = rschema.rdef(term_etype(session, rel.children[0],
+                                               solution, args),
+                                    term_etype(session, rel.children[1].children[0],
+                                               solution, args))
+            if not session.user.matching_groups(rdef.get_groups('read')):
                 # XXX rqlexpr not allowed
                 raise Unauthorized('read', rel.r_type)
     localchecks = {}
@@ -77,7 +106,7 @@
         eschema = schema.eschema(solution[varname])
         if eschema.final:
             continue
-        if not user.matching_groups(eschema.get_groups('read')):
+        if not session.user.matching_groups(eschema.get_groups('read')):
             erqlexprs = eschema.get_rqlexprs('read')
             if not erqlexprs:
                 ex = Unauthorized('read', solution[varname])
@@ -319,8 +348,6 @@
         note: rqlst should not have been simplified at this point
         """
         session = self.session
-        user = session.user
-        schema = self.schema
         msgs = []
         neweids = session.transaction_data.get('neweids', ())
         varkwargs = {}
@@ -335,10 +362,10 @@
         newsolutions = []
         for solution in rqlst.solutions:
             try:
-                localcheck = check_read_access(schema, user, rqlst, solution)
+                localcheck = check_read_access(session, rqlst, solution, self.args)
             except Unauthorized, ex:
                 msg = 'remove %s from solutions since %s has no %s access to %s'
-                msg %= (solution, user.login, ex.args[0], ex.args[1])
+                msg %= (solution, session.user.login, ex.args[0], ex.args[1])
                 msgs.append(msg)
                 LOGGER.info(msg)
             else: