##// END OF EJS Templates
old style: make compare header expand to content
old style: make compare header expand to content

File last commit:

r4116:ffd45b18 rhodecode-2.2.5-gpl
r4152:8d1125a4 rhodecode-2.2.5-gpl
Show More
base.py
416 lines | 16.0 KiB | text/x-python | PythonLexer
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 # -*- coding: utf-8 -*-
# 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, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
renamed project to rhodecode
r547
"""
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 rhodecode.lib.base
~~~~~~~~~~~~~~~~~~
The base Controller API
Provides the BaseController class for subclassing. And usage in different
controllers
:created_on: Oct 06, 2010
:author: marcink
:copyright: (c) 2013 RhodeCode GmbH.
:license: GPLv3, see LICENSE for more details.
"""
Fixes issue #201...
r1373 import logging
Added Request time tracking
r1601 import time
implements #285: Implemented non changeable urls for clone url, and web views
r1813 import traceback
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761
from paste.auth.basic import AuthBasicAuthenticator
Alternative HTTP response codes when client failed to Authenticate correctly
r2132 from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden
patched basic auth function to overcome git issues with proxy that doesn't send both username and password. ref #586
r2912 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761
Fixes issue #201...
r1373 from pylons import config, tmpl_context as c, request, session, url
renamed project to rhodecode
r547 from pylons.controllers import WSGIController
Fixes issue #201...
r1373 from pylons.controllers.util import redirect
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 from pylons.templating import render_mako as render # don't remove this import
gui-improvments
r1304
reduce cookie size for better support of client side sessions
r1718 from rhodecode import __version__, BACKENDS
Implemented basic locking functionality....
r2726 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
added option to ini file to define lightweight dashboard items per page before pagination
r3087 safe_str, safe_int
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 from rhodecode.lib import auth_modules
from rhodecode.lib.auth import AuthUser, HasPermissionAnyMiddleware, CookieStoreWrapper
removed duplicated logic of how we invalidate caches for repos
r3693 from rhodecode.lib.utils import get_repo_slug
Added pre-create user hook....
r4074 from rhodecode.lib.exceptions import UserCreationError
renamed project to rhodecode
r547 from rhodecode.model import meta
reduce cookie size for better support of client side sessions
r1718
don't use config for visual settings. It totally doesn't work on multi instance mode
r2955 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting
#302 - basic notification system, models+tests
r1702 from rhodecode.model.notification import NotificationModel
reduce cookie size for better support of client side sessions
r1718 from rhodecode.model.scm import ScmModel
Implemented basic locking functionality....
r2726 from rhodecode.model.meta import Session
Moved out reposcan into hg Model....
r665
Fixes issue #201...
r1373 log = logging.getLogger(__name__)
pep8ify
r1307
implements #285: Implemented non changeable urls for clone url, and web views
r1813
fixed multiple IP addresses in each of extracted IP....
r3669 def _filter_proxy(ip):
"""
Mads Kiilerich
Use space after , in lists
r3987 HEADERS can have multiple ips inside the left-most being the original
fixed multiple IP addresses in each of extracted IP....
r3669 client, and each successive proxy that passed the request adding the IP
address where it received the request from.
:param ip:
"""
if ',' in ip:
_ips = ip.split(',')
_first_ip = _ips[0].strip()
log.debug('Got multiple IPs %s, using %s' % (','.join(_ips), _first_ip))
return _first_ip
return ip
Add ip reference into BaseController
r2374 def _get_ip_addr(environ):
proxy_key = 'HTTP_X_REAL_IP'
proxy_key2 = 'HTTP_X_FORWARDED_FOR'
def_key = 'REMOTE_ADDR'
fix multiple ips addresses in X_FORWARDER_FOR header
r3153 ip = environ.get(proxy_key)
add IP into base logging, and change a little IP extraction login, if some header is passed as empty
r2486 if ip:
fixed multiple IP addresses in each of extracted IP....
r3669 return _filter_proxy(ip)
add IP into base logging, and change a little IP extraction login, if some header is passed as empty
r2486
fix multiple ips addresses in X_FORWARDER_FOR header
r3153 ip = environ.get(proxy_key2)
add IP into base logging, and change a little IP extraction login, if some header is passed as empty
r2486 if ip:
fixed multiple IP addresses in each of extracted IP....
r3669 return _filter_proxy(ip)
add IP into base logging, and change a little IP extraction login, if some header is passed as empty
r2486
ip = environ.get(def_key, '0.0.0.0')
fixed multiple IP addresses in each of extracted IP....
r3669 return _filter_proxy(ip)
Add ip reference into BaseController
r2374
better path extraction method....
r2490 def _get_access_path(environ):
path = environ.get('PATH_INFO')
org_req = environ.get('pylons.original_request')
if org_req:
path = org_req.environ.get('PATH_INFO')
return path
Alternative HTTP response codes when client failed to Authenticate correctly
r2132 class BasicAuth(AuthBasicAuthenticator):
def __init__(self, realm, authfunc, auth_http_code=None):
self.realm = realm
self.authfunc = authfunc
self._rc_auth_http_code = auth_http_code
def build_authentication(self):
head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
if self._rc_auth_http_code and self._rc_auth_http_code == '403':
# return 403 if alternative http return code is specified in
# RhodeCode config
return HTTPForbidden(headers=head)
return HTTPUnauthorized(headers=head)
patched basic auth function to overcome git issues with proxy that doesn't send both username and password. ref #586
r2912 def authenticate(self, environ):
authorization = AUTHORIZATION(environ)
if not authorization:
return self.build_authentication()
(authmeth, auth) = authorization.split(' ', 1)
if 'basic' != authmeth.lower():
return self.build_authentication()
auth = auth.strip().decode('base64')
_parts = auth.split(':', 1)
if len(_parts) == 2:
username, password = _parts
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 if self.authfunc(username, password, environ):
patched basic auth function to overcome git issues with proxy that doesn't send both username and password. ref #586
r2912 return username
return self.build_authentication()
__call__ = authenticate
Alternative HTTP response codes when client failed to Authenticate correctly
r2132
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 class BaseVCSController(object):
implements #285: Implemented non changeable urls for clone url, and web views
r1813
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 def __init__(self, application, config):
self.application = application
self.config = config
# base path of repo locations
self.basepath = self.config['base_path']
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 #authenticate this VCS request using authfunc
self.authenticate = BasicAuth('', auth_modules.authenticate,
Alternative HTTP response codes when client failed to Authenticate correctly
r2132 config.get('auth_ret_code'))
Added UserIpMap interface for allowed IP addresses and IP restriction access...
r3125 self.ip_addr = '0.0.0.0'
implements #285: Implemented non changeable urls for clone url, and web views
r1813
code garden, pep8
r1978 def _handle_request(self, environ, start_response):
raise NotImplementedError()
implements #285: Implemented non changeable urls for clone url, and web views
r1813 def _get_by_id(self, repo_name):
"""
Fixed spelling of get's to gets
r4089 Gets a special pattern _<ID> from clone url and tries to replace it
implements #285: Implemented non changeable urls for clone url, and web views
r1813 with a repository_name for support of _<ID> non changable urls
:param repo_name:
"""
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116
data = repo_name.split('/')
if len(data) >= 2:
from rhodecode.lib.utils import get_repo_by_id
by_id_match = get_repo_by_id(repo_name)
if by_id_match:
data[1] = by_id_match
implements #285: Implemented non changeable urls for clone url, and web views
r1813
return '/'.join(data)
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 def _invalidate_cache(self, repo_name):
"""
Set's cache for this repository for invalidation on next access
implements #285: Implemented non changeable urls for clone url, and web views
r1813
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 :param repo_name: full repo name, also a cache key
"""
removed duplicated logic of how we invalidate caches for repos
r3693 ScmModel().mark_for_invalidation(repo_name)
implements #285: Implemented non changeable urls for clone url, and web views
r1813
Added UserIpMap interface for allowed IP addresses and IP restriction access...
r3125 def _check_permission(self, action, user, repo_name, ip_addr=None):
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 """
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
"""
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 # check IP
inherit = user.inherit_default_permissions
ip_allowed = AuthUser.check_ip_allowed(user.user_id, ip_addr,
inherit_from_default=inherit)
if ip_allowed:
log.info('Access for IP:%s allowed' % (ip_addr,))
else:
Added UserIpMap interface for allowed IP addresses and IP restriction access...
r3125 return False
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 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
implements #285: Implemented non changeable urls for clone url, and web views
r1813 return True
Added HTTP_X_FORWARDED_FOR as another method of extracting IP for pull/push logs....
r2184 def _get_ip_addr(self, environ):
Add ip reference into BaseController
r2374 return _get_ip_addr(environ)
Added HTTP_X_FORWARDED_FOR as another method of extracting IP for pull/push logs....
r2184
Implementes #509 require SSL flag now works for both git and mercurial....
r2668 def _check_ssl(self, environ, start_response):
"""
Checks the SSL check flag and returns False if SSL is not present
and required True otherwise
"""
org_proto = environ['wsgi._org_proto']
#check if we have SSL required ! if not it's a bad request !
Added form for controlling mercurial extensions...
r2708 require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value)
Implementes #509 require SSL flag now works for both git and mercurial....
r2668 if require_ssl and org_proto == 'http':
log.debug('proto is %s and SSL is required BAD REQUEST !'
% org_proto)
return False
merged + fixed pull request #62: Implemented metatags and visualisation options....
r2674 return True
Implementes #509 require SSL flag now works for both git and mercurial....
r2668
Implemented basic locking functionality....
r2726 def _check_locking_state(self, environ, action, repo, user_id):
"""
Checks locking on this repository, if locking is enabled and lock is
present returns a tuple of make_lock, locked, locked_by.
make_lock can have 3 states None (do nothing) True, make lock
False release lock, This value is later propagated to hooks, which
do the locking. Think about this as signals passed to hooks what to do.
"""
added new suite of tests for VCS operations...
r2752 locked = False # defines that locked error should be thrown to user
Implemented basic locking functionality....
r2726 make_lock = None
repo = Repository.get_by_repo_name(repo)
user = User.get(user_id)
# this is kind of hacky, but due to how mercurial handles client-server
# server see all operation on changeset; bookmarks, phases and
# obsolescence marker in different transaction, we don't want to check
# locking on those
obsolete_call = environ['QUERY_STRING'] in ['cmd=listkeys',]
locked_by = repo.locked
if repo and repo.enable_locking and not obsolete_call:
if action == 'push':
#check if it's already locked !, if it is compare users
user_id, _date = repo.locked
if user.user_id == user_id:
added new suite of tests for VCS operations...
r2752 log.debug('Got push from user %s, now unlocking' % (user))
Implemented basic locking functionality....
r2726 # unlock if we have push from user who locked
make_lock = False
else:
# we're not the same user who locked, ban with 423 !
locked = True
if action == 'pull':
if repo.locked[0] and repo.locked[1]:
locked = True
else:
log.debug('Setting lock on repo %s by %s' % (repo, user))
make_lock = True
else:
log.debug('Repository %s do not have locking enabled' % (repo))
added new suite of tests for VCS operations...
r2752 log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
% (make_lock, locked, locked_by))
Implemented basic locking functionality....
r2726 return make_lock, locked, locked_by
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 def __call__(self, environ, start_response):
start = time.time()
try:
return self._handle_request(environ, start_response)
finally:
logger name update
r1763 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
Wrapped calls for git and hg middleware in extra block that clears db Session....
r1761 log.debug('Request time: %.3fs' % (time.time() - start))
meta.Session.remove()
renamed project to rhodecode
r547 class BaseController(WSGIController):
extended repo creation by repo type. fixed fork creation to maintain repo type.
r659
renamed project to rhodecode
r547 def __before__(self):
Added UserIpMap interface for allowed IP addresses and IP restriction access...
r3125 """
__before__ is called before controller methods and after __call__
"""
renamed hg_app to rhodecode
r548 c.rhodecode_version = __version__
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 rc_config = RhodeCodeSetting.get_app_settings()
merged + fixed pull request #62: Implemented metatags and visualisation options....
r2674 # Visual options
c.visual = AttributeDict({})
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116
added dashboard items config in visual settings
r3904 ## DB stored
don't use config for visual settings. It totally doesn't work on multi instance mode
r2955 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
added dashboard items config in visual settings
r3904 c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100))
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 c.visual.admin_grid_items = safe_int(rc_config.get('rhodecode_admin_grid_items', 100))
repository extra fields implementation...
r3308 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
Implements #842 RhodeCode version disclosure....
r3910 c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version'))
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 c.visual.use_gravatar = str2bool(rc_config.get('rhodecode_use_gravatar'))
c.visual.gravatar_url = rc_config.get('rhodecode_gravatar_url')
c.ga_code = rc_config.get('rhodecode_ga_code')
c.rhodecode_name = rc_config.get('rhodecode_title')
c.clone_uri_tmpl = rc_config.get('rhodecode_clone_uri_tmpl')
Implements #842 RhodeCode version disclosure....
r3910
added dashboard items config in visual settings
r3904 ## INI stored
Added flag to controll option for changing the repos path location...
r3920 c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True))
Add ini option to controll custom advanced hooks settings
r4045 c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True))
added dashboard items config in visual settings
r3904
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 c.rhodecode_instanceid = config.get('instance_id')
c.rhodecode_bugtracker = config.get('bugtracker', url('rc_issue_tracker'))
# END CONFIG VARS
show only open pull requests in the counter, and use repo context bar in pull requests view
r3580 c.repo_name = get_repo_slug(request) # can be empty
extended repo creation by repo type. fixed fork creation to maintain repo type.
r659 c.backends = BACKENDS.keys()
#302 - basic notification system, models+tests
r1702 c.unread_notifications = NotificationModel()\
.get_unread_cnt_for_user(c.rhodecode_user.user_id)
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116
self.cut_off_limit = safe_int(config.get('cut_off_limit'))
commit less models...
r1749 self.sa = meta.Session
another major codes rewrite:...
r1045 self.scm_model = ScmModel(self.sa)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
renamed project to rhodecode
r547 def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
try:
Add ip reference into BaseController
r2374 self.ip_addr = _get_ip_addr(environ)
Some code cleanups and fixes
r1628 # make sure that we update permissions each time we call controller
Major rewrite of auth objects. Moved parts of filling user data into user model....
r1117 api_key = request.GET.get('api_key')
Added pre-create user hook....
r4074
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 if api_key:
# when using API_KEY we are sure user exists.
auth_user = AuthUser(api_key=api_key, ip_addr=self.ip_addr)
authenticated = False
else:
cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
try:
auth_user = AuthUser(user_id=cookie_store.get('user_id', None),
ip_addr=self.ip_addr)
except UserCreationError, e:
from rhodecode.lib import helpers as h
h.flash(e, 'error')
# container auth or other auth functions that create users on
# the fly can throw this exception signaling that there's issue
# with user creation, explanation should be provided in
# Exception itself
auth_user = AuthUser(ip_addr=self.ip_addr)
authenticated = cookie_store.get('is_authenticated')
if not auth_user.is_authenticated and auth_user.user_id is not None:
# user is not authenticated and not empty
auth_user.set_authenticated(authenticated)
- fixes celery sqlalchemy session issues for async forking...
r1728 request.user = auth_user
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 #set globals for auth user
Some code cleanups and fixes
r1628 self.rhodecode_user = c.rhodecode_user = auth_user
add IP into base logging, and change a little IP extraction login, if some header is passed as empty
r2486 log.info('IP: %s User: %s accessed %s' % (
better path extraction method....
r2490 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
fixed logging issue on non-ascii repos
r2027 )
renamed project to rhodecode
r547 return WSGIController.__call__(self, environ, start_response)
finally:
meta.Session.remove()
another major codes rewrite:...
r1045
class BaseRepoController(BaseController):
"""
Some code cleanups and fixes
r1628 Base class for controllers responsible for loading all needed data for
repository loaded items are
source code cleanup: remove trailing white space, normalize file endings
r1203
Some code cleanups and fixes
r1628 c.rhodecode_repo: instance of scm repository
c.rhodecode_db_repo: instance of db
c.repository_followers: number of followers
c.repository_forks: number of forks
Leonardo
Adding the context bar too all pages related to a Repository....
r3527 c.repository_following: weather the current user is following the current repo
another major codes rewrite:...
r1045 """
def __before__(self):
super(BaseRepoController, self).__before__()
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 if c.repo_name: # extracted from routes
_dbr = Repository.get_by_repo_name(c.repo_name)
if not _dbr:
return
log.debug('Found repository in database %s with state `%s`'
% (safe_unicode(_dbr), safe_unicode(_dbr.repo_state)))
route = getattr(request.environ.get('routes.route'), 'name', '')
another major codes rewrite:...
r1045
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 # allow to delete repos that are somehow damages in filesystem
if route in ['delete_repo']:
return
if _dbr.repo_state in [Repository.STATE_PENDING]:
if route in ['repo_creating_home']:
return
check_url = url('repo_creating_home', repo_name=c.repo_name)
return redirect(check_url)
dbr = c.rhodecode_db_repo = _dbr
Fixes issue #201...
r1373 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
if c.rhodecode_repo is None:
log.error('%s this repository is present in database but it '
'cannot be created as an scm instance', c.repo_name)
fixed condition evaluated for gitrepo that returned null, simplified scm functions
r1282
Fixes issue #201...
r1373 redirect(url('home'))
gui-improvments
r1304
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 # update last change according to VCS data
dbr.update_changeset_cache(dbr.get_changeset())
- pull request generates overview based on it's params...
r2440 # some globals counter for menu
c.repository_followers = self.scm_model.get_followers(dbr)
c.repository_forks = self.scm_model.get_forks(dbr)
white space cleanup
r2478 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
Bradley M. Kuhn
Imported some of the GPLv3'd changes from RhodeCode v2.2.5....
r4116 c.repository_following = self.scm_model.is_following_repo(
c.repo_name, self.rhodecode_user.user_id)