diff pylons_app/lib/middleware/simplehg.py @ 366:6484963056cd

implemented cache for repeated queries in simplehg mercurial requests
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 14 Jul 2010 12:31:11 +0200
parents 1ef52a70f3b7
children 664a5b8c551a
line wrap: on
line diff
--- a/pylons_app/lib/middleware/simplehg.py	Wed Jul 14 02:28:51 2010 +0200
+++ b/pylons_app/lib/middleware/simplehg.py	Wed Jul 14 12:31:11 2010 +0200
@@ -2,7 +2,7 @@
 # encoding: utf-8
 # middleware to handle mercurial api calls
 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
- 
+
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; version 2
@@ -27,21 +27,23 @@
 """
 from datetime import datetime
 from itertools import chain
+from mercurial.error import RepoError
 from mercurial.hgweb import hgweb
 from mercurial.hgweb.request import wsgiapplication
-from mercurial.error import RepoError
 from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
-from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware
+from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware, \
+    get_user_cached
 from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache, \
     check_repo_fast
 from pylons_app.model import meta
 from pylons_app.model.db import UserLog, User
-import pylons_app.lib.helpers as h
 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
 import logging
 import os
+import pylons_app.lib.helpers as h
 import traceback
+ 
 log = logging.getLogger(__name__)
 
 class SimpleHg(object):
@@ -56,86 +58,84 @@
     def __call__(self, environ, start_response):
         if not is_mercurial(environ):
             return self.application(environ, start_response)
-        else:
-            #===================================================================
-            # AUTHENTICATE THIS MERCURIAL REQUEST
-            #===================================================================
-            username = REMOTE_USER(environ)
-            if not username:
-                result = self.authenticate(environ)
-                if isinstance(result, str):
-                    AUTH_TYPE.update(environ, 'basic')
-                    REMOTE_USER.update(environ, result)
-                else:
-                    return result.wsgi_application(environ, start_response)
-            
+
+        #===================================================================
+        # AUTHENTICATE THIS MERCURIAL REQUEST
+        #===================================================================
+        username = REMOTE_USER(environ)
+        if not username:
+            result = self.authenticate(environ)
+            if isinstance(result, str):
+                AUTH_TYPE.update(environ, 'basic')
+                REMOTE_USER.update(environ, result)
+            else:
+                return result.wsgi_application(environ, start_response)
+        
+        try:
+            repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
+        except:
+            log.error(traceback.format_exc())
+            return HTTPInternalServerError()(environ, start_response)
+        
+        #===================================================================
+        # CHECK PERMISSIONS FOR THIS REQUEST
+        #===================================================================
+        action = self.__get_action(environ)
+        if action:
+            username = self.__get_environ_user(environ)
             try:
-                repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
+                user = self.__get_user(username)
             except:
                 log.error(traceback.format_exc())
                 return HTTPInternalServerError()(environ, start_response)
+            #check permissions for this repository
+            if action == 'pull':
+                if not HasPermissionAnyMiddleware('repository.read',
+                                                  'repository.write',
+                                                  'repository.admin')\
+                                                    (user, repo_name):
+                    return HTTPForbidden()(environ, start_response)
+            if action == 'push':
+                if not HasPermissionAnyMiddleware('repository.write',
+                                                  'repository.admin')\
+                                                    (user, repo_name):
+                    return HTTPForbidden()(environ, start_response)
             
-            #===================================================================
-            # CHECK PERMISSIONS FOR THIS REQUEST
-            #===================================================================
-            action = self.__get_action(environ)
-            if action:
-                username = self.__get_environ_user(environ)
-                try:
-                    sa = meta.Session
-                    user = sa.query(User)\
-                        .filter(User.username == username).one()
-                except:
-                    log.error(traceback.format_exc())
-                    return HTTPInternalServerError()(environ, start_response)
-                #check permissions for this repository
-                if action == 'pull':
-                    if not HasPermissionAnyMiddleware('repository.read',
-                                                      'repository.write',
-                                                      'repository.admin')\
-                                                        (user, repo_name):
-                        return HTTPForbidden()(environ, start_response)
-                if action == 'push':
-                    if not HasPermissionAnyMiddleware('repository.write',
-                                                      'repository.admin')\
-                                                        (user, repo_name):
-                        return HTTPForbidden()(environ, start_response)
-                
-                #log action    
-                proxy_key = 'HTTP_X_REAL_IP'
-                def_key = 'REMOTE_ADDR'
-                ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
-                self.__log_user_action(user, action, repo_name, ipaddr)            
-            
-            #===================================================================
-            # MERCURIAL REQUEST HANDLING
-            #===================================================================
-            environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path
-            self.baseui = make_ui('db')
-            self.basepath = self.config['base_path']
-            self.repo_path = os.path.join(self.basepath, repo_name)
+            #log action    
+            proxy_key = 'HTTP_X_REAL_IP'
+            def_key = 'REMOTE_ADDR'
+            ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
+            self.__log_user_action(user, action, repo_name, ipaddr)            
+        
+        #===================================================================
+        # MERCURIAL REQUEST HANDLING
+        #===================================================================
+        environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path
+        self.baseui = make_ui('db')
+        self.basepath = self.config['base_path']
+        self.repo_path = os.path.join(self.basepath, repo_name)
 
-            #quick check if that dir exists...
-            if check_repo_fast(repo_name, self.basepath):
+        #quick check if that dir exists...
+        if check_repo_fast(repo_name, self.basepath):
+            return HTTPNotFound()(environ, start_response)
+        try:
+            app = wsgiapplication(self.__make_app)
+        except RepoError as e:
+            if str(e).find('not found') != -1:
                 return HTTPNotFound()(environ, start_response)
-            try:
-                app = wsgiapplication(self.__make_app)
-            except RepoError as e:
-                if str(e).find('not found') != -1:
-                    return HTTPNotFound()(environ, start_response)
-            except Exception:
-                log.error(traceback.format_exc())
-                return HTTPInternalServerError()(environ, start_response)
-            
-            #invalidate cache on push
-            if action == 'push':
-                self.__invalidate_cache(repo_name)
-                messages = []
-                messages.append('thank you for using hg-app')
-            
-                return self.msg_wrapper(app, environ, start_response, messages)
-            else:
-                return app(environ, start_response)           
+        except Exception:
+            log.error(traceback.format_exc())
+            return HTTPInternalServerError()(environ, start_response)
+        
+        #invalidate cache on push
+        if action == 'push':
+            self.__invalidate_cache(repo_name)
+            messages = []
+            messages.append('thank you for using hg-app')
+        
+            return self.msg_wrapper(app, environ, start_response, messages)
+        else:
+            return app(environ, start_response)           
 
 
     def msg_wrapper(self, app, environ, start_response, messages=[]):
@@ -160,6 +160,11 @@
     def __get_environ_user(self, environ):
         return environ.get('REMOTE_USER')
     
+    def __get_user(self, username):
+        return get_user_cached(username)
+        
+        
+                        
     def __get_size(self, repo_path, content_size):
         size = int(content_size)
         for path, dirs, files in os.walk(repo_path):