##// END OF EJS Templates
feat(2fa): Added 2fa option. Fixes: RCCE-65
feat(2fa): Added 2fa option. Fixes: RCCE-65

File last commit:

r5356:99a91100 default
r5360:4cbf1ad2 default
Show More
base.py
607 lines | 21.4 KiB | text/x-python | PythonLexer
copyrights: updated for 2023
r5088 # Copyright (C) 2010-2023 RhodeCode GmbH
project: added all source files and assets
r1 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# 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 Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
The base Controller API
Provides the BaseController class for subclassing. And usage in different
controllers
"""
import logging
import socket
libs: major refactor for python3
r5085 import base64
project: added all source files and assets
r1
core: use a custom filter for rendering all mako templates....
r1949 import markupsafe
project: added all source files and assets
r1 import ipaddress
libs: major refactor for python3
r5085 import paste.httpheaders
project: added all source files and assets
r1 from paste.auth.basic import AuthBasicAuthenticator
from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden, get_exception
import rhodecode
from rhodecode.authentication.base import VCS_TYPE
from rhodecode.lib import auth, utils2
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import AuthUser, CookieStoreWrapper
from rhodecode.lib.exceptions import UserCreationError
pylons: fixed code and test suite after removal of pylons.
r2358 from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes)
libs: major refactor for python3
r5085 from rhodecode.lib.utils2 import AttributeDict
from rhodecode.lib.str_utils import ascii_bytes, safe_int, safe_str
from rhodecode.lib.type_utils import aslist, str2bool
from rhodecode.lib.hash_utils import sha1
dan
ui: introduce user-bookmarks for creation of quick shortcuts
r3424 from rhodecode.model.db import Repository, User, ChangesetComment, UserBookmark
project: added all source files and assets
r1 from rhodecode.model.notification import NotificationModel
from rhodecode.model.settings import VcsSettingsModel, SettingsModel
log = logging.getLogger(__name__)
def _filter_proxy(ip):
"""
Passed in IP addresses in HEADERS can be in a special format of multiple
ips. Those comma separated IPs are passed from various proxies in the
chain of request processing. The left-most being the original client.
We only care about the first IP which came from the org. client.
:param ip: ip string from headers
"""
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
def _filter_port(ip):
"""
Removes a port from ip, there are 4 main cases to handle here.
- ipv4 eg. 127.0.0.1
- ipv6 eg. ::1
- ipv4+port eg. 127.0.0.1:8080
- ipv6+port eg. [::1]:8080
:param ip:
"""
def is_ipv6(ip_addr):
if hasattr(socket, 'inet_pton'):
try:
socket.inet_pton(socket.AF_INET6, ip_addr)
except socket.error:
return False
else:
# fallback to ipaddress
try:
FOLD: into unicode changes
r4959 ipaddress.IPv6Address(safe_str(ip_addr))
project: added all source files and assets
r1 except Exception:
return False
return True
if ':' not in ip: # must be ipv4 pure ip
return ip
if '[' in ip and ']' in ip: # ipv6 with port
return ip.split(']')[0][1:].lower()
# must be ipv6 or ipv4 with port
if is_ipv6(ip):
return ip
else:
ip, _port = ip.split(':')[:2] # means ipv4+port
return ip
def get_ip_addr(environ):
proxy_key = 'HTTP_X_REAL_IP'
proxy_key2 = 'HTTP_X_FORWARDED_FOR'
def_key = 'REMOTE_ADDR'
libs: major refactor for python3
r5085
def ip_filters(ip_):
return _filter_port(_filter_proxy(ip_))
project: added all source files and assets
r1
ip = environ.get(proxy_key)
if ip:
libs: major refactor for python3
r5085 return ip_filters(ip)
project: added all source files and assets
r1
ip = environ.get(proxy_key2)
if ip:
libs: major refactor for python3
r5085 return ip_filters(ip)
project: added all source files and assets
r1
ip = environ.get(def_key, '0.0.0.0')
libs: major refactor for python3
r5085 return ip_filters(ip)
project: added all source files and assets
r1
def get_server_ip_addr(environ, log_errors=True):
hostname = environ.get('SERVER_NAME')
try:
return socket.gethostbyname(hostname)
except Exception as e:
if log_errors:
# in some cases this lookup is not possible, and we don't want to
# make it an exception in logs
log.exception('Could not retrieve server ip address: %s', e)
return hostname
def get_server_port(environ):
return environ.get('SERVER_PORT')
hooks: expose user agent in the variables submitted to pull/push hooks.
r1710 def get_user_agent(environ):
return environ.get('HTTP_USER_AGENT')
project: added all source files and assets
r1 def vcs_operation_context(
Martin Bornhold
vcs: Add flag to indicate if repository is a shadow repository.
r899 environ, repo_name, username, action, scm, check_locking=True,
branch-permissions: handle vcs operations and branch permissions....
r2979 is_shadow_repo=False, check_branch_perms=False, detect_force_push=False):
project: added all source files and assets
r1 """
Generate the context for a vcs operation, e.g. push or pull.
This context is passed over the layers so that hooks triggered by the
vcs operation know details like the user, the user's IP address etc.
:param check_locking: Allows to switch of the computation of the locking
data. This serves mainly the need of the simplevcs middleware to be
able to disable this for certain operations.
"""
# Tri-state value: False: unlock, None: nothing, True: lock
make_lock = None
locked_by = [None, None, None]
is_anonymous = username == User.DEFAULT_USER
vcs-ops: store user_id inside the extras for vcs context operations....
r2411 user = User.get_by_username(username)
project: added all source files and assets
r1 if not is_anonymous and check_locking:
log.debug('Checking locking on repository "%s"', repo_name)
repo = Repository.get_by_repo_name(repo_name)
make_lock, __, locked_by = repo.get_locking_state(
action, user.user_id)
vcs-ops: store user_id inside the extras for vcs context operations....
r2411 user_id = user.user_id
project: added all source files and assets
r1 settings_model = VcsSettingsModel(repo=repo_name)
ui_settings = settings_model.get_ui_settings()
branch-permissions: enabled branch permissions checks for SSH backend.
r2982 # NOTE(marcink): This should be also in sync with
hooks: pass in store_path into env for hooks.
r3094 # rhodecode/apps/ssh_support/lib/backends/base.py:update_environment scm_data
store = [x for x in ui_settings if x.key == '/']
repo_store = ''
if store:
repo_store = store[0].value
branch-permissions: enabled branch permissions checks for SSH backend.
r2982 scm_data = {
project: added all source files and assets
r1 'ip': get_ip_addr(environ),
'username': username,
vcs-ops: store user_id inside the extras for vcs context operations....
r2411 'user_id': user_id,
project: added all source files and assets
r1 'action': action,
'repository': repo_name,
'scm': scm,
'config': rhodecode.CONFIG['__file__'],
hooks: pass in store_path into env for hooks.
r3094 'repo_store': repo_store,
project: added all source files and assets
r1 'make_lock': make_lock,
'locked_by': locked_by,
'server_url': utils2.get_server_url(environ),
hooks: expose user agent in the variables submitted to pull/push hooks.
r1710 'user_agent': get_user_agent(environ),
project: added all source files and assets
r1 'hooks': get_enabled_hook_classes(ui_settings),
Martin Bornhold
vcs: Add flag to indicate if repository is a shadow repository.
r899 'is_shadow_repo': is_shadow_repo,
branch-permissions: handle vcs operations and branch permissions....
r2979 'detect_force_push': detect_force_push,
'check_branch_perms': check_branch_perms,
project: added all source files and assets
r1 }
branch-permissions: enabled branch permissions checks for SSH backend.
r2982 return scm_data
project: added all source files and assets
r1
class BasicAuth(AuthBasicAuthenticator):
Martin Bornhold
vcs: Pass registry to vcs for user authentication....
r591 def __init__(self, realm, authfunc, registry, auth_http_code=None,
Authentication: cache plugins for auth and their settings in the auth_registry....
r4220 initial_call_detection=False, acl_repo_name=None, rc_realm=''):
modernize: updates for python3
r5095 super().__init__(realm=realm, authfunc=authfunc)
project: added all source files and assets
r1 self.realm = realm
Authentication: cache plugins for auth and their settings in the auth_registry....
r4220 self.rc_realm = rc_realm
project: added all source files and assets
r1 self.initial_call = initial_call_detection
self.authfunc = authfunc
Martin Bornhold
vcs: Pass registry to vcs for user authentication....
r591 self.registry = registry
authentication: enabled authentication with auth_token and repository scope....
r1510 self.acl_repo_name = acl_repo_name
project: added all source files and assets
r1 self._rc_auth_http_code = auth_http_code
libs: major refactor for python3
r5085 def _get_response_from_code(self, http_code, fallback):
project: added all source files and assets
r1 try:
return get_exception(safe_int(http_code))
except Exception:
libs: major refactor for python3
r5085 log.exception('Failed to fetch response class for code %s, using fallback: %s', http_code, fallback)
return fallback
project: added all source files and assets
r1
vcs: reduce sql queries used during pull/push operations.
r2140 def get_rc_realm(self):
Authentication: cache plugins for auth and their settings in the auth_registry....
r4220 return safe_str(self.rc_realm)
vcs: reduce sql queries used during pull/push operations.
r2140
project: added all source files and assets
r1 def build_authentication(self):
libs: major refactor for python3
r5085 header = [('WWW-Authenticate', f'Basic realm="{self.realm}"')]
# NOTE: the initial_Call detection seems to be not working/not needed witg latest Mercurial
# investigate if we still need it.
project: added all source files and assets
r1 if self._rc_auth_http_code and not self.initial_call:
# return alternative HTTP code if alternative http return code
# is specified in RhodeCode config, but ONLY if it's not the
# FIRST call
libs: major refactor for python3
r5085 custom_response_klass = self._get_response_from_code(self._rc_auth_http_code, fallback=HTTPUnauthorized)
log.debug('Using custom response class: %s', custom_response_klass)
return custom_response_klass(headers=header)
return HTTPUnauthorized(headers=header)
project: added all source files and assets
r1
def authenticate(self, environ):
libs: major refactor for python3
r5085 authorization = paste.httpheaders.AUTHORIZATION(environ)
project: added all source files and assets
r1 if not authorization:
return self.build_authentication()
libs: major refactor for python3
r5085 (auth_meth, auth_creds_b64) = authorization.split(' ', 1)
if 'basic' != auth_meth.lower():
project: added all source files and assets
r1 return self.build_authentication()
libs: major refactor for python3
r5085
credentials = safe_str(base64.b64decode(auth_creds_b64.strip()))
_parts = credentials.split(':', 1)
project: added all source files and assets
r1 if len(_parts) == 2:
username, password = _parts
auth: use cache_ttl from a plugin to also cache permissions....
r2154 auth_data = self.authfunc(
Martin Bornhold
vcs: Pass registry to vcs for user authentication....
r591 username, password, environ, VCS_TYPE,
auth: use cache_ttl from a plugin to also cache permissions....
r2154 registry=self.registry, acl_repo_name=self.acl_repo_name)
if auth_data:
return {'username': username, 'auth_data': auth_data}
project: added all source files and assets
r1 if username and password:
# we mark that we actually executed authentication once, at
# that point we can use the alternative auth code
self.initial_call = False
return self.build_authentication()
__call__ = authenticate
core: removed usage of global pylons config in base lib.
r2000 def calculate_version_hash(config):
base: drop usage of md5 for calculation of version hash.
r2835 return sha1(
libs: major refactor for python3
r5085 config.get(b'beaker.session.secret', b'') + ascii_bytes(rhodecode.__version__)
)[:8]
tests: remove usage of pylons context var in home app test.
r1893
pyramid: move language extraction into a seperate method.
r1904 def get_current_lang(request):
pyramid: fix problem with default language for users without any explicit one set.
r1919 return getattr(request, '_LOCALE_', request.locale_name)
pyramid: move language extraction into a seperate method.
r1904
exc-tracker: make context attribute behave like in API case...
r4277 def attach_context_attributes(context, request, user_id=None, is_api=None):
js-template-context: made the context pyramid and pylons compatible....
r400 """
pylons: remove pylons as dependency...
r2351 Attach variables into template context called `c`.
js-template-context: made the context pyramid and pylons compatible....
r400 """
pylons: remove pylons as dependency...
r2351 config = request.registry.settings
settings: re-use attached request global config for performance...
r4200 rc_config = SettingsModel().get_all_settings(cache=True, from_request=False)
settings: reduce number of settings fetch since it uses locking for cache invalidation and is generally slow....
r3855 context.rc_config = rc_config
project: added all source files and assets
r1 context.rhodecode_version = rhodecode.__version__
context.rhodecode_edition = config.get('rhodecode.edition')
observers: hide it for CE edition....
r4516 context.rhodecode_edition_id = config.get('rhodecode.edition_id')
project: added all source files and assets
r1 # unique secret + version does not leak the version but keep consistency
core: removed usage of global pylons config in base lib.
r2000 context.rhodecode_version_hash = calculate_version_hash(config)
project: added all source files and assets
r1
# Default language set for the incoming request
pyramid: move language extraction into a seperate method.
r1904 context.language = get_current_lang(request)
project: added all source files and assets
r1
# Visual options
context.visual = AttributeDict({})
vcs: moved svn proxy settings into vcs related settings...
r754 # DB stored Visual Items
project: added all source files and assets
r1 context.visual.show_public_icon = str2bool(
rc_config.get('rhodecode_show_public_icon'))
context.visual.show_private_icon = str2bool(
rc_config.get('rhodecode_show_private_icon'))
context.visual.stylify_metatags = str2bool(
rc_config.get('rhodecode_stylify_metatags'))
context.visual.dashboard_items = safe_int(
rc_config.get('rhodecode_dashboard_items', 100))
context.visual.admin_grid_items = safe_int(
rc_config.get('rhodecode_admin_grid_items', 100))
dan
visual: fixed show revision/commit lenght settings
r3404 context.visual.show_revision_number = str2bool(
rc_config.get('rhodecode_show_revision_number', True))
context.visual.show_sha_length = safe_int(
rc_config.get('rhodecode_show_sha_length', 100))
project: added all source files and assets
r1 context.visual.repository_fields = str2bool(
rc_config.get('rhodecode_repository_fields'))
context.visual.show_version = str2bool(
rc_config.get('rhodecode_show_version'))
context.visual.use_gravatar = str2bool(
rc_config.get('rhodecode_use_gravatar'))
context.visual.gravatar_url = rc_config.get('rhodecode_gravatar_url')
context.visual.default_renderer = rc_config.get(
'rhodecode_markup_renderer', 'rst')
comments: add comments type into comments.
r1324 context.visual.comment_types = ChangesetComment.COMMENT_TYPES
project: added all source files and assets
r1 context.visual.rhodecode_support_url = \
routing: switched static redirection links to pyramid....
r1679 rc_config.get('rhodecode_support_url') or h.route_url('rhodecode_support')
project: added all source files and assets
r1
changelog: ported to pyramid views.
r1931 context.visual.affected_files_cut_off = 60
project: added all source files and assets
r1 context.pre_code = rc_config.get('rhodecode_pre_code')
context.post_code = rc_config.get('rhodecode_post_code')
context.rhodecode_name = rc_config.get('rhodecode_title')
context.default_encodings = aslist(config.get('default_encoding'), sep=',')
# if we have specified default_encoding in the request, it has more
# priority
if request.GET.get('default_encoding'):
context.default_encodings.insert(0, request.GET.get('default_encoding'))
context.clone_uri_tmpl = rc_config.get('rhodecode_clone_uri_tmpl')
clone-urls: allow custom clone by id template.
r4629 context.clone_uri_id_tmpl = rc_config.get('rhodecode_clone_uri_id_tmpl')
ui: allow selecting and specifing ssh clone url....
r2497 context.clone_uri_ssh_tmpl = rc_config.get('rhodecode_clone_uri_ssh_tmpl')
project: added all source files and assets
r1
# INI stored
context.labs_active = str2bool(
config.get('labs_settings_active', 'false'))
ssh: don't show the SSH clone url if ssh is disabled
r2498 context.ssh_enabled = str2bool(
config.get('ssh.generate_authorized_keyfile', 'false'))
Issue #5536 - ability to disable server-side SSH key generation...
r3478 context.ssh_key_generator_enabled = str2bool(
config.get('ssh.enable_ui_key_generator', 'true'))
ssh: don't show the SSH clone url if ssh is disabled
r2498
project: added all source files and assets
r1 context.visual.allow_custom_hooks_settings = str2bool(
config.get('allow_custom_hooks_settings', True))
context.debug_style = str2bool(config.get('debug_style', False))
context.rhodecode_instanceid = config.get('instance_id')
pull-requests: prepare the migration of pull request to pyramid....
r1813 context.visual.cut_off_limit_diff = safe_int(
libs: major refactor for python3
r5085 config.get('cut_off_limit_diff'), default=0)
pull-requests: prepare the migration of pull request to pyramid....
r1813 context.visual.cut_off_limit_file = safe_int(
libs: major refactor for python3
r5085 config.get('cut_off_limit_file'), default=0)
pull-requests: prepare the migration of pull request to pyramid....
r1813
license: added a flag to allow hidding license info.
r4006 context.license = AttributeDict({})
context.license.hide_license_info = str2bool(
config.get('license.hide_license_info', False))
project: added all source files and assets
r1 # AppEnlight
config: major update for the code to make it be almost fully controllable via env for new docker based installer.
r4823 context.appenlight_enabled = config.get('appenlight', False)
project: added all source files and assets
r1 context.appenlight_api_public_key = config.get(
'appenlight.api_public_key', '')
context.appenlight_server_url = config.get('appenlight.server_url', '')
users: use new session store for temporary settings for users....
r3088 diffmode = {
"unified": "unified",
"sideside": "sideside"
}.get(request.GET.get('diffmode'))
exc-tracker: make context attribute behave like in API case...
r4277 if is_api is not None:
is_api = hasattr(request, 'rpc_user')
users: use new session store for temporary settings for users....
r3088 session_attrs = {
# defaults
"clone_url_format": "http",
license: add helpers to allow users hide license warnings.
r4453 "diffmode": "sideside",
"license_fingerprint": request.session.get('license_fingerprint')
users: use new session store for temporary settings for users....
r3088 }
sessions: don't touch session for API calls.
r3749
if not is_api:
# don't access pyramid session for API calls
if diffmode and diffmode != request.session.get('rc_user_session_attr.diffmode'):
request.session['rc_user_session_attr.diffmode'] = diffmode
# session settings per user
libs: major refactor for python3
r5085 for k, v in list(request.session.items()):
sessions: don't touch session for API calls.
r3749 pref = 'rc_user_session_attr.'
if k and k.startswith(pref):
k = k[len(pref):]
session_attrs[k] = v
users: use new session store for temporary settings for users....
r3088
context.user_session_attrs = session_attrs
js-template-context: made the context pyramid and pylons compatible....
r400 # JS template context
context.template_context = {
'repo_name': None,
'repo_type': None,
'repo_landing_commit': None,
'rhodecode_user': {
'username': None,
'email': None,
notifications: support real-time notifications with websockets via channelstream
r526 'notification_status': False
js-template-context: made the context pyramid and pylons compatible....
r400 },
users: use new session store for temporary settings for users....
r3088 'session_attrs': session_attrs,
js-template-context: made the context pyramid and pylons compatible....
r400 'visual': {
'default_renderer': None
},
'commit_data': {
'commit_id': None
},
'pull_request_data': {'pull_request_id': None},
'timeago': {
'refresh_time': 120 * 1000,
'cutoff_limit': 1000 * 60 * 60 * 24 * 7
},
'pyramid_dispatch': {
},
'extra': {'plugins': {}}
}
project: added all source files and assets
r1 # END CONFIG VARS
sessions: don't touch session for API calls.
r3749 if is_api:
csrf_token = None
else:
csrf_token = auth.get_csrf_token(session=request.session)
project: added all source files and assets
r1
sessions: don't touch session for API calls.
r3749 context.csrf_token = csrf_token
libs: major refactor for python3
r5085 context.backends = list(rhodecode.BACKENDS.keys())
repositories: preserve order of defined backends, and switched repo type selector to radios.
r4321
dan
ui: introduce user-bookmarks for creation of quick shortcuts
r3424 unread_count = 0
user_bookmark_list = []
if user_id:
unread_count = NotificationModel().get_unread_cnt_for_user(user_id)
user_bookmark_list = UserBookmark.get_bookmarks_for_user(user_id)
context.unread_notifications = unread_count
context.bookmark_items = user_bookmark_list
dependencies: bumped pyramid to 1.9 webob to 1.7.3 and webtest to 2.0.27...
r1906
# web case
pylons: remove pylons as dependency...
r2351 if hasattr(request, 'user'):
context.auth_user = request.user
context.rhodecode_user = request.user
dependencies: bumped pyramid to 1.9 webob to 1.7.3 and webtest to 2.0.27...
r1906
# api case
pylons: remove pylons as dependency...
r2351 if hasattr(request, 'rpc_user'):
context.auth_user = request.rpc_user
context.rhodecode_user = request.rpc_user
dan
api: attach the call context variables to request for later usage...
r1794
core: always attach pyramid context into request...
r1896 # attach the whole call context to the request
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 request.set_call_context(context)
dan
api: attach the call context variables to request for later usage...
r1794
base: add pyramid_request to tmplContext
r765
pyramid: moved extraction of user into a seperate subscriber.
r1903 def get_auth_user(request):
environ = request.environ
session = request.session
project: added all source files and assets
r1
ip_addr = get_ip_addr(environ)
auth-token: expose fetched token in unified way into request attribute....
r4002
project: added all source files and assets
r1 # make sure that we update permissions each time we call controller
token-access: allow token in headers not only in GET/URL
r4608 _auth_token = (
# ?auth_token=XXX
request.GET.get('auth_token', '')
# ?api_key=XXX !LEGACY
or request.GET.get('api_key', '')
# or headers....
or request.headers.get('X-Rc-Auth-Token', '')
)
base: fix problem that in some view context we don't have matchdict.
r4007 if not _auth_token and request.matchdict:
auth-token: expose fetched token in unified way into request attribute....
r4002 url_auth_token = request.matchdict.get('_auth_token')
_auth_token = url_auth_token
if _auth_token:
log.debug('Using URL extracted auth token `...%s`', _auth_token[-4:])
project: added all source files and assets
r1
if _auth_token:
code: added more logging, and some notes
r1300 # when using API_KEY we assume user exists, and
# doesn't need auth based on cookies.
project: added all source files and assets
r1 auth_user = AuthUser(api_key=_auth_token, ip_addr=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=ip_addr)
except UserCreationError as e:
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. We then create a simple blank
# AuthUser
auth_user = AuthUser(ip_addr=ip_addr)
pylons: fixed code and test suite after removal of pylons.
r2358 # in case someone changes a password for user it triggers session
# flush and forces a re-login
project: added all source files and assets
r1 if password_changed(auth_user, session):
session.invalidate()
code: added more logging, and some notes
r1300 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
project: added all source files and assets
r1 auth_user = AuthUser(ip_addr=ip_addr)
authenticated = cookie_store.get('is_authenticated')
if not auth_user.is_authenticated and auth_user.is_user_object:
# user is not authenticated and not empty
auth_user.set_authenticated(authenticated)
auth-token: expose fetched token in unified way into request attribute....
r4002 return auth_user, _auth_token
project: added all source files and assets
r1
core: use a custom filter for rendering all mako templates....
r1949 def h_filter(s):
"""
Custom filter for Mako templates. Mako by standard uses `markupsafe.escape`
we wrap this with additional functionality that converts None to empty
strings
"""
if s is None:
return markupsafe.Markup()
return markupsafe.escape(s)
pyramid: ported pyramid routing for events
r2016 def add_events_routes(config):
"""
Adds routing that can be used in events. Because some events are triggered
outside of pyramid context, we need to bootstrap request with some
routing registered
"""
testing: cleanup request/config stubs...
r2311
from rhodecode.apps._base import ADMIN_PREFIX
pyramid: ported pyramid routing for events
r2016 config.add_route(name='home', pattern='/')
dashboard: main page grids async load....
r4148 config.add_route(name='main_page_repos_data', pattern='/_home_repos')
config.add_route(name='main_page_repo_groups_data', pattern='/_home_repo_groups')
pyramid: ported pyramid routing for events
r2016
testing: cleanup request/config stubs...
r2311 config.add_route(name='login', pattern=ADMIN_PREFIX + '/login')
config.add_route(name='logout', pattern=ADMIN_PREFIX + '/logout')
pyramid: ported pyramid routing for events
r2016 config.add_route(name='repo_summary', pattern='/{repo_name}')
config.add_route(name='repo_summary_explicit', pattern='/{repo_name}/summary')
config.add_route(name='repo_group_home', pattern='/{repo_group_name}')
config.add_route(name='pullrequest_show',
pattern='/{repo_name}/pull-request/{pull_request_id}')
config.add_route(name='pull_requests_global',
pattern='/pull-request/{pull_request_id}')
dan
hovercards: enable hovercards on parsed commits references.
r4047
pyramid: ported pyramid routing for events
r2016 config.add_route(name='repo_commit',
pattern='/{repo_name}/changeset/{commit_id}')
config.add_route(name='repo_files',
pattern='/{repo_name}/files/{commit_id}/{f_path}')
dan
hovercards: enable hovercards on parsed commits references.
r4047 config.add_route(name='hovercard_user',
pattern='/_hovercard/user/{user_id}')
config.add_route(name='hovercard_user_group',
pattern='/_hovercard/user_group/{user_group_id}')
config.add_route(name='hovercard_pull_request',
pattern='/_hovercard/pull_request/{pull_request_id}')
config.add_route(name='hovercard_repo_commit',
pattern='/_hovercard/commit/{repo_name}/{commit_id}')
pyramid: ported pyramid routing for events
r2016
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 def bootstrap_config(request, registry_name='RcTestRegistry'):
feat(ssh-wrapper-speedup): major rewrite of code to address imports problem with ssh-wrapper-v2...
r5325 from rhodecode.config.config_maker import sanitize_settings_and_apply_defaults
testing: cleanup request/config stubs...
r2311 import pyramid.testing
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 registry = pyramid.testing.Registry(registry_name)
tests: add require methods to testing request....
r2317
tests: fixup the config stubs
r5145 global_config = {'__file__': ''}
testing: cleanup request/config stubs...
r2311 config = pyramid.testing.setUp(registry=registry, request=request)
tests: fixup the config stubs
r5145 sanitize_settings_and_apply_defaults(global_config, config.registry.settings)
testing: cleanup request/config stubs...
r2311
# allow pyramid lookup in testing
config.include('pyramid_mako')
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 config.include('rhodecode.lib.rc_beaker')
caches: rewrite of auth/permission caches to dogpile.
r2845 config.include('rhodecode.lib.rc_cache')
libs: major refactor for python3
r5085 config.include('rhodecode.lib.rc_cache.archive_cache')
testing: cleanup request/config stubs...
r2311 add_events_routes(config)
tests: add require methods to testing request....
r2317
testing: cleanup request/config stubs...
r2311 return config
events: make sure we propagate our dummy request with proper application_url....
r2017 def bootstrap_request(**kwargs):
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 """
Returns a thin version of Request Object that is used in non-web context like testing/celery
"""
helpers: remove usage of pylons session.
r2095
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 import pyramid.testing
from rhodecode.lib.request import ThinRequest as _ThinRequest
class ThinRequest(_ThinRequest):
helpers: remove usage of pylons session.
r2095 application_url = kwargs.pop('application_url', 'http://example.com')
host = kwargs.pop('host', 'example.com:80')
domain = kwargs.pop('domain', 'example.com')
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 class ThinSession(pyramid.testing.DummySession):
helpers: remove usage of pylons session.
r2095 def save(*arg, **kw):
pass
requests: cleaned / unified way of handling requests generation from non-web scope....
r4873 request = ThinRequest(**kwargs)
request.session = ThinSession()
events: make sure we propagate our dummy request with proper application_url....
r2017
helpers: remove usage of pylons session.
r2095 return request