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)
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)
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)
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)
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)
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)
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)