##// END OF EJS Templates
pull-requests: increase stability of concurrent pull requests creation by flushing prematurly the statuses of commits....
pull-requests: increase stability of concurrent pull requests creation by flushing prematurly the statuses of commits. This is required to increase the versions on each concurrent call. Otherwise we could get into an integrity errors of commitsha+version+repo

File last commit:

r3363:f08e98b1 default
r3408:2a133f7e stable
Show More
views.py
462 lines | 16.3 KiB | text/x-python | PythonLexer
core: moved users and user groups autocomplete into pyramid....
r1666 # -*- coding: utf-8 -*-
release: update copyright year to 2018
r2487 # Copyright (C) 2016-2018 RhodeCode GmbH
core: moved users and user groups autocomplete into pyramid....
r1666 #
# 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/
core: moved goto_switcher views into pyramid.
r1668 import re
core: moved users and user groups autocomplete into pyramid....
r1666 import logging
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 import collections
core: moved users and user groups autocomplete into pyramid....
r1666
from pyramid.view import view_config
from rhodecode.apps._base import BaseAppView
core: moved repo_list data to pyramid.
r1667 from rhodecode.lib import helpers as h
apps: cleanup imports
r2080 from rhodecode.lib.auth import (
pull-requests: allow markup rendered description.
r2816 LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator,
CSRFRequired)
core: moved goto_switcher views into pyramid.
r1668 from rhodecode.lib.index import searcher_from_config
quick-search: use smart group search when browsing inside a repository group....
r2804 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
home: moved home and repo group views into pyramid....
r1774 from rhodecode.lib.ext_json import json
goto-switcher: optimized performance and query capabilities....
r2038 from rhodecode.model.db import (
repositories: added option to archive repositories instead of deleting them....
r3090 func, true, or_, in_filter_generator, Repository, RepoGroup, User, UserGroup)
core: moved users and user groups autocomplete into pyramid....
r1666 from rhodecode.model.repo import RepoModel
home: moved home and repo group views into pyramid....
r1774 from rhodecode.model.repo_group import RepoGroupModel
goto-switcher: optimized performance and query capabilities....
r2038 from rhodecode.model.scm import RepoGroupList, RepoList
users: moved get_users from RepoModel to UserModel.
r1677 from rhodecode.model.user import UserModel
user-groups: moved get_user_groups from RepoModel to UserGroupModel.
r1676 from rhodecode.model.user_group import UserGroupModel
core: moved users and user groups autocomplete into pyramid....
r1666
log = logging.getLogger(__name__)
class HomeView(BaseAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.user = c.auth_user.get_instance()
pylons: remove pylons as dependency...
r2351
core: moved users and user groups autocomplete into pyramid....
r1666 return c
@LoginRequired()
@view_config(
route_name='user_autocomplete_data', request_method='GET',
renderer='json_ext', xhr=True)
def user_autocomplete_data(self):
views: load template context for XHR views....
r2308 self.load_default_context()
core: moved users and user groups autocomplete into pyramid....
r1666 query = self.request.GET.get('query')
active = str2bool(self.request.GET.get('active') or True)
include_groups = str2bool(self.request.GET.get('user_groups'))
pull-request-reviewers: added option to add reviewers by picking an user group for pull requests....
r1678 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
user-autocomplete: allow skipping default user.
r1768 skip_default_user = str2bool(self.request.GET.get('skip_default_user'))
core: moved users and user groups autocomplete into pyramid....
r1666
log.debug('generating user list, query:%s, active:%s, with_groups:%s',
query, active, include_groups)
users: moved get_users from RepoModel to UserModel.
r1677 _users = UserModel().get_users(
core: moved users and user groups autocomplete into pyramid....
r1666 name_contains=query, only_active=active)
user-autocomplete: allow skipping default user.
r1768 def maybe_skip_default_user(usr):
if skip_default_user and usr['username'] == UserModel.cls.DEFAULT_USER:
return False
return True
_users = filter(maybe_skip_default_user, _users)
core: moved users and user groups autocomplete into pyramid....
r1666 if include_groups:
# extend with user groups
user-groups: moved get_user_groups from RepoModel to UserGroupModel.
r1676 _user_groups = UserGroupModel().get_user_groups(
pull-request-reviewers: added option to add reviewers by picking an user group for pull requests....
r1678 name_contains=query, only_active=active,
expand_groups=expand_groups)
core: moved users and user groups autocomplete into pyramid....
r1666 _users = _users + _user_groups
return {'suggestions': _users}
@LoginRequired()
@NotAnonymous()
@view_config(
route_name='user_group_autocomplete_data', request_method='GET',
renderer='json_ext', xhr=True)
def user_group_autocomplete_data(self):
views: load template context for XHR views....
r2308 self.load_default_context()
core: moved users and user groups autocomplete into pyramid....
r1666 query = self.request.GET.get('query')
active = str2bool(self.request.GET.get('active') or True)
pull-request-reviewers: added option to add reviewers by picking an user group for pull requests....
r1678 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
core: moved users and user groups autocomplete into pyramid....
r1666 log.debug('generating user group list, query:%s, active:%s',
query, active)
user-groups: moved get_user_groups from RepoModel to UserGroupModel.
r1676 _user_groups = UserGroupModel().get_user_groups(
pull-request-reviewers: added option to add reviewers by picking an user group for pull requests....
r1678 name_contains=query, only_active=active,
expand_groups=expand_groups)
core: moved users and user groups autocomplete into pyramid....
r1666 _user_groups = _user_groups
return {'suggestions': _user_groups}
core: moved repo_list data to pyramid.
r1667
def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 org_query = name_contains
goto-switcher: optimized performance and query capabilities....
r2038 allowed_ids = self._rhodecode_user.repo_acl_ids(
['repository.read', 'repository.write', 'repository.admin'],
quick-filter: make sure we always apply IN filter query. Otherwise we can...
r2167 cache=False, name_filter=name_contains) or [-1]
goto-switcher: optimized performance and query capabilities....
r2038
core: moved repo_list data to pyramid.
r1667 query = Repository.query()\
.order_by(func.length(Repository.repo_name))\
goto-switcher: optimized performance and query capabilities....
r2038 .order_by(Repository.repo_name)\
repositories: added option to archive repositories instead of deleting them....
r3090 .filter(Repository.archived.isnot(true()))\
goto-switcher: optimized performance and query capabilities....
r2038 .filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(Repository.repo_id, allowed_ids)
))
core: moved repo_list data to pyramid.
r1667
if repo_type:
query = query.filter(Repository.repo_type == repo_type)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
Repository.repo_name.ilike(ilike_expression))
query = query.limit(limit)
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 acl_iter = query
goto-switcher: optimized performance and query capabilities....
r2038
core: moved repo_list data to pyramid.
r1667 return [
{
goto-switcher: optimized performance and query capabilities....
r2038 'id': obj.repo_name,
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'value': org_query,
'value_display': obj.repo_name,
goto-switcher: optimized performance and query capabilities....
r2038 'text': obj.repo_name,
core: moved repo_list data to pyramid.
r1667 'type': 'repo',
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'repo_id': obj.repo_id,
'repo_type': obj.repo_type,
'private': obj.private,
goto-switcher: optimized performance and query capabilities....
r2038 'url': h.route_path('repo_summary', repo_name=obj.repo_name)
core: moved repo_list data to pyramid.
r1667 }
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 for obj in acl_iter]
core: moved repo_list data to pyramid.
r1667
core: moved goto_switcher views into pyramid.
r1668 def _get_repo_group_list(self, name_contains=None, limit=20):
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 org_query = name_contains
goto-switcher: optimized performance and query capabilities....
r2038 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
['group.read', 'group.write', 'group.admin'],
quick-filter: make sure we always apply IN filter query. Otherwise we can...
r2167 cache=False, name_filter=name_contains) or [-1]
goto-switcher: optimized performance and query capabilities....
r2038
core: moved goto_switcher views into pyramid.
r1668 query = RepoGroup.query()\
.order_by(func.length(RepoGroup.group_name))\
goto-switcher: optimized performance and query capabilities....
r2038 .order_by(RepoGroup.group_name) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(RepoGroup.group_id, allowed_ids)
))
core: moved goto_switcher views into pyramid.
r1668
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
RepoGroup.group_name.ilike(ilike_expression))
query = query.limit(limit)
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 acl_iter = query
goto-switcher: optimized performance and query capabilities....
r2038
core: moved goto_switcher views into pyramid.
r1668 return [
{
'id': obj.group_name,
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'value': org_query,
'value_display': obj.group_name,
'type': 'repo_group',
goto-switcher: use special commit: prefix to explicitly search for commits....
r2035 'url': h.route_path(
'repo_group_home', repo_group_name=obj.group_name)
core: moved goto_switcher views into pyramid.
r1668 }
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 for obj in acl_iter]
def _get_user_list(self, name_contains=None, limit=20):
org_query = name_contains
if not name_contains:
return []
name_contains = re.compile('(?:user:)(.+)').findall(name_contains)
if len(name_contains) != 1:
return []
name_contains = name_contains[0]
query = User.query()\
.order_by(func.length(User.username))\
.order_by(User.username) \
.filter(User.username != User.DEFAULT_USER)
core: moved goto_switcher views into pyramid.
r1668
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
User.username.ilike(ilike_expression))
query = query.limit(limit)
acl_iter = query
return [
{
'id': obj.user_id,
'value': org_query,
'value_display': obj.username,
'type': 'user',
'icon_link': h.gravatar_url(obj.email, 30),
'url': h.route_path(
'user_profile', username=obj.username)
}
for obj in acl_iter]
quick-serach: added option to also search user-groups.
r2795 def _get_user_groups_list(self, name_contains=None, limit=20):
org_query = name_contains
if not name_contains:
return []
name_contains = re.compile('(?:user_group:)(.+)').findall(name_contains)
if len(name_contains) != 1:
return []
name_contains = name_contains[0]
query = UserGroup.query()\
.order_by(func.length(UserGroup.users_group_name))\
.order_by(UserGroup.users_group_name)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
UserGroup.users_group_name.ilike(ilike_expression))
query = query.limit(limit)
acl_iter = query
return [
{
'id': obj.users_group_id,
'value': org_query,
'value_display': obj.users_group_name,
'type': 'user_group',
'url': h.route_path(
'user_group_profile', user_group_name=obj.users_group_name)
}
for obj in acl_iter]
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 def _get_hash_commit_list(self, auth_user, query):
org_query = query
goto-switcher: use special commit: prefix to explicitly search for commits....
r2035 if not query or len(query) < 3:
core: moved goto_switcher views into pyramid.
r1668 return []
goto-switcher: use special commit: prefix to explicitly search for commits....
r2035 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
core: moved goto_switcher views into pyramid.
r1668
if len(commit_hashes) != 1:
return []
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 commit_hash = commit_hashes[0]
core: moved goto_switcher views into pyramid.
r1668
searcher = searcher_from_config(self.request.registry.settings)
result = searcher.search(
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'commit_id:%s*' % commit_hash, 'commit', auth_user,
core: moved goto_switcher views into pyramid.
r1668 raise_on_exc=False)
return [
{
'id': entry['commit_id'],
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'value': org_query,
'value_display': 'repo `{}` commit: {}'.format(
entry['repository'], entry['commit_id']),
core: moved goto_switcher views into pyramid.
r1668 'type': 'commit',
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 'repo': entry['repository'],
goto-switcher: use special commit: prefix to explicitly search for commits....
r2035 'url': h.route_path(
'repo_commit',
repo_name=entry['repository'], commit_id=entry['commit_id'])
core: moved goto_switcher views into pyramid.
r1668 }
for entry in result['results']]
core: moved repo_list data to pyramid.
r1667 @LoginRequired()
@view_config(
route_name='repo_list_data', request_method='GET',
renderer='json_ext', xhr=True)
def repo_list_data(self):
_ = self.request.translate
views: load template context for XHR views....
r2308 self.load_default_context()
core: moved repo_list data to pyramid.
r1667
query = self.request.GET.get('query')
repo_type = self.request.GET.get('repo_type')
log.debug('generating repo list, query:%s, repo_type:%s',
query, repo_type)
res = []
repos = self._get_repo_list(query, repo_type=repo_type)
if repos:
res.append({
'text': _('Repositories'),
'children': repos
})
data = {
'more': False,
'results': res
}
return data
core: moved goto_switcher views into pyramid.
r1668
@LoginRequired()
@view_config(
route_name='goto_switcher_data', request_method='GET',
renderer='json_ext', xhr=True)
def goto_switcher_data(self):
c = self.load_default_context()
_ = self.request.translate
query = self.request.GET.get('query')
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 log.debug('generating main filter data, query %s', query)
repo-switcher: fix unicode problem
r2787 default_search_val = u'Full text search for: `{}`'.format(query)
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 res = []
if not query:
return {'suggestions': res}
core: moved goto_switcher views into pyramid.
r1668
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 res.append({
'id': -1,
'value': query,
'value_display': default_search_val,
'type': 'search',
'url': h.route_path(
'search', _query={'q': query})
})
quick-search: use smart group search when browsing inside a repository group....
r2804 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
if repo_group_id:
repo_group = RepoGroup.get(repo_group_id)
composed_hint = '{}/{}'.format(repo_group.group_name, query)
show_hint = not query.startswith(repo_group.group_name)
if repo_group and show_hint:
hint = u'Group search: `{}`'.format(composed_hint)
res.append({
'id': -1,
'value': composed_hint,
'value_display': hint,
'type': 'hint',
'url': ""
})
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774
core: moved goto_switcher views into pyramid.
r1668 repo_groups = self._get_repo_group_list(query)
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 for serialized_repo_group in repo_groups:
res.append(serialized_repo_group)
core: moved goto_switcher views into pyramid.
r1668
repos = self._get_repo_list(query)
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 for serialized_repo in repos:
res.append(serialized_repo)
# TODO(marcink): permissions for that ?
search-bar: forbid anonymous users to search
r2776 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
if allowed_user_search:
users = self._get_user_list(query)
for serialized_user in users:
res.append(serialized_user)
core: moved goto_switcher views into pyramid.
r1668
quick-serach: added option to also search user-groups.
r2795 user_groups = self._get_user_groups_list(query)
for serialized_user_group in user_groups:
res.append(serialized_user_group)
core: moved goto_switcher views into pyramid.
r1668 commits = self._get_hash_commit_list(c.auth_user, query)
if commits:
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 unique_repos = collections.OrderedDict()
core: moved goto_switcher views into pyramid.
r1668 for commit in commits:
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 repo_name = commit['repo']
unique_repos.setdefault(repo_name, []).append(commit)
core: moved goto_switcher views into pyramid.
r1668
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 for repo, commits in unique_repos.items():
for commit in commits:
res.append(commit)
core: moved goto_switcher views into pyramid.
r1668
repo-switcher: new unified search box for filtering/accessing users, repos and repo groups....
r2774 return {'suggestions': res}
home: moved home and repo group views into pyramid....
r1774
def _get_groups_and_repos(self, repo_group_id=None):
# repo groups groups
repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
_perms = ['group.read', 'group.write', 'group.admin']
repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
repo_group_list=repo_group_list_acl, admin=False)
# repositories
repo_list = Repository.get_all_repos(group_id=repo_group_id)
_perms = ['repository.read', 'repository.write', 'repository.admin']
repo_list_acl = RepoList(repo_list, perm_set=_perms)
repo_data = RepoModel().get_repos_as_dict(
repo_list=repo_list_acl, admin=False)
return repo_data, repo_group_data
@LoginRequired()
@view_config(
route_name='home', request_method='GET',
renderer='rhodecode:templates/index.mako')
def main_page(self):
c = self.load_default_context()
c.repo_group = None
repo_data, repo_group_data = self._get_groups_and_repos()
# json used to render the grids
c.repos_data = json.dumps(repo_data)
c.repo_groups_data = json.dumps(repo_group_data)
return self._get_template_context(c)
@LoginRequired()
@HasRepoGroupPermissionAnyDecorator(
'group.read', 'group.write', 'group.admin')
@view_config(
route_name='repo_group_home', request_method='GET',
renderer='rhodecode:templates/index_repo_group.mako')
@view_config(
route_name='repo_group_home_slash', request_method='GET',
renderer='rhodecode:templates/index_repo_group.mako')
def repo_group_main_page(self):
c = self.load_default_context()
c.repo_group = self.request.db_repo_group
repo_data, repo_group_data = self._get_groups_and_repos(
c.repo_group.group_id)
# json used to render the grids
c.repos_data = json.dumps(repo_data)
c.repo_groups_data = json.dumps(repo_group_data)
return self._get_template_context(c)
pull-requests: allow markup rendered description.
r2816
@LoginRequired()
@CSRFRequired()
@view_config(
route_name='markup_preview', request_method='POST',
renderer='string', xhr=True)
def markup_preview(self):
# Technically a CSRF token is not needed as no state changes with this
# call. However, as this is a POST is better to have it, so automated
# tools don't flag it as potential CSRF.
# Post is required because the payload could be bigger than the maximum
# allowed by GET.
text = self.request.POST.get('text')
renderer = self.request.POST.get('renderer') or 'rst'
if text:
return h.render(text, renderer=renderer, mentions=True)
return ''
users: use new session store for temporary settings for users....
r3088
@LoginRequired()
@CSRFRequired()
@view_config(
route_name='store_user_session_value', request_method='POST',
renderer='string', xhr=True)
def store_user_session_attr(self):
key = self.request.POST.get('key')
val = self.request.POST.get('val')
existing_value = self.request.session.get(key)
if existing_value != val:
self.request.session[key] = val
return 'stored:{}'.format(key)