diff -r 27249e3fee3d -r e15abfdcce38 server/querier.py --- 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 . """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: