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 | import logging |
|
21 | import logging | |
22 |
|
22 | |||
23 | from rhodecode.apps._base import ADMIN_PREFIX, add_route_requirements |
|
23 | from rhodecode.apps._base import ADMIN_PREFIX, add_route_requirements | |
|
24 | from rhodecode.lib.utils2 import safe_int | |||
24 | from rhodecode.model.db import Repository, Integration, RepoGroup |
|
25 | from rhodecode.model.db import Repository, Integration, RepoGroup | |
25 | from rhodecode.integrations import integration_type_registry |
|
26 | from rhodecode.integrations import integration_type_registry | |
26 |
|
27 | |||
@@ -30,7 +31,6 b' log = logging.getLogger(__name__)' | |||||
30 | def includeme(config): |
|
31 | def includeme(config): | |
31 |
|
32 | |||
32 | # global integrations |
|
33 | # global integrations | |
33 |
|
||||
34 | config.add_route('global_integrations_new', |
|
34 | config.add_route('global_integrations_new', | |
35 | ADMIN_PREFIX + '/integrations/new') |
|
35 | ADMIN_PREFIX + '/integrations/new') | |
36 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
|
36 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', | |
@@ -45,7 +45,7 b' def includeme(config):' | |||||
45 | ADMIN_PREFIX + '/integrations/{integration}') |
|
45 | ADMIN_PREFIX + '/integrations/{integration}') | |
46 | for route_name in ['global_integrations_home', 'global_integrations_list']: |
|
46 | for route_name in ['global_integrations_home', 'global_integrations_list']: | |
47 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
|
47 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', | |
48 |
attr='in |
|
48 | attr='integration_list', | |
49 | renderer='rhodecode:templates/admin/integrations/list.mako', |
|
49 | renderer='rhodecode:templates/admin/integrations/list.mako', | |
50 | request_method='GET', |
|
50 | request_method='GET', | |
51 | route_name=route_name) |
|
51 | route_name=route_name) | |
@@ -57,7 +57,6 b' def includeme(config):' | |||||
57 | ADMIN_PREFIX + '/integrations/{integration}/{integration_id}', |
|
57 | ADMIN_PREFIX + '/integrations/{integration}/{integration_id}', | |
58 | custom_predicates=(valid_integration,)) |
|
58 | custom_predicates=(valid_integration,)) | |
59 |
|
59 | |||
60 |
|
||||
61 | for route_name in ['global_integrations_create', 'global_integrations_edit']: |
|
60 | for route_name in ['global_integrations_create', 'global_integrations_edit']: | |
62 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', |
|
61 | config.add_view('rhodecode.integrations.views.GlobalIntegrationsView', | |
63 | attr='settings_get', |
|
62 | attr='settings_get', | |
@@ -70,154 +69,159 b' def includeme(config):' | |||||
70 | request_method='POST', |
|
69 | request_method='POST', | |
71 | route_name=route_name) |
|
70 | route_name=route_name) | |
72 |
|
71 | |||
73 |
|
||||
74 | # repo group integrations |
|
72 | # repo group integrations | |
75 | config.add_route('repo_group_integrations_home', |
|
73 | config.add_route('repo_group_integrations_home', | |
76 | add_route_requirements( |
|
74 | add_route_requirements('/{repo_group_name}/settings/integrations'), | |
77 |
|
|
75 | repo_group_route=True) | |
78 | ), |
|
76 | ||
79 | custom_predicates=(valid_repo_group,) |
|
77 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
80 |
|
|
78 | attr='integration_list', | |
81 | config.add_route('repo_group_integrations_list', |
|
79 | renderer='rhodecode:templates/admin/integrations/list.mako', | |
82 |
|
|
80 | request_method='GET', | |
83 |
|
|
81 | route_name='repo_group_integrations_home') | |
84 | ), |
|
|||
85 | custom_predicates=(valid_repo_group, valid_integration)) |
|
|||
86 | for route_name in ['repo_group_integrations_home', 'repo_group_integrations_list']: |
|
|||
87 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', |
|
|||
88 | attr='index', |
|
|||
89 | renderer='rhodecode:templates/admin/integrations/list.mako', |
|
|||
90 | request_method='GET', |
|
|||
91 | route_name=route_name) |
|
|||
92 |
|
82 | |||
93 | config.add_route('repo_group_integrations_new', |
|
83 | config.add_route('repo_group_integrations_new', | |
94 | add_route_requirements( |
|
84 | add_route_requirements('/{repo_group_name}/settings/integrations/new'), | |
95 |
|
|
85 | repo_group_route=True) | |
96 | ), |
|
|||
97 | custom_predicates=(valid_repo_group,)) |
|
|||
98 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', |
|
86 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
99 | attr='new_integration', |
|
87 | attr='new_integration', | |
100 | renderer='rhodecode:templates/admin/integrations/new.mako', |
|
88 | renderer='rhodecode:templates/admin/integrations/new.mako', | |
101 | request_method='GET', |
|
89 | request_method='GET', | |
102 | route_name='repo_group_integrations_new') |
|
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 | config.add_route('repo_group_integrations_create', |
|
102 | config.add_route('repo_group_integrations_create', | |
105 | add_route_requirements( |
|
103 | add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/new'), | |
106 | '{repo_group_name}/settings/integrations/{integration}/new', |
|
104 | repo_group_route=True, | |
107 | ), |
|
105 | custom_predicates=(valid_integration,)) | |
108 | custom_predicates=(valid_repo_group, valid_integration)) |
|
106 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |
|
107 | attr='settings_get', | |||
|
108 | renderer='rhodecode:templates/admin/integrations/form.mako', | |||
|
109 | request_method='GET', | |||
|
110 | route_name='repo_group_integrations_create') | |||
|
111 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', | |||
|
112 | attr='settings_post', | |||
|
113 | renderer='rhodecode:templates/admin/integrations/form.mako', | |||
|
114 | request_method='POST', | |||
|
115 | route_name='repo_group_integrations_create') | |||
|
116 | ||||
109 | config.add_route('repo_group_integrations_edit', |
|
117 | config.add_route('repo_group_integrations_edit', | |
110 | add_route_requirements( |
|
118 | add_route_requirements('/{repo_group_name}/settings/integrations/{integration}/{integration_id}'), | |
111 | '{repo_group_name}/settings/integrations/{integration}/{integration_id}', |
|
119 | repo_group_route=True, | |
112 | ), |
|
120 | custom_predicates=(valid_integration,)) | |
113 | custom_predicates=(valid_repo_group, valid_integration)) |
|
|||
114 | for route_name in ['repo_group_integrations_edit', 'repo_group_integrations_create']: |
|
|||
115 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', |
|
|||
116 | attr='settings_get', |
|
|||
117 | renderer='rhodecode:templates/admin/integrations/form.mako', |
|
|||
118 | request_method='GET', |
|
|||
119 | route_name=route_name) |
|
|||
120 | config.add_view('rhodecode.integrations.views.RepoGroupIntegrationsView', |
|
|||
121 | attr='settings_post', |
|
|||
122 | renderer='rhodecode:templates/admin/integrations/form.mako', |
|
|||
123 | request_method='POST', |
|
|||
124 | route_name=route_name) |
|
|||
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 | # repo integrations |
|
133 | # repo integrations | |
128 | config.add_route('repo_integrations_home', |
|
134 | config.add_route('repo_integrations_home', | |
129 | add_route_requirements( |
|
135 | add_route_requirements('/{repo_name}/settings/integrations'), | |
130 | '{repo_name}/settings/integrations', |
|
136 | repo_route=True) | |
131 | ), |
|
137 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
132 | custom_predicates=(valid_repo,)) |
|
138 | attr='integration_list', | |
133 | config.add_route('repo_integrations_list', |
|
139 | request_method='GET', | |
134 | add_route_requirements( |
|
140 | renderer='rhodecode:templates/admin/integrations/list.mako', | |
135 |
|
|
141 | route_name='repo_integrations_home') | |
136 | ), |
|
|||
137 | custom_predicates=(valid_repo, valid_integration)) |
|
|||
138 | for route_name in ['repo_integrations_home', 'repo_integrations_list']: |
|
|||
139 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', |
|
|||
140 | attr='index', |
|
|||
141 | request_method='GET', |
|
|||
142 | renderer='rhodecode:templates/admin/integrations/list.mako', |
|
|||
143 | route_name=route_name) |
|
|||
144 |
|
142 | |||
145 | config.add_route('repo_integrations_new', |
|
143 | config.add_route('repo_integrations_new', | |
146 | add_route_requirements( |
|
144 | add_route_requirements('/{repo_name}/settings/integrations/new'), | |
147 | '{repo_name}/settings/integrations/new', |
|
145 | repo_route=True) | |
148 | ), |
|
|||
149 | custom_predicates=(valid_repo,)) |
|
|||
150 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', |
|
146 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
151 | attr='new_integration', |
|
147 | attr='new_integration', | |
152 | renderer='rhodecode:templates/admin/integrations/new.mako', |
|
148 | renderer='rhodecode:templates/admin/integrations/new.mako', | |
153 | request_method='GET', |
|
149 | request_method='GET', | |
154 | route_name='repo_integrations_new') |
|
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 | config.add_route('repo_integrations_create', |
|
162 | config.add_route('repo_integrations_create', | |
157 | add_route_requirements( |
|
163 | add_route_requirements('/{repo_name}/settings/integrations/{integration}/new'), | |
158 | '{repo_name}/settings/integrations/{integration}/new', |
|
164 | repo_route=True, | |
159 | ), |
|
165 | custom_predicates=(valid_integration,)) | |
160 | custom_predicates=(valid_repo, valid_integration)) |
|
166 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
|
167 | attr='settings_get', | |||
|
168 | renderer='rhodecode:templates/admin/integrations/form.mako', | |||
|
169 | request_method='GET', | |||
|
170 | route_name='repo_integrations_create') | |||
|
171 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |||
|
172 | attr='settings_post', | |||
|
173 | renderer='rhodecode:templates/admin/integrations/form.mako', | |||
|
174 | request_method='POST', | |||
|
175 | route_name='repo_integrations_create') | |||
|
176 | ||||
161 | config.add_route('repo_integrations_edit', |
|
177 | config.add_route('repo_integrations_edit', | |
162 | add_route_requirements( |
|
178 | add_route_requirements('/{repo_name}/settings/integrations/{integration}/{integration_id}'), | |
163 | '{repo_name}/settings/integrations/{integration}/{integration_id}', |
|
179 | repo_route=True, | |
164 | ), |
|
180 | custom_predicates=(valid_integration,)) | |
165 | custom_predicates=(valid_repo, valid_integration)) |
|
181 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
166 | for route_name in ['repo_integrations_edit', 'repo_integrations_create']: |
|
182 | attr='settings_get', | |
167 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', |
|
183 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
168 |
|
|
184 | request_method='GET', | |
169 | renderer='rhodecode:templates/admin/integrations/form.mako', |
|
185 | route_name='repo_integrations_edit') | |
170 | request_method='GET', |
|
186 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', | |
171 | route_name=route_name) |
|
187 | attr='settings_post', | |
172 | config.add_view('rhodecode.integrations.views.RepoIntegrationsView', |
|
188 | renderer='rhodecode:templates/admin/integrations/form.mako', | |
173 | attr='settings_post', |
|
189 | request_method='POST', | |
174 | renderer='rhodecode:templates/admin/integrations/form.mako', |
|
190 | route_name='repo_integrations_edit') | |
175 | request_method='POST', |
|
|||
176 | route_name=route_name) |
|
|||
177 |
|
191 | |||
178 |
|
192 | |||
179 | def valid_repo(info, request): |
|
|||
180 | repo = Repository.get_by_repo_name(info['match']['repo_name']) |
|
|||
181 | if repo: |
|
|||
182 | return True |
|
|||
183 |
|
||||
184 |
|
||||
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 |
|
||||
191 |
|
193 | |||
192 | def valid_integration(info, request): |
|
194 | def valid_integration(info, request): | |
193 | integration_type = info['match']['integration'] |
|
195 | integration_type = info['match']['integration'] | |
194 | integration_id = info['match'].get('integration_id') |
|
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 | if integration_type not in integration_type_registry: |
|
198 | if integration_type not in integration_type_registry: | |
199 | return False |
|
199 | return False | |
200 |
|
200 | |||
201 | repo, repo_group = None, None |
|
201 | if integration_id: | |
202 | if repo_name: |
|
202 | if not safe_int(integration_id): | |
203 | repo = Repository.get_by_repo_name(repo_name) |
|
|||
204 | if not repo: |
|
|||
205 | return False |
|
203 | return False | |
206 |
|
204 | |||
207 | if repo_group_name: |
|
|||
208 | repo_group = RepoGroup.get_by_group_name(repo_group_name) |
|
|||
209 | if not repo_group: |
|
|||
210 | return False |
|
|||
211 |
|
||||
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) |
|
205 | integration = Integration.get(integration_id) | |
217 | if not integration: |
|
206 | if not integration: | |
218 | return False |
|
207 | return False | |
219 | if integration.integration_type != integration_type: |
|
208 | if integration.integration_type != integration_type: | |
220 | return False |
|
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') | |||
|
214 | repo, repo_group = None, None | |||
|
215 | if repo_name: | |||
|
216 | repo = Repository.get_by_repo_name(repo_name) | |||
|
217 | if not repo: | |||
|
218 | return False | |||
|
219 | ||||
|
220 | if repo_group_name: | |||
|
221 | repo_group = RepoGroup.get_by_group_name(repo_group_name) | |||
|
222 | if not repo_group: | |||
|
223 | return False | |||
|
224 | ||||
221 | if repo and repo.repo_id != integration.repo_id: |
|
225 | if repo and repo.repo_id != integration.repo_id: | |
222 | return False |
|
226 | return False | |
223 | if repo_group and repo_group.group_id != integration.repo_group_id: |
|
227 | if repo_group and repo_group.group_id != integration.repo_group_id: |
@@ -20,10 +20,16 b'' | |||||
20 |
|
20 | |||
21 | import pytest |
|
21 | import pytest | |
22 |
|
22 | |||
|
23 | from rhodecode.apps._base import ADMIN_PREFIX | |||
23 | from rhodecode.model.db import Integration |
|
24 | from rhodecode.model.db import Integration | |
24 | from rhodecode.model.meta import Session |
|
25 | from rhodecode.model.meta import Session | |
25 | from rhodecode.integrations import integration_type_registry |
|
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 | @pytest.mark.usefixtures('app', 'autologin_user') |
|
35 | @pytest.mark.usefixtures('app', 'autologin_user') | |
@@ -32,86 +38,141 b' class TestIntegrationsView(object):' | |||||
32 |
|
38 | |||
33 |
|
39 | |||
34 | class TestGlobalIntegrationsView(TestIntegrationsView): |
|
40 | class TestGlobalIntegrationsView(TestIntegrationsView): | |
35 |
def test_index_no_integrations(self |
|
41 | def test_index_no_integrations(self): | |
36 | url = ADMIN_PREFIX + '/integrations' |
|
42 | url = ADMIN_PREFIX + '/integrations' | |
37 | response = app.get(url) |
|
43 | response = self.app.get(url) | |
38 |
|
44 | |||
39 | assert response.status_code == 200 |
|
45 | assert response.status_code == 200 | |
40 | assert 'exist yet' in response.body |
|
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 | url = ADMIN_PREFIX + '/integrations' |
|
49 | url = ADMIN_PREFIX + '/integrations' | |
44 | response = app.get(url) |
|
50 | response = self.app.get(url) | |
45 |
|
51 | |||
46 | assert response.status_code == 200 |
|
52 | assert response.status_code == 200 | |
47 | assert 'exist yet' not in response.body |
|
53 | assert 'exist yet' not in response.body | |
48 | assert global_integration_stub.name in response.body |
|
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 | url = ADMIN_PREFIX + '/integrations/new' |
|
59 | url = ADMIN_PREFIX + '/integrations/new' | |
52 |
|
60 | |||
53 | response = app.get(url) |
|
61 | response = self.app.get(url, status=200) | |
54 |
|
||||
55 | assert response.status_code == 200 |
|
|||
56 |
|
62 | |||
57 | for integration_key in integration_type_registry: |
|
63 | url = (ADMIN_PREFIX + '/integrations/{integration}/new').format( | |
58 |
|
|
64 | integration=IntegrationType.key) | |
59 | integration=integration_key) |
|
65 | assert url in response.body | |
60 | assert nurl in response.body |
|
|||
61 |
|
66 | |||
62 | @pytest.mark.parametrize( |
|
67 | @pytest.mark.parametrize( | |
63 | 'IntegrationType', integration_type_registry.values()) |
|
68 | 'IntegrationType', integration_type_registry.values()) | |
64 |
def test_get_create_integration_page(self, |
|
69 | def test_get_create_integration_page(self, IntegrationType): | |
65 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( |
|
70 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( | |
66 | integration_key=IntegrationType.key) |
|
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 | assert IntegrationType.display_name in response.body |
|
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 | test_repo_group, backend_random): |
|
78 | test_repo_group, backend_random): | |
75 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( |
|
79 | url = ADMIN_PREFIX + '/integrations/{integration_key}/new'.format( | |
76 | integration_key=StubIntegrationType.key) |
|
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 | repo=backend_random.repo, repo_group=test_repo_group) |
|
140 | repo=backend_random.repo, repo_group=test_repo_group) | |
80 |
|
141 | |||
81 |
|
142 | |||
82 | class TestRepoGroupIntegrationsView(TestIntegrationsView): |
|
143 | class TestRepoGroupIntegrationsView(TestIntegrationsView): | |
83 |
def test_index_no_integrations(self, |
|
144 | def test_index_no_integrations(self, test_repo_group): | |
84 | url = '/{repo_group_name}/settings/integrations'.format( |
|
145 | url = '/{repo_group_name}/settings/integrations'.format( | |
85 | repo_group_name=test_repo_group.group_name) |
|
146 | repo_group_name=test_repo_group.group_name) | |
86 | response = app.get(url) |
|
147 | response = self.app.get(url) | |
87 |
|
148 | |||
88 | assert response.status_code == 200 |
|
149 | assert response.status_code == 200 | |
89 | assert 'exist yet' in response.body |
|
150 | assert 'exist yet' in response.body | |
90 |
|
151 | |||
91 |
def test_index_with_integrations( |
|
152 | def test_index_with_integrations( | |
92 |
|
|
153 | self, test_repo_group, repogroup_integration_stub): | |
|
154 | ||||
93 | url = '/{repo_group_name}/settings/integrations'.format( |
|
155 | url = '/{repo_group_name}/settings/integrations'.format( | |
94 | repo_group_name=test_repo_group.group_name) |
|
156 | repo_group_name=test_repo_group.group_name) | |
95 |
|
157 | |||
96 | stub_name = repogroup_integration_stub.name |
|
158 | stub_name = repogroup_integration_stub.name | |
97 | response = app.get(url) |
|
159 | response = self.app.get(url) | |
98 |
|
160 | |||
99 | assert response.status_code == 200 |
|
161 | assert response.status_code == 200 | |
100 | assert 'exist yet' not in response.body |
|
162 | assert 'exist yet' not in response.body | |
101 | assert stub_name in response.body |
|
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 | repo_group_name = test_repo_group.group_name |
|
166 | repo_group_name = test_repo_group.group_name | |
105 | url = '/{repo_group_name}/settings/integrations/new'.format( |
|
167 | url = '/{repo_group_name}/settings/integrations/new'.format( | |
106 | repo_group_name=test_repo_group.group_name) |
|
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 | assert response.status_code == 200 |
|
172 | assert response.status_code == 200 | |
111 |
|
173 | |||
112 | for integration_key in integration_type_registry: |
|
174 | for integration_key in integration_type_registry: | |
113 | nurl = ('/{repo_group_name}/settings/integrations' |
|
175 | nurl = ('/{repo_group_name}/settings/integrations/{integration}/new').format( | |
114 | '/{integration}/new').format( |
|
|||
115 | repo_group_name=repo_group_name, |
|
176 | repo_group_name=repo_group_name, | |
116 | integration=integration_key) |
|
177 | integration=integration_key) | |
117 |
|
178 | |||
@@ -119,86 +180,29 b' class TestRepoGroupIntegrationsView(Test' | |||||
119 |
|
180 | |||
120 | @pytest.mark.parametrize( |
|
181 | @pytest.mark.parametrize( | |
121 | 'IntegrationType', integration_type_registry.values()) |
|
182 | 'IntegrationType', integration_type_registry.values()) | |
122 |
def test_get_create_integration_page( |
|
183 | def test_get_create_integration_page( | |
123 | IntegrationType): |
|
184 | self, test_repo_group, IntegrationType): | |
|
185 | ||||
124 | repo_group_name = test_repo_group.group_name |
|
186 | repo_group_name = test_repo_group.group_name | |
125 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' |
|
187 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' | |
126 | ).format(repo_group_name=repo_group_name, |
|
188 | ).format(repo_group_name=repo_group_name, | |
127 | integration_key=IntegrationType.key) |
|
189 | integration_key=IntegrationType.key) | |
128 |
|
190 | |||
129 | response = app.get(url) |
|
191 | response = self.app.get(url) | |
130 |
|
192 | |||
131 | assert response.status_code == 200 |
|
193 | assert response.status_code == 200 | |
132 | assert IntegrationType.display_name in response.body |
|
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 | StubIntegrationType, csrf_token): |
|
197 | StubIntegrationType, csrf_token): | |
|
198 | ||||
136 | repo_group_name = test_repo_group.group_name |
|
199 | repo_group_name = test_repo_group.group_name | |
137 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' |
|
200 | url = ('/{repo_group_name}/settings/integrations/{integration_key}/new' | |
138 | ).format(repo_group_name=repo_group_name, |
|
201 | ).format(repo_group_name=repo_group_name, | |
139 | integration_key=StubIntegrationType.key) |
|
202 | integration_key=StubIntegrationType.key) | |
140 |
|
203 | |||
141 |
_post_integration_test_helper( |
|
204 | _post_integration_test_helper( | |
142 | repo=backend_random.repo, repo_group=test_repo_group) |
|
205 | self.app, url, csrf_token, admin_view=False, | |
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, |
|
|||
202 | repo=backend_random.repo, repo_group=test_repo_group) |
|
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 | Posts form data to create integration at the url given then deletes it and |
|
212 | Posts form data to create integration at the url given then deletes it and | |
209 | checks if the redirect url is correct. |
|
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 | app.post(url, params={}, status=403) # missing csrf check |
|
217 | app.post(url, params={}, status=403) # missing csrf check | |
213 | response = app.post(url, params={'csrf_token': csrf_token}) |
|
218 | response = app.post(url, params={'csrf_token': csrf_token}) | |
214 | assert response.status_code == 200 |
|
219 | assert response.status_code == 200 | |
@@ -216,15 +221,15 b' def _post_integration_test_helper(app, u' | |||||
216 |
|
221 | |||
217 | scopes_destinations = [ |
|
222 | scopes_destinations = [ | |
218 | ('global', |
|
223 | ('global', | |
219 | ADMIN_PREFIX + '/integrations'), |
|
224 | ADMIN_PREFIX + '/integrations'), | |
220 | ('root-repos', |
|
225 | ('root-repos', | |
221 | ADMIN_PREFIX + '/integrations'), |
|
226 | ADMIN_PREFIX + '/integrations'), | |
222 |
('repo:%s' % |
|
227 | ('repo:%s' % repo_name, | |
223 |
'/%s/settings/integrations' % |
|
228 | '/%s/settings/integrations' % repo_name), | |
224 |
('repogroup:%s' % repo_group |
|
229 | ('repogroup:%s' % repo_group_name, | |
225 |
'/%s/settings/integrations' % repo_group |
|
230 | '/%s/settings/integrations' % repo_group_name), | |
226 |
('repogroup-recursive:%s' % repo_group |
|
231 | ('repogroup-recursive:%s' % repo_group_name, | |
227 |
'/%s/settings/integrations' % repo_group |
|
232 | '/%s/settings/integrations' % repo_group_name), | |
228 | ] |
|
233 | ] | |
229 |
|
234 | |||
230 | for scope, destination in scopes_destinations: |
|
235 | for scope, destination in scopes_destinations: |
@@ -18,45 +18,40 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 | import pylons |
|
|||
22 | import deform |
|
21 | import deform | |
23 | import logging |
|
22 | import logging | |
24 | import colander |
|
|||
25 | import peppercorn |
|
23 | import peppercorn | |
26 | import webhelpers.paginate |
|
24 | import webhelpers.paginate | |
27 |
|
25 | |||
28 |
from pyramid.httpexceptions import HTTPFound, HTTPForbidden |
|
26 | from pyramid.httpexceptions import HTTPFound, HTTPForbidden | |
29 | from pyramid.renderers import render |
|
|||
30 | from pyramid.response import Response |
|
|||
31 |
|
27 | |||
|
28 | from rhodecode.apps._base import BaseAppView | |||
|
29 | from rhodecode.integrations import integration_type_registry | |||
32 | from rhodecode.apps.admin.navigation import navigation_list |
|
30 | from rhodecode.apps.admin.navigation import navigation_list | |
33 |
from rhodecode.lib import |
|
31 | from rhodecode.lib.auth import ( | |
34 |
|
|
32 | LoginRequired, CSRFRequired, HasPermissionAnyDecorator, | |
|
33 | HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator) | |||
35 | from rhodecode.lib.utils2 import safe_int |
|
34 | from rhodecode.lib.utils2 import safe_int | |
36 | from rhodecode.lib.helpers import Page |
|
35 | from rhodecode.lib.helpers import Page | |
37 | from rhodecode.model.db import Repository, RepoGroup, Session, Integration |
|
36 | from rhodecode.model.db import Repository, RepoGroup, Session, Integration | |
38 | from rhodecode.model.scm import ScmModel |
|
37 | from rhodecode.model.scm import ScmModel | |
39 | from rhodecode.model.integration import IntegrationModel |
|
38 | from rhodecode.model.integration import IntegrationModel | |
40 | from rhodecode.translation import _ |
|
|||
41 | from rhodecode.integrations import integration_type_registry |
|
|||
42 | from rhodecode.model.validation_schema.schemas.integration_schema import ( |
|
39 | from rhodecode.model.validation_schema.schemas.integration_schema import ( | |
43 | make_integration_schema, IntegrationScopeType) |
|
40 | make_integration_schema, IntegrationScopeType) | |
44 |
|
41 | |||
45 | log = logging.getLogger(__name__) |
|
42 | log = logging.getLogger(__name__) | |
46 |
|
43 | |||
47 |
|
44 | |||
48 |
class IntegrationSettingsViewBase( |
|
45 | class IntegrationSettingsViewBase(BaseAppView): | |
49 | """ Base Integration settings view used by both repo / global settings """ |
|
46 | """ | |
|
47 | Base Integration settings view used by both repo / global settings | |||
|
48 | """ | |||
50 |
|
49 | |||
51 | def __init__(self, context, request): |
|
50 | def __init__(self, context, request): | |
52 | self.context = context |
|
51 | super(IntegrationSettingsViewBase, self).__init__(context, request) | |
53 | self.request = request |
|
52 | self._load_view_context() | |
54 | self._load_general_context() |
|
|||
55 |
|
53 | |||
56 | if not self.perm_check(request.user): |
|
54 | def _load_view_context(self): | |
57 | raise HTTPForbidden() |
|
|||
58 |
|
||||
59 | def _load_general_context(self): |
|
|||
60 | """ |
|
55 | """ | |
61 | This avoids boilerplate for repo/global+list/edit+views/templates |
|
56 | This avoids boilerplate for repo/global+list/edit+views/templates | |
62 | by doing all possible contexts at the same time however it should |
|
57 | by doing all possible contexts at the same time however it should | |
@@ -110,25 +105,12 b' class IntegrationSettingsViewBase(object' | |||||
110 |
|
105 | |||
111 | return False |
|
106 | return False | |
112 |
|
107 | |||
113 | def _template_c_context(self): |
|
108 | def _get_local_tmpl_context(self, include_app_defaults=False): | |
114 | # TODO: dan: this is a stopgap in order to inherit from current pylons |
|
109 | _ = self.request.translate | |
115 | # based admin/repo settings templates - this should be removed entirely |
|
110 | c = super(IntegrationSettingsViewBase, self)._get_local_tmpl_context( | |
116 | # after port to pyramid |
|
111 | include_app_defaults=include_app_defaults) | |
117 |
|
112 | |||
118 | c = pylons.tmpl_context |
|
|||
119 | c.active = 'integrations' |
|
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 | return c |
|
115 | return c | |
134 |
|
116 | |||
@@ -142,6 +124,7 b' class IntegrationSettingsViewBase(object' | |||||
142 | no_scope=not self.admin_view) |
|
124 | no_scope=not self.admin_view) | |
143 |
|
125 | |||
144 | def _form_defaults(self): |
|
126 | def _form_defaults(self): | |
|
127 | _ = self.request.translate | |||
145 | defaults = {} |
|
128 | defaults = {} | |
146 |
|
129 | |||
147 | if self.integration: |
|
130 | if self.integration: | |
@@ -178,28 +161,79 b' class IntegrationSettingsViewBase(object' | |||||
178 | return defaults |
|
161 | return defaults | |
179 |
|
162 | |||
180 | def _delete_integration(self, integration): |
|
163 | def _delete_integration(self, integration): | |
181 | Session().delete(self.integration) |
|
164 | _ = self.request.translate | |
|
165 | Session().delete(integration) | |||
182 | Session().commit() |
|
166 | Session().commit() | |
183 | self.request.session.flash( |
|
167 | self.request.session.flash( | |
184 | _('Integration {integration_name} deleted successfully.').format( |
|
168 | _('Integration {integration_name} deleted successfully.').format( | |
185 |
integration_name= |
|
169 | integration_name=integration.name), | |
186 | queue='success') |
|
170 | queue='success') | |
187 |
|
171 | |||
188 | if self.repo: |
|
172 | if self.repo: | |
189 |
redirect_to = self.request.route_ |
|
173 | redirect_to = self.request.route_path( | |
190 | 'repo_integrations_home', repo_name=self.repo.repo_name) |
|
174 | 'repo_integrations_home', repo_name=self.repo.repo_name) | |
191 | elif self.repo_group: |
|
175 | elif self.repo_group: | |
192 |
redirect_to = self.request.route_ |
|
176 | redirect_to = self.request.route_path( | |
193 | 'repo_group_integrations_home', |
|
177 | 'repo_group_integrations_home', | |
194 | repo_group_name=self.repo_group.group_name) |
|
178 | repo_group_name=self.repo_group.group_name) | |
195 | else: |
|
179 | else: | |
196 |
redirect_to = self.request.route_ |
|
180 | redirect_to = self.request.route_path('global_integrations_home') | |
197 | raise HTTPFound(redirect_to) |
|
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 | View that displays the integration settings as a form. |
|
234 | View that displays the integration settings as a form. | |
202 | """ |
|
235 | """ | |
|
236 | c = self.load_default_context() | |||
203 |
|
237 | |||
204 | defaults = defaults or self._form_defaults() |
|
238 | defaults = defaults or self._form_defaults() | |
205 | schema = self._form_schema() |
|
239 | schema = self._form_schema() | |
@@ -211,20 +245,18 b' class IntegrationSettingsViewBase(object' | |||||
211 |
|
245 | |||
212 | form = form or deform.Form(schema, appstruct=defaults, buttons=buttons) |
|
246 | form = form or deform.Form(schema, appstruct=defaults, buttons=buttons) | |
213 |
|
247 | |||
214 | template_context = { |
|
248 | c.form = form | |
215 | 'form': form, |
|
249 | c.current_IntegrationType = self.IntegrationType | |
216 |
|
|
250 | c.integration = self.integration | |
217 | 'integration': self.integration, |
|
|||
218 | 'c': self._template_c_context(), |
|
|||
219 | } |
|
|||
220 |
|
251 | |||
221 | return template_context |
|
252 | return self._get_template_context(c) | |
222 |
|
253 | |||
223 | @auth.CSRFRequired() |
|
254 | def _settings_post(self): | |
224 | def settings_post(self): |
|
|||
225 | """ |
|
255 | """ | |
226 | View that validates and stores the integration settings. |
|
256 | View that validates and stores the integration settings. | |
227 | """ |
|
257 | """ | |
|
258 | _ = self.request.translate | |||
|
259 | ||||
228 | controls = self.request.POST.items() |
|
260 | controls = self.request.POST.items() | |
229 | pstruct = peppercorn.parse(controls) |
|
261 | pstruct = peppercorn.parse(controls) | |
230 |
|
262 | |||
@@ -264,7 +296,7 b' class IntegrationSettingsViewBase(object' | |||||
264 | _('Errors exist when saving integration settings. ' |
|
296 | _('Errors exist when saving integration settings. ' | |
265 | 'Please check the form inputs.'), |
|
297 | 'Please check the form inputs.'), | |
266 | queue='error') |
|
298 | queue='error') | |
267 | return self.settings_get(form=e) |
|
299 | return self._settings_get(form=e) | |
268 |
|
300 | |||
269 | if not self.integration: |
|
301 | if not self.integration: | |
270 | self.integration = Integration() |
|
302 | self.integration = Integration() | |
@@ -314,77 +346,110 b' class IntegrationSettingsViewBase(object' | |||||
314 |
|
346 | |||
315 | return HTTPFound(redirect_to) |
|
347 | return HTTPFound(redirect_to) | |
316 |
|
348 | |||
317 |
def |
|
349 | def _new_integration(self): | |
318 | """ List integrations """ |
|
350 | c = self.load_default_context() | |
319 | if self.repo: |
|
351 | c.available_integrations = integration_type_registry | |
320 | scope = self.repo |
|
352 | return self._get_template_context(c) | |
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') |
|
|||
344 |
|
353 | |||
345 | integrations.sort( |
|
354 | def load_default_context(self): | |
346 | key=lambda x: getattr(x[1], sort_field), |
|
355 | raise NotImplementedError() | |
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 |
|
|||
373 |
|
356 | |||
374 |
|
357 | |||
375 | class GlobalIntegrationsView(IntegrationSettingsViewBase): |
|
358 | class GlobalIntegrationsView(IntegrationSettingsViewBase): | |
376 | def perm_check(self, user): |
|
359 | def load_default_context(self): | |
377 | return auth.HasPermissionAll('hg.admin').check_permissions(user=user) |
|
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 | class RepoIntegrationsView(IntegrationSettingsViewBase): |
|
389 | class RepoIntegrationsView(IntegrationSettingsViewBase): | |
381 | def perm_check(self, user): |
|
390 | def load_default_context(self): | |
382 | return auth.HasRepoPermissionAll('repository.admin')( |
|
391 | c = self._get_local_tmpl_context() | |
383 | repo_name=self.repo.repo_name, user=user) |
|
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 | class RepoGroupIntegrationsView(IntegrationSettingsViewBase): |
|
427 | class RepoGroupIntegrationsView(IntegrationSettingsViewBase): | |
387 | def perm_check(self, user): |
|
428 | def load_default_context(self): | |
388 | return auth.HasRepoGroupPermissionAll('group.admin')( |
|
429 | c = self._get_local_tmpl_context() | |
389 | group_name=self.repo_group.group_name, user=user) |
|
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 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); |
|
23 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); | |
24 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); |
|
24 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); | |
25 | pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/settings/integrations', ['repo_group_name']); |
|
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 | pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']); |
|
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 | pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); |
|
28 | pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); | |
29 | pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); |
|
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 | pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']); |
|
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 | pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); |
|
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 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
33 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); | |
34 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
34 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); | |
35 | pyroutes.register('ops_ping', '/_admin/ops/ping', []); |
|
35 | pyroutes.register('ops_ping', '/_admin/ops/ping', []); |
@@ -7,10 +7,10 b'' | |||||
7 | » |
|
7 | » | |
8 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_integrations_home', repo_name=c.repo.repo_name))} |
|
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 | request.route_url(route_name='repo_integrations_list', |
|
11 | request.route_url(route_name='repo_integrations_list', | |
12 | repo_name=c.repo.repo_name, |
|
12 | repo_name=c.repo.repo_name, | |
13 | integration=current_IntegrationType.key))} |
|
13 | integration=c.current_IntegrationType.key))} | |
14 | %elif c.repo_group: |
|
14 | %elif c.repo_group: | |
15 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} |
|
15 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
16 | » |
|
16 | » | |
@@ -20,10 +20,10 b'' | |||||
20 | » |
|
20 | » | |
21 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_group_integrations_home', repo_group_name=c.repo_group.group_name))} |
|
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 | request.route_url(route_name='repo_group_integrations_list', |
|
24 | request.route_url(route_name='repo_group_integrations_list', | |
25 | repo_group_name=c.repo_group.group_name, |
|
25 | repo_group_name=c.repo_group.group_name, | |
26 | integration=current_IntegrationType.key))} |
|
26 | integration=c.current_IntegrationType.key))} | |
27 | %else: |
|
27 | %else: | |
28 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} |
|
28 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
29 | » |
|
29 | » | |
@@ -31,17 +31,17 b'' | |||||
31 | » |
|
31 | » | |
32 | ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))} |
|
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 | request.route_url(route_name='global_integrations_list', |
|
35 | request.route_url(route_name='global_integrations_list', | |
36 | integration=current_IntegrationType.key))} |
|
36 | integration=c.current_IntegrationType.key))} | |
37 | %endif |
|
37 | %endif | |
38 |
|
38 | |||
39 | %if integration: |
|
39 | %if c.integration: | |
40 | » |
|
40 | » | |
41 | ${integration.name} |
|
41 | ${c.integration.name} | |
42 | %elif current_IntegrationType: |
|
42 | %elif c.current_IntegrationType: | |
43 | » |
|
43 | » | |
44 | ${current_IntegrationType.display_name} |
|
44 | ${c.current_IntegrationType.display_name} | |
45 | %endif |
|
45 | %endif | |
46 | </%def> |
|
46 | </%def> | |
47 |
|
47 | |||
@@ -54,16 +54,16 b'' | |||||
54 | <div class="panel panel-default"> |
|
54 | <div class="panel panel-default"> | |
55 | <div class="panel-heading"> |
|
55 | <div class="panel-heading"> | |
56 | <h2 class="panel-title"> |
|
56 | <h2 class="panel-title"> | |
57 | %if integration: |
|
57 | %if c.integration: | |
58 | ${current_IntegrationType.display_name} - ${integration.name} |
|
58 | ${c.current_IntegrationType.display_name} - ${c.integration.name} | |
59 | %else: |
|
59 | %else: | |
60 | ${_('Create New %(integration_type)s Integration') % { |
|
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 | %endif |
|
63 | %endif | |
64 | </h2> |
|
64 | </h2> | |
65 | </div> |
|
65 | </div> | |
66 | <div class="panel-body"> |
|
66 | <div class="panel-body"> | |
67 | ${form.render() | n} |
|
67 | ${c.form.render() | n} | |
68 | </div> |
|
68 | </div> | |
69 | </div> |
|
69 | </div> |
@@ -15,22 +15,22 b'' | |||||
15 | » |
|
15 | » | |
16 | ${h.link_to(_('Settings'),h.url('admin_settings'))} |
|
16 | ${h.link_to(_('Settings'),h.url('admin_settings'))} | |
17 | %endif |
|
17 | %endif | |
18 | %if current_IntegrationType: |
|
18 | %if c.current_IntegrationType: | |
19 | » |
|
19 | » | |
20 | %if c.repo: |
|
20 | %if c.repo: | |
21 | ${h.link_to(_('Integrations'), |
|
21 | ${h.link_to(_('Integrations'), | |
22 |
request.route_ |
|
22 | request.route_path(route_name='repo_integrations_home', | |
23 | repo_name=c.repo.repo_name))} |
|
23 | repo_name=c.repo.repo_name))} | |
24 | %elif c.repo_group: |
|
24 | %elif c.repo_group: | |
25 | ${h.link_to(_('Integrations'), |
|
25 | ${h.link_to(_('Integrations'), | |
26 |
request.route_ |
|
26 | request.route_path(route_name='repo_group_integrations_home', | |
27 | repo_group_name=c.repo_group.group_name))} |
|
27 | repo_group_name=c.repo_group.group_name))} | |
28 | %else: |
|
28 | %else: | |
29 | ${h.link_to(_('Integrations'), |
|
29 | ${h.link_to(_('Integrations'), | |
30 |
request.route_ |
|
30 | request.route_path(route_name='global_integrations_home'))} | |
31 | %endif |
|
31 | %endif | |
32 | » |
|
32 | » | |
33 | ${current_IntegrationType.display_name} |
|
33 | ${c.current_IntegrationType.display_name} | |
34 | %else: |
|
34 | %else: | |
35 | » |
|
35 | » | |
36 | ${_('Integrations')} |
|
36 | ${_('Integrations')} | |
@@ -61,9 +61,9 b'' | |||||
61 | home_url = request.route_path('global_integrations_home') |
|
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 | if c.repo: |
|
68 | if c.repo: | |
69 | list_url = request.route_path('repo_integrations_list', |
|
69 | list_url = request.route_path('repo_integrations_list', | |
@@ -78,12 +78,14 b'' | |||||
78 | integration=integration_key) |
|
78 | integration=integration_key) | |
79 | %> |
|
79 | %> | |
80 | <a href="${list_url}" |
|
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 | ${IntegrationType.display_name} |
|
82 | ${IntegrationType.display_name} | |
83 | </a> |
|
83 | </a> | |
84 | %endfor |
|
84 | %endfor | |
85 |
|
85 | |||
86 | <% |
|
86 | <% | |
|
87 | integration_type = c.current_IntegrationType and c.current_IntegrationType.display_name or '' | |||
|
88 | ||||
87 | if c.repo: |
|
89 | if c.repo: | |
88 | create_url = h.route_path('repo_integrations_new', repo_name=c.repo.repo_name) |
|
90 | create_url = h.route_path('repo_integrations_new', repo_name=c.repo.repo_name) | |
89 | elif c.repo_group: |
|
91 | elif c.repo_group: | |
@@ -98,19 +100,19 b'' | |||||
98 | <table class="rctable integrations"> |
|
100 | <table class="rctable integrations"> | |
99 | <thead> |
|
101 | <thead> | |
100 | <tr> |
|
102 | <tr> | |
101 | <th><a href="?sort=enabled:${rev_sort_dir}">${_('Enabled')}</a></th> |
|
103 | <th><a href="?sort=enabled:${c.rev_sort_dir}">${_('Enabled')}</a></th> | |
102 | <th><a href="?sort=name:${rev_sort_dir}">${_('Name')}</a></th> |
|
104 | <th><a href="?sort=name:${c.rev_sort_dir}">${_('Name')}</a></th> | |
103 | <th colspan="2"><a href="?sort=integration_type:${rev_sort_dir}">${_('Type')}</a></th> |
|
105 | <th colspan="2"><a href="?sort=integration_type:${c.rev_sort_dir}">${_('Type')}</a></th> | |
104 | <th><a href="?sort=scope:${rev_sort_dir}">${_('Scope')}</a></th> |
|
106 | <th><a href="?sort=scope:${c.rev_sort_dir}">${_('Scope')}</a></th> | |
105 | <th>${_('Actions')}</th> |
|
107 | <th>${_('Actions')}</th> | |
106 | <th></th> |
|
108 | <th></th> | |
107 | </tr> |
|
109 | </tr> | |
108 | </thead> |
|
110 | </thead> | |
109 | <tbody> |
|
111 | <tbody> | |
110 | %if not integrations_list: |
|
112 | %if not c.integrations_list: | |
111 | <tr> |
|
113 | <tr> | |
112 | <td colspan="7"> |
|
114 | <td colspan="7"> | |
113 | <% integration_type = current_IntegrationType and current_IntegrationType.display_name or '' %> |
|
115 | ||
114 | %if c.repo: |
|
116 | %if c.repo: | |
115 | ${_('No {type} integrations for repo {repo} exist yet.').format(type=integration_type, repo=c.repo.repo_name)} |
|
117 | ${_('No {type} integrations for repo {repo} exist yet.').format(type=integration_type, repo=c.repo.repo_name)} | |
116 | %elif c.repo_group: |
|
118 | %elif c.repo_group: | |
@@ -119,14 +121,14 b'' | |||||
119 | ${_('No {type} integrations exist yet.').format(type=integration_type)} |
|
121 | ${_('No {type} integrations exist yet.').format(type=integration_type)} | |
120 | %endif |
|
122 | %endif | |
121 |
|
123 | |||
122 | %if current_IntegrationType: |
|
124 | %if c.current_IntegrationType: | |
123 | <% |
|
125 | <% | |
124 | if c.repo: |
|
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 | elif c.repo_group: |
|
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 | else: |
|
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 | %endif |
|
133 | %endif | |
132 |
|
134 | |||
@@ -134,7 +136,7 b'' | |||||
134 | </td> |
|
136 | </td> | |
135 | </tr> |
|
137 | </tr> | |
136 | %endif |
|
138 | %endif | |
137 | %for IntegrationType, integration in integrations_list: |
|
139 | %for IntegrationType, integration in c.integrations_list: | |
138 | <tr id="integration_${integration.integration_id}"> |
|
140 | <tr id="integration_${integration.integration_id}"> | |
139 | <td class="td-enabled"> |
|
141 | <td class="td-enabled"> | |
140 | %if integration.enabled: |
|
142 | %if integration.enabled: | |
@@ -147,9 +149,9 b'' | |||||
147 | ${integration.name} |
|
149 | ${integration.name} | |
148 | </td> |
|
150 | </td> | |
149 | <td class="td-icon"> |
|
151 | <td class="td-icon"> | |
150 | %if integration.integration_type in available_integrations: |
|
152 | %if integration.integration_type in c.available_integrations: | |
151 | <div class="integration-icon"> |
|
153 | <div class="integration-icon"> | |
152 | ${available_integrations[integration.integration_type].icon|n} |
|
154 | ${c.available_integrations[integration.integration_type].icon|n} | |
153 | </div> |
|
155 | </div> | |
154 | %else: |
|
156 | %else: | |
155 | ? |
|
157 | ? | |
@@ -220,7 +222,7 b'' | |||||
220 | </table> |
|
222 | </table> | |
221 | <div class="integrations-paginator"> |
|
223 | <div class="integrations-paginator"> | |
222 | <div class="pagination-wh pagination-left"> |
|
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 | </div> |
|
226 | </div> | |
225 | </div> |
|
227 | </div> | |
226 | </div> |
|
228 | </div> |
@@ -36,7 +36,7 b'' | |||||
36 | %endif |
|
36 | %endif | |
37 | </%def> |
|
37 | </%def> | |
38 |
|
38 | |||
39 | %for integration, IntegrationType in available_integrations.items(): |
|
39 | %for integration, IntegrationType in c.available_integrations.items(): | |
40 | <% |
|
40 | <% | |
41 | if c.repo: |
|
41 | if c.repo: | |
42 | create_url = request.route_path('repo_integrations_create', |
|
42 | create_url = request.route_path('repo_integrations_create', |
@@ -25,21 +25,21 b' from rhodecode import events' | |||||
25 | from rhodecode.tests.fixture import Fixture |
|
25 | from rhodecode.tests.fixture import Fixture | |
26 | from rhodecode.model.db import Session, Integration |
|
26 | from rhodecode.model.db import Session, Integration | |
27 | from rhodecode.model.integration import IntegrationModel |
|
27 | from rhodecode.model.integration import IntegrationModel | |
28 | from rhodecode.integrations.types.base import IntegrationTypeBase |
|
|||
29 |
|
28 | |||
30 |
|
29 | |||
31 | class TestDeleteScopesDeletesIntegrations(object): |
|
30 | class TestDeleteScopesDeletesIntegrations(object): | |
32 |
def test_delete_repo_with_integration_deletes_integration( |
|
31 | def test_delete_repo_with_integration_deletes_integration( | |
33 | repo_integration_stub): |
|
32 | self, repo_integration_stub): | |
|
33 | ||||
34 | Session().delete(repo_integration_stub.repo) |
|
34 | Session().delete(repo_integration_stub.repo) | |
35 | Session().commit() |
|
35 | Session().commit() | |
36 | Session().expire_all() |
|
36 | Session().expire_all() | |
37 | integration = Integration.get(repo_integration_stub.integration_id) |
|
37 | integration = Integration.get(repo_integration_stub.integration_id) | |
38 | assert integration is None |
|
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 | Session().delete(repogroup_integration_stub.repo_group) |
|
43 | Session().delete(repogroup_integration_stub.repo_group) | |
44 | Session().commit() |
|
44 | Session().commit() | |
45 | Session().expire_all() |
|
45 | Session().expire_all() | |
@@ -146,7 +146,6 b' def test_enabled_integration_repo_scopes' | |||||
146 | integrations['root_repo'], |
|
146 | integrations['root_repo'], | |
147 | ] |
|
147 | ] | |
148 |
|
148 | |||
149 |
|
||||
150 | triggered_integrations = IntegrationModel().get_for_event( |
|
149 | triggered_integrations = IntegrationModel().get_for_event( | |
151 | events.RepoEvent(repos['other_repo'])) |
|
150 | events.RepoEvent(repos['other_repo'])) | |
152 |
|
151 | |||
@@ -157,7 +156,6 b' def test_enabled_integration_repo_scopes' | |||||
157 | integrations['other_group_recursive'], |
|
156 | integrations['other_group_recursive'], | |
158 | ] |
|
157 | ] | |
159 |
|
158 | |||
160 |
|
||||
161 | triggered_integrations = IntegrationModel().get_for_event( |
|
159 | triggered_integrations = IntegrationModel().get_for_event( | |
162 | events.RepoEvent(repos['parent_repo'])) |
|
160 | events.RepoEvent(repos['parent_repo'])) | |
163 |
|
161 | |||
@@ -193,26 +191,22 b' def test_disabled_integration_repo_scope' | |||||
193 |
|
191 | |||
194 | assert triggered_integrations == [] |
|
192 | assert triggered_integrations == [] | |
195 |
|
193 | |||
196 |
|
||||
197 | triggered_integrations = IntegrationModel().get_for_event( |
|
194 | triggered_integrations = IntegrationModel().get_for_event( | |
198 | events.RepoEvent(repos['parent_repo'])) |
|
195 | events.RepoEvent(repos['parent_repo'])) | |
199 |
|
196 | |||
200 | assert triggered_integrations == [] |
|
197 | assert triggered_integrations == [] | |
201 |
|
198 | |||
202 |
|
||||
203 | triggered_integrations = IntegrationModel().get_for_event( |
|
199 | triggered_integrations = IntegrationModel().get_for_event( | |
204 | events.RepoEvent(repos['child_repo'])) |
|
200 | events.RepoEvent(repos['child_repo'])) | |
205 |
|
201 | |||
206 | assert triggered_integrations == [] |
|
202 | assert triggered_integrations == [] | |
207 |
|
203 | |||
208 |
|
||||
209 | triggered_integrations = IntegrationModel().get_for_event( |
|
204 | triggered_integrations = IntegrationModel().get_for_event( | |
210 | events.RepoEvent(repos['other_repo'])) |
|
205 | events.RepoEvent(repos['other_repo'])) | |
211 |
|
206 | |||
212 | assert triggered_integrations == [] |
|
207 | assert triggered_integrations == [] | |
213 |
|
208 | |||
214 |
|
209 | |||
215 |
|
||||
216 | def test_enabled_non_repo_integrations(integration_repos): |
|
210 | def test_enabled_non_repo_integrations(integration_repos): | |
217 | integrations = integration_repos['integrations'] |
|
211 | integrations = integration_repos['integrations'] | |
218 |
|
212 |
@@ -336,7 +336,7 b' def test_repo_group(request):' | |||||
336 | usage automatically |
|
336 | usage automatically | |
337 | """ |
|
337 | """ | |
338 | fixture = Fixture() |
|
338 | fixture = Fixture() | |
339 |
repogroupid = 'test_repo_group_%s' % |
|
339 | repogroupid = 'test_repo_group_%s' % str(time.time()).replace('.', '') | |
340 | repo_group = fixture.create_repo_group(repogroupid) |
|
340 | repo_group = fixture.create_repo_group(repogroupid) | |
341 |
|
341 | |||
342 | def _cleanup(): |
|
342 | def _cleanup(): | |
@@ -353,7 +353,7 b' def test_user_group(request):' | |||||
353 | usage automatically |
|
353 | usage automatically | |
354 | """ |
|
354 | """ | |
355 | fixture = Fixture() |
|
355 | fixture = Fixture() | |
356 |
usergroupid = 'test_user_group_%s' % |
|
356 | usergroupid = 'test_user_group_%s' % str(time.time()).replace('.', '') | |
357 | user_group = fixture.create_user_group(usergroupid) |
|
357 | user_group = fixture.create_user_group(usergroupid) | |
358 |
|
358 | |||
359 | def _cleanup(): |
|
359 | def _cleanup(): |
General Comments 0
You need to be logged in to leave comments.
Login now