##// END OF EJS Templates
routing: use a common method to extract the f_path for repo views....
routing: use a common method to extract the f_path for repo views. The extra slashes can cause odd issues with GIT, the previous pylons code had a fix in routing. This ports this fix into pyramid helper in base app.

File last commit:

r1929:0c7b3df6 default
r1929:0c7b3df6 default
Show More
__init__.py
416 lines | 13.3 KiB | text/x-python | PythonLexer
user-profile: migrated to pyramid views.
r1502 # -*- coding: utf-8 -*-
# Copyright (C) 2016-2017 RhodeCode GmbH
#
# 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/
pyramid: added checks for password change for authenticated users.
r1539 import time
user-profile: migrated to pyramid views.
r1502 import logging
core: make pylons global be used in obsolete parts of the code....
r1895
my-account: switched my-password view to pyramid.
r1537 from pyramid.httpexceptions import HTTPFound
user-profile: migrated to pyramid views.
r1502
pyramid: added checks for password change for authenticated users.
r1539 from rhodecode.lib import helpers as h
tags/branches/bookmarks: moved views into pyramid.
r1746 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
repo-view: handle empty repo or missing requirements in base view for repositories.
r1714 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
core: added supports of repo based views via pyramid.
r1554 from rhodecode.model import repo
home: moved home and repo group views into pyramid....
r1774 from rhodecode.model import repo_group
pyramid: added checks for password change for authenticated users.
r1539 from rhodecode.model.db import User
core: added supports of repo based views via pyramid.
r1554 from rhodecode.model.scm import ScmModel
user-profile: migrated to pyramid views.
r1502
log = logging.getLogger(__name__)
my-account-auth-tokens: moved into pyramid apps....
r1505 ADMIN_PREFIX = '/_admin'
STATIC_FILE_PREFIX = '/_static'
pyramid: moved add_route_requirements into pyramid base app....
r1928 URL_NAME_REQUIREMENTS = {
# group name can have a slash in them, but they must not end with a slash
'group_name': r'.*?[^/]',
'repo_group_name': r'.*?[^/]',
# repo names can have a slash in them, but they must not end with a slash
'repo_name': r'.*?[^/]',
# file path eats up everything at the end
'f_path': r'.*',
# reference types
'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
}
my-account-auth-tokens: moved into pyramid apps....
r1505
home: moved home and repo group views into pyramid....
r1774 def add_route_with_slash(config,name, pattern, **kw):
config.add_route(name, pattern, **kw)
if not pattern.endswith('/'):
config.add_route(name + '_slash', pattern + '/', **kw)
pyramid: moved add_route_requirements into pyramid base app....
r1928 def add_route_requirements(route_path, requirements=URL_NAME_REQUIREMENTS):
"""
Adds regex requirements to pyramid routes using a mapping dict
e.g::
add_route_requirements('{repo_name}/settings')
"""
for key, regex in requirements.items():
route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
return route_path
tags/branches/bookmarks: moved views into pyramid.
r1746 def get_format_ref_id(repo):
"""Returns a `repo` specific reference formatter function"""
if h.is_svn(repo):
return _format_ref_id_svn
else:
return _format_ref_id
def _format_ref_id(name, raw_id):
"""Default formatting of a given reference `name`"""
return name
def _format_ref_id_svn(name, raw_id):
"""Special way of formatting a reference for Subversion including path"""
return '%s@%s' % (name, raw_id)
user-profile: migrated to pyramid views.
r1502 class TemplateArgs(StrictAttributeDict):
pass
class BaseAppView(object):
def __init__(self, context, request):
self.request = request
self.context = context
self.session = request.session
pyramid: base view improvements
r1534 self._rhodecode_user = request.user # auth user
my-account: switched my-password view to pyramid.
r1537 self._rhodecode_db_user = self._rhodecode_user.get_instance()
pyramid: added checks for password change for authenticated users.
r1539 self._maybe_needs_password_change(
request.matched_route.name, self._rhodecode_db_user)
def _maybe_needs_password_change(self, view_name, user_obj):
log.debug('Checking if user %s needs password change on view %s',
user_obj, view_name)
skip_user_views = [
'logout', 'login',
'my_account_password', 'my_account_password_update'
]
if not user_obj:
return
if user_obj.username == User.DEFAULT_USER:
return
now = time.time()
should_change = user_obj.user_data.get('force_password_change')
change_after = safe_int(should_change) or 0
if should_change and now > change_after:
log.debug('User %s requires password change', user_obj)
h.flash('You are required to change your password', 'warning',
ignore_duplicate=True)
if view_name not in skip_user_views:
raise HTTPFound(
self.request.route_path('my_account_password'))
user-profile: migrated to pyramid views.
r1502
repo-summary: re-implemented summary view as pyramid....
r1785 def _get_local_tmpl_context(self, include_app_defaults=False):
pyramid-views: always register auth_user for via the base view....
r1533 c = TemplateArgs()
c.auth_user = self.request.user
pyramid: changes for pyramid migration.
r1908 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
c.rhodecode_user = self.request.user
repo-summary: re-implemented summary view as pyramid....
r1785 if include_app_defaults:
# NOTE(marcink): after full pyramid migration include_app_defaults
# should be turned on by default
from rhodecode.lib.base import attach_context_attributes
attach_context_attributes(c, self.request, self.request.user.user_id)
pyramid: changes for pyramid migration.
r1908
pyramid-views: always register auth_user for via the base view....
r1533 return c
user-profile: migrated to pyramid views.
r1502
my-account-auth-tokens: moved into pyramid apps....
r1505 def _register_global_c(self, tmpl_args):
"""
Registers attributes to pylons global `c`
"""
pyramid: changes for pyramid migration.
r1908
my-account-auth-tokens: moved into pyramid apps....
r1505 # TODO(marcink): remove once pyramid migration is finished
core: make pylons global be used in obsolete parts of the code....
r1895 from pylons import tmpl_context as c
pyramid: allows easier turning off the pylons components.
r1912 try:
for k, v in tmpl_args.items():
setattr(c, k, v)
except TypeError:
log.exception('Failed to register pylons C')
pass
my-account-auth-tokens: moved into pyramid apps....
r1505
user-profile: migrated to pyramid views.
r1502 def _get_template_context(self, tmpl_args):
my-account-auth-tokens: moved into pyramid apps....
r1505 self._register_global_c(tmpl_args)
user-profile: migrated to pyramid views.
r1502
login: switch to re-use the baseApp pyramid view.
r1536 local_tmpl_args = {
user-profile: migrated to pyramid views.
r1502 'defaults': {},
'errors': {},
pyramid: expose a temporary TemplateContext under `_c`
r1924 # register a fake 'c' to be used in templates instead of global
# pylons c, after migration to pyramid we should rename it to 'c'
# make sure we replace usage of _c in templates too
'_c': tmpl_args
user-profile: migrated to pyramid views.
r1502 }
login: switch to re-use the baseApp pyramid view.
r1536 local_tmpl_args.update(tmpl_args)
return local_tmpl_args
user-profile: migrated to pyramid views.
r1502
pyramid: base view improvements
r1534 def load_default_context(self):
"""
example:
def load_default_context(self):
c = self._get_local_tmpl_context()
c.custom_var = 'foobar'
self._register_global_c(c)
return c
"""
raise NotImplementedError('Needs implementation in view class')
core: added supports of repo based views via pyramid.
r1554
class RepoAppView(BaseAppView):
def __init__(self, context, request):
super(RepoAppView, self).__init__(context, request)
self.db_repo = request.db_repo
self.db_repo_name = self.db_repo.repo_name
self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
repo-view: handle empty repo or missing requirements in base view for repositories.
r1714 def _handle_missing_requirements(self, error):
log.error(
'Requirements are missing for repository %s: %s',
self.db_repo_name, error.message)
repo-summary: re-implemented summary view as pyramid....
r1785 def _get_local_tmpl_context(self, include_app_defaults=False):
c = super(RepoAppView, self)._get_local_tmpl_context(
include_app_defaults=include_app_defaults)
core: added supports of repo based views via pyramid.
r1554 # register common vars for this type of view
c.rhodecode_db_repo = self.db_repo
c.repo_name = self.db_repo_name
c.repository_pull_requests = self.db_repo_pull_requests
repo-view: handle empty repo or missing requirements in base view for repositories.
r1714
c.repository_requirements_missing = False
try:
self.rhodecode_vcs_repo = self.db_repo.scm_instance()
except RepositoryRequirementError as e:
c.repository_requirements_missing = True
self._handle_missing_requirements(e)
core: added supports of repo based views via pyramid.
r1554 return c
routing: use a common method to extract the f_path for repo views....
r1929 def _get_f_path(self, matchdict, default=None):
f_path = matchdict.get('f_path')
if f_path:
# fix for multiple initial slashes that causes errors for GIT
return f_path.lstrip('/')
return default
core: added supports of repo based views via pyramid.
r1554
data-grid: create a common re-usable app with datagrid rendering helpers
r1646 class DataGridAppView(object):
"""
Common class to have re-usable grid rendering components
"""
base-grid-view: allow specifing custom mapping for sort columns.
r1649 def _extract_ordering(self, request, column_map=None):
column_map = column_map or {}
data-grid: create a common re-usable app with datagrid rendering helpers
r1646 column_index = safe_int(request.GET.get('order[0][column]'))
order_dir = request.GET.get(
'order[0][dir]', 'desc')
order_by = request.GET.get(
'columns[%s][data][sort]' % column_index, 'name_raw')
# translate datatable to DB columns
base-grid-view: allow specifing custom mapping for sort columns.
r1649 order_by = column_map.get(order_by) or order_by
data-grid: create a common re-usable app with datagrid rendering helpers
r1646
search_q = request.GET.get('search[value]')
return search_q, order_by, order_dir
def _extract_chunk(self, request):
start = safe_int(request.GET.get('start'), 0)
length = safe_int(request.GET.get('length'), 25)
draw = safe_int(request.GET.get('draw'))
return draw, start, length
tags/branches/bookmarks: moved views into pyramid.
r1746 class BaseReferencesView(RepoAppView):
"""
Base for reference view for branches, tags and bookmarks.
"""
def load_default_context(self):
c = self._get_local_tmpl_context()
# TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
c.repo_info = self.db_repo
self._register_global_c(c)
return c
def load_refs_context(self, ref_items, partials_template):
core: use new style pyramid partial renderer where possible.
r1897 _render = self.request.get_partial_renderer(partials_template)
tags/branches/bookmarks: moved views into pyramid.
r1746 pre_load = ["author", "date", "message"]
is_svn = h.is_svn(self.rhodecode_vcs_repo)
refs: refactored references code to remove any pylons elements....
r1898 is_hg = h.is_hg(self.rhodecode_vcs_repo)
tags/branches/bookmarks: moved views into pyramid.
r1746 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
refs: refactored references code to remove any pylons elements....
r1898 closed_refs = {}
if is_hg:
closed_refs = self.rhodecode_vcs_repo.branches_closed
data = []
tags/branches/bookmarks: moved views into pyramid.
r1746 for ref_name, commit_id in ref_items:
commit = self.rhodecode_vcs_repo.get_commit(
commit_id=commit_id, pre_load=pre_load)
refs: refactored references code to remove any pylons elements....
r1898 closed = ref_name in closed_refs
tags/branches/bookmarks: moved views into pyramid.
r1746
# TODO: johbo: Unify generation of reference links
use_commit_id = '/' in ref_name or is_svn
files: ported repository files controllers to pyramid views.
r1927
if use_commit_id:
files_url = h.route_path(
'repo_files',
repo_name=self.db_repo_name,
f_path=ref_name if is_svn else '',
commit_id=commit_id)
else:
files_url = h.route_path(
'repo_files',
repo_name=self.db_repo_name,
f_path=ref_name if is_svn else '',
commit_id=ref_name,
_query=dict(at=ref_name))
tags/branches/bookmarks: moved views into pyramid.
r1746
refs: refactored references code to remove any pylons elements....
r1898 data.append({
"name": _render('name', ref_name, files_url, closed),
tags/branches/bookmarks: moved views into pyramid.
r1746 "name_raw": ref_name,
"date": _render('date', commit.date),
"date_raw": datetime_to_time(commit.date),
"author": _render('author', commit.author),
"commit": _render(
'commit', commit.message, commit.raw_id, commit.idx),
"commit_raw": commit.idx,
"compare": _render(
'compare', format_ref_id(ref_name, commit.raw_id)),
})
refs: refactored references code to remove any pylons elements....
r1898
return data
tags/branches/bookmarks: moved views into pyramid.
r1746
core: added supports of repo based views via pyramid.
r1554 class RepoRoutePredicate(object):
def __init__(self, val, config):
self.val = val
def text(self):
return 'repo_route = %s' % self.val
phash = text
def __call__(self, info, request):
predicates: skip route matching for vcs type calls.
r1778
if hasattr(request, 'vcs_call'):
# skip vcs calls
return
core: added supports of repo based views via pyramid.
r1554 repo_name = info['match']['repo_name']
repo_model = repo.RepoModel()
by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
home: moved home and repo group views into pyramid....
r1774
core: added supports of repo based views via pyramid.
r1554 if by_name_match:
# register this as request object we can re-use later
request.db_repo = by_name_match
return True
by_id_match = repo_model.get_repo_by_id(repo_name)
if by_id_match:
request.db_repo = by_id_match
return True
return False
pull-requests: moved the listing of pull requests for repo into pyramid....
r1766 class RepoTypeRoutePredicate(object):
def __init__(self, val, config):
self.val = val or ['hg', 'git', 'svn']
def text(self):
return 'repo_accepted_type = %s' % self.val
phash = text
def __call__(self, info, request):
predicates: skip route matching for vcs type calls.
r1778 if hasattr(request, 'vcs_call'):
# skip vcs calls
return
pull-requests: moved the listing of pull requests for repo into pyramid....
r1766
rhodecode_db_repo = request.db_repo
log.debug(
'%s checking repo type for %s in %s',
self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
if rhodecode_db_repo.repo_type in self.val:
return True
else:
log.warning('Current view is not supported for repo type:%s',
rhodecode_db_repo.repo_type)
pull-request: extended default reviewers functionality....
r1769 #
# h.flash(h.literal(
# _('Action not supported for %s.' % rhodecode_repo.alias)),
# category='warning')
# return redirect(
repo-summary: re-implemented summary view as pyramid....
r1785 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
pull-request: extended default reviewers functionality....
r1769
pull-requests: moved the listing of pull requests for repo into pyramid....
r1766 return False
home: moved home and repo group views into pyramid....
r1774 class RepoGroupRoutePredicate(object):
def __init__(self, val, config):
self.val = val
def text(self):
return 'repo_group_route = %s' % self.val
phash = text
def __call__(self, info, request):
predicates: skip route matching for vcs type calls.
r1778 if hasattr(request, 'vcs_call'):
# skip vcs calls
return
home: moved home and repo group views into pyramid....
r1774 repo_group_name = info['match']['repo_group_name']
repo_group_model = repo_group.RepoGroupModel()
by_name_match = repo_group_model.get_by_group_name(
repo_group_name, cache=True)
if by_name_match:
# register this as request object we can re-use later
request.db_repo_group = by_name_match
return True
return False
pull-requests: moved the listing of pull requests for repo into pyramid....
r1766
core: added supports of repo based views via pyramid.
r1554 def includeme(config):
config.add_route_predicate(
'repo_route', RepoRoutePredicate)
pull-requests: moved the listing of pull requests for repo into pyramid....
r1766 config.add_route_predicate(
home: moved home and repo group views into pyramid....
r1774 'repo_accepted_types', RepoTypeRoutePredicate)
config.add_route_predicate(
'repo_group_route', RepoGroupRoutePredicate)