changeset 1761:b265be1c6093 beta

Wrapped calls for git and hg middleware in extra block that clears db Session. tries to fix #318
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 07 Dec 2011 22:08:12 +0200
parents 9dda1146327c
children a69d0029bd27
files rhodecode/lib/base.py rhodecode/lib/middleware/simplegit.py rhodecode/lib/middleware/simplehg.py
diffstat 3 files changed, 79 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/lib/base.py	Wed Dec 07 20:43:16 2011 +0200
+++ b/rhodecode/lib/base.py	Wed Dec 07 22:08:12 2011 +0200
@@ -4,6 +4,9 @@
 """
 import logging
 import time
+
+from paste.auth.basic import AuthBasicAuthenticator
+
 from pylons import config, tmpl_context as c, request, session, url
 from pylons.controllers import WSGIController
 from pylons.controllers.util import redirect
@@ -12,8 +15,9 @@
 from rhodecode import __version__, BACKENDS
 
 from rhodecode.lib import str2bool
-from rhodecode.lib.auth import AuthUser, get_container_username
-from rhodecode.lib.utils import get_repo_slug
+from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
+    HasPermissionAnyMiddleware
+from rhodecode.lib.utils import get_repo_slug, invalidate_cache
 from rhodecode.model import meta
 
 from rhodecode.model.db import Repository
@@ -22,6 +26,60 @@
 
 log = logging.getLogger(__name__)
 
+class BaseVCSController(object):
+    
+    def __init__(self, application, config):
+        self.application = application
+        self.config = config
+        # base path of repo locations
+        self.basepath = self.config['base_path']
+        #authenticate this mercurial request using authfunc
+        self.authenticate = AuthBasicAuthenticator('', authfunc)
+        self.ipaddr = '0.0.0.0'
+    
+    def _invalidate_cache(self, repo_name):
+        """
+        Set's cache for this repository for invalidation on next access
+        
+        :param repo_name: full repo name, also a cache key
+        """
+        invalidate_cache('get_repo_cached_%s' % repo_name)
+                
+    def _check_permission(self, action, user, repo_name):
+        """
+        Checks permissions using action (push/pull) user and repository
+        name
+
+        :param action: push or pull action
+        :param user: user instance
+        :param repo_name: repository name
+        """
+        if action == 'push':
+            if not HasPermissionAnyMiddleware('repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
+
+        else:
+            #any other action need at least read permission
+            if not HasPermissionAnyMiddleware('repository.read',
+                                              'repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
+
+        return True        
+        
+    def __call__(self, environ, start_response):
+        start = time.time()
+        try:
+            return self._handle_request(environ, start_response)
+        finally:
+            log = logging.getLogger(self.__class__.__name__)
+            log.debug('Request time: %.3fs' % (time.time() - start))
+            meta.Session.remove()
+
+
 class BaseController(WSGIController):
 
     def __before__(self):
--- a/rhodecode/lib/middleware/simplegit.py	Wed Dec 07 20:43:16 2011 +0200
+++ b/rhodecode/lib/middleware/simplegit.py	Wed Dec 07 22:08:12 2011 +0200
@@ -30,7 +30,6 @@
 
 from dulwich import server as dulserver
 
-
 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
 
     def handle(self):
@@ -66,12 +65,12 @@
 from dulwich.repo import Repo
 from dulwich.web import HTTPGitApplication
 
-from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
 from rhodecode.lib import safe_str
-from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware, get_container_username
-from rhodecode.lib.utils import invalidate_cache, is_valid_repo
+from rhodecode.lib.base import BaseVCSController
+from rhodecode.lib.auth import get_container_username
+from rhodecode.lib.utils import is_valid_repo
 from rhodecode.model.db import User
 
 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
@@ -91,17 +90,9 @@
     return False
 
 
-class SimpleGit(object):
+class SimpleGit(BaseVCSController):
 
-    def __init__(self, application, config):
-        self.application = application
-        self.config = config
-        # base path of repo locations
-        self.basepath = self.config['base_path']
-        #authenticate this mercurial request using authfunc
-        self.authenticate = AuthBasicAuthenticator('', authfunc)
-
-    def __call__(self, environ, start_response):
+    def _handle_request(self, environ, start_response):
         if not is_git(environ):
             return self.application(environ, start_response)
 
@@ -132,9 +123,8 @@
         if action in ['pull', 'push']:
             anonymous_user = self.__get_user('default')
             username = anonymous_user.username
-            anonymous_perm = self.__check_permission(action,
-                                                     anonymous_user,
-                                                     repo_name)
+            anonymous_perm = self._check_permission(action,anonymous_user,
+                                                    repo_name)
 
             if anonymous_perm is not True or anonymous_user.active is False:
                 if anonymous_perm is not True:
@@ -179,16 +169,11 @@
                                                          start_response)
 
                     #check permissions for this repository
-                    perm = self.__check_permission(action, user,
+                    perm = self._check_permission(action, user,
                                                    repo_name)
                     if perm is not True:
                         return HTTPForbidden()(environ, start_response)
 
-        extras = {'ip': ipaddr,
-                  'username': username,
-                  'action': action,
-                  'repository': repo_name}
-
         #===================================================================
         # GIT REQUEST HANDLING
         #===================================================================
@@ -203,7 +188,7 @@
         try:
             #invalidate cache on push
             if action == 'push':
-                self.__invalidate_cache(repo_name)
+                self._invalidate_cache(repo_name)
 
             app = self.__make_app(repo_name, repo_path)
             return app(environ, start_response)
@@ -225,31 +210,6 @@
 
         return gitserve
 
-    def __check_permission(self, action, user, repo_name):
-        """
-        Checks permissions using action (push/pull) user and repository
-        name
-
-        :param action: push or pull action
-        :param user: user instance
-        :param repo_name: repository name
-        """
-        if action == 'push':
-            if not HasPermissionAnyMiddleware('repository.write',
-                                              'repository.admin')(user,
-                                                                  repo_name):
-                return False
-
-        else:
-            #any other action need at least read permission
-            if not HasPermissionAnyMiddleware('repository.read',
-                                              'repository.write',
-                                              'repository.admin')(user,
-                                                                  repo_name):
-                return False
-
-        return True
-
     def __get_repository(self, environ):
         """
         Get's repository name out of PATH_INFO header
@@ -285,10 +245,3 @@
                                service_cmd if service_cmd else 'other')
         else:
             return 'other'
-
-    def __invalidate_cache(self, repo_name):
-        """we know that some change was made to repositories and we should
-        invalidate the cache to see the changes right away but only for
-        push requests"""
-        invalidate_cache('get_repo_cached_%s' % repo_name)
-
--- a/rhodecode/lib/middleware/simplehg.py	Wed Dec 07 20:43:16 2011 +0200
+++ b/rhodecode/lib/middleware/simplehg.py	Wed Dec 07 22:08:12 2011 +0200
@@ -31,13 +31,12 @@
 from mercurial.error import RepoError
 from mercurial.hgweb import hgweb_mod
 
-from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
 from rhodecode.lib import safe_str
-from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware, get_container_username
-from rhodecode.lib.utils import make_ui, invalidate_cache, \
-    is_valid_repo, ui_sections
+from rhodecode.lib.base import BaseVCSController
+from rhodecode.lib.auth import get_container_username
+from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
 from rhodecode.model.db import User
 
 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
@@ -55,18 +54,9 @@
     return False
 
 
-class SimpleHg(object):
+class SimpleHg(BaseVCSController):
 
-    def __init__(self, application, config):
-        self.application = application
-        self.config = config
-        # base path of repo locations
-        self.basepath = self.config['base_path']
-        #authenticate this mercurial request using authfunc
-        self.authenticate = AuthBasicAuthenticator('', authfunc)
-        self.ipaddr = '0.0.0.0'
-
-    def __call__(self, environ, start_response):
+    def _handle_request(self, environ, start_response):
         if not is_mercurial(environ):
             return self.application(environ, start_response)
 
@@ -98,9 +88,8 @@
             anonymous_user = self.__get_user('default')
 
             username = anonymous_user.username
-            anonymous_perm = self.__check_permission(action,
-                                                     anonymous_user,
-                                                     repo_name)
+            anonymous_perm = self._check_permission(action,anonymous_user,
+                                                    repo_name)
 
             if anonymous_perm is not True or anonymous_user.active is False:
                 if anonymous_perm is not True:
@@ -145,7 +134,7 @@
                                                          start_response)
 
                     #check permissions for this repository
-                    perm = self.__check_permission(action, user,
+                    perm = self._check_permission(action, user,
                                                    repo_name)
                     if perm is not True:
                         return HTTPForbidden()(environ, start_response)
@@ -171,9 +160,9 @@
             return HTTPNotFound()(environ, start_response)
 
         try:
-            #invalidate cache on push
+            # invalidate cache on push
             if action == 'push':
-                self.__invalidate_cache(repo_name)
+                self._invalidate_cache(repo_name)
 
             app = self.__make_app(repo_path, baseui, extras)
             return app(environ, start_response)
@@ -192,31 +181,6 @@
         return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
 
 
-    def __check_permission(self, action, user, repo_name):
-        """
-        Checks permissions using action (push/pull) user and repository
-        name
-
-        :param action: push or pull action
-        :param user: user instance
-        :param repo_name: repository name
-        """
-        if action == 'push':
-            if not HasPermissionAnyMiddleware('repository.write',
-                                              'repository.admin')(user,
-                                                                  repo_name):
-                return False
-
-        else:
-            #any other action need at least read permission
-            if not HasPermissionAnyMiddleware('repository.read',
-                                              'repository.write',
-                                              'repository.admin')(user,
-                                                                  repo_name):
-                return False
-
-        return True
-
     def __get_repository(self, environ):
         """
         Get's repository name out of PATH_INFO header
@@ -257,11 +221,6 @@
                 else:
                     return 'pull'
 
-    def __invalidate_cache(self, repo_name):
-        """we know that some change was made to repositories and we should
-        invalidate the cache to see the changes right away but only for
-        push requests"""
-        invalidate_cache('get_repo_cached_%s' % repo_name)
 
     def __inject_extras(self, repo_path, baseui, extras={}):
         """