Mercurial > kallithea
comparison rhodecode/lib/base.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl
Imported some of the GPLv3'd changes from RhodeCode v2.2.5.
This imports changes between changesets 21af6c4eab3d and 6177597791c2 in
RhodeCode's original repository, including only changes to Python files and HTML.
RhodeCode clearly licensed its changes to these files under GPLv3
in their /LICENSE file, which states the following:
The Python code and integrated HTML are licensed under the GPLv3 license.
(See:
https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE
or
http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE
for an online copy of that LICENSE file)
Conservancy reviewed these changes and confirmed that they can be licensed as
a whole to the Kallithea project under GPLv3-only.
While some of the contents committed herein are clearly licensed
GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the
statement above from RhodeCode indicates that they intend GPLv3-only as their
license, per GPLv3ยง14 and other relevant sections of GPLv3.
author | Bradley M. Kuhn <bkuhn@sfconservancy.org> |
---|---|
date | Wed, 02 Jul 2014 19:03:13 -0400 |
parents | a5888ca796b5 |
children | 7e5f8c12a3fc |
comparison
equal
deleted
inserted
replaced
4115:8b7294a804a0 | 4116:ffd45b185016 |
---|---|
1 """The base Controller API | 1 # -*- coding: utf-8 -*- |
2 | 2 # This program is free software: you can redistribute it and/or modify |
3 Provides the BaseController class for subclassing. | 3 # it under the terms of the GNU General Public License as published by |
4 # the Free Software Foundation, either version 3 of the License, or | |
5 # (at your option) any later version. | |
6 # | |
7 # This program is distributed in the hope that it will be useful, | |
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 # GNU General Public License for more details. | |
11 # | |
12 # You should have received a copy of the GNU General Public License | |
13 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
14 | |
4 """ | 15 """ |
16 rhodecode.lib.base | |
17 ~~~~~~~~~~~~~~~~~~ | |
18 | |
19 The base Controller API | |
20 Provides the BaseController class for subclassing. And usage in different | |
21 controllers | |
22 | |
23 :created_on: Oct 06, 2010 | |
24 :author: marcink | |
25 :copyright: (c) 2013 RhodeCode GmbH. | |
26 :license: GPLv3, see LICENSE for more details. | |
27 """ | |
28 | |
5 import logging | 29 import logging |
6 import time | 30 import time |
7 import traceback | 31 import traceback |
8 | 32 |
9 from paste.auth.basic import AuthBasicAuthenticator | 33 from paste.auth.basic import AuthBasicAuthenticator |
11 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION | 35 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION |
12 | 36 |
13 from pylons import config, tmpl_context as c, request, session, url | 37 from pylons import config, tmpl_context as c, request, session, url |
14 from pylons.controllers import WSGIController | 38 from pylons.controllers import WSGIController |
15 from pylons.controllers.util import redirect | 39 from pylons.controllers.util import redirect |
16 from pylons.templating import render_mako as render | 40 from pylons.templating import render_mako as render # don't remove this import |
17 | 41 |
18 from rhodecode import __version__, BACKENDS | 42 from rhodecode import __version__, BACKENDS |
19 | 43 |
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ | 44 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ |
21 safe_str, safe_int | 45 safe_str, safe_int |
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ | 46 from rhodecode.lib import auth_modules |
23 HasPermissionAnyMiddleware, CookieStoreWrapper | 47 from rhodecode.lib.auth import AuthUser, HasPermissionAnyMiddleware, CookieStoreWrapper |
24 from rhodecode.lib.utils import get_repo_slug | 48 from rhodecode.lib.utils import get_repo_slug |
25 from rhodecode.lib.exceptions import UserCreationError | 49 from rhodecode.lib.exceptions import UserCreationError |
26 from rhodecode.model import meta | 50 from rhodecode.model import meta |
27 | 51 |
28 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting | 52 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting |
98 return self.build_authentication() | 122 return self.build_authentication() |
99 auth = auth.strip().decode('base64') | 123 auth = auth.strip().decode('base64') |
100 _parts = auth.split(':', 1) | 124 _parts = auth.split(':', 1) |
101 if len(_parts) == 2: | 125 if len(_parts) == 2: |
102 username, password = _parts | 126 username, password = _parts |
103 if self.authfunc(environ, username, password): | 127 if self.authfunc(username, password, environ): |
104 return username | 128 return username |
105 return self.build_authentication() | 129 return self.build_authentication() |
106 | 130 |
107 __call__ = authenticate | 131 __call__ = authenticate |
108 | 132 |
112 def __init__(self, application, config): | 136 def __init__(self, application, config): |
113 self.application = application | 137 self.application = application |
114 self.config = config | 138 self.config = config |
115 # base path of repo locations | 139 # base path of repo locations |
116 self.basepath = self.config['base_path'] | 140 self.basepath = self.config['base_path'] |
117 #authenticate this mercurial request using authfunc | 141 #authenticate this VCS request using authfunc |
118 self.authenticate = BasicAuth('', authfunc, | 142 self.authenticate = BasicAuth('', auth_modules.authenticate, |
119 config.get('auth_ret_code')) | 143 config.get('auth_ret_code')) |
120 self.ip_addr = '0.0.0.0' | 144 self.ip_addr = '0.0.0.0' |
121 | 145 |
122 def _handle_request(self, environ, start_response): | 146 def _handle_request(self, environ, start_response): |
123 raise NotImplementedError() | 147 raise NotImplementedError() |
127 Gets a special pattern _<ID> from clone url and tries to replace it | 151 Gets a special pattern _<ID> from clone url and tries to replace it |
128 with a repository_name for support of _<ID> non changable urls | 152 with a repository_name for support of _<ID> non changable urls |
129 | 153 |
130 :param repo_name: | 154 :param repo_name: |
131 """ | 155 """ |
132 try: | 156 |
133 data = repo_name.split('/') | 157 data = repo_name.split('/') |
134 if len(data) >= 2: | 158 if len(data) >= 2: |
135 by_id = data[1].split('_') | 159 from rhodecode.lib.utils import get_repo_by_id |
136 if len(by_id) == 2 and by_id[1].isdigit(): | 160 by_id_match = get_repo_by_id(repo_name) |
137 _repo_name = Repository.get(by_id[1]).repo_name | 161 if by_id_match: |
138 data[1] = _repo_name | 162 data[1] = by_id_match |
139 except Exception: | |
140 log.debug('Failed to extract repo_name from id %s' % ( | |
141 traceback.format_exc() | |
142 ) | |
143 ) | |
144 | 163 |
145 return '/'.join(data) | 164 return '/'.join(data) |
146 | 165 |
147 def _invalidate_cache(self, repo_name): | 166 def _invalidate_cache(self, repo_name): |
148 """ | 167 """ |
159 | 178 |
160 :param action: push or pull action | 179 :param action: push or pull action |
161 :param user: user instance | 180 :param user: user instance |
162 :param repo_name: repository name | 181 :param repo_name: repository name |
163 """ | 182 """ |
164 #check IP | 183 # check IP |
165 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr) | 184 inherit = user.inherit_default_permissions |
166 if not authuser.ip_allowed: | 185 ip_allowed = AuthUser.check_ip_allowed(user.user_id, ip_addr, |
186 inherit_from_default=inherit) | |
187 if ip_allowed: | |
188 log.info('Access for IP:%s allowed' % (ip_addr,)) | |
189 else: | |
167 return False | 190 return False |
168 else: | 191 |
169 log.info('Access for IP:%s allowed' % (ip_addr)) | |
170 if action == 'push': | 192 if action == 'push': |
171 if not HasPermissionAnyMiddleware('repository.write', | 193 if not HasPermissionAnyMiddleware('repository.write', |
172 'repository.admin')(user, | 194 'repository.admin')(user, |
173 repo_name): | 195 repo_name): |
174 return False | 196 return False |
259 def __before__(self): | 281 def __before__(self): |
260 """ | 282 """ |
261 __before__ is called before controller methods and after __call__ | 283 __before__ is called before controller methods and after __call__ |
262 """ | 284 """ |
263 c.rhodecode_version = __version__ | 285 c.rhodecode_version = __version__ |
264 c.rhodecode_instanceid = config.get('instance_id') | 286 rc_config = RhodeCodeSetting.get_app_settings() |
265 c.rhodecode_name = config.get('rhodecode_title') | 287 |
266 c.rhodecode_bugtracker = config.get('bugtracker', 'http://bitbucket.org/marcinkuzminski/rhodecode/issues') | |
267 c.use_gravatar = str2bool(config.get('use_gravatar')) | |
268 c.ga_code = config.get('rhodecode_ga_code') | |
269 # Visual options | 288 # Visual options |
270 c.visual = AttributeDict({}) | 289 c.visual = AttributeDict({}) |
271 rc_config = RhodeCodeSetting.get_app_settings() | 290 |
272 ## DB stored | 291 ## DB stored |
273 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon')) | 292 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon')) |
274 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon')) | 293 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon')) |
275 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags')) | 294 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags')) |
276 c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100)) | 295 c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100)) |
296 c.visual.admin_grid_items = safe_int(rc_config.get('rhodecode_admin_grid_items', 100)) | |
277 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) | 297 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) |
278 c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version')) | 298 c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version')) |
299 c.visual.use_gravatar = str2bool(rc_config.get('rhodecode_use_gravatar')) | |
300 c.visual.gravatar_url = rc_config.get('rhodecode_gravatar_url') | |
301 | |
302 c.ga_code = rc_config.get('rhodecode_ga_code') | |
303 c.rhodecode_name = rc_config.get('rhodecode_title') | |
304 c.clone_uri_tmpl = rc_config.get('rhodecode_clone_uri_tmpl') | |
279 | 305 |
280 ## INI stored | 306 ## INI stored |
281 self.cut_off_limit = int(config.get('cut_off_limit')) | |
282 c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True)) | 307 c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True)) |
283 c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True)) | 308 c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True)) |
309 | |
310 c.rhodecode_instanceid = config.get('instance_id') | |
311 c.rhodecode_bugtracker = config.get('bugtracker', url('rc_issue_tracker')) | |
312 # END CONFIG VARS | |
284 | 313 |
285 c.repo_name = get_repo_slug(request) # can be empty | 314 c.repo_name = get_repo_slug(request) # can be empty |
286 c.backends = BACKENDS.keys() | 315 c.backends = BACKENDS.keys() |
287 c.unread_notifications = NotificationModel()\ | 316 c.unread_notifications = NotificationModel()\ |
288 .get_unread_cnt_for_user(c.rhodecode_user.user_id) | 317 .get_unread_cnt_for_user(c.rhodecode_user.user_id) |
318 | |
319 self.cut_off_limit = safe_int(config.get('cut_off_limit')) | |
289 self.sa = meta.Session | 320 self.sa = meta.Session |
290 self.scm_model = ScmModel(self.sa) | 321 self.scm_model = ScmModel(self.sa) |
291 | 322 |
292 def __call__(self, environ, start_response): | 323 def __call__(self, environ, start_response): |
293 """Invoke the Controller""" | 324 """Invoke the Controller""" |
296 # available in environ['pylons.routes_dict'] | 327 # available in environ['pylons.routes_dict'] |
297 try: | 328 try: |
298 self.ip_addr = _get_ip_addr(environ) | 329 self.ip_addr = _get_ip_addr(environ) |
299 # make sure that we update permissions each time we call controller | 330 # make sure that we update permissions each time we call controller |
300 api_key = request.GET.get('api_key') | 331 api_key = request.GET.get('api_key') |
301 cookie_store = CookieStoreWrapper(session.get('rhodecode_user')) | 332 |
302 user_id = cookie_store.get('user_id', None) | 333 if api_key: |
303 username = get_container_username(environ, config) | 334 # when using API_KEY we are sure user exists. |
304 try: | 335 auth_user = AuthUser(api_key=api_key, ip_addr=self.ip_addr) |
305 auth_user = AuthUser(user_id, api_key, username, self.ip_addr) | 336 authenticated = False |
306 except UserCreationError, e: | 337 else: |
307 from rhodecode.lib import helpers as h | 338 cookie_store = CookieStoreWrapper(session.get('rhodecode_user')) |
308 h.flash(e, 'error') | 339 try: |
309 # container auth or other auth functions that create users on | 340 auth_user = AuthUser(user_id=cookie_store.get('user_id', None), |
310 # the fly can throw this exception signaling that there's issue | 341 ip_addr=self.ip_addr) |
311 # with user creation, explanation should be provided in | 342 except UserCreationError, e: |
312 # Exception itself | 343 from rhodecode.lib import helpers as h |
313 auth_user = AuthUser(ip_addr=self.ip_addr) | 344 h.flash(e, 'error') |
314 | 345 # container auth or other auth functions that create users on |
346 # the fly can throw this exception signaling that there's issue | |
347 # with user creation, explanation should be provided in | |
348 # Exception itself | |
349 auth_user = AuthUser(ip_addr=self.ip_addr) | |
350 | |
351 authenticated = cookie_store.get('is_authenticated') | |
352 | |
353 if not auth_user.is_authenticated and auth_user.user_id is not None: | |
354 # user is not authenticated and not empty | |
355 auth_user.set_authenticated(authenticated) | |
315 request.user = auth_user | 356 request.user = auth_user |
357 #set globals for auth user | |
316 self.rhodecode_user = c.rhodecode_user = auth_user | 358 self.rhodecode_user = c.rhodecode_user = auth_user |
317 if not self.rhodecode_user.is_authenticated and \ | |
318 self.rhodecode_user.user_id is not None: | |
319 self.rhodecode_user.set_authenticated( | |
320 cookie_store.get('is_authenticated') | |
321 ) | |
322 log.info('IP: %s User: %s accessed %s' % ( | 359 log.info('IP: %s User: %s accessed %s' % ( |
323 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ))) | 360 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ))) |
324 ) | 361 ) |
325 return WSGIController.__call__(self, environ, start_response) | 362 return WSGIController.__call__(self, environ, start_response) |
326 finally: | 363 finally: |
339 c.repository_following: weather the current user is following the current repo | 376 c.repository_following: weather the current user is following the current repo |
340 """ | 377 """ |
341 | 378 |
342 def __before__(self): | 379 def __before__(self): |
343 super(BaseRepoController, self).__before__() | 380 super(BaseRepoController, self).__before__() |
344 if c.repo_name: | 381 if c.repo_name: # extracted from routes |
345 | 382 _dbr = Repository.get_by_repo_name(c.repo_name) |
346 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) | 383 if not _dbr: |
384 return | |
385 | |
386 log.debug('Found repository in database %s with state `%s`' | |
387 % (safe_unicode(_dbr), safe_unicode(_dbr.repo_state))) | |
388 route = getattr(request.environ.get('routes.route'), 'name', '') | |
389 | |
390 # allow to delete repos that are somehow damages in filesystem | |
391 if route in ['delete_repo']: | |
392 return | |
393 | |
394 if _dbr.repo_state in [Repository.STATE_PENDING]: | |
395 if route in ['repo_creating_home']: | |
396 return | |
397 check_url = url('repo_creating_home', repo_name=c.repo_name) | |
398 return redirect(check_url) | |
399 | |
400 dbr = c.rhodecode_db_repo = _dbr | |
347 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance | 401 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance |
348 # update last change according to VCS data | |
349 dbr.update_changeset_cache(dbr.get_changeset()) | |
350 if c.rhodecode_repo is None: | 402 if c.rhodecode_repo is None: |
351 log.error('%s this repository is present in database but it ' | 403 log.error('%s this repository is present in database but it ' |
352 'cannot be created as an scm instance', c.repo_name) | 404 'cannot be created as an scm instance', c.repo_name) |
353 | 405 |
354 redirect(url('home')) | 406 redirect(url('home')) |
407 | |
408 # update last change according to VCS data | |
409 dbr.update_changeset_cache(dbr.get_changeset()) | |
355 | 410 |
356 # some globals counter for menu | 411 # some globals counter for menu |
357 c.repository_followers = self.scm_model.get_followers(dbr) | 412 c.repository_followers = self.scm_model.get_followers(dbr) |
358 c.repository_forks = self.scm_model.get_forks(dbr) | 413 c.repository_forks = self.scm_model.get_forks(dbr) |
359 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) | 414 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) |
360 c.repository_following = self.scm_model.is_following_repo(c.repo_name, | 415 c.repository_following = self.scm_model.is_following_repo( |
361 self.rhodecode_user.user_id) | 416 c.repo_name, self.rhodecode_user.user_id) |