# HG changeset patch # User Sylvain Thénault # Date 1272385663 -7200 # Node ID 0b7805928a27337d1b515b9785aedceb944069c7 # Parent 4f0047cfecb57c2df8a1a2575118ecf427b8485a [repo security] deal with rewriten constant nodes in check_read_access, necessary when repo is used as an external source diff -r 4f0047cfecb5 -r 0b7805928a27 server/querier.py --- a/server/querier.py Tue Apr 27 14:25:38 2010 +0200 +++ b/server/querier.py Tue Apr 27 18:27:43 2010 +0200 @@ -48,7 +48,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 +65,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 +76,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 +93,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 +335,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 = {} @@ -342,10 +356,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: diff -r 4f0047cfecb5 -r 0b7805928a27 server/test/unittest_security.py --- a/server/test/unittest_security.py Tue Apr 27 14:25:38 2010 +0200 +++ b/server/test/unittest_security.py Tue Apr 27 18:27:43 2010 +0200 @@ -32,12 +32,12 @@ self.schema['Personne'].set_action_permissions('read', ('users', 'managers')) self.repo.vreg.solutions(self.session, rqlst, None) solution = rqlst.solutions[0] - check_read_access(self.schema, self.session.user, rqlst, solution) + check_read_access(self.session, rqlst, solution, {}) cnx = self.login('anon') cu = cnx.cursor() self.assertRaises(Unauthorized, check_read_access, - self.schema, cnx.user(self.session), rqlst, solution) + self.session, rqlst, solution, {}) self.assertRaises(Unauthorized, cu.execute, rql) def test_upassword_not_selectable(self):