Exemple #1
0
 def _handle_rc_scm_extras(self,
                           username,
                           repo_name,
                           repo_alias,
                           action=None):
     from kallithea import CONFIG
     from kallithea.lib.base import _get_ip_addr
     try:
         from tg import request
         environ = request.environ
     except TypeError:
         # we might use this outside of request context, let's fake the
         # environ data
         from webob import Request
         environ = Request.blank('').environ
     extras = {
         'ip': _get_ip_addr(environ),
         'username': username,
         'action': action or 'push_local',
         'repository': repo_name,
         'scm': repo_alias,
         'config': CONFIG['__file__'],
         'server_url': get_server_url(environ),
         'make_lock': None,
         'locked_by': [None, None]
     }
     _set_extras(extras)
Exemple #2
0
 def _handle_rc_scm_extras(self, username, repo_name, repo_alias,
                           action=None):
     from kallithea import CONFIG
     from kallithea.lib.base import _get_ip_addr
     try:
         from pylons import request
         environ = request.environ
     except TypeError:
         # we might use this outside of request context, let's fake the
         # environ data
         from webob import Request
         environ = Request.blank('').environ
     extras = {
         'ip': _get_ip_addr(environ),
         'username': username,
         'action': action or 'push_local',
         'repository': repo_name,
         'scm': repo_alias,
         'config': CONFIG['__file__'],
         'server_url': get_server_url(environ),
         'make_lock': None,
         'locked_by': [None, None]
     }
     _set_extras(extras)
Exemple #3
0
    def _handle_request(self, environ, start_response):
        if not is_mercurial(environ):
            return self.application(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            str_repo_name = environ['REPO_NAME'] = self.__get_repository(environ)
            assert isinstance(str_repo_name, str), str_repo_name
            repo_name = safe_unicode(str_repo_name)
            assert safe_str(repo_name) == str_repo_name, (str_repo_name, repo_name)
            log.debug('Extracted repo name is %s', repo_name)
        except Exception as e:
            log.error('error extracting repo_name: %r', e)
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'hg'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        try:
            action = self.__get_action(environ)
        except HTTPBadRequest as e:
            return e(environ, start_response)

        #======================================================================
        # CHECK PERMISSIONS
        #======================================================================
        user, response_app = self._authorize(environ, start_response, action, repo_name, ip_addr)
        if response_app is not None:
            return response_app(environ, start_response)

        # extras are injected into mercurial UI object and later available
        # in hg hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': user.username,
            'action': action,
            'repository': repo_name,
            'scm': 'hg',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }
        #======================================================================
        # MERCURIAL REQUEST HANDLING
        #======================================================================
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
        log.debug('Repository path is %s', repo_path)

        # A Mercurial HTTP server will see listkeys operations (bookmarks,
        # phases and obsolescence marker) in a different request - we don't
        # want to check locking on those
        if environ['QUERY_STRING'] == 'cmd=listkeys':
            pass
        # CHECK LOCKING only if it's not ANONYMOUS USER
        elif not user.is_default_user:
            log.debug('Checking locking on repository')
            make_lock, locked, locked_by = check_locking_state(action, repo_name, user)
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock,
                           'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s', extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            log.info('%s action on Mercurial repo "%s" by "%s" from %s',
                     action, str_repo_name, safe_str(user.username), ip_addr)
            app = self.__make_app(repo_path, baseui, extras)
            result = app(environ, start_response)
            if action == 'push':
                result = WSGIResultCloseCallback(result,
                    lambda: self._invalidate_cache(repo_name))
            return result
        except RepoError as e:
            if str(e).find('not found') != -1:
                return HTTPNotFound()(environ, start_response)
        except HTTPLockedRC as e:
            # Before Mercurial 3.6, lock exceptions were caught here
            log.debug('Locked, response %s: %s', e.code, e.title)
            return e(environ, start_response)
        except Exception:
            log.error(traceback.format_exc())
            return HTTPInternalServerError()(environ, start_response)
Exemple #4
0
    def _handle_request(self, environ, start_response):
        if not is_git(environ):
            return self.application(environ, start_response)
        if not self._check_ssl(environ):
            return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        username = None
        self._git_first_op = False
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            str_repo_name = self.__get_repository(environ)
            repo_name = safe_unicode(str_repo_name)
            log.debug('Extracted repo name is %s', repo_name)
        except Exception as e:
            log.error('error extracting repo_name: %r', e)
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'git'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        action = self.__get_action(environ)

        #======================================================================
        # CHECK ANONYMOUS PERMISSION
        #======================================================================
        if action in ['pull', 'push']:
            anonymous_user = User.get_default_user(cache=True)
            username = anonymous_user.username
            if anonymous_user.active:
                # ONLY check permissions if the user is activated
                anonymous_perm = self._check_permission(action, anonymous_user,
                                                        repo_name, ip_addr)
            else:
                anonymous_perm = False

            if not anonymous_user.active or not anonymous_perm:
                if not anonymous_user.active:
                    log.debug('Anonymous access is disabled, running '
                              'authentication')

                if not anonymous_perm:
                    log.debug('Not enough credentials to access this '
                              'repository as anonymous user')

                username = None
                #==============================================================
                # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
                # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
                #==============================================================

                # try to auth based on environ, container auth methods
                log.debug('Running PRE-AUTH for container based authentication')
                pre_auth = auth_modules.authenticate('', '', environ)
                if pre_auth is not None and pre_auth.get('username'):
                    username = pre_auth['username']
                log.debug('PRE-AUTH got %s as username', username)

                # If not authenticated by the container, running basic auth
                if not username:
                    self.authenticate.realm = \
                        safe_str(self.config['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
                #==============================================================
                try:
                    user = User.get_by_username_or_email(username)
                    if user is None or not user.active:
                        return HTTPForbidden()(environ, start_response)
                    username = user.username
                except Exception:
                    log.error(traceback.format_exc())
                    return HTTPInternalServerError()(environ, start_response)

                #check permissions for this repository
                perm = self._check_permission(action, user, repo_name, ip_addr)
                if not perm:
                    return HTTPForbidden()(environ, start_response)

        # extras are injected into UI object and later available
        # in hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': username,
            'action': action,
            'repository': repo_name,
            'scm': 'git',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }

        #===================================================================
        # GIT REQUEST HANDLING
        #===================================================================
        repo_path = os.path.join(safe_str(self.basepath),str_repo_name)
        log.debug('Repository path is %s', repo_path)

        # CHECK LOCKING only if it's not ANONYMOUS USER
        if username != User.DEFAULT_USER:
            log.debug('Checking locking on repository')
            (make_lock,
             locked,
             locked_by) = self._check_locking_state(
                            environ=environ, action=action,
                            repo=repo_name, user_id=user.user_id
                       )
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock,
                           'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s', extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            self._handle_githooks(repo_name, action, baseui, environ)
            log.info('%s action on Git repo "%s" by "%s" from %s',
                     action, str_repo_name, safe_str(username), ip_addr)
            app = self.__make_app(repo_name, repo_path, extras)
            result = app(environ, start_response)
            if action == 'push':
                result = WSGIResultCloseCallback(result,
                    lambda: self._invalidate_cache(repo_name))
            return result
        except HTTPLockedRC as e:
            _code = CONFIG.get('lock_ret_code')
            log.debug('Repository LOCKED ret code %s!', _code)
            return e(environ, start_response)
        except Exception:
            log.error(traceback.format_exc())
            return HTTPInternalServerError()(environ, start_response)
    def _handle_request(self, environ, start_response):
        if not is_git(environ):
            return self.application(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        self._git_first_op = False
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            str_repo_name = self.__get_repository(environ)
            repo_name = safe_unicode(str_repo_name)
            log.debug('Extracted repo name is %s', repo_name)
        except Exception as e:
            log.error('error extracting repo_name: %r', e)
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'git'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        action = self.__get_action(environ)

        #======================================================================
        # CHECK PERMISSIONS
        #======================================================================
        user, response_app = self._authorize(environ, start_response, action, repo_name, ip_addr)
        if response_app is not None:
            return response_app(environ, start_response)

        # extras are injected into UI object and later available
        # in hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': user.username,
            'action': action,
            'repository': repo_name,
            'scm': 'git',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }

        #===================================================================
        # GIT REQUEST HANDLING
        #===================================================================
        repo_path = os.path.join(safe_str(self.basepath),str_repo_name)
        log.debug('Repository path is %s', repo_path)

        # CHECK LOCKING only if it's not ANONYMOUS USER
        if not user.is_default_user:
            log.debug('Checking locking on repository')
            make_lock, locked, locked_by = check_locking_state(action, repo_name, user)
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock,
                           'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s', extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            self._handle_githooks(repo_name, action, baseui, environ)
            log.info('%s action on Git repo "%s" by "%s" from %s',
                     action, str_repo_name, safe_str(user.username), ip_addr)
            app = self.__make_app(repo_name, repo_path, extras)
            result = app(environ, start_response)
            if action == 'push':
                result = WSGIResultCloseCallback(result,
                    lambda: self._invalidate_cache(repo_name))
            return result
        except HTTPLockedRC as e:
            log.debug('Locked, response %s: %s', e.code, e.title)
            return e(environ, start_response)
        except Exception:
            log.error(traceback.format_exc())
            return HTTPInternalServerError()(environ, start_response)
Exemple #6
0
    def _handle_request(self, environ, start_response):
        if not is_git(environ):
            return self.application(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        self._git_first_op = False
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            str_repo_name = self.__get_repository(environ)
            repo_name = safe_unicode(str_repo_name)
            log.debug('Extracted repo name is %s', repo_name)
        except Exception as e:
            log.error('error extracting repo_name: %r', e)
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'git'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        action = self.__get_action(environ)

        #======================================================================
        # CHECK PERMISSIONS
        #======================================================================
        user, response_app = self._authorize(environ, start_response, action,
                                             repo_name, ip_addr)
        if response_app is not None:
            return response_app(environ, start_response)

        # extras are injected into UI object and later available
        # in hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': user.username,
            'action': action,
            'repository': repo_name,
            'scm': 'git',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }

        #===================================================================
        # GIT REQUEST HANDLING
        #===================================================================
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
        log.debug('Repository path is %s', repo_path)

        # CHECK LOCKING only if it's not ANONYMOUS USER
        if not user.is_default_user:
            log.debug('Checking locking on repository')
            make_lock, locked, locked_by = check_locking_state(
                action, repo_name, user)
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock, 'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s', extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            self._handle_githooks(repo_name, action, baseui, environ)
            log.info('%s action on Git repo "%s" by "%s" from %s', action,
                     str_repo_name, safe_str(user.username), ip_addr)
            app = self.__make_app(repo_name, repo_path, extras)
            result = app(environ, start_response)
            if action == 'push':
                result = WSGIResultCloseCallback(
                    result, lambda: self._invalidate_cache(repo_name))
            return result
        except HTTPLockedRC as e:
            log.debug('Locked, response %s: %s', e.code, e.title)
            return e(environ, start_response)
        except Exception:
            log.error(traceback.format_exc())
            return HTTPInternalServerError()(environ, start_response)
Exemple #7
0
    def _handle_request(self, environ, start_response):
        if not is_git(environ):
            return self.application(environ, start_response)
        if not self._check_ssl(environ):
            return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        username = None
        self._git_first_op = False
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            repo_name = self.__get_repository(environ)
            log.debug('Extracted repo name is %s' % repo_name)
        except Exception:
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'git'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        action = self.__get_action(environ)

        #======================================================================
        # CHECK ANONYMOUS PERMISSION
        #======================================================================
        if action in ['pull', 'push']:
            anonymous_user = self.__get_user('default')
            username = anonymous_user.username
            if anonymous_user.active:
                # ONLY check permissions if the user is activated
                anonymous_perm = self._check_permission(
                    action, anonymous_user, repo_name, ip_addr)
            else:
                anonymous_perm = False

            if not anonymous_user.active or not anonymous_perm:
                if not anonymous_user.active:
                    log.debug('Anonymous access is disabled, running '
                              'authentication')

                if not anonymous_perm:
                    log.debug('Not enough credentials to access this '
                              'repository as anonymous user')

                username = None
                #==============================================================
                # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
                # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
                #==============================================================

                # try to auth based on environ, container auth methods
                log.debug(
                    'Running PRE-AUTH for container based authentication')
                pre_auth = auth_modules.authenticate('', '', environ)
                if pre_auth and pre_auth.get('username'):
                    username = pre_auth['username']
                log.debug('PRE-AUTH got %s as username' % username)

                # If not authenticated by the container, running basic auth
                if not username:
                    self.authenticate.realm = \
                        safe_str(self.config['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
                #==============================================================
                try:
                    user = self.__get_user(username)
                    if user is None or not user.active:
                        return HTTPForbidden()(environ, start_response)
                    username = user.username
                except Exception:
                    log.error(traceback.format_exc())
                    return HTTPInternalServerError()(environ, start_response)

                #check permissions for this repository
                perm = self._check_permission(action, user, repo_name, ip_addr)
                if not perm:
                    return HTTPForbidden()(environ, start_response)

        # extras are injected into UI object and later available
        # in hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': username,
            'action': action,
            'repository': repo_name,
            'scm': 'git',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }

        #===================================================================
        # GIT REQUEST HANDLING
        #===================================================================
        str_repo_name = safe_str(repo_name)
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
        log.debug('Repository path is %s' % repo_path)

        # CHECK LOCKING only if it's not ANONYMOUS USER
        if username != User.DEFAULT_USER:
            log.debug('Checking locking on repository')
            (make_lock, locked,
             locked_by) = self._check_locking_state(environ=environ,
                                                    action=action,
                                                    repo=repo_name,
                                                    user_id=user.user_id)
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock, 'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s' % extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            self._handle_githooks(repo_name, action, baseui, environ)
            log.info('%s action on Git repo "%s" by "%s" from %s' %
                     (action, str_repo_name, safe_str(username), ip_addr))
            app = self.__make_app(repo_name, repo_path, extras)
            return app(environ, start_response)
        except HTTPLockedRC, e:
            _code = CONFIG.get('lock_ret_code')
            log.debug('Repository LOCKED ret code %s!' % (_code))
            return e(environ, start_response)
Exemple #8
0
    def _handle_request(self, environ, start_response):
        if not is_mercurial(environ):
            return self.application(environ, start_response)

        ip_addr = self._get_ip_addr(environ)
        # skip passing error to error controller
        environ['pylons.status_code_redirect'] = True

        #======================================================================
        # EXTRACT REPOSITORY NAME FROM ENV
        #======================================================================
        try:
            str_repo_name = environ['REPO_NAME'] = self.__get_repository(
                environ)
            assert isinstance(str_repo_name, str), str_repo_name
            repo_name = safe_unicode(str_repo_name)
            assert safe_str(repo_name) == str_repo_name, (str_repo_name,
                                                          repo_name)
            log.debug('Extracted repo name is %s', repo_name)
        except Exception as e:
            log.error('error extracting repo_name: %r', e)
            return HTTPInternalServerError()(environ, start_response)

        # quick check if that dir exists...
        if not is_valid_repo(repo_name, self.basepath, 'hg'):
            return HTTPNotFound()(environ, start_response)

        #======================================================================
        # GET ACTION PULL or PUSH
        #======================================================================
        try:
            action = self.__get_action(environ)
        except HTTPBadRequest as e:
            return e(environ, start_response)

        #======================================================================
        # CHECK PERMISSIONS
        #======================================================================
        user, response_app = self._authorize(environ, start_response, action,
                                             repo_name, ip_addr)
        if response_app is not None:
            return response_app(environ, start_response)

        # extras are injected into mercurial UI object and later available
        # in hg hooks executed by kallithea
        from kallithea import CONFIG
        server_url = get_server_url(environ)
        extras = {
            'ip': ip_addr,
            'username': user.username,
            'action': action,
            'repository': repo_name,
            'scm': 'hg',
            'config': CONFIG['__file__'],
            'server_url': server_url,
            'make_lock': None,
            'locked_by': [None, None]
        }
        #======================================================================
        # MERCURIAL REQUEST HANDLING
        #======================================================================
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
        log.debug('Repository path is %s', repo_path)

        # A Mercurial HTTP server will see listkeys operations (bookmarks,
        # phases and obsolescence marker) in a different request - we don't
        # want to check locking on those
        if environ['QUERY_STRING'] == 'cmd=listkeys':
            pass
        # CHECK LOCKING only if it's not ANONYMOUS USER
        elif not user.is_default_user:
            log.debug('Checking locking on repository')
            make_lock, locked, locked_by = check_locking_state(
                action, repo_name, user)
            # store the make_lock for later evaluation in hooks
            extras.update({'make_lock': make_lock, 'locked_by': locked_by})

        fix_PATH()
        log.debug('HOOKS extras is %s', extras)
        baseui = make_ui('db')
        self.__inject_extras(repo_path, baseui, extras)

        try:
            log.info('%s action on Mercurial repo "%s" by "%s" from %s',
                     action, str_repo_name, safe_str(user.username), ip_addr)
            app = self.__make_app(repo_path, baseui, extras)
            result = app(environ, start_response)
            if action == 'push':
                result = WSGIResultCloseCallback(
                    result, lambda: self._invalidate_cache(repo_name))
            return result
        except RepoError as e:
            if str(e).find('not found') != -1:
                return HTTPNotFound()(environ, start_response)
        except HTTPLockedRC as e:
            # Before Mercurial 3.6, lock exceptions were caught here
            log.debug('Locked, response %s: %s', e.code, e.title)
            return e(environ, start_response)
        except Exception:
            log.error(traceback.format_exc())
            return HTTPInternalServerError()(environ, start_response)