--- 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: