diff --git a/rhodecode/lib/middleware/simplegit.py b/rhodecode/lib/middleware/simplegit.py --- a/rhodecode/lib/middleware/simplegit.py +++ b/rhodecode/lib/middleware/simplegit.py @@ -8,7 +8,7 @@ :created_on: Apr 28, 2010 :author: marcink - :copyright: (C) 2009-2010 Marcin Kuzminski + :copyright: (C) 2010-2012 Marcin Kuzminski :license: GPLv3, see COPYING for more details. """ # This program is free software: you can redistribute it and/or modify @@ -27,7 +27,6 @@ import os import logging import traceback -import time from dulwich import server as dulserver @@ -67,13 +66,12 @@ dulserver.DEFAULT_HANDLERS = { 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 -from rhodecode.lib.utils import invalidate_cache, is_valid_repo -from rhodecode.model import meta +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 @@ -93,24 +91,7 @@ def is_git(environ): return False -class SimpleGit(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) - - 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 SimpleGit(BaseVCSController): def _handle_request(self, environ, start_response): if not is_git(environ): @@ -143,9 +124,8 @@ class SimpleGit(object): 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: @@ -159,27 +139,29 @@ class SimpleGit(object): # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS #============================================================== - if not REMOTE_USER(environ): + # Attempting to retrieve username from the container + username = get_container_username(environ, self.config) + + # If not authenticated by the container, running basic auth + if not username: self.authenticate.realm = \ safe_str(self.config['rhodecode_realm']) result = self.authenticate(environ) if isinstance(result, str): AUTH_TYPE.update(environ, 'basic') REMOTE_USER.update(environ, result) + username = result else: return result.wsgi_application(environ, start_response) #============================================================== - # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM - # BASIC AUTH + # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME #============================================================== - if action in ['pull', 'push']: - username = REMOTE_USER(environ) try: user = self.__get_user(username) - if user is None: - return HTTPForbidden()(environ, start_response) + if user is None or not user.active: + return HTTPForbidden()(environ, start_response) username = user.username except: log.error(traceback.format_exc()) @@ -187,16 +169,11 @@ class SimpleGit(object): 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 #=================================================================== @@ -211,8 +188,8 @@ class SimpleGit(object): try: #invalidate cache on push if action == 'push': - self.__invalidate_cache(repo_name) - + self._invalidate_cache(repo_name) + log.info('%s action on GIT repo "%s"' % (action, repo_name)) app = self.__make_app(repo_name, repo_path) return app(environ, start_response) except Exception: @@ -222,7 +199,7 @@ class SimpleGit(object): def __make_app(self, repo_name, repo_path): """ Make an wsgi application using dulserver - + :param repo_name: name of the repository :param repo_path: full path to the repository """ @@ -233,31 +210,6 @@ class SimpleGit(object): 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 @@ -265,6 +217,7 @@ class SimpleGit(object): :param environ: environ where PATH_INFO is stored """ try: + environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO']) repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) if repo_name.endswith('/'): repo_name = repo_name.rstrip('/') @@ -293,10 +246,3 @@ class SimpleGit(object): 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) -