Mercurial > kallithea
diff rhodecode/lib/base.py @ 2031:82a88013a3fd
merge 1.3 into stable
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 26 Feb 2012 17:25:09 +0200 |
parents | bdb6fbc8265f 61f9aeb2129e |
children | 79a95f338fd0 |
line wrap: on
line diff
--- a/rhodecode/lib/base.py Sun Feb 19 20:21:14 2012 +0200 +++ b/rhodecode/lib/base.py Sun Feb 26 17:25:09 2012 +0200 @@ -3,35 +3,125 @@ Provides the BaseController class for subclassing. """ import logging +import time +import traceback + +from paste.auth.basic import AuthBasicAuthenticator from pylons import config, tmpl_context as c, request, session, url from pylons.controllers import WSGIController from pylons.controllers.util import redirect from pylons.templating import render_mako as render -from rhodecode import __version__ -from rhodecode.lib import str2bool -from rhodecode.lib.auth import AuthUser -from rhodecode.lib.utils import get_repo_slug +from rhodecode import __version__, BACKENDS + +from rhodecode.lib import str2bool, safe_unicode +from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ + HasPermissionAnyMiddleware, CookieStoreWrapper +from rhodecode.lib.utils import get_repo_slug, invalidate_cache from rhodecode.model import meta + +from rhodecode.model.db import Repository +from rhodecode.model.notification import NotificationModel from rhodecode.model.scm import ScmModel -from rhodecode import BACKENDS -from rhodecode.model.db import Repository log = logging.getLogger(__name__) + +class BaseVCSController(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) + self.ipaddr = '0.0.0.0' + + def _handle_request(self, environ, start_response): + raise NotImplementedError() + + def _get_by_id(self, repo_name): + """ + Get's a special pattern _<ID> from clone url and tries to replace it + with a repository_name for support of _<ID> non changable urls + + :param repo_name: + """ + try: + data = repo_name.split('/') + if len(data) >= 2: + by_id = data[1].split('_') + if len(by_id) == 2 and by_id[1].isdigit(): + _repo_name = Repository.get(by_id[1]).repo_name + data[1] = _repo_name + except: + log.debug('Failed to extract repo_name from id %s' % ( + traceback.format_exc() + ) + ) + + return '/'.join(data) + + def _invalidate_cache(self, repo_name): + """ + Set's cache for this repository for invalidation on next access + + :param repo_name: full repo name, also a cache key + """ + invalidate_cache('get_repo_cached_%s' % repo_name) + + 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 __call__(self, environ, start_response): + start = time.time() + try: + return self._handle_request(environ, start_response) + finally: + log = logging.getLogger('rhodecode.' + self.__class__.__name__) + log.debug('Request time: %.3fs' % (time.time() - start)) + meta.Session.remove() + + class BaseController(WSGIController): def __before__(self): c.rhodecode_version = __version__ + c.rhodecode_instanceid = config.get('instance_id') c.rhodecode_name = config.get('rhodecode_title') c.use_gravatar = str2bool(config.get('use_gravatar')) c.ga_code = config.get('rhodecode_ga_code') c.repo_name = get_repo_slug(request) c.backends = BACKENDS.keys() + c.unread_notifications = NotificationModel()\ + .get_unread_cnt_for_user(c.rhodecode_user.user_id) self.cut_off_limit = int(config.get('cut_off_limit')) - self.sa = meta.Session() + self.sa = meta.Session self.scm_model = ScmModel(self.sa) def __call__(self, environ, start_response): @@ -39,18 +129,30 @@ # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] + start = time.time() try: - # putting this here makes sure that we update permissions each time + # make sure that we update permissions each time we call controller api_key = request.GET.get('api_key') - user_id = getattr(session.get('rhodecode_user'), 'user_id', None) - self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key) - self.rhodecode_user.set_authenticated( - getattr(session.get('rhodecode_user'), - 'is_authenticated', False)) - session['rhodecode_user'] = self.rhodecode_user - session.save() + cookie_store = CookieStoreWrapper(session.get('rhodecode_user')) + user_id = cookie_store.get('user_id', None) + username = get_container_username(environ, config) + + auth_user = AuthUser(user_id, api_key, username) + request.user = auth_user + self.rhodecode_user = c.rhodecode_user = auth_user + if not self.rhodecode_user.is_authenticated and \ + self.rhodecode_user.user_id is not None: + self.rhodecode_user.set_authenticated( + cookie_store.get('is_authenticated') + ) + log.info('User: %s accessed %s' % ( + auth_user, safe_unicode(environ.get('PATH_INFO'))) + ) return WSGIController.__call__(self, environ, start_response) finally: + log.info('Request to %s time: %.3fs' % ( + safe_unicode(environ.get('PATH_INFO')), time.time() - start) + ) meta.Session.remove() @@ -80,4 +182,3 @@ c.repository_followers = self.scm_model.get_followers(c.repo_name) c.repository_forks = self.scm_model.get_forks(c.repo_name) -