diff --git a/rhodecode/integrations/routes.py b/rhodecode/integrations/routes.py
--- a/rhodecode/integrations/routes.py
+++ b/rhodecode/integrations/routes.py
@@ -21,6 +21,7 @@
import logging
from rhodecode.apps._base import ADMIN_PREFIX, add_route_requirements
+from rhodecode.lib.utils2 import safe_int
from rhodecode.model.db import Repository, Integration, RepoGroup
from rhodecode.integrations import integration_type_registry
@@ -30,7 +31,6 @@ log = logging.getLogger(__name__)
def includeme(config):
# global integrations
-
config.add_route('global_integrations_new',
ADMIN_PREFIX + '/integrations/new')
config.add_view('rhodecode.integrations.views.GlobalIntegrationsView',
@@ -45,7 +45,7 @@ def includeme(config):
ADMIN_PREFIX + '/integrations/{integration}')
for route_name in ['global_integrations_home', 'global_integrations_list']:
config.add_view('rhodecode.integrations.views.GlobalIntegrationsView',
- attr='index',
+ attr='integration_list',
renderer='rhodecode:templates/admin/integrations/list.mako',
request_method='GET',
route_name=route_name)
@@ -57,7 +57,6 @@ def includeme(config):
ADMIN_PREFIX + '/integrations/{integration}/{integration_id}',
custom_predicates=(valid_integration,))
-
for route_name in ['global_integrations_create', 'global_integrations_edit']:
config.add_view('rhodecode.integrations.views.GlobalIntegrationsView',
attr='settings_get',
@@ -70,154 +69,159 @@ def includeme(config):
request_method='POST',
route_name=route_name)
-
# repo group integrations
config.add_route('repo_group_integrations_home',
- add_route_requirements(
- '{repo_group_name}/settings/integrations',
- ),
- custom_predicates=(valid_repo_group,)
- )
- config.add_route('repo_group_integrations_list',
- add_route_requirements(
- '{repo_group_name}/settings/integrations/{integration}',
- ),
- custom_predicates=(valid_repo_group, valid_integration))
- for route_name in ['repo_group_integrations_home', 'repo_group_integrations_list']:
- config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
- attr='index',
- renderer='rhodecode:templates/admin/integrations/list.mako',
- request_method='GET',
- route_name=route_name)
+ add_route_requirements('/{repo_group_name}/settings/integrations'),
+ repo_group_route=True)
+
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='integration_list',
+ renderer='rhodecode:templates/admin/integrations/list.mako',
+ request_method='GET',
+ route_name='repo_group_integrations_home')
config.add_route('repo_group_integrations_new',
- add_route_requirements(
- '{repo_group_name}/settings/integrations/new',
- ),
- custom_predicates=(valid_repo_group,))
+ add_route_requirements('/{repo_group_name}/settings/integrations/new'),
+ repo_group_route=True)
config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
attr='new_integration',
renderer='rhodecode:templates/admin/integrations/new.mako',
request_method='GET',
route_name='repo_group_integrations_new')
+ config.add_route('repo_group_integrations_list',
+ add_route_requirements('/{repo_group_name}/settings/integrations/{integration}'),
+ repo_group_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='integration_list',
+ renderer='rhodecode:templates/admin/integrations/list.mako',
+ request_method='GET',
+ route_name='repo_group_integrations_list')
+
config.add_route('repo_group_integrations_create',
- add_route_requirements(
- '{repo_group_name}/settings/integrations/{integration}/new',
- ),
- custom_predicates=(valid_repo_group, valid_integration))
+ add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/new'),
+ repo_group_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='settings_get',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='GET',
+ route_name='repo_group_integrations_create')
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='settings_post',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='POST',
+ route_name='repo_group_integrations_create')
+
config.add_route('repo_group_integrations_edit',
- add_route_requirements(
- '{repo_group_name}/settings/integrations/{integration}/{integration_id}',
- ),
- custom_predicates=(valid_repo_group, valid_integration))
- for route_name in ['repo_group_integrations_edit', 'repo_group_integrations_create']:
- config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
- attr='settings_get',
- renderer='rhodecode:templates/admin/integrations/form.mako',
- request_method='GET',
- route_name=route_name)
- config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
- attr='settings_post',
- renderer='rhodecode:templates/admin/integrations/form.mako',
- request_method='POST',
- route_name=route_name)
+ add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/{integration_id}'),
+ repo_group_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='settings_get',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='GET',
+ route_name='repo_group_integrations_edit')
+ config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView',
+ attr='settings_post',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='POST',
+ route_name='repo_group_integrations_edit')
# repo integrations
config.add_route('repo_integrations_home',
- add_route_requirements(
- '{repo_name}/settings/integrations',
- ),
- custom_predicates=(valid_repo,))
- config.add_route('repo_integrations_list',
- add_route_requirements(
- '{repo_name}/settings/integrations/{integration}',
- ),
- custom_predicates=(valid_repo, valid_integration))
- for route_name in ['repo_integrations_home', 'repo_integrations_list']:
- config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
- attr='index',
- request_method='GET',
- renderer='rhodecode:templates/admin/integrations/list.mako',
- route_name=route_name)
+ add_route_requirements('/{repo_name}/settings/integrations'),
+ repo_route=True)
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='integration_list',
+ request_method='GET',
+ renderer='rhodecode:templates/admin/integrations/list.mako',
+ route_name='repo_integrations_home')
config.add_route('repo_integrations_new',
- add_route_requirements(
- '{repo_name}/settings/integrations/new',
- ),
- custom_predicates=(valid_repo,))
+ add_route_requirements('/{repo_name}/settings/integrations/new'),
+ repo_route=True)
config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
attr='new_integration',
renderer='rhodecode:templates/admin/integrations/new.mako',
request_method='GET',
route_name='repo_integrations_new')
+ config.add_route('repo_integrations_list',
+ add_route_requirements('/{repo_name}/settings/integrations/{integration}'),
+ repo_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='integration_list',
+ request_method='GET',
+ renderer='rhodecode:templates/admin/integrations/list.mako',
+ route_name='repo_integrations_list')
+
config.add_route('repo_integrations_create',
- add_route_requirements(
- '{repo_name}/settings/integrations/{integration}/new',
- ),
- custom_predicates=(valid_repo, valid_integration))
+ add_route_requirements('/{repo_name}/settings/integrations/{integration}/new'),
+ repo_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='settings_get',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='GET',
+ route_name='repo_integrations_create')
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='settings_post',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='POST',
+ route_name='repo_integrations_create')
+
config.add_route('repo_integrations_edit',
- add_route_requirements(
- '{repo_name}/settings/integrations/{integration}/{integration_id}',
- ),
- custom_predicates=(valid_repo, valid_integration))
- for route_name in ['repo_integrations_edit', 'repo_integrations_create']:
- config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
- attr='settings_get',
- renderer='rhodecode:templates/admin/integrations/form.mako',
- request_method='GET',
- route_name=route_name)
- config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
- attr='settings_post',
- renderer='rhodecode:templates/admin/integrations/form.mako',
- request_method='POST',
- route_name=route_name)
+ add_route_requirements('/{repo_name}/settings/integrations/{integration}/{integration_id}'),
+ repo_route=True,
+ custom_predicates=(valid_integration,))
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='settings_get',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='GET',
+ route_name='repo_integrations_edit')
+ config.add_view('rhodecode.integrations.views.RepoIntegrationsView',
+ attr='settings_post',
+ renderer='rhodecode:templates/admin/integrations/form.mako',
+ request_method='POST',
+ route_name='repo_integrations_edit')
-def valid_repo(info, request):
- repo = Repository.get_by_repo_name(info['match']['repo_name'])
- if repo:
- return True
-
-
-def valid_repo_group(info, request):
- repo_group = RepoGroup.get_by_group_name(info['match']['repo_group_name'])
- if repo_group:
- return True
- return False
-
def valid_integration(info, request):
integration_type = info['match']['integration']
integration_id = info['match'].get('integration_id')
- repo_name = info['match'].get('repo_name')
- repo_group_name = info['match'].get('repo_group_name')
if integration_type not in integration_type_registry:
return False
- repo, repo_group = None, None
- if repo_name:
- repo = Repository.get_by_repo_name(repo_name)
- if not repo:
+ if integration_id:
+ if not safe_int(integration_id):
return False
- if repo_group_name:
- repo_group = RepoGroup.get_by_group_name(repo_group_name)
- if not repo_group:
- return False
-
- if repo_name and repo_group:
- raise Exception('Either repo or repo_group can be set, not both')
-
- if integration_id:
integration = Integration.get(integration_id)
if not integration:
return False
if integration.integration_type != integration_type:
return False
+
+ # match types to repo or repo group
+ repo_name = info['match'].get('repo_name')
+ repo_group_name = info['match'].get('repo_group_name')
+ repo, repo_group = None, None
+ if repo_name:
+ repo = Repository.get_by_repo_name(repo_name)
+ if not repo:
+ return False
+
+ if repo_group_name:
+ repo_group = RepoGroup.get_by_group_name(repo_group_name)
+ if not repo_group:
+ return False
+
if repo and repo.repo_id != integration.repo_id:
return False
if repo_group and repo_group.group_id != integration.repo_group_id:
diff --git a/rhodecode/integrations/tests/__init__.py b/rhodecode/integrations/tests/__init__.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/integrations/tests/__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/tests/functional/test_integrations.py b/rhodecode/integrations/tests/test_integrations.py
rename from rhodecode/tests/functional/test_integrations.py
rename to rhodecode/integrations/tests/test_integrations.py
--- a/rhodecode/tests/functional/test_integrations.py
+++ b/rhodecode/integrations/tests/test_integrations.py
@@ -20,10 +20,16 @@
import pytest
+from rhodecode.apps._base import ADMIN_PREFIX
from rhodecode.model.db import Integration
from rhodecode.model.meta import Session
from rhodecode.integrations import integration_type_registry
-from rhodecode.config.routing import ADMIN_PREFIX
+
+
+def route_path(name, **kwargs):
+ return {
+ 'home': '/',
+ }[name].format(**kwargs)
@pytest.mark.usefixtures('app', 'autologin_user')
@@ -32,86 +38,141 @@ class TestIntegrationsView(object):
class TestGlobalIntegrationsView(TestIntegrationsView):
- def test_index_no_integrations(self, app):
+ def test_index_no_integrations(self):
url = ADMIN_PREFIX + '/integrations'
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
assert 'exist yet' in response.body
- def test_index_with_integrations(self, app, global_integration_stub):
+ def test_index_with_integrations(self, global_integration_stub):
url = ADMIN_PREFIX + '/integrations'
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
assert 'exist yet' not in response.body
assert global_integration_stub.name in response.body
- def test_new_integration_page(self, app):
+ @pytest.mark.parametrize(
+ 'IntegrationType', integration_type_registry.values())
+ def test_new_integration_page(self, IntegrationType):
url = ADMIN_PREFIX + '/integrations/new'
- response = app.get(url)
-
- assert response.status_code == 200
+ response = self.app.get(url, status=200)
- for integration_key in integration_type_registry:
- nurl = (ADMIN_PREFIX + '/integrations/{integration}/new').format(
- integration=integration_key)
- assert nurl in response.body
+ url = (ADMIN_PREFIX + '/integrations/{integration}/new').format(
+ integration=IntegrationType.key)
+ assert url in response.body
@pytest.mark.parametrize(
'IntegrationType', integration_type_registry.values())
- def test_get_create_integration_page(self, app, IntegrationType):
+ def test_get_create_integration_page(self, IntegrationType):
url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format(
integration_key=IntegrationType.key)
- response = app.get(url)
+ response = self.app.get(url, status=200)
- assert response.status_code == 200
assert IntegrationType.display_name in response.body
- def test_post_integration_page(self, app, StubIntegrationType, csrf_token,
+ def test_post_integration_page(self, StubIntegrationType, csrf_token,
test_repo_group, backend_random):
url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format(
integration_key=StubIntegrationType.key)
- _post_integration_test_helper(app, url, csrf_token, admin_view=True,
+ _post_integration_test_helper(self.app, url, csrf_token, admin_view=True,
+ repo=backend_random.repo, repo_group=test_repo_group)
+
+
+class TestRepoIntegrationsView(TestIntegrationsView):
+ def test_index_no_integrations(self, backend_random):
+ url = '/{repo_name}/settings/integrations'.format(
+ repo_name=backend_random.repo.repo_name)
+ response = self.app.get(url)
+
+ assert response.status_code == 200
+ assert 'exist yet' in response.body
+
+ def test_index_with_integrations(self, repo_integration_stub):
+ url = '/{repo_name}/settings/integrations'.format(
+ repo_name=repo_integration_stub.repo.repo_name)
+ stub_name = repo_integration_stub.name
+
+ response = self.app.get(url)
+
+ assert response.status_code == 200
+ assert stub_name in response.body
+ assert 'exist yet' not in response.body
+
+ @pytest.mark.parametrize(
+ 'IntegrationType', integration_type_registry.values())
+ def test_new_integration_page(self, backend_random, IntegrationType):
+ repo_name = backend_random.repo.repo_name
+ url = '/{repo_name}/settings/integrations/new'.format(
+ repo_name=repo_name)
+
+ response = self.app.get(url, status=200)
+
+ url = '/{repo_name}/settings/integrations/{integration}/new'.format(
+ repo_name=repo_name,
+ integration=IntegrationType.key)
+
+ assert url in response.body
+
+ @pytest.mark.parametrize(
+ 'IntegrationType', integration_type_registry.values())
+ def test_get_create_integration_page(self, backend_random, IntegrationType):
+ repo_name = backend_random.repo.repo_name
+ url = '/{repo_name}/settings/integrations/{integration_key}/new'.format(
+ repo_name=repo_name, integration_key=IntegrationType.key)
+
+ response = self.app.get(url, status=200)
+
+ assert IntegrationType.display_name in response.body
+
+ def test_post_integration_page(self, backend_random, test_repo_group,
+ StubIntegrationType, csrf_token):
+ repo_name = backend_random.repo.repo_name
+ url = '/{repo_name}/settings/integrations/{integration_key}/new'.format(
+ repo_name=repo_name, integration_key=StubIntegrationType.key)
+
+ _post_integration_test_helper(
+ self.app, url, csrf_token, admin_view=False,
repo=backend_random.repo, repo_group=test_repo_group)
class TestRepoGroupIntegrationsView(TestIntegrationsView):
- def test_index_no_integrations(self, app, test_repo_group):
+ def test_index_no_integrations(self, test_repo_group):
url = '/{repo_group_name}/settings/integrations'.format(
repo_group_name=test_repo_group.group_name)
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
assert 'exist yet' in response.body
- def test_index_with_integrations(self, app, test_repo_group,
- repogroup_integration_stub):
+ def test_index_with_integrations(
+ self, test_repo_group, repogroup_integration_stub):
+
url = '/{repo_group_name}/settings/integrations'.format(
repo_group_name=test_repo_group.group_name)
stub_name = repogroup_integration_stub.name
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
assert 'exist yet' not in response.body
assert stub_name in response.body
- def test_new_integration_page(self, app, test_repo_group):
+ def test_new_integration_page(self, test_repo_group):
repo_group_name = test_repo_group.group_name
url = '/{repo_group_name}/settings/integrations/new'.format(
repo_group_name=test_repo_group.group_name)
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
for integration_key in integration_type_registry:
- nurl = ('/{repo_group_name}/settings/integrations'
- '/{integration}/new').format(
+ nurl = ('/{repo_group_name}/settings/integrations/{integration}/new').format(
repo_group_name=repo_group_name,
integration=integration_key)
@@ -119,86 +180,29 @@ class TestRepoGroupIntegrationsView(Test
@pytest.mark.parametrize(
'IntegrationType', integration_type_registry.values())
- def test_get_create_integration_page(self, app, test_repo_group,
- IntegrationType):
+ def test_get_create_integration_page(
+ self, test_repo_group, IntegrationType):
+
repo_group_name = test_repo_group.group_name
url = ('/{repo_group_name}/settings/integrations/{integration_key}/new'
).format(repo_group_name=repo_group_name,
integration_key=IntegrationType.key)
- response = app.get(url)
+ response = self.app.get(url)
assert response.status_code == 200
assert IntegrationType.display_name in response.body
- def test_post_integration_page(self, app, test_repo_group, backend_random,
+ def test_post_integration_page(self, test_repo_group, backend_random,
StubIntegrationType, csrf_token):
+
repo_group_name = test_repo_group.group_name
url = ('/{repo_group_name}/settings/integrations/{integration_key}/new'
).format(repo_group_name=repo_group_name,
integration_key=StubIntegrationType.key)
- _post_integration_test_helper(app, url, csrf_token, admin_view=False,
- repo=backend_random.repo, repo_group=test_repo_group)
-
-
-class TestRepoIntegrationsView(TestIntegrationsView):
- def test_index_no_integrations(self, app, backend_random):
- url = '/{repo_name}/settings/integrations'.format(
- repo_name=backend_random.repo.repo_name)
- response = app.get(url)
-
- assert response.status_code == 200
- assert 'exist yet' in response.body
-
- def test_index_with_integrations(self, app, repo_integration_stub):
- url = '/{repo_name}/settings/integrations'.format(
- repo_name=repo_integration_stub.repo.repo_name)
- stub_name = repo_integration_stub.name
-
- response = app.get(url)
-
- assert response.status_code == 200
- assert stub_name in response.body
- assert 'exist yet' not in response.body
-
- def test_new_integration_page(self, app, backend_random):
- repo_name = backend_random.repo.repo_name
- url = '/{repo_name}/settings/integrations/new'.format(
- repo_name=repo_name)
-
- response = app.get(url)
-
- assert response.status_code == 200
-
- for integration_key in integration_type_registry:
- nurl = ('/{repo_name}/settings/integrations'
- '/{integration}/new').format(
- repo_name=repo_name,
- integration=integration_key)
-
- assert nurl in response.body
-
- @pytest.mark.parametrize(
- 'IntegrationType', integration_type_registry.values())
- def test_get_create_integration_page(self, app, backend_random,
- IntegrationType):
- repo_name = backend_random.repo.repo_name
- url = '/{repo_name}/settings/integrations/{integration_key}/new'.format(
- repo_name=repo_name, integration_key=IntegrationType.key)
-
- response = app.get(url)
-
- assert response.status_code == 200
- assert IntegrationType.display_name in response.body
-
- def test_post_integration_page(self, app, backend_random, test_repo_group,
- StubIntegrationType, csrf_token):
- repo_name = backend_random.repo.repo_name
- url = '/{repo_name}/settings/integrations/{integration_key}/new'.format(
- repo_name=repo_name, integration_key=StubIntegrationType.key)
-
- _post_integration_test_helper(app, url, csrf_token, admin_view=False,
+ _post_integration_test_helper(
+ self.app, url, csrf_token, admin_view=False,
repo=backend_random.repo, repo_group=test_repo_group)
@@ -208,7 +212,8 @@ def _post_integration_test_helper(app, u
Posts form data to create integration at the url given then deletes it and
checks if the redirect url is correct.
"""
-
+ repo_name = repo.repo_name
+ repo_group_name = repo_group.group_name
app.post(url, params={}, status=403) # missing csrf check
response = app.post(url, params={'csrf_token': csrf_token})
assert response.status_code == 200
@@ -216,15 +221,15 @@ def _post_integration_test_helper(app, u
scopes_destinations = [
('global',
- ADMIN_PREFIX + '/integrations'),
+ ADMIN_PREFIX + '/integrations'),
('root-repos',
ADMIN_PREFIX + '/integrations'),
- ('repo:%s' % repo.repo_name,
- '/%s/settings/integrations' % repo.repo_name),
- ('repogroup:%s' % repo_group.group_name,
- '/%s/settings/integrations' % repo_group.group_name),
- ('repogroup-recursive:%s' % repo_group.group_name,
- '/%s/settings/integrations' % repo_group.group_name),
+ ('repo:%s' % repo_name,
+ '/%s/settings/integrations' % repo_name),
+ ('repogroup:%s' % repo_group_name,
+ '/%s/settings/integrations' % repo_group_name),
+ ('repogroup-recursive:%s' % repo_group_name,
+ '/%s/settings/integrations' % repo_group_name),
]
for scope, destination in scopes_destinations:
diff --git a/rhodecode/integrations/views.py b/rhodecode/integrations/views.py
--- a/rhodecode/integrations/views.py
+++ b/rhodecode/integrations/views.py
@@ -18,45 +18,40 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
-import pylons
import deform
import logging
-import colander
import peppercorn
import webhelpers.paginate
-from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPBadRequest
-from pyramid.renderers import render
-from pyramid.response import Response
+from pyramid.httpexceptions import HTTPFound, HTTPForbidden
+from rhodecode.apps._base import BaseAppView
+from rhodecode.integrations import integration_type_registry
from rhodecode.apps.admin.navigation import navigation_list
-from rhodecode.lib import auth
-from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
+from rhodecode.lib.auth import (
+ LoginRequired, CSRFRequired, HasPermissionAnyDecorator,
+ HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
from rhodecode.lib.utils2 import safe_int
from rhodecode.lib.helpers import Page
from rhodecode.model.db import Repository, RepoGroup, Session, Integration
from rhodecode.model.scm import ScmModel
from rhodecode.model.integration import IntegrationModel
-from rhodecode.translation import _
-from rhodecode.integrations import integration_type_registry
from rhodecode.model.validation_schema.schemas.integration_schema import (
make_integration_schema, IntegrationScopeType)
log = logging.getLogger(__name__)
-class IntegrationSettingsViewBase(object):
- """ Base Integration settings view used by both repo / global settings """
+class IntegrationSettingsViewBase(BaseAppView):
+ """
+ Base Integration settings view used by both repo / global settings
+ """
def __init__(self, context, request):
- self.context = context
- self.request = request
- self._load_general_context()
+ super(IntegrationSettingsViewBase, self).__init__(context, request)
+ self._load_view_context()
- if not self.perm_check(request.user):
- raise HTTPForbidden()
-
- def _load_general_context(self):
+ def _load_view_context(self):
"""
This avoids boilerplate for repo/global+list/edit+views/templates
by doing all possible contexts at the same time however it should
@@ -110,25 +105,12 @@ class IntegrationSettingsViewBase(object
return False
- def _template_c_context(self):
- # TODO: dan: this is a stopgap in order to inherit from current pylons
- # based admin/repo settings templates - this should be removed entirely
- # after port to pyramid
+ def _get_local_tmpl_context(self, include_app_defaults=False):
+ _ = self.request.translate
+ c = super(IntegrationSettingsViewBase, self)._get_local_tmpl_context(
+ include_app_defaults=include_app_defaults)
- c = pylons.tmpl_context
c.active = 'integrations'
- c.rhodecode_user = self.request.user
- c.repo = self.repo
- c.repo_group = self.repo_group
- c.repo_name = self.repo and self.repo.repo_name or None
- c.repo_group_name = self.repo_group and self.repo_group.group_name or None
-
- if self.repo:
- c.repo_info = self.repo
- c.rhodecode_db_repo = self.repo
- c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
- else:
- c.navlist = navigation_list(self.request)
return c
@@ -142,6 +124,7 @@ class IntegrationSettingsViewBase(object
no_scope=not self.admin_view)
def _form_defaults(self):
+ _ = self.request.translate
defaults = {}
if self.integration:
@@ -178,28 +161,79 @@ class IntegrationSettingsViewBase(object
return defaults
def _delete_integration(self, integration):
- Session().delete(self.integration)
+ _ = self.request.translate
+ Session().delete(integration)
Session().commit()
self.request.session.flash(
_('Integration {integration_name} deleted successfully.').format(
- integration_name=self.integration.name),
+ integration_name=integration.name),
queue='success')
if self.repo:
- redirect_to = self.request.route_url(
+ redirect_to = self.request.route_path(
'repo_integrations_home', repo_name=self.repo.repo_name)
elif self.repo_group:
- redirect_to = self.request.route_url(
+ redirect_to = self.request.route_path(
'repo_group_integrations_home',
repo_group_name=self.repo_group.group_name)
else:
- redirect_to = self.request.route_url('global_integrations_home')
+ redirect_to = self.request.route_path('global_integrations_home')
raise HTTPFound(redirect_to)
- def settings_get(self, defaults=None, form=None):
+ def _integration_list(self):
+ """ List integrations """
+
+ c = self.load_default_context()
+ if self.repo:
+ scope = self.repo
+ elif self.repo_group:
+ scope = self.repo_group
+ else:
+ scope = 'all'
+
+ integrations = []
+
+ for IntType, integration in IntegrationModel().get_integrations(
+ scope=scope, IntegrationType=self.IntegrationType):
+
+ # extra permissions check *just in case*
+ if not self._has_perms_for_integration(integration):
+ continue
+
+ integrations.append((IntType, integration))
+
+ sort_arg = self.request.GET.get('sort', 'name:asc')
+ if ':' in sort_arg:
+ sort_field, sort_dir = sort_arg.split(':')
+ else:
+ sort_field = sort_arg, 'asc'
+
+ assert sort_field in ('name', 'integration_type', 'enabled', 'scope')
+
+ integrations.sort(
+ key=lambda x: getattr(x[1], sort_field),
+ reverse=(sort_dir == 'desc'))
+
+ page_url = webhelpers.paginate.PageURL(
+ self.request.path, self.request.GET)
+ page = safe_int(self.request.GET.get('page', 1), 1)
+
+ integrations = Page(
+ integrations, page=page, items_per_page=10, url=page_url)
+
+ c.rev_sort_dir = sort_dir != 'desc' and 'desc' or 'asc'
+
+ c.current_IntegrationType = self.IntegrationType
+ c.integrations_list = integrations
+ c.available_integrations = integration_type_registry
+
+ return self._get_template_context(c)
+
+ def _settings_get(self, defaults=None, form=None):
"""
View that displays the integration settings as a form.
"""
+ c = self.load_default_context()
defaults = defaults or self._form_defaults()
schema = self._form_schema()
@@ -211,20 +245,18 @@ class IntegrationSettingsViewBase(object
form = form or deform.Form(schema, appstruct=defaults, buttons=buttons)
- template_context = {
- 'form': form,
- 'current_IntegrationType': self.IntegrationType,
- 'integration': self.integration,
- 'c': self._template_c_context(),
- }
+ c.form = form
+ c.current_IntegrationType = self.IntegrationType
+ c.integration = self.integration
- return template_context
+ return self._get_template_context(c)
- @auth.CSRFRequired()
- def settings_post(self):
+ def _settings_post(self):
"""
View that validates and stores the integration settings.
"""
+ _ = self.request.translate
+
controls = self.request.POST.items()
pstruct = peppercorn.parse(controls)
@@ -264,7 +296,7 @@ class IntegrationSettingsViewBase(object
_('Errors exist when saving integration settings. '
'Please check the form inputs.'),
queue='error')
- return self.settings_get(form=e)
+ return self._settings_get(form=e)
if not self.integration:
self.integration = Integration()
@@ -314,77 +346,110 @@ class IntegrationSettingsViewBase(object
return HTTPFound(redirect_to)
- def index(self):
- """ List integrations """
- if self.repo:
- scope = self.repo
- elif self.repo_group:
- scope = self.repo_group
- else:
- scope = 'all'
-
- integrations = []
-
- for IntType, integration in IntegrationModel().get_integrations(
- scope=scope, IntegrationType=self.IntegrationType):
-
- # extra permissions check *just in case*
- if not self._has_perms_for_integration(integration):
- continue
-
- integrations.append((IntType, integration))
-
- sort_arg = self.request.GET.get('sort', 'name:asc')
- if ':' in sort_arg:
- sort_field, sort_dir = sort_arg.split(':')
- else:
- sort_field = sort_arg, 'asc'
-
- assert sort_field in ('name', 'integration_type', 'enabled', 'scope')
+ def _new_integration(self):
+ c = self.load_default_context()
+ c.available_integrations = integration_type_registry
+ return self._get_template_context(c)
- integrations.sort(
- key=lambda x: getattr(x[1], sort_field),
- reverse=(sort_dir == 'desc'))
-
- page_url = webhelpers.paginate.PageURL(
- self.request.path, self.request.GET)
- page = safe_int(self.request.GET.get('page', 1), 1)
-
- integrations = Page(integrations, page=page, items_per_page=10,
- url=page_url)
-
- template_context = {
- 'sort_field': sort_field,
- 'rev_sort_dir': sort_dir != 'desc' and 'desc' or 'asc',
- 'current_IntegrationType': self.IntegrationType,
- 'integrations_list': integrations,
- 'available_integrations': integration_type_registry,
- 'c': self._template_c_context(),
- 'request': self.request,
- }
- return template_context
-
- def new_integration(self):
- template_context = {
- 'available_integrations': integration_type_registry,
- 'c': self._template_c_context(),
- }
- return template_context
+ def load_default_context(self):
+ raise NotImplementedError()
class GlobalIntegrationsView(IntegrationSettingsViewBase):
- def perm_check(self, user):
- return auth.HasPermissionAll('hg.admin').check_permissions(user=user)
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+ c.repo = self.repo
+ c.repo_group = self.repo_group
+ c.navlist = navigation_list(self.request)
+ self._register_global_c(c)
+ return c
+
+ @LoginRequired()
+ @HasPermissionAnyDecorator('hg.admin')
+ def integration_list(self):
+ return self._integration_list()
+
+ @LoginRequired()
+ @HasPermissionAnyDecorator('hg.admin')
+ def settings_get(self):
+ return self._settings_get()
+
+ @LoginRequired()
+ @HasPermissionAnyDecorator('hg.admin')
+ @CSRFRequired()
+ def settings_post(self):
+ return self._settings_post()
+
+ @LoginRequired()
+ @HasPermissionAnyDecorator('hg.admin')
+ def new_integration(self):
+ return self._new_integration()
class RepoIntegrationsView(IntegrationSettingsViewBase):
- def perm_check(self, user):
- return auth.HasRepoPermissionAll('repository.admin')(
- repo_name=self.repo.repo_name, user=user)
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+
+ c.repo = self.repo
+ c.repo_group = self.repo_group
+
+ # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
+ c.repo_info = self.db_repo = self.repo
+ c.rhodecode_db_repo = self.repo
+ c.repo_name = self.db_repo.repo_name
+ c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
+
+ self._register_global_c(c)
+ return c
+
+ @LoginRequired()
+ @HasRepoPermissionAnyDecorator('repository.admin')
+ def integration_list(self):
+ return self._integration_list()
+
+ @LoginRequired()
+ @HasRepoPermissionAnyDecorator('repository.admin')
+ def settings_get(self):
+ return self._settings_get()
+
+ @LoginRequired()
+ @HasRepoPermissionAnyDecorator('repository.admin')
+ @CSRFRequired()
+ def settings_post(self):
+ return self._settings_post()
+
+ @LoginRequired()
+ @HasRepoPermissionAnyDecorator('repository.admin')
+ def new_integration(self):
+ return self._new_integration()
class RepoGroupIntegrationsView(IntegrationSettingsViewBase):
- def perm_check(self, user):
- return auth.HasRepoGroupPermissionAll('group.admin')(
- group_name=self.repo_group.group_name, user=user)
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+ c.repo = self.repo
+ c.repo_group = self.repo_group
+ c.navlist = navigation_list(self.request)
+ self._register_global_c(c)
+ return c
+
+ @LoginRequired()
+ @HasRepoGroupPermissionAnyDecorator('group.admin')
+ def integration_list(self):
+ return self._integration_list()
+ @LoginRequired()
+ @HasRepoGroupPermissionAnyDecorator('group.admin')
+ def settings_get(self):
+ return self._settings_get()
+
+ @LoginRequired()
+ @HasRepoGroupPermissionAnyDecorator('group.admin')
+ @CSRFRequired()
+ def settings_post(self):
+ return self._settings_post()
+
+ @LoginRequired()
+ @HasRepoGroupPermissionAnyDecorator('group.admin')
+ def new_integration(self):
+ return self._new_integration()
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
@@ -23,13 +23,13 @@ function registerRCRoutes() {
pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/settings/integrations', ['repo_group_name']);
+ pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
- pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
+ pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
- pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
pyroutes.register('ops_ping', '/_admin/ops/ping', []);
diff --git a/rhodecode/templates/admin/integrations/form.mako b/rhodecode/templates/admin/integrations/form.mako
--- a/rhodecode/templates/admin/integrations/form.mako
+++ b/rhodecode/templates/admin/integrations/form.mako
@@ -7,10 +7,10 @@
»
${h.link_to(_('Integrations'),request.route_url(route_name='repo_integrations_home', repo_name=c.repo.repo_name))}
»
- ${h.link_to(current_IntegrationType.display_name,
+ ${h.link_to(c.current_IntegrationType.display_name,
request.route_url(route_name='repo_integrations_list',
repo_name=c.repo.repo_name,
- integration=current_IntegrationType.key))}
+ integration=c.current_IntegrationType.key))}
%elif c.repo_group:
${h.link_to(_('Admin'),h.route_path('admin_home'))}
»
@@ -20,10 +20,10 @@
»
${h.link_to(_('Integrations'),request.route_url(route_name='repo_group_integrations_home', repo_group_name=c.repo_group.group_name))}
»
- ${h.link_to(current_IntegrationType.display_name,
+ ${h.link_to(c.current_IntegrationType.display_name,
request.route_url(route_name='repo_group_integrations_list',
repo_group_name=c.repo_group.group_name,
- integration=current_IntegrationType.key))}
+ integration=c.current_IntegrationType.key))}
%else:
${h.link_to(_('Admin'),h.route_path('admin_home'))}
»
@@ -31,17 +31,17 @@
»
${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
»
- ${h.link_to(current_IntegrationType.display_name,
+ ${h.link_to(c.current_IntegrationType.display_name,
request.route_url(route_name='global_integrations_list',
- integration=current_IntegrationType.key))}
+ integration=c.current_IntegrationType.key))}
%endif
- %if integration:
+ %if c.integration:
»
- ${integration.name}
- %elif current_IntegrationType:
+ ${c.integration.name}
+ %elif c.current_IntegrationType:
»
- ${current_IntegrationType.display_name}
+ ${c.current_IntegrationType.display_name}
%endif
%def>
@@ -54,16 +54,16 @@
- %if integration:
- ${current_IntegrationType.display_name} - ${integration.name}
+ %if c.integration:
+ ${c.current_IntegrationType.display_name} - ${c.integration.name}
%else:
${_('Create New %(integration_type)s Integration') % {
- 'integration_type': current_IntegrationType.display_name
+ 'integration_type': c.current_IntegrationType.display_name
}}
%endif
- ${form.render() | n}
+ ${c.form.render() | n}
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
@@ -15,22 +15,22 @@
»
${h.link_to(_('Settings'),h.url('admin_settings'))}
%endif
- %if current_IntegrationType:
+ %if c.current_IntegrationType:
»
%if c.repo:
${h.link_to(_('Integrations'),
- request.route_url(route_name='repo_integrations_home',
- repo_name=c.repo.repo_name))}
+ request.route_path(route_name='repo_integrations_home',
+ repo_name=c.repo.repo_name))}
%elif c.repo_group:
${h.link_to(_('Integrations'),
- request.route_url(route_name='repo_group_integrations_home',
- repo_group_name=c.repo_group.group_name))}
+ request.route_path(route_name='repo_group_integrations_home',
+ repo_group_name=c.repo_group.group_name))}
%else:
${h.link_to(_('Integrations'),
- request.route_url(route_name='global_integrations_home'))}
+ request.route_path(route_name='global_integrations_home'))}
%endif
»
- ${current_IntegrationType.display_name}
+ ${c.current_IntegrationType.display_name}
%else:
»
${_('Integrations')}
@@ -61,9 +61,9 @@
home_url = request.route_path('global_integrations_home')
%>
- ${_('All')}
+ ${_('All')}
- %for integration_key, IntegrationType in available_integrations.items():
+ %for integration_key, IntegrationType in c.available_integrations.items():
<%
if c.repo:
list_url = request.route_path('repo_integrations_list',
@@ -78,12 +78,14 @@
integration=integration_key)
%>
+ class="btn ${c.current_IntegrationType and integration_key == c.current_IntegrationType.key and 'btn-primary' or ''}">
${IntegrationType.display_name}
%endfor
<%
+ integration_type = c.current_IntegrationType and c.current_IntegrationType.display_name or ''
+
if c.repo:
create_url = h.route_path('repo_integrations_new', repo_name=c.repo.repo_name)
elif c.repo_group:
@@ -98,19 +100,19 @@
- ${_('Enabled')} |
- ${_('Name')} |
- ${_('Type')} |
- ${_('Scope')} |
+ ${_('Enabled')} |
+ ${_('Name')} |
+ ${_('Type')} |
+ ${_('Scope')} |
${_('Actions')} |
|
- %if not integrations_list:
+ %if not c.integrations_list:
- <% integration_type = current_IntegrationType and current_IntegrationType.display_name or '' %>
+
%if c.repo:
${_('No {type} integrations for repo {repo} exist yet.').format(type=integration_type, repo=c.repo.repo_name)}
%elif c.repo_group:
@@ -119,14 +121,14 @@
${_('No {type} integrations exist yet.').format(type=integration_type)}
%endif
- %if current_IntegrationType:
+ %if c.current_IntegrationType:
<%
if c.repo:
- create_url = h.route_path('repo_integrations_create', repo_name=c.repo.repo_name, integration=current_IntegrationType.key)
+ create_url = h.route_path('repo_integrations_create', repo_name=c.repo.repo_name, integration=c.current_IntegrationType.key)
elif c.repo_group:
- create_url = h.route_path('repo_group_integrations_create', repo_group_name=c.repo_group.group_name, integration=current_IntegrationType.key)
+ create_url = h.route_path('repo_group_integrations_create', repo_group_name=c.repo_group.group_name, integration=c.current_IntegrationType.key)
else:
- create_url = h.route_path('global_integrations_create', integration=current_IntegrationType.key)
+ create_url = h.route_path('global_integrations_create', integration=c.current_IntegrationType.key)
%>
%endif
@@ -134,7 +136,7 @@
|
%endif
- %for IntegrationType, integration in integrations_list:
+ %for IntegrationType, integration in c.integrations_list:
%if integration.enabled:
@@ -147,9 +149,9 @@
${integration.name}
|
- %if integration.integration_type in available_integrations:
+ %if integration.integration_type in c.available_integrations:
- ${available_integrations[integration.integration_type].icon|n}
+ ${c.available_integrations[integration.integration_type].icon|n}
%else:
?
@@ -220,7 +222,7 @@
|
diff --git a/rhodecode/templates/admin/integrations/new.mako b/rhodecode/templates/admin/integrations/new.mako
--- a/rhodecode/templates/admin/integrations/new.mako
+++ b/rhodecode/templates/admin/integrations/new.mako
@@ -36,7 +36,7 @@
%endif
%def>
- %for integration, IntegrationType in available_integrations.items():
+ %for integration, IntegrationType in c.available_integrations.items():
<%
if c.repo:
create_url = request.route_path('repo_integrations_create',
diff --git a/rhodecode/tests/integrations/test_integration.py b/rhodecode/tests/integrations/test_integration.py
--- a/rhodecode/tests/integrations/test_integration.py
+++ b/rhodecode/tests/integrations/test_integration.py
@@ -25,21 +25,21 @@ from rhodecode import events
from rhodecode.tests.fixture import Fixture
from rhodecode.model.db import Session, Integration
from rhodecode.model.integration import IntegrationModel
-from rhodecode.integrations.types.base import IntegrationTypeBase
class TestDeleteScopesDeletesIntegrations(object):
- def test_delete_repo_with_integration_deletes_integration(self,
- repo_integration_stub):
+ def test_delete_repo_with_integration_deletes_integration(
+ self, repo_integration_stub):
+
Session().delete(repo_integration_stub.repo)
Session().commit()
Session().expire_all()
integration = Integration.get(repo_integration_stub.integration_id)
assert integration is None
+ def test_delete_repo_group_with_integration_deletes_integration(
+ self, repogroup_integration_stub):
- def test_delete_repo_group_with_integration_deletes_integration(self,
- repogroup_integration_stub):
Session().delete(repogroup_integration_stub.repo_group)
Session().commit()
Session().expire_all()
@@ -146,7 +146,6 @@ def test_enabled_integration_repo_scopes
integrations['root_repo'],
]
-
triggered_integrations = IntegrationModel().get_for_event(
events.RepoEvent(repos['other_repo']))
@@ -157,7 +156,6 @@ def test_enabled_integration_repo_scopes
integrations['other_group_recursive'],
]
-
triggered_integrations = IntegrationModel().get_for_event(
events.RepoEvent(repos['parent_repo']))
@@ -193,26 +191,22 @@ def test_disabled_integration_repo_scope
assert triggered_integrations == []
-
triggered_integrations = IntegrationModel().get_for_event(
events.RepoEvent(repos['parent_repo']))
assert triggered_integrations == []
-
triggered_integrations = IntegrationModel().get_for_event(
events.RepoEvent(repos['child_repo']))
assert triggered_integrations == []
-
triggered_integrations = IntegrationModel().get_for_event(
events.RepoEvent(repos['other_repo']))
assert triggered_integrations == []
-
def test_enabled_non_repo_integrations(integration_repos):
integrations = integration_repos['integrations']
diff --git a/rhodecode/tests/plugin.py b/rhodecode/tests/plugin.py
--- a/rhodecode/tests/plugin.py
+++ b/rhodecode/tests/plugin.py
@@ -336,7 +336,7 @@ def test_repo_group(request):
usage automatically
"""
fixture = Fixture()
- repogroupid = 'test_repo_group_%s' % int(time.time())
+ repogroupid = 'test_repo_group_%s' % str(time.time()).replace('.', '')
repo_group = fixture.create_repo_group(repogroupid)
def _cleanup():
@@ -353,7 +353,7 @@ def test_user_group(request):
usage automatically
"""
fixture = Fixture()
- usergroupid = 'test_user_group_%s' % int(time.time())
+ usergroupid = 'test_user_group_%s' % str(time.time()).replace('.', '')
user_group = fixture.create_user_group(usergroupid)
def _cleanup():