##// END OF EJS Templates
integrations: rewrote usage of pylons components inside integrations....
marcink -
r1990:32399c6a default
parent child Browse files
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='index',
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 '{repo_group_name}/settings/integrations',
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 add_route_requirements(
80 request_method='GET',
83 '{repo_group_name}/settings/integrations/{integration}',
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 '{repo_group_name}/settings/integrations/new',
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 '{repo_name}/settings/integrations/{integration}',
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 attr='settings_get',
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, app):
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, app, global_integration_stub):
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 nurl = (ADMIN_PREFIX + '/integrations/{integration}/new').format(
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, app, IntegrationType):
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, app, StubIntegrationType, csrf_token,
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, app, test_repo_group):
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(self, app, test_repo_group,
152 def test_index_with_integrations(
92 repogroup_integration_stub):
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, app, test_repo_group):
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(self, app, test_repo_group,
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, app, test_repo_group, backend_random,
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(app, url, csrf_token, admin_view=False,
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' % repo.repo_name,
227 ('repo:%s' % repo_name,
223 '/%s/settings/integrations' % repo.repo_name),
228 '/%s/settings/integrations' % repo_name),
224 ('repogroup:%s' % repo_group.group_name,
229 ('repogroup:%s' % repo_group_name,
225 '/%s/settings/integrations' % repo_group.group_name),
230 '/%s/settings/integrations' % repo_group_name),
226 ('repogroup-recursive:%s' % repo_group.group_name,
231 ('repogroup-recursive:%s' % repo_group_name,
227 '/%s/settings/integrations' % repo_group.group_name),
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, HTTPBadRequest
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 auth
31 from rhodecode.lib.auth import (
34 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
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(object):
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=self.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_url(
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_url(
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_url('global_integrations_home')
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 'current_IntegrationType': self.IntegrationType,
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 index(self):
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 &raquo;
7 &raquo;
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 &raquo;
9 &raquo;
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 &raquo;
16 &raquo;
@@ -20,10 +20,10 b''
20 &raquo;
20 &raquo;
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 &raquo;
22 &raquo;
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 &raquo;
29 &raquo;
@@ -31,17 +31,17 b''
31 &raquo;
31 &raquo;
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 &raquo;
33 &raquo;
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 &raquo;
40 &raquo;
41 ${integration.name}
41 ${c.integration.name}
42 %elif current_IntegrationType:
42 %elif c.current_IntegrationType:
43 &raquo;
43 &raquo;
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 &raquo;
15 &raquo;
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 &raquo;
19 &raquo;
20 %if c.repo:
20 %if c.repo:
21 ${h.link_to(_('Integrations'),
21 ${h.link_to(_('Integrations'),
22 request.route_url(route_name='repo_integrations_home',
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_url(route_name='repo_group_integrations_home',
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_url(route_name='global_integrations_home'))}
30 request.route_path(route_name='global_integrations_home'))}
31 %endif
31 %endif
32 &raquo;
32 &raquo;
33 ${current_IntegrationType.display_name}
33 ${c.current_IntegrationType.display_name}
34 %else:
34 %else:
35 &raquo;
35 &raquo;
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(self,
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' % int(time.time())
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' % int(time.time())
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