Show More
@@ -0,0 +1,19 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | ||
|
3 | # Copyright (C) 2016-2017 RhodeCode GmbH | |
|
4 | # | |
|
5 | # This program is free software: you can redistribute it and/or modify | |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
|
7 | # (only), as published by the Free Software Foundation. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
|
16 | # | |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
@@ -21,6 +21,7 b'' | |||
|
21 | 21 | import logging |
|
22 | 22 | |
|
23 | 23 | from rhodecode.apps._base import ADMIN_PREFIX, add_route_requirements |
|
24 | from rhodecode.lib.utils2 import safe_int | |
|
24 | 25 | from rhodecode.model.db import Repository, Integration, RepoGroup |
|
25 | 26 | from rhodecode.integrations import integration_type_registry |
|
26 | 27 | |
@@ -30,7 +31,6 b' log = logging.getLogger(__name__)' | |||
|
30 | 31 | def includeme(config): |
|
31 | 32 | |
|
32 | 33 | # global integrations |
|
33 | ||
|
34 | 34 | config.add_route('global_integrations_new', |
|
35 | 35 | ADMIN_PREFIX + '/integrations/new') |
|
36 | 36 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
@@ -45,7 +45,7 b' def includeme(config):' | |||
|
45 | 45 | ADMIN_PREFIX + '/integrations/{integration}') |
|
46 | 46 | for route_name in ['global_integrations_home', 'global_integrations_list']: |
|
47 | 47 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
|
48 |
attr='in |
|
|
48 | attr='integration_list', | |
|
49 | 49 | renderer='rhodecode:templates/admin/integrations/list.mako', |
|
50 | 50 | request_method='GET', |
|
51 | 51 | route_name=route_name) |
@@ -57,7 +57,6 b' def includeme(config):' | |||
|
57 | 57 | ADMIN_PREFIX + '/integrations/{integration}/{integration_id}', |
|
58 | 58 | custom_predicates=(valid_integration,)) |
|
59 | 59 | |
|
60 | ||
|
61 | 60 | for route_name in ['global_integrations_create', 'global_integrations_edit']: |
|
62 | 61 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
|
63 | 62 | attr='settings_get', |
@@ -70,134 +69,148 b' def includeme(config):' | |||
|
70 | 69 | request_method='POST', |
|
71 | 70 | route_name=route_name) |
|
72 | 71 | |
|
73 | ||
|
74 | 72 | # repo group integrations |
|
75 | 73 | config.add_route('repo_group_integrations_home', |
|
76 | add_route_requirements( | |
|
77 |
|
|
|
78 | ), | |
|
79 | custom_predicates=(valid_repo_group,) | |
|
80 | ) | |
|
81 | config.add_route('repo_group_integrations_list', | |
|
82 | add_route_requirements( | |
|
83 | '{repo_group_name}/settings/integrations/{integration}', | |
|
84 | ), | |
|
85 | custom_predicates=(valid_repo_group, valid_integration)) | |
|
86 | for route_name in ['repo_group_integrations_home', 'repo_group_integrations_list']: | |
|
74 | add_route_requirements('/{repo_group_name}/settings/integrations'), | |
|
75 | repo_group_route=True) | |
|
76 | ||
|
87 | 77 |
|
|
88 |
|
|
|
78 | attr='integration_list', | |
|
89 | 79 |
|
|
90 | 80 |
|
|
91 |
|
|
|
81 | route_name='repo_group_integrations_home') | |
|
92 | 82 | |
|
93 | 83 | config.add_route('repo_group_integrations_new', |
|
94 | add_route_requirements( | |
|
95 |
|
|
|
96 | ), | |
|
97 | custom_predicates=(valid_repo_group,)) | |
|
84 | add_route_requirements('/{repo_group_name}/settings/integrations/new'), | |
|
85 | repo_group_route=True) | |
|
98 | 86 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', |
|
99 | 87 | attr='new_integration', |
|
100 | 88 | renderer='rhodecode:templates/admin/integrations/new.mako', |
|
101 | 89 | request_method='GET', |
|
102 | 90 | route_name='repo_group_integrations_new') |
|
103 | 91 | |
|
92 | config.add_route('repo_group_integrations_list', | |
|
93 | add_route_requirements('/{repo_group_name}/settings/integrations/{integration}'), | |
|
94 | repo_group_route=True, | |
|
95 | custom_predicates=(valid_integration,)) | |
|
96 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
|
97 | attr='integration_list', | |
|
98 | renderer='rhodecode:templates/admin/integrations/list.mako', | |
|
99 | request_method='GET', | |
|
100 | route_name='repo_group_integrations_list') | |
|
101 | ||
|
104 | 102 | config.add_route('repo_group_integrations_create', |
|
105 | add_route_requirements( | |
|
106 | '{repo_group_name}/settings/integrations/{integration}/new', | |
|
107 | ), | |
|
108 | custom_predicates=(valid_repo_group, valid_integration)) | |
|
109 | config.add_route('repo_group_integrations_edit', | |
|
110 | add_route_requirements( | |
|
111 | '{repo_group_name}/settings/integrations/{integration}/{integration_id}', | |
|
112 | ), | |
|
113 | custom_predicates=(valid_repo_group, valid_integration)) | |
|
114 | for route_name in ['repo_group_integrations_edit', 'repo_group_integrations_create']: | |
|
103 | add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/new'), | |
|
104 | repo_group_route=True, | |
|
105 | custom_predicates=(valid_integration,)) | |
|
115 | 106 |
|
|
116 | 107 |
|
|
117 | 108 |
|
|
118 | 109 |
|
|
119 |
|
|
|
110 | route_name='repo_group_integrations_create') | |
|
120 | 111 |
|
|
121 | 112 |
|
|
122 | 113 |
|
|
123 | 114 |
|
|
124 |
|
|
|
115 | route_name='repo_group_integrations_create') | |
|
116 | ||
|
117 | config.add_route('repo_group_integrations_edit', | |
|
118 | add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/{integration_id}'), | |
|
119 | repo_group_route=True, | |
|
120 | custom_predicates=(valid_integration,)) | |
|
125 | 121 | |
|
122 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
|
123 | attr='settings_get', | |
|
124 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
|
125 | request_method='GET', | |
|
126 | route_name='repo_group_integrations_edit') | |
|
127 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
|
128 | attr='settings_post', | |
|
129 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
|
130 | request_method='POST', | |
|
131 | route_name='repo_group_integrations_edit') | |
|
126 | 132 | |
|
127 | 133 | # repo integrations |
|
128 | 134 | config.add_route('repo_integrations_home', |
|
129 | add_route_requirements( | |
|
130 | '{repo_name}/settings/integrations', | |
|
131 | ), | |
|
132 | custom_predicates=(valid_repo,)) | |
|
133 | config.add_route('repo_integrations_list', | |
|
134 | add_route_requirements( | |
|
135 | '{repo_name}/settings/integrations/{integration}', | |
|
136 | ), | |
|
137 | custom_predicates=(valid_repo, valid_integration)) | |
|
138 | for route_name in ['repo_integrations_home', 'repo_integrations_list']: | |
|
135 | add_route_requirements('/{repo_name}/settings/integrations'), | |
|
136 | repo_route=True) | |
|
139 | 137 |
|
|
140 |
|
|
|
138 | attr='integration_list', | |
|
141 | 139 |
|
|
142 | 140 |
|
|
143 |
|
|
|
141 | route_name='repo_integrations_home') | |
|
144 | 142 | |
|
145 | 143 | config.add_route('repo_integrations_new', |
|
146 | add_route_requirements( | |
|
147 | '{repo_name}/settings/integrations/new', | |
|
148 | ), | |
|
149 | custom_predicates=(valid_repo,)) | |
|
144 | add_route_requirements('/{repo_name}/settings/integrations/new'), | |
|
145 | repo_route=True) | |
|
150 | 146 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', |
|
151 | 147 | attr='new_integration', |
|
152 | 148 | renderer='rhodecode:templates/admin/integrations/new.mako', |
|
153 | 149 | request_method='GET', |
|
154 | 150 | route_name='repo_integrations_new') |
|
155 | 151 | |
|
152 | config.add_route('repo_integrations_list', | |
|
153 | add_route_requirements('/{repo_name}/settings/integrations/{integration}'), | |
|
154 | repo_route=True, | |
|
155 | custom_predicates=(valid_integration,)) | |
|
156 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
|
157 | attr='integration_list', | |
|
158 | request_method='GET', | |
|
159 | renderer='rhodecode:templates/admin/integrations/list.mako', | |
|
160 | route_name='repo_integrations_list') | |
|
161 | ||
|
156 | 162 | config.add_route('repo_integrations_create', |
|
157 | add_route_requirements( | |
|
158 | '{repo_name}/settings/integrations/{integration}/new', | |
|
159 | ), | |
|
160 | custom_predicates=(valid_repo, valid_integration)) | |
|
161 | config.add_route('repo_integrations_edit', | |
|
162 | add_route_requirements( | |
|
163 | '{repo_name}/settings/integrations/{integration}/{integration_id}', | |
|
164 | ), | |
|
165 | custom_predicates=(valid_repo, valid_integration)) | |
|
166 | for route_name in ['repo_integrations_edit', 'repo_integrations_create']: | |
|
163 | add_route_requirements('/{repo_name}/settings/integrations/{integration}/new'), | |
|
164 | repo_route=True, | |
|
165 | custom_predicates=(valid_integration,)) | |
|
167 | 166 |
|
|
168 | 167 |
|
|
169 | 168 |
|
|
170 | 169 |
|
|
171 |
|
|
|
170 | route_name='repo_integrations_create') | |
|
172 | 171 |
|
|
173 | 172 |
|
|
174 | 173 |
|
|
175 | 174 |
|
|
176 |
|
|
|
177 | ||
|
175 | route_name='repo_integrations_create') | |
|
178 | 176 | |
|
179 | def valid_repo(info, request): | |
|
180 | repo = Repository.get_by_repo_name(info['match']['repo_name']) | |
|
181 | if repo: | |
|
182 | return True | |
|
183 | ||
|
177 | config.add_route('repo_integrations_edit', | |
|
178 | add_route_requirements('/{repo_name}/settings/integrations/{integration}/{integration_id}'), | |
|
179 | repo_route=True, | |
|
180 | custom_predicates=(valid_integration,)) | |
|
181 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
|
182 | attr='settings_get', | |
|
183 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
|
184 | request_method='GET', | |
|
185 | route_name='repo_integrations_edit') | |
|
186 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
|
187 | attr='settings_post', | |
|
188 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
|
189 | request_method='POST', | |
|
190 | route_name='repo_integrations_edit') | |
|
184 | 191 | |
|
185 | def valid_repo_group(info, request): | |
|
186 | repo_group = RepoGroup.get_by_group_name(info['match']['repo_group_name']) | |
|
187 | if repo_group: | |
|
188 | return True | |
|
189 | return False | |
|
190 | 192 | |
|
191 | 193 | |
|
192 | 194 | def valid_integration(info, request): |
|
193 | 195 | integration_type = info['match']['integration'] |
|
194 | 196 | integration_id = info['match'].get('integration_id') |
|
195 | repo_name = info['match'].get('repo_name') | |
|
196 | repo_group_name = info['match'].get('repo_group_name') | |
|
197 | 197 | |
|
198 | 198 | if integration_type not in integration_type_registry: |
|
199 | 199 | return False |
|
200 | 200 | |
|
201 | if integration_id: | |
|
202 | if not safe_int(integration_id): | |
|
203 | return False | |
|
204 | ||
|
205 | integration = Integration.get(integration_id) | |
|
206 | if not integration: | |
|
207 | return False | |
|
208 | if integration.integration_type != integration_type: | |
|
209 | return False | |
|
210 | ||
|
211 | # match types to repo or repo group | |
|
212 | repo_name = info['match'].get('repo_name') | |
|
213 | repo_group_name = info['match'].get('repo_group_name') | |
|
201 | 214 | repo, repo_group = None, None |
|
202 | 215 | if repo_name: |
|
203 | 216 | repo = Repository.get_by_repo_name(repo_name) |
@@ -209,15 +222,6 b' def valid_integration(info, request):' | |||
|
209 | 222 | if not repo_group: |
|
210 | 223 | return False |
|
211 | 224 | |
|
212 | if repo_name and repo_group: | |
|
213 | raise Exception('Either repo or repo_group can be set, not both') | |
|
214 | ||
|
215 | if integration_id: | |
|
216 | integration = Integration.get(integration_id) | |
|
217 | if not integration: | |
|
218 | return False | |
|
219 | if integration.integration_type != integration_type: | |
|
220 | return False | |
|
221 | 225 | if repo and repo.repo_id != integration.repo_id: |
|
222 | 226 | return False |
|
223 | 227 | if repo_group and repo_group.group_id != integration.repo_group_id: |
@@ -20,10 +20,16 b'' | |||
|
20 | 20 | |
|
21 | 21 | import pytest |
|
22 | 22 | |
|
23 | from rhodecode.apps._base import ADMIN_PREFIX | |
|
23 | 24 | from rhodecode.model.db import Integration |
|
24 | 25 | from rhodecode.model.meta import Session |
|
25 | 26 | from rhodecode.integrations import integration_type_registry |
|
26 | from rhodecode.config.routing import ADMIN_PREFIX | |
|
27 | ||
|
28 | ||
|
29 | def route_path(name, **kwargs): | |
|
30 | return { | |
|
31 | 'home': '/', | |
|
32 | }[name].format(**kwargs) | |
|
27 | 33 | |
|
28 | 34 | |
|
29 | 35 | @pytest.mark.usefixtures('app', 'autologin_user') |
@@ -32,86 +38,141 b' class TestIntegrationsView(object):' | |||
|
32 | 38 | |
|
33 | 39 | |
|
34 | 40 | class TestGlobalIntegrationsView(TestIntegrationsView): |
|
35 |
def test_index_no_integrations(self |
|
|
41 | def test_index_no_integrations(self): | |
|
36 | 42 | url = ADMIN_PREFIX + '/integrations' |
|
37 | response = app.get(url) | |
|
43 | response = self.app.get(url) | |
|
38 | 44 | |
|
39 | 45 | assert response.status_code == 200 |
|
40 | 46 | assert 'exist yet' in response.body |
|
41 | 47 | |
|
42 |
def test_index_with_integrations(self, |
|
|
48 | def test_index_with_integrations(self, global_integration_stub): | |
|
43 | 49 | url = ADMIN_PREFIX + '/integrations' |
|
44 | response = app.get(url) | |
|
50 | response = self.app.get(url) | |
|
45 | 51 | |
|
46 | 52 | assert response.status_code == 200 |
|
47 | 53 | assert 'exist yet' not in response.body |
|
48 | 54 | assert global_integration_stub.name in response.body |
|
49 | 55 | |
|
50 | def test_new_integration_page(self, app): | |
|
56 | @pytest.mark.parametrize( | |
|
57 | 'IntegrationType', integration_type_registry.values()) | |
|
58 | def test_new_integration_page(self, IntegrationType): | |
|
51 | 59 | url = ADMIN_PREFIX + '/integrations/new' |
|
52 | 60 | |
|
53 | response = app.get(url) | |
|
54 | ||
|
55 | assert response.status_code == 200 | |
|
61 | response = self.app.get(url, status=200) | |
|
56 | 62 | |
|
57 | for integration_key in integration_type_registry: | |
|
58 |
|
|
|
59 | integration=integration_key) | |
|
60 | assert nurl in response.body | |
|
63 | url = (ADMIN_PREFIX + '/integrations/{integration}/new').format( | |
|
64 | integration=IntegrationType.key) | |
|
65 | assert url in response.body | |
|
61 | 66 | |
|
62 | 67 | @pytest.mark.parametrize( |
|
63 | 68 | 'IntegrationType', integration_type_registry.values()) |
|
64 |
def test_get_create_integration_page(self, |
|
|
69 | def test_get_create_integration_page(self, IntegrationType): | |
|
65 | 70 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( |
|
66 | 71 | integration_key=IntegrationType.key) |
|
67 | 72 | |
|
68 | response = app.get(url) | |
|
73 | response = self.app.get(url, status=200) | |
|
69 | 74 | |
|
70 | assert response.status_code == 200 | |
|
71 | 75 | assert IntegrationType.display_name in response.body |
|
72 | 76 | |
|
73 |
def test_post_integration_page(self, |
|
|
77 | def test_post_integration_page(self, StubIntegrationType, csrf_token, | |
|
74 | 78 | test_repo_group, backend_random): |
|
75 | 79 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( |
|
76 | 80 | integration_key=StubIntegrationType.key) |
|
77 | 81 | |
|
78 | _post_integration_test_helper(app, url, csrf_token, admin_view=True, | |
|
82 | _post_integration_test_helper(self.app, url, csrf_token, admin_view=True, | |
|
83 | repo=backend_random.repo, repo_group=test_repo_group) | |
|
84 | ||
|
85 | ||
|
86 | class TestRepoIntegrationsView(TestIntegrationsView): | |
|
87 | def test_index_no_integrations(self, backend_random): | |
|
88 | url = '/{repo_name}/settings/integrations'.format( | |
|
89 | repo_name=backend_random.repo.repo_name) | |
|
90 | response = self.app.get(url) | |
|
91 | ||
|
92 | assert response.status_code == 200 | |
|
93 | assert 'exist yet' in response.body | |
|
94 | ||
|
95 | def test_index_with_integrations(self, repo_integration_stub): | |
|
96 | url = '/{repo_name}/settings/integrations'.format( | |
|
97 | repo_name=repo_integration_stub.repo.repo_name) | |
|
98 | stub_name = repo_integration_stub.name | |
|
99 | ||
|
100 | response = self.app.get(url) | |
|
101 | ||
|
102 | assert response.status_code == 200 | |
|
103 | assert stub_name in response.body | |
|
104 | assert 'exist yet' not in response.body | |
|
105 | ||
|
106 | @pytest.mark.parametrize( | |
|
107 | 'IntegrationType', integration_type_registry.values()) | |
|
108 | def test_new_integration_page(self, backend_random, IntegrationType): | |
|
109 | repo_name = backend_random.repo.repo_name | |
|
110 | url = '/{repo_name}/settings/integrations/new'.format( | |
|
111 | repo_name=repo_name) | |
|
112 | ||
|
113 | response = self.app.get(url, status=200) | |
|
114 | ||
|
115 | url = '/{repo_name}/settings/integrations/{integration}/new'.format( | |
|
116 | repo_name=repo_name, | |
|
117 | integration=IntegrationType.key) | |
|
118 | ||
|
119 | assert url in response.body | |
|
120 | ||
|
121 | @pytest.mark.parametrize( | |
|
122 | 'IntegrationType', integration_type_registry.values()) | |
|
123 | def test_get_create_integration_page(self, backend_random, IntegrationType): | |
|
124 | repo_name = backend_random.repo.repo_name | |
|
125 | url = '/{repo_name}/settings/integrations/{integration_key}/new'.format( | |
|
126 | repo_name=repo_name, integration_key=IntegrationType.key) | |
|
127 | ||
|
128 | response = self.app.get(url, status=200) | |
|
129 | ||
|
130 | assert IntegrationType.display_name in response.body | |
|
131 | ||
|
132 | def test_post_integration_page(self, backend_random, test_repo_group, | |
|
133 | StubIntegrationType, csrf_token): | |
|
134 | repo_name = backend_random.repo.repo_name | |
|
135 | url = '/{repo_name}/settings/integrations/{integration_key}/new'.format( | |
|
136 | repo_name=repo_name, integration_key=StubIntegrationType.key) | |
|
137 | ||
|
138 | _post_integration_test_helper( | |
|
139 | self.app, url, csrf_token, admin_view=False, | |
|
79 | 140 | repo=backend_random.repo, repo_group=test_repo_group) |
|
80 | 141 | |
|
81 | 142 | |
|
82 | 143 | class TestRepoGroupIntegrationsView(TestIntegrationsView): |
|
83 |
def test_index_no_integrations(self, |
|
|
144 | def test_index_no_integrations(self, test_repo_group): | |
|
84 | 145 | url = '/{repo_group_name}/settings/integrations'.format( |
|
85 | 146 | repo_group_name=test_repo_group.group_name) |
|
86 | response = app.get(url) | |
|
147 | response = self.app.get(url) | |
|
87 | 148 | |
|
88 | 149 | assert response.status_code == 200 |
|
89 | 150 | assert 'exist yet' in response.body |
|
90 | 151 | |
|
91 |
def test_index_with_integrations( |
|
|
92 |
|
|
|
152 | def test_index_with_integrations( | |
|
153 | self, test_repo_group, repogroup_integration_stub): | |
|
154 | ||
|
93 | 155 | url = '/{repo_group_name}/settings/integrations'.format( |
|
94 | 156 | repo_group_name=test_repo_group.group_name) |
|
95 | 157 | |
|
96 | 158 | stub_name = repogroup_integration_stub.name |
|
97 | response = app.get(url) | |
|
159 | response = self.app.get(url) | |
|
98 | 160 | |
|
99 | 161 | assert response.status_code == 200 |
|
100 | 162 | assert 'exist yet' not in response.body |
|
101 | 163 | assert stub_name in response.body |
|
102 | 164 | |
|
103 |
def test_new_integration_page(self, |
|
|
165 | def test_new_integration_page(self, test_repo_group): | |
|
104 | 166 | repo_group_name = test_repo_group.group_name |
|
105 | 167 | url = '/{repo_group_name}/settings/integrations/new'.format( |
|
106 | 168 | repo_group_name=test_repo_group.group_name) |
|
107 | 169 | |
|
108 | response = app.get(url) | |
|
170 | response = self.app.get(url) | |
|
109 | 171 | |
|
110 | 172 | assert response.status_code == 200 |
|
111 | 173 | |
|
112 | 174 | for integration_key in integration_type_registry: |
|
113 | nurl = ('/{repo_group_name}/settings/integrations' | |
|
114 | '/{integration}/new').format( | |
|
175 | nurl = ('/{repo_group_name}/settings/integrations/{integration}/new').format( | |
|
115 | 176 | repo_group_name=repo_group_name, |
|
116 | 177 | integration=integration_key) |
|
117 | 178 | |
@@ -119,86 +180,29 b' class TestRepoGroupIntegrationsView(Test' | |||
|
119 | 180 | |
|
120 | 181 | @pytest.mark.parametrize( |
|
121 | 182 | 'IntegrationType', integration_type_registry.values()) |
|
122 |
def test_get_create_integration_page( |
|
|
123 | IntegrationType): | |
|
183 | def test_get_create_integration_page( | |
|
184 | self, test_repo_group, IntegrationType): | |
|
185 | ||
|
124 | 186 | repo_group_name = test_repo_group.group_name |
|
125 | 187 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' |
|
126 | 188 | ).format(repo_group_name=repo_group_name, |
|
127 | 189 | integration_key=IntegrationType.key) |
|
128 | 190 | |
|
129 | response = app.get(url) | |
|
191 | response = self.app.get(url) | |
|
130 | 192 | |
|
131 | 193 | assert response.status_code == 200 |
|
132 | 194 | assert IntegrationType.display_name in response.body |
|
133 | 195 | |
|
134 |
def test_post_integration_page(self, |
|
|
196 | def test_post_integration_page(self, test_repo_group, backend_random, | |
|
135 | 197 | StubIntegrationType, csrf_token): |
|
198 | ||
|
136 | 199 | repo_group_name = test_repo_group.group_name |
|
137 | 200 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' |
|
138 | 201 | ).format(repo_group_name=repo_group_name, |
|
139 | 202 | integration_key=StubIntegrationType.key) |
|
140 | 203 | |
|
141 |
_post_integration_test_helper( |
|
|
142 | repo=backend_random.repo, repo_group=test_repo_group) | |
|
143 | ||
|
144 | ||
|
145 | class TestRepoIntegrationsView(TestIntegrationsView): | |
|
146 | def test_index_no_integrations(self, app, backend_random): | |
|
147 | url = '/{repo_name}/settings/integrations'.format( | |
|
148 | repo_name=backend_random.repo.repo_name) | |
|
149 | response = app.get(url) | |
|
150 | ||
|
151 | assert response.status_code == 200 | |
|
152 | assert 'exist yet' in response.body | |
|
153 | ||
|
154 | def test_index_with_integrations(self, app, repo_integration_stub): | |
|
155 | url = '/{repo_name}/settings/integrations'.format( | |
|
156 | repo_name=repo_integration_stub.repo.repo_name) | |
|
157 | stub_name = repo_integration_stub.name | |
|
158 | ||
|
159 | response = app.get(url) | |
|
160 | ||
|
161 | assert response.status_code == 200 | |
|
162 | assert stub_name in response.body | |
|
163 | assert 'exist yet' not in response.body | |
|
164 | ||
|
165 | def test_new_integration_page(self, app, backend_random): | |
|
166 | repo_name = backend_random.repo.repo_name | |
|
167 | url = '/{repo_name}/settings/integrations/new'.format( | |
|
168 | repo_name=repo_name) | |
|
169 | ||
|
170 | response = app.get(url) | |
|
171 | ||
|
172 | assert response.status_code == 200 | |
|
173 | ||
|
174 | for integration_key in integration_type_registry: | |
|
175 | nurl = ('/{repo_name}/settings/integrations' | |
|
176 | '/{integration}/new').format( | |
|
177 | repo_name=repo_name, | |
|
178 | integration=integration_key) | |
|
179 | ||
|
180 | assert nurl in response.body | |
|
181 | ||
|
182 | @pytest.mark.parametrize( | |
|
183 | 'IntegrationType', integration_type_registry.values()) | |
|
184 | def test_get_create_integration_page(self, app, backend_random, | |
|
185 | IntegrationType): | |
|
186 | repo_name = backend_random.repo.repo_name | |
|
187 | url = '/{repo_name}/settings/integrations/{integration_key}/new'.format( | |
|
188 | repo_name=repo_name, integration_key=IntegrationType.key) | |
|
189 | ||
|
190 | response = app.get(url) | |
|
191 | ||
|
192 | assert response.status_code == 200 | |
|
193 | assert IntegrationType.display_name in response.body | |
|
194 | ||
|
195 | def test_post_integration_page(self, app, backend_random, test_repo_group, | |
|
196 | StubIntegrationType, csrf_token): | |
|
197 | repo_name = backend_random.repo.repo_name | |
|
198 | url = '/{repo_name}/settings/integrations/{integration_key}/new'.format( | |
|
199 | repo_name=repo_name, integration_key=StubIntegrationType.key) | |
|
200 | ||
|
201 | _post_integration_test_helper(app, url, csrf_token, admin_view=False, | |
|
204 | _post_integration_test_helper( | |
|
205 | self.app, url, csrf_token, admin_view=False, | |
|
202 | 206 | repo=backend_random.repo, repo_group=test_repo_group) |
|
203 | 207 | |
|
204 | 208 | |
@@ -208,7 +212,8 b' def _post_integration_test_helper(app, u' | |||
|
208 | 212 | Posts form data to create integration at the url given then deletes it and |
|
209 | 213 | checks if the redirect url is correct. |
|
210 | 214 | """ |
|
211 | ||
|
215 | repo_name = repo.repo_name | |
|
216 | repo_group_name = repo_group.group_name | |
|
212 | 217 | app.post(url, params={}, status=403) # missing csrf check |
|
213 | 218 | response = app.post(url, params={'csrf_token': csrf_token}) |
|
214 | 219 | assert response.status_code == 200 |
@@ -219,12 +224,12 b' def _post_integration_test_helper(app, u' | |||
|
219 | 224 | ADMIN_PREFIX + '/integrations'), |
|
220 | 225 | ('root-repos', |
|
221 | 226 | ADMIN_PREFIX + '/integrations'), |
|
222 |
('repo:%s' % |
|
|
223 |
'/%s/settings/integrations' % |
|
|
224 |
('repogroup:%s' % repo_group |
|
|
225 |
'/%s/settings/integrations' % repo_group |
|
|
226 |
('repogroup-recursive:%s' % repo_group |
|
|
227 |
'/%s/settings/integrations' % repo_group |
|
|
227 | ('repo:%s' % repo_name, | |
|
228 | '/%s/settings/integrations' % repo_name), | |
|
229 | ('repogroup:%s' % repo_group_name, | |
|
230 | '/%s/settings/integrations' % repo_group_name), | |
|
231 | ('repogroup-recursive:%s' % repo_group_name, | |
|
232 | '/%s/settings/integrations' % repo_group_name), | |
|
228 | 233 | ] |
|
229 | 234 | |
|
230 | 235 | for scope, destination in scopes_destinations: |
@@ -18,45 +18,40 b'' | |||
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | import pylons | |
|
22 | 21 | import deform |
|
23 | 22 | import logging |
|
24 | import colander | |
|
25 | 23 | import peppercorn |
|
26 | 24 | import webhelpers.paginate |
|
27 | 25 | |
|
28 |
from pyramid.httpexceptions import HTTPFound, HTTPForbidden |
|
|
29 | from pyramid.renderers import render | |
|
30 | from pyramid.response import Response | |
|
26 | from pyramid.httpexceptions import HTTPFound, HTTPForbidden | |
|
31 | 27 | |
|
28 | from rhodecode.apps._base import BaseAppView | |
|
29 | from rhodecode.integrations import integration_type_registry | |
|
32 | 30 | from rhodecode.apps.admin.navigation import navigation_list |
|
33 |
from rhodecode.lib import |
|
|
34 |
|
|
|
31 | from rhodecode.lib.auth import ( | |
|
32 | LoginRequired, CSRFRequired, HasPermissionAnyDecorator, | |
|
33 | HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator) | |
|
35 | 34 | from rhodecode.lib.utils2 import safe_int |
|
36 | 35 | from rhodecode.lib.helpers import Page |
|
37 | 36 | from rhodecode.model.db import Repository, RepoGroup, Session, Integration |
|
38 | 37 | from rhodecode.model.scm import ScmModel |
|
39 | 38 | from rhodecode.model.integration import IntegrationModel |
|
40 | from rhodecode.translation import _ | |
|
41 | from rhodecode.integrations import integration_type_registry | |
|
42 | 39 | from rhodecode.model.validation_schema.schemas.integration_schema import ( |
|
43 | 40 | make_integration_schema, IntegrationScopeType) |
|
44 | 41 | |
|
45 | 42 | log = logging.getLogger(__name__) |
|
46 | 43 | |
|
47 | 44 | |
|
48 |
class IntegrationSettingsViewBase( |
|
|
49 | """ Base Integration settings view used by both repo / global settings """ | |
|
45 | class IntegrationSettingsViewBase(BaseAppView): | |
|
46 | """ | |
|
47 | Base Integration settings view used by both repo / global settings | |
|
48 | """ | |
|
50 | 49 | |
|
51 | 50 | def __init__(self, context, request): |
|
52 | self.context = context | |
|
53 | self.request = request | |
|
54 | self._load_general_context() | |
|
51 | super(IntegrationSettingsViewBase, self).__init__(context, request) | |
|
52 | self._load_view_context() | |
|
55 | 53 | |
|
56 | if not self.perm_check(request.user): | |
|
57 | raise HTTPForbidden() | |
|
58 | ||
|
59 | def _load_general_context(self): | |
|
54 | def _load_view_context(self): | |
|
60 | 55 | """ |
|
61 | 56 | This avoids boilerplate for repo/global+list/edit+views/templates |
|
62 | 57 | by doing all possible contexts at the same time however it should |
@@ -110,25 +105,12 b' class IntegrationSettingsViewBase(object' | |||
|
110 | 105 | |
|
111 | 106 | return False |
|
112 | 107 | |
|
113 | def _template_c_context(self): | |
|
114 | # TODO: dan: this is a stopgap in order to inherit from current pylons | |
|
115 | # based admin/repo settings templates - this should be removed entirely | |
|
116 | # after port to pyramid | |
|
108 | def _get_local_tmpl_context(self, include_app_defaults=False): | |
|
109 | _ = self.request.translate | |
|
110 | c = super(IntegrationSettingsViewBase, self)._get_local_tmpl_context( | |
|
111 | include_app_defaults=include_app_defaults) | |
|
117 | 112 | |
|
118 | c = pylons.tmpl_context | |
|
119 | 113 | c.active = 'integrations' |
|
120 | c.rhodecode_user = self.request.user | |
|
121 | c.repo = self.repo | |
|
122 | c.repo_group = self.repo_group | |
|
123 | c.repo_name = self.repo and self.repo.repo_name or None | |
|
124 | c.repo_group_name = self.repo_group and self.repo_group.group_name or None | |
|
125 | ||
|
126 | if self.repo: | |
|
127 | c.repo_info = self.repo | |
|
128 | c.rhodecode_db_repo = self.repo | |
|
129 | c.repository_pull_requests = ScmModel().get_pull_requests(self.repo) | |
|
130 | else: | |
|
131 | c.navlist = navigation_list(self.request) | |
|
132 | 114 | |
|
133 | 115 | return c |
|
134 | 116 | |
@@ -142,6 +124,7 b' class IntegrationSettingsViewBase(object' | |||
|
142 | 124 | no_scope=not self.admin_view) |
|
143 | 125 | |
|
144 | 126 | def _form_defaults(self): |
|
127 | _ = self.request.translate | |
|
145 | 128 | defaults = {} |
|
146 | 129 | |
|
147 | 130 | if self.integration: |
@@ -178,28 +161,79 b' class IntegrationSettingsViewBase(object' | |||
|
178 | 161 | return defaults |
|
179 | 162 | |
|
180 | 163 | def _delete_integration(self, integration): |
|
181 | Session().delete(self.integration) | |
|
164 | _ = self.request.translate | |
|
165 | Session().delete(integration) | |
|
182 | 166 | Session().commit() |
|
183 | 167 | self.request.session.flash( |
|
184 | 168 | _('Integration {integration_name} deleted successfully.').format( |
|
185 |
integration_name= |
|
|
169 | integration_name=integration.name), | |
|
186 | 170 | queue='success') |
|
187 | 171 | |
|
188 | 172 | if self.repo: |
|
189 |
redirect_to = self.request.route_ |
|
|
173 | redirect_to = self.request.route_path( | |
|
190 | 174 | 'repo_integrations_home', repo_name=self.repo.repo_name) |
|
191 | 175 | elif self.repo_group: |
|
192 |
redirect_to = self.request.route_ |
|
|
176 | redirect_to = self.request.route_path( | |
|
193 | 177 | 'repo_group_integrations_home', |
|
194 | 178 | repo_group_name=self.repo_group.group_name) |
|
195 | 179 | else: |
|
196 |
redirect_to = self.request.route_ |
|
|
180 | redirect_to = self.request.route_path('global_integrations_home') | |
|
197 | 181 | raise HTTPFound(redirect_to) |
|
198 | 182 | |
|
199 | def settings_get(self, defaults=None, form=None): | |
|
183 | def _integration_list(self): | |
|
184 | """ List integrations """ | |
|
185 | ||
|
186 | c = self.load_default_context() | |
|
187 | if self.repo: | |
|
188 | scope = self.repo | |
|
189 | elif self.repo_group: | |
|
190 | scope = self.repo_group | |
|
191 | else: | |
|
192 | scope = 'all' | |
|
193 | ||
|
194 | integrations = [] | |
|
195 | ||
|
196 | for IntType, integration in IntegrationModel().get_integrations( | |
|
197 | scope=scope, IntegrationType=self.IntegrationType): | |
|
198 | ||
|
199 | # extra permissions check *just in case* | |
|
200 | if not self._has_perms_for_integration(integration): | |
|
201 | continue | |
|
202 | ||
|
203 | integrations.append((IntType, integration)) | |
|
204 | ||
|
205 | sort_arg = self.request.GET.get('sort', 'name:asc') | |
|
206 | if ':' in sort_arg: | |
|
207 | sort_field, sort_dir = sort_arg.split(':') | |
|
208 | else: | |
|
209 | sort_field = sort_arg, 'asc' | |
|
210 | ||
|
211 | assert sort_field in ('name', 'integration_type', 'enabled', 'scope') | |
|
212 | ||
|
213 | integrations.sort( | |
|
214 | key=lambda x: getattr(x[1], sort_field), | |
|
215 | reverse=(sort_dir == 'desc')) | |
|
216 | ||
|
217 | page_url = webhelpers.paginate.PageURL( | |
|
218 | self.request.path, self.request.GET) | |
|
219 | page = safe_int(self.request.GET.get('page', 1), 1) | |
|
220 | ||
|
221 | integrations = Page( | |
|
222 | integrations, page=page, items_per_page=10, url=page_url) | |
|
223 | ||
|
224 | c.rev_sort_dir = sort_dir != 'desc' and 'desc' or 'asc' | |
|
225 | ||
|
226 | c.current_IntegrationType = self.IntegrationType | |
|
227 | c.integrations_list = integrations | |
|
228 | c.available_integrations = integration_type_registry | |
|
229 | ||
|
230 | return self._get_template_context(c) | |
|
231 | ||
|
232 | def _settings_get(self, defaults=None, form=None): | |
|
200 | 233 | """ |
|
201 | 234 | View that displays the integration settings as a form. |
|
202 | 235 | """ |
|
236 | c = self.load_default_context() | |
|
203 | 237 | |
|
204 | 238 | defaults = defaults or self._form_defaults() |
|
205 | 239 | schema = self._form_schema() |
@@ -211,20 +245,18 b' class IntegrationSettingsViewBase(object' | |||
|
211 | 245 | |
|
212 | 246 | form = form or deform.Form(schema, appstruct=defaults, buttons=buttons) |
|
213 | 247 | |
|
214 | template_context = { | |
|
215 | 'form': form, | |
|
216 |
|
|
|
217 | 'integration': self.integration, | |
|
218 | 'c': self._template_c_context(), | |
|
219 | } | |
|
248 | c.form = form | |
|
249 | c.current_IntegrationType = self.IntegrationType | |
|
250 | c.integration = self.integration | |
|
220 | 251 | |
|
221 | return template_context | |
|
252 | return self._get_template_context(c) | |
|
222 | 253 | |
|
223 | @auth.CSRFRequired() | |
|
224 | def settings_post(self): | |
|
254 | def _settings_post(self): | |
|
225 | 255 | """ |
|
226 | 256 | View that validates and stores the integration settings. |
|
227 | 257 | """ |
|
258 | _ = self.request.translate | |
|
259 | ||
|
228 | 260 | controls = self.request.POST.items() |
|
229 | 261 | pstruct = peppercorn.parse(controls) |
|
230 | 262 | |
@@ -264,7 +296,7 b' class IntegrationSettingsViewBase(object' | |||
|
264 | 296 | _('Errors exist when saving integration settings. ' |
|
265 | 297 | 'Please check the form inputs.'), |
|
266 | 298 | queue='error') |
|
267 | return self.settings_get(form=e) | |
|
299 | return self._settings_get(form=e) | |
|
268 | 300 | |
|
269 | 301 | if not self.integration: |
|
270 | 302 | self.integration = Integration() |
@@ -314,77 +346,110 b' class IntegrationSettingsViewBase(object' | |||
|
314 | 346 | |
|
315 | 347 | return HTTPFound(redirect_to) |
|
316 | 348 | |
|
317 |
def |
|
|
318 | """ List integrations """ | |
|
319 | if self.repo: | |
|
320 | scope = self.repo | |
|
321 | elif self.repo_group: | |
|
322 | scope = self.repo_group | |
|
323 | else: | |
|
324 | scope = 'all' | |
|
325 | ||
|
326 | integrations = [] | |
|
327 | ||
|
328 | for IntType, integration in IntegrationModel().get_integrations( | |
|
329 | scope=scope, IntegrationType=self.IntegrationType): | |
|
330 | ||
|
331 | # extra permissions check *just in case* | |
|
332 | if not self._has_perms_for_integration(integration): | |
|
333 | continue | |
|
334 | ||
|
335 | integrations.append((IntType, integration)) | |
|
336 | ||
|
337 | sort_arg = self.request.GET.get('sort', 'name:asc') | |
|
338 | if ':' in sort_arg: | |
|
339 | sort_field, sort_dir = sort_arg.split(':') | |
|
340 | else: | |
|
341 | sort_field = sort_arg, 'asc' | |
|
342 | ||
|
343 | assert sort_field in ('name', 'integration_type', 'enabled', 'scope') | |
|
349 | def _new_integration(self): | |
|
350 | c = self.load_default_context() | |
|
351 | c.available_integrations = integration_type_registry | |
|
352 | return self._get_template_context(c) | |
|
344 | 353 | |
|
345 | integrations.sort( | |
|
346 | key=lambda x: getattr(x[1], sort_field), | |
|
347 | reverse=(sort_dir == 'desc')) | |
|
348 | ||
|
349 | page_url = webhelpers.paginate.PageURL( | |
|
350 | self.request.path, self.request.GET) | |
|
351 | page = safe_int(self.request.GET.get('page', 1), 1) | |
|
352 | ||
|
353 | integrations = Page(integrations, page=page, items_per_page=10, | |
|
354 | url=page_url) | |
|
355 | ||
|
356 | template_context = { | |
|
357 | 'sort_field': sort_field, | |
|
358 | 'rev_sort_dir': sort_dir != 'desc' and 'desc' or 'asc', | |
|
359 | 'current_IntegrationType': self.IntegrationType, | |
|
360 | 'integrations_list': integrations, | |
|
361 | 'available_integrations': integration_type_registry, | |
|
362 | 'c': self._template_c_context(), | |
|
363 | 'request': self.request, | |
|
364 | } | |
|
365 | return template_context | |
|
366 | ||
|
367 | def new_integration(self): | |
|
368 | template_context = { | |
|
369 | 'available_integrations': integration_type_registry, | |
|
370 | 'c': self._template_c_context(), | |
|
371 | } | |
|
372 | return template_context | |
|
354 | def load_default_context(self): | |
|
355 | raise NotImplementedError() | |
|
373 | 356 | |
|
374 | 357 | |
|
375 | 358 | class GlobalIntegrationsView(IntegrationSettingsViewBase): |
|
376 | def perm_check(self, user): | |
|
377 | return auth.HasPermissionAll('hg.admin').check_permissions(user=user) | |
|
359 | def load_default_context(self): | |
|
360 | c = self._get_local_tmpl_context() | |
|
361 | c.repo = self.repo | |
|
362 | c.repo_group = self.repo_group | |
|
363 | c.navlist = navigation_list(self.request) | |
|
364 | self._register_global_c(c) | |
|
365 | return c | |
|
366 | ||
|
367 | @LoginRequired() | |
|
368 | @HasPermissionAnyDecorator('hg.admin') | |
|
369 | def integration_list(self): | |
|
370 | return self._integration_list() | |
|
371 | ||
|
372 | @LoginRequired() | |
|
373 | @HasPermissionAnyDecorator('hg.admin') | |
|
374 | def settings_get(self): | |
|
375 | return self._settings_get() | |
|
376 | ||
|
377 | @LoginRequired() | |
|
378 | @HasPermissionAnyDecorator('hg.admin') | |
|
379 | @CSRFRequired() | |
|
380 | def settings_post(self): | |
|
381 | return self._settings_post() | |
|
382 | ||
|
383 | @LoginRequired() | |
|
384 | @HasPermissionAnyDecorator('hg.admin') | |
|
385 | def new_integration(self): | |
|
386 | return self._new_integration() | |
|
378 | 387 | |
|
379 | 388 | |
|
380 | 389 | class RepoIntegrationsView(IntegrationSettingsViewBase): |
|
381 | def perm_check(self, user): | |
|
382 | return auth.HasRepoPermissionAll('repository.admin')( | |
|
383 | repo_name=self.repo.repo_name, user=user) | |
|
390 | def load_default_context(self): | |
|
391 | c = self._get_local_tmpl_context() | |
|
392 | ||
|
393 | c.repo = self.repo | |
|
394 | c.repo_group = self.repo_group | |
|
395 | ||
|
396 | # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead | |
|
397 | c.repo_info = self.db_repo = self.repo | |
|
398 | c.rhodecode_db_repo = self.repo | |
|
399 | c.repo_name = self.db_repo.repo_name | |
|
400 | c.repository_pull_requests = ScmModel().get_pull_requests(self.repo) | |
|
401 | ||
|
402 | self._register_global_c(c) | |
|
403 | return c | |
|
404 | ||
|
405 | @LoginRequired() | |
|
406 | @HasRepoPermissionAnyDecorator('repository.admin') | |
|
407 | def integration_list(self): | |
|
408 | return self._integration_list() | |
|
409 | ||
|
410 | @LoginRequired() | |
|
411 | @HasRepoPermissionAnyDecorator('repository.admin') | |
|
412 | def settings_get(self): | |
|
413 | return self._settings_get() | |
|
414 | ||
|
415 | @LoginRequired() | |
|
416 | @HasRepoPermissionAnyDecorator('repository.admin') | |
|
417 | @CSRFRequired() | |
|
418 | def settings_post(self): | |
|
419 | return self._settings_post() | |
|
420 | ||
|
421 | @LoginRequired() | |
|
422 | @HasRepoPermissionAnyDecorator('repository.admin') | |
|
423 | def new_integration(self): | |
|
424 | return self._new_integration() | |
|
384 | 425 | |
|
385 | 426 | |
|
386 | 427 | class RepoGroupIntegrationsView(IntegrationSettingsViewBase): |
|
387 | def perm_check(self, user): | |
|
388 | return auth.HasRepoGroupPermissionAll('group.admin')( | |
|
389 | group_name=self.repo_group.group_name, user=user) | |
|
428 | def load_default_context(self): | |
|
429 | c = self._get_local_tmpl_context() | |
|
430 | c.repo = self.repo | |
|
431 | c.repo_group = self.repo_group | |
|
432 | c.navlist = navigation_list(self.request) | |
|
433 | self._register_global_c(c) | |
|
434 | return c | |
|
435 | ||
|
436 | @LoginRequired() | |
|
437 | @HasRepoGroupPermissionAnyDecorator('group.admin') | |
|
438 | def integration_list(self): | |
|
439 | return self._integration_list() | |
|
390 | 440 | |
|
441 | @LoginRequired() | |
|
442 | @HasRepoGroupPermissionAnyDecorator('group.admin') | |
|
443 | def settings_get(self): | |
|
444 | return self._settings_get() | |
|
445 | ||
|
446 | @LoginRequired() | |
|
447 | @HasRepoGroupPermissionAnyDecorator('group.admin') | |
|
448 | @CSRFRequired() | |
|
449 | def settings_post(self): | |
|
450 | return self._settings_post() | |
|
451 | ||
|
452 | @LoginRequired() | |
|
453 | @HasRepoGroupPermissionAnyDecorator('group.admin') | |
|
454 | def new_integration(self): | |
|
455 | return self._new_integration() |
@@ -23,13 +23,13 b' function registerRCRoutes() {' | |||
|
23 | 23 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); |
|
24 | 24 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); |
|
25 | 25 | pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/settings/integrations', ['repo_group_name']); |
|
26 | pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']); | |
|
26 | 27 | pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']); |
|
27 | pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']); | |
|
28 | 28 | pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); |
|
29 | 29 | pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); |
|
30 | 30 | pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']); |
|
31 | pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']); | |
|
31 | 32 | pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); |
|
32 | pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']); | |
|
33 | 33 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
34 | 34 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
35 | 35 | pyroutes.register('ops_ping', '/_admin/ops/ping', []); |
@@ -7,10 +7,10 b'' | |||
|
7 | 7 | » |
|
8 | 8 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_integrations_home', repo_name=c.repo.repo_name))} |
|
9 | 9 | » |
|
10 | ${h.link_to(current_IntegrationType.display_name, | |
|
10 | ${h.link_to(c.current_IntegrationType.display_name, | |
|
11 | 11 | request.route_url(route_name='repo_integrations_list', |
|
12 | 12 | repo_name=c.repo.repo_name, |
|
13 | integration=current_IntegrationType.key))} | |
|
13 | integration=c.current_IntegrationType.key))} | |
|
14 | 14 | %elif c.repo_group: |
|
15 | 15 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} |
|
16 | 16 | » |
@@ -20,10 +20,10 b'' | |||
|
20 | 20 | » |
|
21 | 21 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_group_integrations_home', repo_group_name=c.repo_group.group_name))} |
|
22 | 22 | » |
|
23 | ${h.link_to(current_IntegrationType.display_name, | |
|
23 | ${h.link_to(c.current_IntegrationType.display_name, | |
|
24 | 24 | request.route_url(route_name='repo_group_integrations_list', |
|
25 | 25 | repo_group_name=c.repo_group.group_name, |
|
26 | integration=current_IntegrationType.key))} | |
|
26 | integration=c.current_IntegrationType.key))} | |
|
27 | 27 | %else: |
|
28 | 28 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} |
|
29 | 29 | » |
@@ -31,17 +31,17 b'' | |||
|
31 | 31 | » |
|
32 | 32 | ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))} |
|
33 | 33 | » |
|
34 | ${h.link_to(current_IntegrationType.display_name, | |
|
34 | ${h.link_to(c.current_IntegrationType.display_name, | |
|
35 | 35 | request.route_url(route_name='global_integrations_list', |
|
36 | integration=current_IntegrationType.key))} | |
|
36 | integration=c.current_IntegrationType.key))} | |
|
37 | 37 | %endif |
|
38 | 38 | |
|
39 | %if integration: | |
|
39 | %if c.integration: | |
|
40 | 40 | » |
|
41 | ${integration.name} | |
|
42 | %elif current_IntegrationType: | |
|
41 | ${c.integration.name} | |
|
42 | %elif c.current_IntegrationType: | |
|
43 | 43 | » |
|
44 | ${current_IntegrationType.display_name} | |
|
44 | ${c.current_IntegrationType.display_name} | |
|
45 | 45 | %endif |
|
46 | 46 | </%def> |
|
47 | 47 | |
@@ -54,16 +54,16 b'' | |||
|
54 | 54 | <div class="panel panel-default"> |
|
55 | 55 | <div class="panel-heading"> |
|
56 | 56 | <h2 class="panel-title"> |
|
57 | %if integration: | |
|
58 | ${current_IntegrationType.display_name} - ${integration.name} | |
|
57 | %if c.integration: | |
|
58 | ${c.current_IntegrationType.display_name} - ${c.integration.name} | |
|
59 | 59 | %else: |
|
60 | 60 | ${_('Create New %(integration_type)s Integration') % { |
|
61 | 'integration_type': current_IntegrationType.display_name | |
|
61 | 'integration_type': c.current_IntegrationType.display_name | |
|
62 | 62 | }} |
|
63 | 63 | %endif |
|
64 | 64 | </h2> |
|
65 | 65 | </div> |
|
66 | 66 | <div class="panel-body"> |
|
67 | ${form.render() | n} | |
|
67 | ${c.form.render() | n} | |
|
68 | 68 | </div> |
|
69 | 69 | </div> |
@@ -15,22 +15,22 b'' | |||
|
15 | 15 | » |
|
16 | 16 | ${h.link_to(_('Settings'),h.url('admin_settings'))} |
|
17 | 17 | %endif |
|
18 | %if current_IntegrationType: | |
|
18 | %if c.current_IntegrationType: | |
|
19 | 19 | » |
|
20 | 20 | %if c.repo: |
|
21 | 21 | ${h.link_to(_('Integrations'), |
|
22 |
request.route_ |
|
|
22 | request.route_path(route_name='repo_integrations_home', | |
|
23 | 23 | repo_name=c.repo.repo_name))} |
|
24 | 24 | %elif c.repo_group: |
|
25 | 25 | ${h.link_to(_('Integrations'), |
|
26 |
request.route_ |
|
|
26 | request.route_path(route_name='repo_group_integrations_home', | |
|
27 | 27 | repo_group_name=c.repo_group.group_name))} |
|
28 | 28 | %else: |
|
29 | 29 | ${h.link_to(_('Integrations'), |
|
30 |
request.route_ |
|
|
30 | request.route_path(route_name='global_integrations_home'))} | |
|
31 | 31 | %endif |
|
32 | 32 | » |
|
33 | ${current_IntegrationType.display_name} | |
|
33 | ${c.current_IntegrationType.display_name} | |
|
34 | 34 | %else: |
|
35 | 35 | » |
|
36 | 36 | ${_('Integrations')} |
@@ -61,9 +61,9 b'' | |||
|
61 | 61 | home_url = request.route_path('global_integrations_home') |
|
62 | 62 | %> |
|
63 | 63 | |
|
64 | <a href="${home_url}" class="btn ${not current_IntegrationType and 'btn-primary' or ''}">${_('All')}</a> | |
|
64 | <a href="${home_url}" class="btn ${not c.current_IntegrationType and 'btn-primary' or ''}">${_('All')}</a> | |
|
65 | 65 | |
|
66 | %for integration_key, IntegrationType in available_integrations.items(): | |
|
66 | %for integration_key, IntegrationType in c.available_integrations.items(): | |
|
67 | 67 | <% |
|
68 | 68 | if c.repo: |
|
69 | 69 | list_url = request.route_path('repo_integrations_list', |
@@ -78,12 +78,14 b'' | |||
|
78 | 78 | integration=integration_key) |
|
79 | 79 | %> |
|
80 | 80 | <a href="${list_url}" |
|
81 | class="btn ${current_IntegrationType and integration_key == current_IntegrationType.key and 'btn-primary' or ''}"> | |
|
81 | class="btn ${c.current_IntegrationType and integration_key == c.current_IntegrationType.key and 'btn-primary' or ''}"> | |
|
82 | 82 | ${IntegrationType.display_name} |
|
83 | 83 | </a> |
|
84 | 84 | %endfor |
|
85 | 85 | |
|
86 | 86 | <% |
|
87 | integration_type = c.current_IntegrationType and c.current_IntegrationType.display_name or '' | |
|
88 | ||
|
87 | 89 | if c.repo: |
|
88 | 90 | create_url = h.route_path('repo_integrations_new', repo_name=c.repo.repo_name) |
|
89 | 91 | elif c.repo_group: |
@@ -98,19 +100,19 b'' | |||
|
98 | 100 | <table class="rctable integrations"> |
|
99 | 101 | <thead> |
|
100 | 102 | <tr> |
|
101 | <th><a href="?sort=enabled:${rev_sort_dir}">${_('Enabled')}</a></th> | |
|
102 | <th><a href="?sort=name:${rev_sort_dir}">${_('Name')}</a></th> | |
|
103 | <th colspan="2"><a href="?sort=integration_type:${rev_sort_dir}">${_('Type')}</a></th> | |
|
104 | <th><a href="?sort=scope:${rev_sort_dir}">${_('Scope')}</a></th> | |
|
103 | <th><a href="?sort=enabled:${c.rev_sort_dir}">${_('Enabled')}</a></th> | |
|
104 | <th><a href="?sort=name:${c.rev_sort_dir}">${_('Name')}</a></th> | |
|
105 | <th colspan="2"><a href="?sort=integration_type:${c.rev_sort_dir}">${_('Type')}</a></th> | |
|
106 | <th><a href="?sort=scope:${c.rev_sort_dir}">${_('Scope')}</a></th> | |
|
105 | 107 | <th>${_('Actions')}</th> |
|
106 | 108 | <th></th> |
|
107 | 109 | </tr> |
|
108 | 110 | </thead> |
|
109 | 111 | <tbody> |
|
110 | %if not integrations_list: | |
|
112 | %if not c.integrations_list: | |
|
111 | 113 | <tr> |
|
112 | 114 | <td colspan="7"> |
|
113 | <% integration_type = current_IntegrationType and current_IntegrationType.display_name or '' %> | |
|
115 | ||
|
114 | 116 | %if c.repo: |
|
115 | 117 | ${_('No {type} integrations for repo {repo} exist yet.').format(type=integration_type, repo=c.repo.repo_name)} |
|
116 | 118 | %elif c.repo_group: |
@@ -119,14 +121,14 b'' | |||
|
119 | 121 | ${_('No {type} integrations exist yet.').format(type=integration_type)} |
|
120 | 122 | %endif |
|
121 | 123 | |
|
122 | %if current_IntegrationType: | |
|
124 | %if c.current_IntegrationType: | |
|
123 | 125 | <% |
|
124 | 126 | if c.repo: |
|
125 | create_url = h.route_path('repo_integrations_create', repo_name=c.repo.repo_name, integration=current_IntegrationType.key) | |
|
127 | create_url = h.route_path('repo_integrations_create', repo_name=c.repo.repo_name, integration=c.current_IntegrationType.key) | |
|
126 | 128 | elif c.repo_group: |
|
127 | create_url = h.route_path('repo_group_integrations_create', repo_group_name=c.repo_group.group_name, integration=current_IntegrationType.key) | |
|
129 | create_url = h.route_path('repo_group_integrations_create', repo_group_name=c.repo_group.group_name, integration=c.current_IntegrationType.key) | |
|
128 | 130 | else: |
|
129 | create_url = h.route_path('global_integrations_create', integration=current_IntegrationType.key) | |
|
131 | create_url = h.route_path('global_integrations_create', integration=c.current_IntegrationType.key) | |
|
130 | 132 | %> |
|
131 | 133 | %endif |
|
132 | 134 | |
@@ -134,7 +136,7 b'' | |||
|
134 | 136 | </td> |
|
135 | 137 | </tr> |
|
136 | 138 | %endif |
|
137 | %for IntegrationType, integration in integrations_list: | |
|
139 | %for IntegrationType, integration in c.integrations_list: | |
|
138 | 140 | <tr id="integration_${integration.integration_id}"> |
|
139 | 141 | <td class="td-enabled"> |
|
140 | 142 | %if integration.enabled: |
@@ -147,9 +149,9 b'' | |||
|
147 | 149 | ${integration.name} |
|
148 | 150 | </td> |
|
149 | 151 | <td class="td-icon"> |
|
150 | %if integration.integration_type in available_integrations: | |
|
152 | %if integration.integration_type in c.available_integrations: | |
|
151 | 153 | <div class="integration-icon"> |
|
152 | ${available_integrations[integration.integration_type].icon|n} | |
|
154 | ${c.available_integrations[integration.integration_type].icon|n} | |
|
153 | 155 | </div> |
|
154 | 156 | %else: |
|
155 | 157 | ? |
@@ -220,7 +222,7 b'' | |||
|
220 | 222 | </table> |
|
221 | 223 | <div class="integrations-paginator"> |
|
222 | 224 | <div class="pagination-wh pagination-left"> |
|
223 | ${integrations_list.pager('$link_previous ~2~ $link_next')} | |
|
225 | ${c.integrations_list.pager('$link_previous ~2~ $link_next')} | |
|
224 | 226 | </div> |
|
225 | 227 | </div> |
|
226 | 228 | </div> |
@@ -36,7 +36,7 b'' | |||
|
36 | 36 | %endif |
|
37 | 37 | </%def> |
|
38 | 38 | |
|
39 | %for integration, IntegrationType in available_integrations.items(): | |
|
39 | %for integration, IntegrationType in c.available_integrations.items(): | |
|
40 | 40 | <% |
|
41 | 41 | if c.repo: |
|
42 | 42 | create_url = request.route_path('repo_integrations_create', |
@@ -25,21 +25,21 b' from rhodecode import events' | |||
|
25 | 25 | from rhodecode.tests.fixture import Fixture |
|
26 | 26 | from rhodecode.model.db import Session, Integration |
|
27 | 27 | from rhodecode.model.integration import IntegrationModel |
|
28 | from rhodecode.integrations.types.base import IntegrationTypeBase | |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | class TestDeleteScopesDeletesIntegrations(object): |
|
32 |
def test_delete_repo_with_integration_deletes_integration( |
|
|
33 | repo_integration_stub): | |
|
31 | def test_delete_repo_with_integration_deletes_integration( | |
|
32 | self, repo_integration_stub): | |
|
33 | ||
|
34 | 34 | Session().delete(repo_integration_stub.repo) |
|
35 | 35 | Session().commit() |
|
36 | 36 | Session().expire_all() |
|
37 | 37 | integration = Integration.get(repo_integration_stub.integration_id) |
|
38 | 38 | assert integration is None |
|
39 | 39 | |
|
40 | def test_delete_repo_group_with_integration_deletes_integration( | |
|
41 | self, repogroup_integration_stub): | |
|
40 | 42 | |
|
41 | def test_delete_repo_group_with_integration_deletes_integration(self, | |
|
42 | repogroup_integration_stub): | |
|
43 | 43 | Session().delete(repogroup_integration_stub.repo_group) |
|
44 | 44 | Session().commit() |
|
45 | 45 | Session().expire_all() |
@@ -146,7 +146,6 b' def test_enabled_integration_repo_scopes' | |||
|
146 | 146 | integrations['root_repo'], |
|
147 | 147 | ] |
|
148 | 148 | |
|
149 | ||
|
150 | 149 | triggered_integrations = IntegrationModel().get_for_event( |
|
151 | 150 | events.RepoEvent(repos['other_repo'])) |
|
152 | 151 | |
@@ -157,7 +156,6 b' def test_enabled_integration_repo_scopes' | |||
|
157 | 156 | integrations['other_group_recursive'], |
|
158 | 157 | ] |
|
159 | 158 | |
|
160 | ||
|
161 | 159 | triggered_integrations = IntegrationModel().get_for_event( |
|
162 | 160 | events.RepoEvent(repos['parent_repo'])) |
|
163 | 161 | |
@@ -193,26 +191,22 b' def test_disabled_integration_repo_scope' | |||
|
193 | 191 | |
|
194 | 192 | assert triggered_integrations == [] |
|
195 | 193 | |
|
196 | ||
|
197 | 194 | triggered_integrations = IntegrationModel().get_for_event( |
|
198 | 195 | events.RepoEvent(repos['parent_repo'])) |
|
199 | 196 | |
|
200 | 197 | assert triggered_integrations == [] |
|
201 | 198 | |
|
202 | ||
|
203 | 199 | triggered_integrations = IntegrationModel().get_for_event( |
|
204 | 200 | events.RepoEvent(repos['child_repo'])) |
|
205 | 201 | |
|
206 | 202 | assert triggered_integrations == [] |
|
207 | 203 | |
|
208 | ||
|
209 | 204 | triggered_integrations = IntegrationModel().get_for_event( |
|
210 | 205 | events.RepoEvent(repos['other_repo'])) |
|
211 | 206 | |
|
212 | 207 | assert triggered_integrations == [] |
|
213 | 208 | |
|
214 | 209 | |
|
215 | ||
|
216 | 210 | def test_enabled_non_repo_integrations(integration_repos): |
|
217 | 211 | integrations = integration_repos['integrations'] |
|
218 | 212 |
@@ -336,7 +336,7 b' def test_repo_group(request):' | |||
|
336 | 336 | usage automatically |
|
337 | 337 | """ |
|
338 | 338 | fixture = Fixture() |
|
339 |
repogroupid = 'test_repo_group_%s' % |
|
|
339 | repogroupid = 'test_repo_group_%s' % str(time.time()).replace('.', '') | |
|
340 | 340 | repo_group = fixture.create_repo_group(repogroupid) |
|
341 | 341 | |
|
342 | 342 | def _cleanup(): |
@@ -353,7 +353,7 b' def test_user_group(request):' | |||
|
353 | 353 | usage automatically |
|
354 | 354 | """ |
|
355 | 355 | fixture = Fixture() |
|
356 |
usergroupid = 'test_user_group_%s' % |
|
|
356 | usergroupid = 'test_user_group_%s' % str(time.time()).replace('.', '') | |
|
357 | 357 | user_group = fixture.create_user_group(usergroupid) |
|
358 | 358 | |
|
359 | 359 | def _cleanup(): |
General Comments 0
You need to be logged in to leave comments.
Login now