Commits

Marcin Kuzminski committed da59b7e

Changed import to base. Removed action logging from auth to simplehg.
Splited loggin and invalidation action to private methods inside simplehg.

Comments (0)

Files changed (3)

pylons_app/lib/auth.py

 from pylons import session, url
 from pylons.controllers.util import abort, redirect
 from pylons_app.model import meta
-from pylons_app.model.db import Users, UserLogs
+from pylons_app.model.db import Users
 from sqlalchemy.exc import OperationalError
 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 import crypt
         if user.active:
             if user.username == username and user.password == password_crypt:
                 log.info('user %s authenticated correctly', username)
-                if environ:
-                    http_accept = environ.get('HTTP_ACCEPT')
-            
-                    if http_accept.startswith('application/mercurial') or \
-                        environ['PATH_INFO'].find('raw-file') != -1:
-                        repo = environ['PATH_INFO']
-                        for qry in environ['QUERY_STRING'].split('&'):
-                            if qry.startswith('cmd'):
-                                
-                                try:
-                                    user_log = UserLogs()
-                                    user_log.user_id = user.user_id
-                                    user_log.action = qry
-                                    user_log.repository = repo
-                                    user_log.action_date = datetime.now()
-                                    sa.add(user_log)
-                                    sa.commit()
-                                    log.info('Adding user %s, action %s', username, qry)
-                                except Exception as e:
-                                    sa.rollback()
-                                    log.error(e)
-                                  
                 return True
         else:
             log.error('user %s is disabled', username)

pylons_app/lib/simplehg.py

 SimpleHG middleware for handling mercurial protocol request (push/clone etc.)
 It's implemented with basic auth function
 """
-
+from datetime import datetime
 from mercurial.hgweb import hgweb
 from mercurial.hgweb.request import wsgiapplication
 from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
-from pylons_app.lib.utils import is_mercurial
 from pylons_app.lib.auth import authfunc
-from pylons_app.lib.utils import make_ui, invalidate_cache
+from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache
+from pylons_app.model import meta
+from pylons_app.model.db import UserLogs, Users
 from webob.exc import HTTPNotFound
+import logging
 import os
+log = logging.getLogger(__name__)
 
 class SimpleHg(object):
 
                                                             .replace('*', '')
             self.repo_path = os.path.join(self.basepath, repo_name)
             try:
-                app = wsgiapplication(self._make_app)
+                app = wsgiapplication(self.__make_app)
             except Exception as e:
                 return HTTPNotFound()(environ, start_response)
             
-            """we know that some change was made to repositories and we should
-            invalidate the cache to see the changes right away"""
-            invalidate_cache('full_changelog', repo_name)
-            invalidate_cache('cached_repo_list')
+            action = self.__get_action(environ)            
+            #invalidate cache on push
+            if action == 'push':
+                self.__invalidate_cache(repo_name)
+            
+            if action:
+                username = self.__get_environ_user(environ)
+                self.__log_user_action(username, action, repo_name)            
             return app(environ, start_response)            
 
-    def _make_app(self):
+    def __make_app(self):
         hgserve = hgweb(self.repo_path)
         return  self.load_web_settings(hgserve)
+    
+    def __get_environ_user(self, environ):
+        return environ.get('REMOTE_USER')
         
-                
+    def __get_action(self, environ):
+        """
+        Maps mercurial request commands into a pull or push command.
+        @param environ:
+        """
+        mapping = {
+            'changegroup': 'pull',
+            'changegroupsubset': 'pull',
+            'unbundle': 'push',
+            'stream_out': 'pull',
+        }                    
+        for qry in environ['QUERY_STRING'].split('&'):
+            if qry.startswith('cmd'):
+                cmd = qry.split('=')[-1]
+                if mapping.has_key(cmd):
+                    return mapping[cmd]
+    
+    def __log_user_action(self, username, action, repo):
+        sa = meta.Session
+        try:
+            user = sa.query(Users)\
+                    .filter(Users.username == username).one()
+            user_log = UserLogs()
+            user_log.user_id = user.user_id
+            user_log.action = action
+            user_log.repository = repo.replace('/', '')
+            user_log.action_date = datetime.now()
+            sa.add(user_log)
+            sa.commit()
+            log.info('Adding user %s, action %s on %s',
+                                            username, action, repo)
+        except Exception as e:
+            sa.rollback()
+            log.error('could not log user action:%s', str(e))
+    
+    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('cached_repo_list')
+        invalidate_cache('full_changelog', repo_name)
+           
+                   
     def load_web_settings(self, hgserve):
         repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False)
         #set the global ui for hgserve

pylons_app/lib/utils.py

         region_invalidate(_get_repos_cached, None, *args)
         
     if name == 'full_changelog':
-        from pylons_app.controllers.changelog import _full_changelog_cached
+        from pylons_app.lib.base import _full_changelog_cached
         region_invalidate(_full_changelog_cached, None, *args)
         
 from vcs.backends.base import BaseChangeset