backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 05 Jul 2010 18:00:33 +0200
changeset 5890 141b935a38fc
parent 5883 7a5f370c5be1 (current diff)
parent 5889 014ea69e5200 (diff)
child 5891 99024ad59223
backport stable
cwconfig.py
cwvreg.py
selectors.py
server/querier.py
server/sources/rql2sql.py
server/test/unittest_hook.py
server/test/unittest_repository.py
server/test/unittest_rql2sql.py
server/test/unittest_security.py
web/controller.py
web/request.py
web/test/unittest_viewselector.py
web/views/embedding.py
--- a/cwconfig.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/cwconfig.py	Mon Jul 05 18:00:33 2010 +0200
@@ -131,6 +131,7 @@
 
    Directory where pid files will be written
 """
+
 __docformat__ = "restructuredtext en"
 _ = unicode
 
@@ -985,12 +986,12 @@
 
     @cached
     def instance_md5_version(self):
-        import md5
+        import hashlib
         infos = []
         for pkg in self.cubes():
             version = self.cube_version(pkg)
             infos.append('%s-%s' % (pkg, version))
-        return md5.new(';'.join(infos)).hexdigest()
+        return hashlib.md5(';'.join(infos)).hexdigest()
 
     def load_configuration(self):
         """load instance's configuration files"""
--- a/cwvreg.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/cwvreg.py	Mon Jul 05 18:00:33 2010 +0200
@@ -189,6 +189,7 @@
 
 .. automethod:: cubicweb.vregistry.Registry.object_by_id
 """
+
 __docformat__ = "restructuredtext en"
 _ = unicode
 
--- a/selectors.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/selectors.py	Mon Jul 05 18:00:33 2010 +0200
@@ -191,6 +191,7 @@
 
 .. |cubicweb| replace:: *CubicWeb*
 """
+
 __docformat__ = "restructuredtext en"
 
 import logging
--- a/server/querier.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/querier.py	Mon Jul 05 18:00:33 2010 +0200
@@ -29,7 +29,8 @@
 from logilab.common.compat import any
 from rql import RQLSyntaxError
 from rql.stmts import Union, Select
-from rql.nodes import Relation, VariableRef, Constant, SubQuery, Function
+from rql.nodes import (Relation, VariableRef, Constant, SubQuery, Function,
+                       Exists, Not)
 
 from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid
 from cubicweb import server
@@ -113,7 +114,16 @@
                 ex = Unauthorized('read', solution[varname])
                 ex.var = varname
                 raise ex
-            localchecks[varname] = erqlexprs
+            # don't insert security on variable only referenced by 'NOT X relation Y' or
+            # 'NOT EXISTS(X relation Y)'
+            varinfo = rqlst.defined_vars[varname].stinfo
+            if varinfo['selected'] or (
+                len([r for r in varinfo['relations']
+                     if (not schema.rschema(r.r_type).final
+                         and ((isinstance(r.parent, Exists) and r.parent.neged(strict=True))
+                              or isinstance(r.parent, Not)))])
+                != len(varinfo['relations'])):
+                localchecks[varname] = erqlexprs
     return localchecks
 
 def add_noinvariant(noinvariant, restricted, select, nbtrees):
--- a/server/sources/rql2sql.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/sources/rql2sql.py	Mon Jul 05 18:00:33 2010 +0200
@@ -428,16 +428,15 @@
             p = compnode.parent
             oor = None
             while not isinstance(p, Select):
-                if p in ors:
+                if p in ors or p is None: # p is None for nodes already in fakehaving
                     break
                 if isinstance(p, Or):
                     oor = p
                 p = p.parent
             else:
                 node = oor or compnode
-                if not node in fakehaving:
-                    fakehaving.append(node)
-                    compnode.parent.remove(node)
+                fakehaving.append(node)
+                node.parent.remove(node)
     return fakehaving
 
 class SQLGenerator(object):
--- a/server/test/unittest_hook.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/test/unittest_hook.py	Mon Jul 05 18:00:33 2010 +0200
@@ -16,9 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""unit/functional tests for cubicweb.server.hook
-
-"""
+"""unit/functional tests for cubicweb.server.hook"""
 
 from logilab.common.testlib import TestCase, unittest_main, mock_object
 
--- a/server/test/unittest_repository.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/test/unittest_repository.py	Mon Jul 05 18:00:33 2010 +0200
@@ -212,7 +212,7 @@
     def test_transaction_interleaved(self):
         self.skip('implement me')
 
-    def test_close_wait_processing_request(self):
+    def test_close_kill_processing_request(self):
         repo = self.repo
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
         repo.execute(cnxid, 'INSERT CWUser X: X login "toto", X upassword "tutu", X in_group G WHERE G name "users"')
@@ -223,9 +223,12 @@
             repo.close(cnxid)
         t = threading.Thread(target=close_in_a_few_moment)
         t.start()
-        try:
+        def run_transaction():
             repo.execute(cnxid, 'DELETE CWUser X WHERE X login "toto"')
             repo.commit(cnxid)
+        try:
+            ex = self.assertRaises(Exception, run_transaction)
+            self.assertEquals(str(ex), 'try to access pool on a closed session')
         finally:
             t.join()
 
--- a/server/test/unittest_rql2sql.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/test/unittest_rql2sql.py	Mon Jul 05 18:00:33 2010 +0200
@@ -178,9 +178,8 @@
 FROM cw_Personne AS _X
 WHERE _X.cw_prenom=lulu AND NOT (EXISTS(SELECT 1 FROM owned_by_relation AS rel_owned_by0, in_group_relation AS rel_in_group1, cw_CWGroup AS _G WHERE rel_owned_by0.eid_from=_X.cw_eid AND rel_in_group1.eid_from=rel_owned_by0.eid_to AND rel_in_group1.eid_to=_G.cw_eid AND ((_G.cw_name=lulufanclub) OR (_G.cw_name=managers))))'''),
 
-
+]
 
-]
 
 ADVANCED= [
     ("Societe S WHERE S nom 'Logilab' OR S nom 'Caesium'",
@@ -575,6 +574,7 @@
 
     ]
 
+
 MULTIPLE_SEL = [
     ("DISTINCT Any X,Y where P is Personne, P nom X , P prenom Y;",
      '''SELECT DISTINCT _P.cw_nom, _P.cw_prenom
@@ -589,7 +589,9 @@
 WHERE _Y.cw_nom=_X.cw_nom AND NOT (_Y.cw_eid=_X.cw_eid)''')
     ]
 
+
 NEGATIONS = [
+
     ("Personne X WHERE NOT X evaluee Y;",
      '''SELECT _X.cw_eid
 FROM cw_Personne AS _X
@@ -1455,6 +1457,12 @@
                     '''SELECT (A || _X.cw_ref)
 FROM cw_Affaire AS _X''')
 
+    def test_or_having_fake_terms(self):
+        self._check('Any X WHERE X is CWUser, X creation_date D HAVING YEAR(D) = "2010" OR D = NULL',
+                    '''SELECT _X.cw_eid
+FROM cw_CWUser AS _X
+WHERE ((CAST(EXTRACT(YEAR from _X.cw_creation_date) AS INTEGER)=2010) OR (_X.cw_creation_date IS NULL))''')
+
 
 class SqliteSQLGeneratorTC(PostgresSQLGeneratorTC):
     backend = 'sqlite'
@@ -1579,6 +1587,13 @@
             yield t
 
 
+    def test_or_having_fake_terms(self):
+        self._check('Any X WHERE X is CWUser, X creation_date D HAVING YEAR(D) = "2010" OR D = NULL',
+                    '''SELECT _X.cw_eid
+FROM cw_CWUser AS _X
+WHERE ((YEAR(_X.cw_creation_date)=2010) OR (_X.cw_creation_date IS NULL))''')
+
+
 
 class MySQLGenerator(PostgresSQLGeneratorTC):
     backend = 'mysql'
@@ -1660,6 +1675,14 @@
                     '''SELECT SUBSTRING(_P.cw_nom, 1, 1)
 FROM cw_Personne AS _P''')
 
+
+    def test_or_having_fake_terms(self):
+        self._check('Any X WHERE X is CWUser, X creation_date D HAVING YEAR(D) = "2010" OR D = NULL',
+                    '''SELECT _X.cw_eid
+FROM cw_CWUser AS _X
+WHERE ((EXTRACT(YEAR from _X.cw_creation_date)=2010) OR (_X.cw_creation_date IS NULL))''')
+
+
 class removeUnsusedSolutionsTC(TestCase):
     def test_invariant_not_varying(self):
         rqlst = mock_object(defined_vars={})
--- a/server/test/unittest_security.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/server/test/unittest_security.py	Mon Jul 05 18:00:33 2010 +0200
@@ -15,8 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""functional tests for server'security
-"""
+"""functional tests for server'security"""
+
 import sys
 
 from logilab.common.testlib import unittest_main, TestCase
@@ -66,6 +66,27 @@
                           cu.execute, 'Any X,P WHERE X is CWUser, X upassword P')
 
 
+class SecurityRewritingTC(BaseSecurityTC):
+    def hijack_source_execute(self):
+        def syntax_tree_search(*args, **kwargs):
+            self.query = (args, kwargs)
+            return []
+        self.repo.system_source.syntax_tree_search = syntax_tree_search
+
+    def tearDown(self):
+        self.repo.system_source.__dict__.pop('syntax_tree_search', None)
+        BaseSecurityTC.tearDown(self)
+
+    def test_not_relation_read_security(self):
+        cnx = self.login('iaminusersgrouponly')
+        self.hijack_source_execute()
+        self.execute('Any U WHERE NOT A todo_by U, A is Affaire')
+        self.assertEquals(self.query[0][1].as_string(),
+                          'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
+        self.execute('Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
+        self.assertEquals(self.query[0][1].as_string(),
+                          'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
+
 class SecurityTC(BaseSecurityTC):
 
     def setUp(self):
@@ -420,7 +441,6 @@
         self.failUnless(x.creation_date)
         cnx.rollback()
 
-
 class BaseSchemaSecurityTC(BaseSecurityTC):
     """tests related to the base schema permission configuration"""
 
--- a/web/controller.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/web/controller.py	Mon Jul 05 18:00:33 2010 +0200
@@ -15,10 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""abstract controller classe for CubicWeb web client
+"""abstract controller classe for CubicWeb web client"""
 
-
-"""
 __docformat__ = "restructuredtext en"
 
 from logilab.mtconverter import xml_escape
--- a/web/request.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/web/request.py	Mon Jul 05 18:00:33 2010 +0200
@@ -20,12 +20,7 @@
 __docformat__ = "restructuredtext en"
 
 import Cookie
-try:
-    import hashlib
-    hashlib.hash
-except AttributeError:
-    # python 2.5 ...
-    import sha as hashlib
+import hashlib
 import time
 import random
 import base64
@@ -369,9 +364,9 @@
 
     def register_onetime_callback(self, func, *args):
         cbname = 'cb_%s' % (
-            hashlib.sha('%s%s%s%s' % (time.time(), func.__name__,
-                                      random.random(),
-                                      self.user.login)).hexdigest())
+            hashlib.sha1('%s%s%s%s' % (time.time(), func.__name__,
+                                       random.random(),
+                                       self.user.login)).hexdigest())
         def _cb(req):
             try:
                 ret = func(req, *args)
--- a/web/test/unittest_viewselector.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/web/test/unittest_viewselector.py	Mon Jul 05 18:00:33 2010 +0200
@@ -16,8 +16,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""XXX rename, split, reorganize this
-"""
+"""XXX rename, split, reorganize this"""
+
 from logilab.common.testlib import unittest_main
 
 from cubicweb.devtools.testlib import CubicWebTC
--- a/web/views/embedding.py	Mon Jul 05 15:59:14 2010 +0200
+++ b/web/views/embedding.py	Mon Jul 05 18:00:33 2010 +0200
@@ -16,7 +16,8 @@
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Objects interacting together to provides the external page embeding
-functionality."""
+functionality.
+"""
 
 __docformat__ = "restructuredtext en"