[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 14 Apr 2010 10:29:38 +0200
changeset 5244 5467674ad101
parent 5243 1ab7acb9abe9
child 5246 3246b1f88a18
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
dbapi.py
selectors.py
web/application.py
web/httpcache.py
web/request.py
web/test/data/views.py
web/views/basecontrollers.py
--- a/dbapi.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/dbapi.py	Wed Apr 14 10:29:38 2010 +0200
@@ -156,6 +156,11 @@
     cnx = repo_connect(repo, login, cnxprops=cnxprops, **kwargs)
     return repo, cnx
 
+class _NeedAuthAccessMock(object):
+    def __getattribute__(self, attr):
+        raise AuthenticationError()
+    def __nonzero__(self):
+        return False
 
 class DBAPISession(object):
     def __init__(self, cnx, login=None, authinfo=None):
@@ -166,7 +171,7 @@
 
     @property
     def anonymous_session(self):
-        return self.cnx is None or self.cnx.anonymous_connection
+        return not self.cnx or self.cnx.anonymous_connection
 
     @property
     def sessionid(self):
@@ -190,7 +195,8 @@
         else:
             # these args are initialized after a connection is
             # established
-            self.session = self.cnx = self._user = None
+            self.session = None
+            self.cnx = self._user = _NeedAuthAccessMock()
 
     def base_url(self):
         return self.vreg.config['base-url']
@@ -203,7 +209,7 @@
         or an anonymous connection is open
         """
         self.session = session
-        if session.cnx is not None:
+        if session.cnx:
             self.cnx = session.cnx
             self.execute = session.cnx.cursor(self).execute
         self.set_user(user)
@@ -251,8 +257,6 @@
 
     def get_shared_data(self, key, default=None, pop=False):
         """return value associated to `key` in shared data"""
-        if self.cnx is None:
-            return default # before the connection has been established
         return self.cnx.get_shared_data(key, default, pop)
 
     def set_shared_data(self, key, value, querydata=False):
@@ -283,7 +287,7 @@
 
     @property
     def user(self):
-        if self._user is None and self.cnx:
+        if not self._user and self.cnx:
             self.set_user(self.cnx.user(self, {'lang': self.lang}))
         return self._user
 
--- a/selectors.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/selectors.py	Wed Apr 14 10:29:38 2010 +0200
@@ -1044,7 +1044,7 @@
 
     May only be used on the web side, not on the data repository side.
     """
-    if req.cnx is None:
+    if not req.cnx:
         return 1
     return 0
 
--- a/web/application.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/web/application.py	Wed Apr 14 10:29:38 2010 +0200
@@ -173,7 +173,6 @@
 
         :raise Redirect: if authentication has occured and succeed
         """
-        assert req.cnx is None # at this point no cnx should be set on the request
         cookie = req.get_cookie()
         try:
             sessionid = str(cookie[self.SESSION_VAR].value)
@@ -306,7 +305,7 @@
             return self.main_publish(path, req)
         finally:
             cnx = req.cnx
-            if cnx is not None:
+            if cnx:
                 with self._logfile_lock:
                     try:
                         result = ['\n'+'*'*80]
@@ -357,12 +356,13 @@
                     raise Unauthorized(req._('not authorized'))
                 req.update_search_state()
                 result = controller.publish(rset=rset)
-                if req.cnx is not None:
-                    # req.cnx is None if anonymous aren't allowed and we are
-                    # displaying the cookie authentication form
+                if req.cnx:
+                    # no req.cnx if anonymous aren't allowed and we are
+                    # displaying some anonymous enabled view such as the cookie
+                    # authentication form
                     req.cnx.commit()
             except (StatusResponse, DirectResponse):
-                if req.cnx is not None:
+                if req.cnx:
                     req.cnx.commit()
                 raise
             except (AuthenticationError, LogOut):
@@ -401,7 +401,7 @@
             except Exception, ex:
                 self.error_handler(req, ex, tb=True)
         finally:
-            if req.cnx is not None:
+            if req.cnx:
                 try:
                     req.cnx.rollback()
                 except:
--- a/web/httpcache.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/web/httpcache.py	Wed Apr 14 10:29:38 2010 +0200
@@ -43,7 +43,7 @@
     """
 
     def etag(self):
-        if self.req.cnx is None:
+        if not self.req.cnx: # session without established connection to the repo
             return self.view.__regid__
         return self.view.__regid__ + '/' + ','.join(sorted(self.req.user.groups))
 
--- a/web/request.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/web/request.py	Wed Apr 14 10:29:38 2010 +0200
@@ -152,7 +152,7 @@
         self._ = self.__ = gettext
         self.lang = lang
         self.debug('request language: %s', lang)
-        if self.cnx is not None:
+        if self.cnx:
             self.cnx.set_session_props(lang=lang)
 
     # input form parameters management ########################################
@@ -280,7 +280,7 @@
     def update_search_state(self):
         """update the current search state"""
         searchstate = self.form.get('__mode')
-        if not searchstate and self.cnx is not None:
+        if not searchstate and self.cnx:
             searchstate = self.session.data.get('search_state', 'normal')
         self.set_search_state(searchstate)
 
@@ -291,7 +291,7 @@
         else:
             self.search_state = ('linksearch', searchstate.split(':'))
             assert len(self.search_state[-1]) == 4
-        if self.cnx is not None:
+        if self.cnx:
             self.session.data['search_state'] = searchstate
 
     def match_search_state(self, rset):
--- a/web/test/data/views.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/web/test/data/views.py	Wed Apr 14 10:29:38 2010 +0200
@@ -14,7 +14,7 @@
 # user
 # NOTE: this require "cookie" authentication mode
 def auto_login_publish(self, path, req):
-    if (req.cnx is None or req.cnx.anonymous_connection) and req.form.get('__fblogin'):
+    if (not req.cnx or req.cnx.anonymous_connection) and req.form.get('__fblogin'):
         login = password = req.form.pop('__fblogin')
         self.repo.register_user(login, password)
         req.form['__login'] = login
--- a/web/views/basecontrollers.py	Wed Apr 14 10:25:51 2010 +0200
+++ b/web/views/basecontrollers.py	Wed Apr 14 10:29:38 2010 +0200
@@ -116,10 +116,10 @@
         req = self._cw
         if rset is None and not hasattr(req, '_rql_processed'):
             req._rql_processed = True
-            if req.cnx is None:
+            if req.cnx:
+                rset = self.process_rql(req.form.get('rql'))
+            else:
                 rset = None
-            else:
-                rset = self.process_rql(req.form.get('rql'))
         if rset and rset.rowcount == 1 and '__method' in req.form:
             entity = rset.get_entity(0, 0)
             try: