##// END OF EJS Templates
integrations-db: don't use default contructor to be consisten with other modules...
marcink -
r448:b686b009 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,258 +1,258 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2016 RhodeCode GmbH
3 # Copyright (C) 2012-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
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 colander
21 import colander
22 import logging
22 import logging
23 import pylons
23 import pylons
24
24
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
26 from pyramid.renderers import render
26 from pyramid.renderers import render
27 from pyramid.response import Response
27 from pyramid.response import Response
28
28
29 from rhodecode.lib import auth
29 from rhodecode.lib import auth
30 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
30 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from rhodecode.model.db import Repository, Session, Integration
31 from rhodecode.model.db import Repository, Session, Integration
32 from rhodecode.model.scm import ScmModel
32 from rhodecode.model.scm import ScmModel
33 from rhodecode.model.integration import IntegrationModel
33 from rhodecode.model.integration import IntegrationModel
34 from rhodecode.admin.navigation import navigation_list
34 from rhodecode.admin.navigation import navigation_list
35 from rhodecode.translation import _
35 from rhodecode.translation import _
36 from rhodecode.integrations import integration_type_registry
36 from rhodecode.integrations import integration_type_registry
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 class IntegrationSettingsViewBase(object):
41 class IntegrationSettingsViewBase(object):
42 """ Base Integration settings view used by both repo / global settings """
42 """ Base Integration settings view used by both repo / global settings """
43
43
44 def __init__(self, context, request):
44 def __init__(self, context, request):
45 self.context = context
45 self.context = context
46 self.request = request
46 self.request = request
47 self._load_general_context()
47 self._load_general_context()
48
48
49 if not self.perm_check(request.user):
49 if not self.perm_check(request.user):
50 raise HTTPForbidden()
50 raise HTTPForbidden()
51
51
52 def _load_general_context(self):
52 def _load_general_context(self):
53 """
53 """
54 This avoids boilerplate for repo/global+list/edit+views/templates
54 This avoids boilerplate for repo/global+list/edit+views/templates
55 by doing all possible contexts at the same time however it should
55 by doing all possible contexts at the same time however it should
56 be split up into separate functions once more "contexts" exist
56 be split up into separate functions once more "contexts" exist
57 """
57 """
58
58
59 self.IntegrationType = None
59 self.IntegrationType = None
60 self.repo = None
60 self.repo = None
61 self.integration = None
61 self.integration = None
62 self.integrations = {}
62 self.integrations = {}
63
63
64 request = self.request
64 request = self.request
65
65
66 if 'repo_name' in request.matchdict: # we're in a repo context
66 if 'repo_name' in request.matchdict: # we're in a repo context
67 repo_name = request.matchdict['repo_name']
67 repo_name = request.matchdict['repo_name']
68 self.repo = Repository.get_by_repo_name(repo_name)
68 self.repo = Repository.get_by_repo_name(repo_name)
69
69
70 if 'integration' in request.matchdict: # we're in integration context
70 if 'integration' in request.matchdict: # we're in integration context
71 integration_type = request.matchdict['integration']
71 integration_type = request.matchdict['integration']
72 self.IntegrationType = integration_type_registry[integration_type]
72 self.IntegrationType = integration_type_registry[integration_type]
73
73
74 if 'integration_id' in request.matchdict: # single integration context
74 if 'integration_id' in request.matchdict: # single integration context
75 integration_id = request.matchdict['integration_id']
75 integration_id = request.matchdict['integration_id']
76 self.integration = Integration.get(integration_id)
76 self.integration = Integration.get(integration_id)
77 else: # list integrations context
77 else: # list integrations context
78 for integration in IntegrationModel().get_integrations(self.repo):
78 for integration in IntegrationModel().get_integrations(self.repo):
79 self.integrations.setdefault(integration.integration_type, []
79 self.integrations.setdefault(integration.integration_type, []
80 ).append(integration)
80 ).append(integration)
81
81
82 self.settings = self.integration and self.integration.settings or {}
82 self.settings = self.integration and self.integration.settings or {}
83
83
84 def _template_c_context(self):
84 def _template_c_context(self):
85 # TODO: dan: this is a stopgap in order to inherit from current pylons
85 # TODO: dan: this is a stopgap in order to inherit from current pylons
86 # based admin/repo settings templates - this should be removed entirely
86 # based admin/repo settings templates - this should be removed entirely
87 # after port to pyramid
87 # after port to pyramid
88
88
89 c = pylons.tmpl_context
89 c = pylons.tmpl_context
90 c.active = 'integrations'
90 c.active = 'integrations'
91 c.rhodecode_user = self.request.user
91 c.rhodecode_user = self.request.user
92 c.repo = self.repo
92 c.repo = self.repo
93 c.repo_name = self.repo and self.repo.repo_name or None
93 c.repo_name = self.repo and self.repo.repo_name or None
94 if self.repo:
94 if self.repo:
95 c.repo_info = self.repo
95 c.repo_info = self.repo
96 c.rhodecode_db_repo = self.repo
96 c.rhodecode_db_repo = self.repo
97 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
97 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
98 else:
98 else:
99 c.navlist = navigation_list(self.request)
99 c.navlist = navigation_list(self.request)
100
100
101 return c
101 return c
102
102
103 def _form_schema(self):
103 def _form_schema(self):
104 return self.IntegrationType.settings_schema()
104 return self.IntegrationType.settings_schema()
105
105
106 def settings_get(self, defaults=None, errors=None):
106 def settings_get(self, defaults=None, errors=None):
107 """
107 """
108 View that displays the plugin settings as a form.
108 View that displays the plugin settings as a form.
109 """
109 """
110 defaults = defaults or {}
110 defaults = defaults or {}
111 errors = errors or {}
111 errors = errors or {}
112
112
113 schema = self._form_schema()
113 schema = self._form_schema()
114
114
115 if not defaults:
115 if not defaults:
116 if self.integration:
116 if self.integration:
117 defaults['enabled'] = self.integration.enabled
117 defaults['enabled'] = self.integration.enabled
118 defaults['name'] = self.integration.name
118 defaults['name'] = self.integration.name
119 else:
119 else:
120 if self.repo:
120 if self.repo:
121 scope = self.repo.repo_name
121 scope = self.repo.repo_name
122 else:
122 else:
123 scope = _('Global')
123 scope = _('Global')
124
124
125 defaults['name'] = '{} {} integration'.format(scope,
125 defaults['name'] = '{} {} integration'.format(scope,
126 self.IntegrationType.display_name)
126 self.IntegrationType.display_name)
127 defaults['enabled'] = True
127 defaults['enabled'] = True
128
128
129 for node in schema:
129 for node in schema:
130 setting = self.settings.get(node.name)
130 setting = self.settings.get(node.name)
131 if setting is not None:
131 if setting is not None:
132 defaults.setdefault(node.name, setting)
132 defaults.setdefault(node.name, setting)
133 else:
133 else:
134 if node.default:
134 if node.default:
135 defaults.setdefault(node.name, node.default)
135 defaults.setdefault(node.name, node.default)
136
136
137 template_context = {
137 template_context = {
138 'defaults': defaults,
138 'defaults': defaults,
139 'errors': errors,
139 'errors': errors,
140 'schema': schema,
140 'schema': schema,
141 'current_IntegrationType': self.IntegrationType,
141 'current_IntegrationType': self.IntegrationType,
142 'integration': self.integration,
142 'integration': self.integration,
143 'settings': self.settings,
143 'settings': self.settings,
144 'resource': self.context,
144 'resource': self.context,
145 'c': self._template_c_context(),
145 'c': self._template_c_context(),
146 }
146 }
147
147
148 return template_context
148 return template_context
149
149
150 @auth.CSRFRequired()
150 @auth.CSRFRequired()
151 def settings_post(self):
151 def settings_post(self):
152 """
152 """
153 View that validates and stores the plugin settings.
153 View that validates and stores the plugin settings.
154 """
154 """
155 if self.request.params.get('delete'):
155 if self.request.params.get('delete'):
156 Session().delete(self.integration)
156 Session().delete(self.integration)
157 Session().commit()
157 Session().commit()
158 self.request.session.flash(
158 self.request.session.flash(
159 _('Integration {integration_name} deleted successfully.').format(
159 _('Integration {integration_name} deleted successfully.').format(
160 integration_name=self.integration.name),
160 integration_name=self.integration.name),
161 queue='success')
161 queue='success')
162 if self.repo:
162 if self.repo:
163 redirect_to = self.request.route_url(
163 redirect_to = self.request.route_url(
164 'repo_integrations_home', repo_name=self.repo.repo_name)
164 'repo_integrations_home', repo_name=self.repo.repo_name)
165 else:
165 else:
166 redirect_to = self.request.route_url('global_integrations_home')
166 redirect_to = self.request.route_url('global_integrations_home')
167 raise HTTPFound(redirect_to)
167 raise HTTPFound(redirect_to)
168
168
169 schema = self._form_schema()
169 schema = self._form_schema()
170
170
171 params = {}
171 params = {}
172 for node in schema.children:
172 for node in schema.children:
173 if type(node.typ) in (colander.Set, colander.List):
173 if type(node.typ) in (colander.Set, colander.List):
174 val = self.request.params.getall(node.name)
174 val = self.request.params.getall(node.name)
175 else:
175 else:
176 val = self.request.params.get(node.name)
176 val = self.request.params.get(node.name)
177 if val:
177 if val:
178 params[node.name] = val
178 params[node.name] = val
179
179
180 try:
180 try:
181 valid_data = schema.deserialize(params)
181 valid_data = schema.deserialize(params)
182 except colander.Invalid, e:
182 except colander.Invalid as e:
183 # Display error message and display form again.
183 # Display error message and display form again.
184 self.request.session.flash(
184 self.request.session.flash(
185 _('Errors exist when saving plugin settings. '
185 _('Errors exist when saving plugin settings. '
186 'Please check the form inputs.'),
186 'Please check the form inputs.'),
187 queue='error')
187 queue='error')
188 return self.settings_get(errors=e.asdict(), defaults=params)
188 return self.settings_get(errors=e.asdict(), defaults=params)
189
189
190 if not self.integration:
190 if not self.integration:
191 self.integration = Integration(
191 self.integration = Integration()
192 integration_type=self.IntegrationType.key)
192 self.integration.integration_type = self.IntegrationType.key
193 if self.repo:
193 if self.repo:
194 self.integration.repo = self.repo
194 self.integration.repo = self.repo
195 Session.add(self.integration)
195 Session().add(self.integration)
196
196
197 self.integration.enabled = valid_data.pop('enabled', False)
197 self.integration.enabled = valid_data.pop('enabled', False)
198 self.integration.name = valid_data.pop('name')
198 self.integration.name = valid_data.pop('name')
199 self.integration.settings = valid_data
199 self.integration.settings = valid_data
200
200
201 Session.commit()
201 Session().commit()
202
202
203 # Display success message and redirect.
203 # Display success message and redirect.
204 self.request.session.flash(
204 self.request.session.flash(
205 _('Integration {integration_name} updated successfully.').format(
205 _('Integration {integration_name} updated successfully.').format(
206 integration_name=self.IntegrationType.display_name),
206 integration_name=self.IntegrationType.display_name),
207 queue='success')
207 queue='success')
208
208
209 if self.repo:
209 if self.repo:
210 redirect_to = self.request.route_url(
210 redirect_to = self.request.route_url(
211 'repo_integrations_edit', repo_name=self.repo.repo_name,
211 'repo_integrations_edit', repo_name=self.repo.repo_name,
212 integration=self.integration.integration_type,
212 integration=self.integration.integration_type,
213 integration_id=self.integration.integration_id)
213 integration_id=self.integration.integration_id)
214 else:
214 else:
215 redirect_to = self.request.route_url(
215 redirect_to = self.request.route_url(
216 'global_integrations_edit',
216 'global_integrations_edit',
217 integration=self.integration.integration_type,
217 integration=self.integration.integration_type,
218 integration_id=self.integration.integration_id)
218 integration_id=self.integration.integration_id)
219
219
220 return HTTPFound(redirect_to)
220 return HTTPFound(redirect_to)
221
221
222 def index(self):
222 def index(self):
223 current_integrations = self.integrations
223 current_integrations = self.integrations
224 if self.IntegrationType:
224 if self.IntegrationType:
225 current_integrations = {
225 current_integrations = {
226 self.IntegrationType.key: self.integrations.get(
226 self.IntegrationType.key: self.integrations.get(
227 self.IntegrationType.key, [])
227 self.IntegrationType.key, [])
228 }
228 }
229
229
230 template_context = {
230 template_context = {
231 'current_IntegrationType': self.IntegrationType,
231 'current_IntegrationType': self.IntegrationType,
232 'current_integrations': current_integrations,
232 'current_integrations': current_integrations,
233 'current_integration': 'none',
233 'current_integration': 'none',
234 'available_integrations': integration_type_registry,
234 'available_integrations': integration_type_registry,
235 'c': self._template_c_context()
235 'c': self._template_c_context()
236 }
236 }
237
237
238 if self.repo:
238 if self.repo:
239 html = render('rhodecode:templates/admin/integrations/list.html',
239 html = render('rhodecode:templates/admin/integrations/list.html',
240 template_context,
240 template_context,
241 request=self.request)
241 request=self.request)
242 else:
242 else:
243 html = render('rhodecode:templates/admin/integrations/list.html',
243 html = render('rhodecode:templates/admin/integrations/list.html',
244 template_context,
244 template_context,
245 request=self.request)
245 request=self.request)
246
246
247 return Response(html)
247 return Response(html)
248
248
249
249
250 class GlobalIntegrationsView(IntegrationSettingsViewBase):
250 class GlobalIntegrationsView(IntegrationSettingsViewBase):
251 def perm_check(self, user):
251 def perm_check(self, user):
252 return auth.HasPermissionAll('hg.admin').check_permissions(user=user)
252 return auth.HasPermissionAll('hg.admin').check_permissions(user=user)
253
253
254
254
255 class RepoIntegrationsView(IntegrationSettingsViewBase):
255 class RepoIntegrationsView(IntegrationSettingsViewBase):
256 def perm_check(self, user):
256 def perm_check(self, user):
257 return auth.HasRepoPermissionAll('repository.admin'
257 return auth.HasRepoPermissionAll('repository.admin'
258 )(repo_name=self.repo.repo_name, user=user)
258 )(repo_name=self.repo.repo_name, user=user)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,132 +1,132 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2016 RhodeCode GmbH
3 # Copyright (C) 2011-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
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
21
22 """
22 """
23 Model for integrations
23 Model for integrations
24 """
24 """
25
25
26
26
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from pylons import tmpl_context as c
30 from pylons import tmpl_context as c
31 from pylons.i18n.translation import _, ungettext
31 from pylons.i18n.translation import _, ungettext
32 from sqlalchemy import or_
32 from sqlalchemy import or_
33 from sqlalchemy.sql.expression import false, true
33 from sqlalchemy.sql.expression import false, true
34 from mako import exceptions
34 from mako import exceptions
35
35
36 import rhodecode
36 import rhodecode
37 from rhodecode import events
37 from rhodecode import events
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.caching_query import FromCache
39 from rhodecode.lib.caching_query import FromCache
40 from rhodecode.lib.utils import PartialRenderer
40 from rhodecode.lib.utils import PartialRenderer
41 from rhodecode.model import BaseModel
41 from rhodecode.model import BaseModel
42 from rhodecode.model.db import Integration, User
42 from rhodecode.model.db import Integration, User
43 from rhodecode.model.meta import Session
43 from rhodecode.model.meta import Session
44 from rhodecode.integrations import integration_type_registry
44 from rhodecode.integrations import integration_type_registry
45 from rhodecode.integrations.types.base import IntegrationTypeBase
45 from rhodecode.integrations.types.base import IntegrationTypeBase
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class IntegrationModel(BaseModel):
50 class IntegrationModel(BaseModel):
51
51
52 cls = Integration
52 cls = Integration
53
53
54 def __get_integration(self, integration):
54 def __get_integration(self, integration):
55 if isinstance(integration, Integration):
55 if isinstance(integration, Integration):
56 return integration
56 return integration
57 elif isinstance(integration, (int, long)):
57 elif isinstance(integration, (int, long)):
58 return self.sa.query(Integration).get(integration)
58 return self.sa.query(Integration).get(integration)
59 else:
59 else:
60 if integration:
60 if integration:
61 raise Exception('integration must be int, long or Instance'
61 raise Exception('integration must be int, long or Instance'
62 ' of Integration got %s' % type(integration))
62 ' of Integration got %s' % type(integration))
63
63
64 def create(self, IntegrationType, enabled, name, settings, repo=None):
64 def create(self, IntegrationType, enabled, name, settings, repo=None):
65 """ Create an IntegrationType integration """
65 """ Create an IntegrationType integration """
66 integration = Integration(
66 integration = Integration()
67 integration_type=IntegrationType.key,
67 integration.integration_type = IntegrationType.key
68 settings={},
68 integration.settings = {}
69 repo=repo,
69 integration.repo = repo
70 enabled=enabled,
70 integration.enabled = enabled
71 name=name
71 integration.name = name
72 )
72
73 self.sa.add(integration)
73 self.sa.add(integration)
74 self.sa.commit()
74 self.sa.commit()
75 return integration
75 return integration
76
76
77 def delete(self, integration):
77 def delete(self, integration):
78 try:
78 try:
79 integration = self.__get_integration(integration)
79 integration = self.__get_integration(integration)
80 if integration:
80 if integration:
81 self.sa.delete(integration)
81 self.sa.delete(integration)
82 return True
82 return True
83 except Exception:
83 except Exception:
84 log.error(traceback.format_exc())
84 log.error(traceback.format_exc())
85 raise
85 raise
86 return False
86 return False
87
87
88 def get_integration_handler(self, integration):
88 def get_integration_handler(self, integration):
89 TypeClass = integration_type_registry.get(integration.integration_type)
89 TypeClass = integration_type_registry.get(integration.integration_type)
90 if not TypeClass:
90 if not TypeClass:
91 log.error('No class could be found for integration type: {}'.format(
91 log.error('No class could be found for integration type: {}'.format(
92 integration.integration_type))
92 integration.integration_type))
93 return None
93 return None
94
94
95 return TypeClass(integration.settings)
95 return TypeClass(integration.settings)
96
96
97 def send_event(self, integration, event):
97 def send_event(self, integration, event):
98 """ Send an event to an integration """
98 """ Send an event to an integration """
99 handler = self.get_integration_handler(integration)
99 handler = self.get_integration_handler(integration)
100 if handler:
100 if handler:
101 handler.send_event(event)
101 handler.send_event(event)
102
102
103 def get_integrations(self, repo=None):
103 def get_integrations(self, repo=None):
104 if repo:
104 if repo:
105 return self.sa.query(Integration).filter(
105 return self.sa.query(Integration).filter(
106 Integration.repo_id==repo.repo_id).all()
106 Integration.repo_id==repo.repo_id).all()
107
107
108 # global integrations
108 # global integrations
109 return self.sa.query(Integration).filter(
109 return self.sa.query(Integration).filter(
110 Integration.repo_id==None).all()
110 Integration.repo_id==None).all()
111
111
112 def get_for_event(self, event, cache=False):
112 def get_for_event(self, event, cache=False):
113 """
113 """
114 Get integrations that match an event
114 Get integrations that match an event
115 """
115 """
116 query = self.sa.query(Integration).filter(Integration.enabled==True)
116 query = self.sa.query(Integration).filter(Integration.enabled==True)
117
117
118 if isinstance(event, events.RepoEvent): # global + repo integrations
118 if isinstance(event, events.RepoEvent): # global + repo integrations
119 query = query.filter(
119 query = query.filter(
120 or_(Integration.repo_id==None,
120 or_(Integration.repo_id==None,
121 Integration.repo_id==event.repo.repo_id))
121 Integration.repo_id==event.repo.repo_id))
122 if cache:
122 if cache:
123 query = query.options(FromCache(
123 query = query.options(FromCache(
124 "sql_cache_short",
124 "sql_cache_short",
125 "get_enabled_repo_integrations_%i" % event.repo.repo_id))
125 "get_enabled_repo_integrations_%i" % event.repo.repo_id))
126 else: # only global integrations
126 else: # only global integrations
127 query = query.filter(Integration.repo_id==None)
127 query = query.filter(Integration.repo_id==None)
128 if cache:
128 if cache:
129 query = query.options(FromCache(
129 query = query.options(FromCache(
130 "sql_cache_short", "get_enabled_global_integrations"))
130 "sql_cache_short", "get_enabled_global_integrations"))
131
131
132 return query.all()
132 return query.all()
@@ -1,96 +1,95 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
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 pytest
21 import pytest
22 import requests
22 import requests
23 from mock import Mock, patch
23 from mock import Mock, patch
24
24
25 from rhodecode import events
25 from rhodecode import events
26 from rhodecode.model.db import Session, Integration
26 from rhodecode.model.db import Session, Integration
27 from rhodecode.integrations.types.slack import SlackIntegrationType
27 from rhodecode.integrations.types.slack import SlackIntegrationType
28
28
29 @pytest.fixture
29 @pytest.fixture
30 def repo_push_event(backend, user_regular):
30 def repo_push_event(backend, user_regular):
31 commits = [
31 commits = [
32 {'message': 'ancestor commit fixes #15'},
32 {'message': 'ancestor commit fixes #15'},
33 {'message': 'quick fixes'},
33 {'message': 'quick fixes'},
34 {'message': 'change that fixes #41, #2'},
34 {'message': 'change that fixes #41, #2'},
35 {'message': 'this is because 5b23c3532 broke stuff'},
35 {'message': 'this is because 5b23c3532 broke stuff'},
36 {'message': 'last commit'},
36 {'message': 'last commit'},
37 ]
37 ]
38 commit_ids = backend.create_master_repo(commits).values()
38 commit_ids = backend.create_master_repo(commits).values()
39 repo = backend.create_repo()
39 repo = backend.create_repo()
40 scm_extras = {
40 scm_extras = {
41 'ip': '127.0.0.1',
41 'ip': '127.0.0.1',
42 'username': user_regular.username,
42 'username': user_regular.username,
43 'action': '',
43 'action': '',
44 'repository': repo.repo_name,
44 'repository': repo.repo_name,
45 'scm': repo.scm_instance().alias,
45 'scm': repo.scm_instance().alias,
46 'config': '',
46 'config': '',
47 'server_url': 'http://example.com',
47 'server_url': 'http://example.com',
48 'make_lock': None,
48 'make_lock': None,
49 'locked_by': [None],
49 'locked_by': [None],
50 'commit_ids': commit_ids,
50 'commit_ids': commit_ids,
51 }
51 }
52
52
53 return events.RepoPushEvent(repo_name=repo.repo_name,
53 return events.RepoPushEvent(repo_name=repo.repo_name,
54 pushed_commit_ids=commit_ids,
54 pushed_commit_ids=commit_ids,
55 extras=scm_extras)
55 extras=scm_extras)
56
56
57
57
58 @pytest.fixture
58 @pytest.fixture
59 def slack_settings():
59 def slack_settings():
60 return {
60 return {
61 "service": "mock://slackintegration",
61 "service": "mock://slackintegration",
62 "events": [
62 "events": [
63 "pullrequest-create",
63 "pullrequest-create",
64 "repo-push",
64 "repo-push",
65 ],
65 ],
66 "channel": "#testing",
66 "channel": "#testing",
67 "icon_emoji": ":recycle:",
67 "icon_emoji": ":recycle:",
68 "username": "rhodecode-test"
68 "username": "rhodecode-test"
69 }
69 }
70
70
71
71
72 @pytest.fixture
72 @pytest.fixture
73 def slack_integration(request, app, slack_settings):
73 def slack_integration(request, app, slack_settings):
74 integration = Integration(
74 integration = Integration()
75 name='test slack integration',
75 integration.name = 'test slack integration'
76 enabled=True,
76 integration.enabled = True
77 integration_type=SlackIntegrationType.key
77 integration.integration_type = SlackIntegrationType.key
78 )
79 integration.settings = slack_settings
78 integration.settings = slack_settings
80 Session().add(integration)
79 Session().add(integration)
81 Session().commit()
80 Session().commit()
82 request.addfinalizer(lambda: Session().delete(integration))
81 request.addfinalizer(lambda: Session().delete(integration))
83 return integration
82 return integration
84
83
85
84
86 def test_slack_push(slack_integration, repo_push_event):
85 def test_slack_push(slack_integration, repo_push_event):
87 with patch('rhodecode.integrations.types.slack.post_text_to_slack') as call:
86 with patch('rhodecode.integrations.types.slack.post_text_to_slack') as call:
88 events.trigger(repo_push_event)
87 events.trigger(repo_push_event)
89 assert 'pushed to' in call.call_args[0][1]
88 assert 'pushed to' in call.call_args[0][1]
90
89
91 slack_integration.settings['events'] = []
90 slack_integration.settings['events'] = []
92 Session().commit()
91 Session().commit()
93
92
94 with patch('rhodecode.integrations.types.slack.post_text_to_slack') as call:
93 with patch('rhodecode.integrations.types.slack.post_text_to_slack') as call:
95 events.trigger(repo_push_event)
94 events.trigger(repo_push_event)
96 assert not call.call_args
95 assert not call.call_args
General Comments 0
You need to be logged in to leave comments. Login now