diff --git a/rhodecode/api/tests/test_get_gist.py b/rhodecode/api/tests/test_get_gist.py --- a/rhodecode/api/tests/test_get_gist.py +++ b/rhodecode/api/tests/test_get_gist.py @@ -28,7 +28,7 @@ from rhodecode.api.tests.utils import ( @pytest.mark.usefixtures("testuser_api", "app") class TestApiGetGist(object): - def test_api_get_gist(self, gist_util): + def test_api_get_gist(self, gist_util, http_host_stub): gist = gist_util.create_gist() gist_id = gist.gist_access_id gist_created_on = gist.created_on @@ -45,14 +45,14 @@ class TestApiGetGist(object): 'expires': -1.0, 'gist_id': int(gist_id), 'type': 'public', - 'url': 'http://test.example.com:80/_admin/gists/%s' % (gist_id,), + 'url': 'http://%s/_admin/gists/%s' % (http_host_stub, gist_id,), 'acl_level': Gist.ACL_LEVEL_PUBLIC, 'content': None, } assert_ok(id_, expected, given=response.body) - def test_api_get_gist_with_content(self, gist_util): + def test_api_get_gist_with_content(self, gist_util, http_host_stub): mapping = { u'filename1.txt': {'content': u'hello world'}, u'filename1ą.txt': {'content': u'hello worldę'} @@ -73,7 +73,7 @@ class TestApiGetGist(object): 'expires': -1.0, 'gist_id': int(gist_id), 'type': 'public', - 'url': 'http://test.example.com:80/_admin/gists/%s' % (gist_id,), + 'url': 'http://%s/_admin/gists/%s' % (http_host_stub, gist_id,), 'acl_level': Gist.ACL_LEVEL_PUBLIC, 'content': { u'filename1.txt': u'hello world', diff --git a/rhodecode/api/tests/test_get_pull_request.py b/rhodecode/api/tests/test_get_pull_request.py --- a/rhodecode/api/tests/test_get_pull_request.py +++ b/rhodecode/api/tests/test_get_pull_request.py @@ -19,13 +19,13 @@ # and proprietary license terms, please see https://rhodecode.com/licenses/ -import mock import pytest import urlobject from pylons import url from rhodecode.api.tests.utils import ( build_data, api_call, assert_error, assert_ok) +from rhodecode.lib.utils2 import safe_unicode pytestmark = pytest.mark.backends("git", "hg") @@ -33,7 +33,7 @@ pytestmark = pytest.mark.backends("git", @pytest.mark.usefixtures("testuser_api", "app") class TestGetPullRequest(object): - def test_api_get_pull_request(self, pr_util): + def test_api_get_pull_request(self, pr_util, http_host_stub, http_host_only_stub): from rhodecode.model.pull_request import PullRequestModel pull_request = pr_util.create_pull_request(mergeable=True) id_, params = build_data( @@ -50,16 +50,16 @@ class TestGetPullRequest(object): 'pullrequest_show', repo_name=pull_request.target_repo.repo_name, pull_request_id=pull_request.pull_request_id, qualified=True)) - pr_url = unicode( - url_obj.with_netloc('test.example.com:80')) - source_url = unicode( - pull_request.source_repo.clone_url() - .with_netloc('test.example.com:80')) - target_url = unicode( - pull_request.target_repo.clone_url() - .with_netloc('test.example.com:80')) - shadow_url = unicode( + + pr_url = safe_unicode( + url_obj.with_netloc(http_host_stub)) + source_url = safe_unicode( + pull_request.source_repo.clone_url().with_netloc(http_host_only_stub)) + target_url = safe_unicode( + pull_request.target_repo.clone_url().with_netloc(http_host_only_stub)) + shadow_url = safe_unicode( PullRequestModel().get_shadow_clone_url(pull_request)) + expected = { 'pull_request_id': pull_request.pull_request_id, 'url': pr_url, diff --git a/rhodecode/api/tests/test_update_repo.py b/rhodecode/api/tests/test_update_repo.py --- a/rhodecode/api/tests/test_update_repo.py +++ b/rhodecode/api/tests/test_update_repo.py @@ -26,7 +26,7 @@ from rhodecode.tests import TEST_USER_AD from rhodecode.api.tests.utils import ( build_data, api_call, assert_error, assert_ok, crash, jsonify) from rhodecode.tests.fixture import Fixture - +from rhodecode.tests.plugin import http_host_stub, http_host_only_stub fixture = Fixture() @@ -71,14 +71,15 @@ class TestApiUpdateRepo(object): ({'repo_name': 'new_repo_name'}, { 'repo_name': 'new_repo_name', - 'url': 'http://test.example.com:80/new_repo_name' + 'url': 'http://{}/new_repo_name'.format(http_host_only_stub()) }), ({'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), '_group': 'test_group_for_update'}, { 'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), - 'url': 'http://test.example.com:80/test_group_for_update/{}'.format(UPDATE_REPO_NAME) + 'url': 'http://{}/test_group_for_update/{}'.format( + http_host_only_stub(), UPDATE_REPO_NAME) }), ]) def test_api_update_repo(self, updates, expected, backend): diff --git a/rhodecode/apps/__init__.py b/rhodecode/apps/__init__.py --- a/rhodecode/apps/__init__.py +++ b/rhodecode/apps/__init__.py @@ -0,0 +1,19 @@ +# -*- 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 . +# +# 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/ diff --git a/rhodecode/apps/_base/__init__.py b/rhodecode/apps/_base/__init__.py --- a/rhodecode/apps/_base/__init__.py +++ b/rhodecode/apps/_base/__init__.py @@ -29,6 +29,7 @@ from rhodecode.lib.utils2 import StrictA from rhodecode.lib.vcs.exceptions import RepositoryRequirementError from rhodecode.lib.ext_json import json from rhodecode.model import repo +from rhodecode.model import repo_group from rhodecode.model.db import User from rhodecode.model.scm import ScmModel @@ -39,6 +40,12 @@ ADMIN_PREFIX = '/_admin' STATIC_FILE_PREFIX = '/_static' +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) + + def get_format_ref_id(repo): """Returns a `repo` specific reference formatter function""" if h.is_svn(repo): @@ -253,8 +260,7 @@ class RepoRoutePredicate(object): repo_name = info['match']['repo_name'] repo_model = repo.RepoModel() by_name_match = repo_model.get_by_repo_name(repo_name, cache=True) - # if we match quickly from database, short circuit the operation, - # and validate repo based on the type. + if by_name_match: # register this as request object we can re-use later request.db_repo = by_name_match @@ -300,9 +306,33 @@ class RepoTypeRoutePredicate(object): return False +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): + 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 + def includeme(config): config.add_route_predicate( 'repo_route', RepoRoutePredicate) config.add_route_predicate( - 'repo_accepted_types', RepoTypeRoutePredicate) \ No newline at end of file + 'repo_accepted_types', RepoTypeRoutePredicate) + config.add_route_predicate( + 'repo_group_route', RepoGroupRoutePredicate) diff --git a/rhodecode/tests/functional/test_home.py b/rhodecode/apps/home/tests/test_home.py rename from rhodecode/tests/functional/test_home.py rename to rhodecode/apps/home/tests/test_home.py --- a/rhodecode/tests/functional/test_home.py +++ b/rhodecode/apps/home/tests/test_home.py @@ -28,18 +28,25 @@ from rhodecode.model.meta import Session from rhodecode.model.repo import RepoModel from rhodecode.model.repo_group import RepoGroupModel from rhodecode.model.settings import SettingsModel -from rhodecode.tests import TestController, url +from rhodecode.tests import TestController from rhodecode.tests.fixture import Fixture fixture = Fixture() +def route_path(name, **kwargs): + return { + 'home': '/', + 'repo_group_home': '/{repo_group_name}' + }[name].format(**kwargs) + + class TestHomeController(TestController): def test_index(self): self.log_user() - response = self.app.get(url(controller='home', action='index')) + response = self.app.get(route_path('home')) # if global permission is set response.mustcontain('Add Repository') @@ -49,7 +56,7 @@ class TestHomeController(TestController) def test_index_contains_statics_with_ver(self): self.log_user() - response = self.app.get(url(controller='home', action='index')) + response = self.app.get(route_path('home')) rhodecode_version_hash = c.rhodecode_version_hash response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash)) @@ -57,7 +64,7 @@ class TestHomeController(TestController) def test_index_contains_backend_specific_details(self, backend): self.log_user() - response = self.app.get(url(controller='home', action='index')) + response = self.app.get(route_path('home')) tip = backend.repo.get_commit().raw_id # html in javascript variable: @@ -69,17 +76,16 @@ class TestHomeController(TestController) def test_index_with_anonymous_access_disabled(self): with fixture.anon_access(False): - response = self.app.get(url(controller='home', action='index'), - status=302) + response = self.app.get(route_path('home'), status=302) assert 'login' in response.location def test_index_page_on_groups(self, autologin_user, repo_group): - response = self.app.get(url('repo_group_home', group_name='gr1')) + response = self.app.get(route_path('repo_group_home', repo_group_name='gr1')) response.mustcontain("gr1/repo_in_group") def test_index_page_on_group_with_trailing_slash( self, autologin_user, repo_group): - response = self.app.get(url('repo_group_home', group_name='gr1') + '/') + response = self.app.get(route_path('repo_group_home', repo_group_name='gr1') + '/') response.mustcontain("gr1/repo_in_group") @pytest.fixture(scope='class') @@ -93,15 +99,17 @@ class TestHomeController(TestController) RepoGroupModel().delete(repo_group='gr1', force_delete=True) Session().commit() - def test_index_with_name_with_tags(self, autologin_user): - user = User.get_by_username('test_admin') + def test_index_with_name_with_tags(self, user_util, autologin_user): + user = user_util.create_user() + username = user.username user.name = '' user.lastname = ( '') Session().add(user) Session().commit() + user_util.create_repo(owner=username) - response = self.app.get(url(controller='home', action='index')) + response = self.app.get(route_path('home')) response.mustcontain( '<img src="/image1" onload="' 'alert('Hello, World!');">') @@ -122,7 +130,7 @@ class TestHomeController(TestController) Session().commit() SettingsModel().invalidate_settings_cache() - response = self.app.get(url(controller='home', action='index')) + response = self.app.get(route_path('home')) if state is True: response.mustcontain(version_string) if state is False: diff --git a/rhodecode/apps/home/views.py b/rhodecode/apps/home/views.py --- a/rhodecode/apps/home/views.py +++ b/rhodecode/apps/home/views.py @@ -25,12 +25,15 @@ from pyramid.view import view_config from rhodecode.apps._base import BaseAppView from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, NotAnonymous +from rhodecode.lib.auth import LoginRequired, NotAnonymous, \ + HasRepoGroupPermissionAnyDecorator from rhodecode.lib.index import searcher_from_config from rhodecode.lib.utils2 import safe_unicode, str2bool +from rhodecode.lib.ext_json import json from rhodecode.model.db import func, Repository, RepoGroup from rhodecode.model.repo import RepoModel -from rhodecode.model.scm import ScmModel +from rhodecode.model.repo_group import RepoGroupModel +from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList from rhodecode.model.user import UserModel from rhodecode.model.user_group import UserGroupModel @@ -143,7 +146,7 @@ class HomeView(BaseAppView): 'text': obj.group_name, 'type': 'group', 'obj': {}, - 'url': h.url('repo_group_home', group_name=obj.group_name) + 'url': h.route_path('repo_group_home', repo_group_name=obj.group_name) } for obj in repo_groups_iter] @@ -246,3 +249,56 @@ class HomeView(BaseAppView): 'results': res } return data + + 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) diff --git a/rhodecode/apps/login/views.py b/rhodecode/apps/login/views.py --- a/rhodecode/apps/login/views.py +++ b/rhodecode/apps/login/views.py @@ -25,7 +25,6 @@ import formencode import logging import urlparse -from pylons import url from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config from recaptcha.client.captcha import submit @@ -91,20 +90,21 @@ def get_came_from(request): came_from = safe_str(request.GET.get('came_from', '')) parsed = urlparse.urlparse(came_from) allowed_schemes = ['http', 'https'] + default_came_from = h.route_path('home') if parsed.scheme and parsed.scheme not in allowed_schemes: log.error('Suspicious URL scheme detected %s for url %s' % (parsed.scheme, parsed)) - came_from = url('home') + came_from = default_came_from elif parsed.netloc and request.host != parsed.netloc: log.error('Suspicious NETLOC detected %s for url %s server url ' 'is: %s' % (parsed.netloc, parsed, request.host)) - came_from = url('home') + came_from = default_came_from elif any(bad_str in parsed.path for bad_str in ('\r', '\n')): log.error('Header injection detected `%s` for url %s server url ' % (parsed.path, parsed)) - came_from = url('home') + came_from = default_came_from - return came_from or url('home') + return came_from or default_came_from class LoginView(BaseAppView): @@ -215,7 +215,7 @@ class LoginView(BaseAppView): action='user.logout', action_data=action_data, user=auth_user, commit=True) self.session.delete() - return HTTPFound(url('home')) + return HTTPFound(h.route_path('home')) @HasPermissionAnyDecorator( 'hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate') diff --git a/rhodecode/apps/my_account/tests/test_my_account_password.py b/rhodecode/apps/my_account/tests/test_my_account_password.py --- a/rhodecode/apps/my_account/tests/test_my_account_password.py +++ b/rhodecode/apps/my_account/tests/test_my_account_password.py @@ -132,6 +132,7 @@ class TestMyAccountPassword(TestControll self.app.post(route_path('my_account_password'), form_data) response = self.app.get(route_path('home')) - new_password_hash = response.session['rhodecode_user']['password'] + session = response.get_session_from_response() + new_password_hash = session['rhodecode_user']['password'] assert old_password_hash != new_password_hash \ No newline at end of file diff --git a/rhodecode/apps/repo_group/__init__.py b/rhodecode/apps/repo_group/__init__.py new file mode 100644 --- /dev/null +++ b/rhodecode/apps/repo_group/__init__.py @@ -0,0 +1,33 @@ +# -*- 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 . +# +# 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/ +from rhodecode.apps._base import add_route_with_slash + + +def includeme(config): + + # Summary + add_route_with_slash( + config, + name='repo_group_home', + pattern='/{repo_group_name:.*?[^/]}', repo_group_route=True) + + # Scan module for configuration decorators. + config.scan() + diff --git a/rhodecode/apps/repository/__init__.py b/rhodecode/apps/repository/__init__.py --- a/rhodecode/apps/repository/__init__.py +++ b/rhodecode/apps/repository/__init__.py @@ -23,6 +23,10 @@ def includeme(config): # Summary config.add_route( + name='repo_summary', + pattern='/{repo_name:.*?[^/]}', repo_route=True) + + config.add_route( name='repo_summary_explicit', pattern='/{repo_name:.*?[^/]}/summary', repo_route=True) diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -292,6 +292,7 @@ def includeme(config): config.include('rhodecode.apps.login') config.include('rhodecode.apps.home') config.include('rhodecode.apps.repository') + config.include('rhodecode.apps.repo_group') config.include('rhodecode.apps.search') config.include('rhodecode.apps.user_profile') config.include('rhodecode.apps.my_account') diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -184,9 +184,6 @@ def make_map(config): # CUSTOM ROUTES HERE #========================================================================== - # MAIN PAGE - rmap.connect('home', '/', controller='home', action='index') - # ping and pylons error test rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping') rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test') @@ -1002,13 +999,6 @@ def make_map(config): conditions={'function': check_repo}, requirements=URL_NAME_REQUIREMENTS) - # must be here for proper group/repo catching pattern - _connect_with_slash( - rmap, 'repo_group_home', '/{group_name}', - controller='home', action='index_repo_group', - conditions={'function': check_group}, - requirements=URL_NAME_REQUIREMENTS) - # catch all, at the end _connect_with_slash( rmap, 'summary_home', '/{repo_name}', jsroute=True, diff --git a/rhodecode/controllers/admin/repo_groups.py b/rhodecode/controllers/admin/repo_groups.py --- a/rhodecode/controllers/admin/repo_groups.py +++ b/rhodecode/controllers/admin/repo_groups.py @@ -193,10 +193,10 @@ class RepoGroupsController(BaseControlle _new_group_name = form_result['group_name_full'] repo_group_url = h.link_to( _new_group_name, - h.url('repo_group_home', group_name=_new_group_name)) + h.route_path('repo_group_home', repo_group_name=_new_group_name)) h.flash(h.literal(_('Created repository group %s') % repo_group_url), category='success') - # TODO: in futureaction_logger(, '', '', '', self.sa) + # TODO: in future action_logger(, '', '', '', self.sa) except formencode.Invalid as errors: return htmlfill.render( render('admin/repo_groups/repo_group_add.mako'), @@ -234,7 +234,6 @@ class RepoGroupsController(BaseControlle # # Or using helpers: # h.form(url('repos_group', group_name=GROUP_NAME), method='put') - # url('repo_group_home', group_name=GROUP_NAME) c.repo_group = RepoGroupModel()._get_repo_group(group_name) can_create_in_root = self._can_create_repo_group() @@ -284,7 +283,6 @@ class RepoGroupsController(BaseControlle # # Or using helpers: # h.form(url('repos_group', group_name=GROUP_NAME), method='delete') - # url('repo_group_home', group_name=GROUP_NAME) gr = c.repo_group = RepoGroupModel()._get_repo_group(group_name) repos = gr.repositories.all() diff --git a/rhodecode/controllers/admin/repos.py b/rhodecode/controllers/admin/repos.py --- a/rhodecode/controllers/admin/repos.py +++ b/rhodecode/controllers/admin/repos.py @@ -185,7 +185,7 @@ class ReposController(BaseRepoController except Exception as e: msg = self._log_creation_exception(e, form_result.get('repo_name')) h.flash(msg, category='error') - return redirect(url('home')) + return redirect(h.route_path('home')) return redirect(h.url('repo_creating_home', repo_name=form_result['repo_name_full'], @@ -265,7 +265,7 @@ class ReposController(BaseRepoController if task.failed(): msg = self._log_creation_exception(task.result, c.repo) h.flash(msg, category='error') - return redirect(url('home'), code=501) + return redirect(h.route_path('home'), code=501) repo = Repository.get_by_repo_name(repo_name) if repo and repo.repo_state == Repository.STATE_CREATED: diff --git a/rhodecode/controllers/forks.py b/rhodecode/controllers/forks.py --- a/rhodecode/controllers/forks.py +++ b/rhodecode/controllers/forks.py @@ -139,7 +139,7 @@ class ForksController(BaseRepoController c.repo_info = Repository.get_by_repo_name(repo_name) if not c.repo_info: h.not_mapped_error(repo_name) - return redirect(url('home')) + return redirect(h.route_path('home')) defaults = self.__load_data(repo_name) diff --git a/rhodecode/controllers/home.py b/rhodecode/controllers/home.py --- a/rhodecode/controllers/home.py +++ b/rhodecode/controllers/home.py @@ -65,46 +65,3 @@ class HomeController(BaseController): msg = ('RhodeCode Enterprise %s test exception. Generation time: %s' % (c.rhodecode_name, time.time())) raise TestException(msg) - - 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() - def index(self): - 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 render('/index.mako') - - @LoginRequired() - @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write', - 'group.admin') - def index_repo_group(self, group_name): - """GET /repo_group_name: Show a specific item""" - c.repo_group = RepoGroupModel()._get_repo_group(group_name) - 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 render('index_repo_group.mako') diff --git a/rhodecode/events/base.py b/rhodecode/events/base.py --- a/rhodecode/events/base.py +++ b/rhodecode/events/base.py @@ -82,7 +82,7 @@ class RhodecodeEvent(object): if self.request: from rhodecode.lib import helpers as h try: - return h.url('home', qualified=True) + return h.route_url('home') except Exception: log.exception('Failed to fetch URL for server') return default diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -1377,7 +1377,7 @@ class PermsDecorator(object): if anonymous: came_from = self._get_came_from() h.flash(_('You need to be signed in to view this page'), - category='warning') + category='warning') raise HTTPFound( h.route_path('login', _query={'came_from': came_from})) @@ -1429,10 +1429,16 @@ class HasRepoPermissionAllDecorator(Perm def check_permissions(self, user): perms = user.permissions repo_name = self._get_repo_name() + try: user_perms = set([perms['repositories'][repo_name]]) except KeyError: + log.debug('cannot locate repo with name: `%s` in permissions defs', + repo_name) return False + + log.debug('checking `%s` permissions for repo `%s`', + user_perms, repo_name) if self.required_perms.issubset(user_perms): return True return False @@ -1450,11 +1456,16 @@ class HasRepoPermissionAnyDecorator(Perm def check_permissions(self, user): perms = user.permissions repo_name = self._get_repo_name() + try: user_perms = set([perms['repositories'][repo_name]]) except KeyError: + log.debug('cannot locate repo with name: `%s` in permissions defs', + repo_name) return False + log.debug('checking `%s` permissions for repo `%s`', + user_perms, repo_name) if self.required_perms.intersection(user_perms): return True return False @@ -1476,8 +1487,12 @@ class HasRepoGroupPermissionAllDecorator try: user_perms = set([perms['repositories_groups'][group_name]]) except KeyError: + log.debug('cannot locate repo group with name: `%s` in permissions defs', + group_name) return False + log.debug('checking `%s` permissions for repo group `%s`', + user_perms, group_name) if self.required_perms.issubset(user_perms): return True return False @@ -1496,11 +1511,16 @@ class HasRepoGroupPermissionAnyDecorator def check_permissions(self, user): perms = user.permissions group_name = self._get_repo_group_name() + try: user_perms = set([perms['repositories_groups'][group_name]]) except KeyError: + log.debug('cannot locate repo group with name: `%s` in permissions defs', + group_name) return False + log.debug('checking `%s` permissions for repo group `%s`', + user_perms, group_name) if self.required_perms.intersection(user_perms): return True return False diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -555,7 +555,7 @@ class BaseRepoController(BaseController) "The repository at %(repo_name)s cannot be located.") % {'repo_name': c.repo_name}, category='error', ignore_duplicate=True) - redirect(url('home')) + redirect(h.route_path('home')) # update last change according to VCS data if not missing_requirements: diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -1534,7 +1534,7 @@ def breadcrumb_repo_link(repo): """ path = [ - link_to(group.name, url('repo_group_home', group_name=group.group_name)) + link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name)) for group in repo.groups_with_parents ] + [ link_to(repo.just_name, url('summary_home', repo_name=repo.repo_name)) @@ -1960,24 +1960,24 @@ def get_last_path_part(file_node): return u'../' + path -def route_url(*args, **kwds): +def route_url(*args, **kwargs): """ Wrapper around pyramids `route_url` (fully qualified url) function. It is used to generate URLs from within pylons views or templates. This will be removed when pyramid migration if finished. """ req = get_current_request() - return req.route_url(*args, **kwds) + return req.route_url(*args, **kwargs) -def route_path(*args, **kwds): +def route_path(*args, **kwargs): """ Wrapper around pyramids `route_path` function. It is used to generate URLs from within pylons views or templates. This will be removed when pyramid migration if finished. """ req = get_current_request() - return req.route_path(*args, **kwds) + return req.route_path(*args, **kwargs) def route_path_or_none(*args, **kwargs): diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -96,10 +96,11 @@ def repo_name_slug(value): # PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS #============================================================================== def get_repo_slug(request): - if isinstance(request, Request) and getattr(request, 'matchdict', None): + if isinstance(request, Request) and getattr(request, 'db_repo', None): # pyramid - _repo = request.matchdict.get('repo_name') + _repo = request.db_repo.repo_name else: + # TODO(marcink): remove after pylons migration... _repo = request.environ['pylons.routes_dict'].get('repo_name') if _repo: @@ -110,7 +111,7 @@ def get_repo_slug(request): def get_repo_group_slug(request): if isinstance(request, Request) and getattr(request, 'matchdict', None): # pyramid - _group = request.matchdict.get('group_name') + _group = request.matchdict.get('repo_group_name') else: _group = request.environ['pylons.routes_dict'].get('group_name') diff --git a/rhodecode/lib/utils2.py b/rhodecode/lib/utils2.py --- a/rhodecode/lib/utils2.py +++ b/rhodecode/lib/utils2.py @@ -572,7 +572,8 @@ def credentials_filter(uri): return ''.join(uri) -def get_clone_url(uri_tmpl, qualifed_home_url, repo_name, repo_id, **override): +def get_clone_url(request, uri_tmpl, repo_name, repo_id, **override): + qualifed_home_url = request.route_url('home') parsed_url = urlobject.URLObject(qualifed_home_url) decoded_path = safe_unicode(urllib.unquote(parsed_url.path.rstrip('/'))) args = { diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -44,8 +44,8 @@ from sqlalchemy.sql.expression import tr from beaker.cache import cache_region from zope.cachedescriptors.property import Lazy as LazyProperty -from pylons import url from pylons.i18n.translation import lazy_ugettext as _ +from pyramid.threadlocal import get_current_request from rhodecode.lib.vcs import get_vcs_instance from rhodecode.lib.vcs.backends.base import EmptyCommit, Reference @@ -1774,7 +1774,7 @@ class Repository(Base, BaseModel): 'repo_name': repo.repo_name, 'repo_type': repo.repo_type, 'clone_uri': repo.clone_uri or '', - 'url': url('summary_home', repo_name=self.repo_name, qualified=True), + 'url': repo.home_url(), 'private': repo.private, 'created_on': repo.created_on, 'description': repo.description, @@ -1908,7 +1908,6 @@ class Repository(Base, BaseModel): return clone_uri def clone_url(self, **override): - qualified_home_url = url('home', qualified=True) uri_tmpl = None if 'with_id' in override: @@ -1930,11 +1929,16 @@ class Repository(Base, BaseModel): # ie, not having tmpl_context set up pass - return get_clone_url(uri_tmpl=uri_tmpl, - qualifed_home_url=qualified_home_url, + request = get_current_request() + return get_clone_url(request=request, + uri_tmpl=uri_tmpl, repo_name=self.repo_name, repo_id=self.repo_id, **override) + def home_url(self): + request = get_current_request() + return request.route_url('repo_summary', repo_name=self.repo_name) + def set_state(self, state): self.repo_state = state Session().add(self) @@ -3299,6 +3303,7 @@ class _PullRequestBase(BaseModel): return None def get_api_data(self): + from pylons import url from rhodecode.model.pull_request import PullRequestModel pull_request = self merge_status = PullRequestModel().merge_status(pull_request) @@ -3690,6 +3695,8 @@ class Gist(Base, BaseModel): def gist_url(self): import rhodecode + from pylons import url + alias_url = rhodecode.CONFIG.get('gist_alias_url') if alias_url: return alias_url.replace('{gistid}', self.gist_access_id) diff --git a/rhodecode/model/notification.py b/rhodecode/model/notification.py --- a/rhodecode/model/notification.py +++ b/rhodecode/model/notification.py @@ -334,9 +334,9 @@ class EmailNotificationModel(BaseModel): """ kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name - + instance_url = h.route_url('home') _kwargs = { - 'instance_url': h.url('home', qualified=True), + 'instance_url': instance_url, 'whitespace_filter': self.whitespace_filter } _kwargs.update(kwargs) diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -131,6 +131,7 @@ class RepoModel(BaseModel): :param repo_name: :return: repo object if matched else None """ + try: _repo_id = self._extract_id_from_repo_name(repo_name) if _repo_id: diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -99,6 +99,7 @@ function registerRCRoutes() { pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); pyroutes.register('repo_list_data', '/_repos', []); pyroutes.register('goto_switcher_data', '/_goto_data', []); + pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']); pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']); pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); @@ -121,6 +122,8 @@ function registerRCRoutes() { pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']); pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']); pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']); + pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']); + pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']); pyroutes.register('search', '/_admin/search', []); pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']); pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']); diff --git a/rhodecode/templates/admin/integrations/list.mako b/rhodecode/templates/admin/integrations/list.mako --- a/rhodecode/templates/admin/integrations/list.mako +++ b/rhodecode/templates/admin/integrations/list.mako @@ -164,7 +164,7 @@ ${_('repo')}:${integration.repo.repo_name} %elif integration.repo_group: - + ${_('repogroup')}:${integration.repo_group.group_name} %if integration.child_repos_only: ${_('child repos only')} diff --git a/rhodecode/templates/admin/repo_groups/repo_group_edit.mako b/rhodecode/templates/admin/repo_groups/repo_group_edit.mako --- a/rhodecode/templates/admin/repo_groups/repo_group_edit.mako +++ b/rhodecode/templates/admin/repo_groups/repo_group_edit.mako @@ -13,7 +13,7 @@ » ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} %if c.repo_group.parent_group: - » ${h.link_to(c.repo_group.parent_group.name,h.url('repo_group_home',group_name=c.repo_group.parent_group.group_name))} + » ${h.link_to(c.repo_group.parent_group.name, h.route_path('repo_group_home', repo_group_name=c.repo_group.parent_group.group_name))} %endif » ${c.repo_group.name} diff --git a/rhodecode/templates/admin/repos/repo_creating.mako b/rhodecode/templates/admin/repos/repo_creating.mako --- a/rhodecode/templates/admin/repos/repo_creating.mako +++ b/rhodecode/templates/admin/repos/repo_creating.mako @@ -61,7 +61,7 @@ } } else { - window.location = "${h.url('home')}"; + window.location = "${h.route_path('home')}"; } } }); diff --git a/rhodecode/templates/admin/users/user_edit_advanced.mako b/rhodecode/templates/admin/users/user_edit_advanced.mako --- a/rhodecode/templates/admin/users/user_edit_advanced.mako +++ b/rhodecode/templates/admin/users/user_edit_advanced.mako @@ -59,7 +59,7 @@ ${h.secure_form(h.url('create_personal_repo_group', user_id=c.user.user_id), method='post')} %if c.personal_repo_group: -
${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, url('repo_group_home', group_name=c.personal_repo_group.group_name))}
+
${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, h.route_path('repo_group_home', repo_group_name=c.personal_repo_group.group_name))}
%else:
${_('This user currently does not have a personal repository group')} diff --git a/rhodecode/templates/base/base.mako b/rhodecode/templates/base/base.mako --- a/rhodecode/templates/base/base.mako +++ b/rhodecode/templates/base/base.mako @@ -7,7 +7,7 @@