##// END OF EJS Templates
integrations: fixed flash message queue.
marcink -
r424:918fa151 default
parent child Browse files
Show More
@@ -1,257 +1,258 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import colander
22 22 import logging
23 23 import pylons
24 24
25 25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
26 26 from pyramid.renderers import render
27 27 from pyramid.response import Response
28 28
29 29 from rhodecode.lib import auth
30 30 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
31 31 from rhodecode.model.db import Repository, Session, Integration
32 32 from rhodecode.model.scm import ScmModel
33 33 from rhodecode.model.integration import IntegrationModel
34 34 from rhodecode.admin.navigation import navigation_list
35 35 from rhodecode.translation import _
36 36 from rhodecode.integrations import integration_type_registry
37 37
38 38 log = logging.getLogger(__name__)
39 39
40 40
41 41 class IntegrationSettingsViewBase(object):
42 42 """ Base Integration settings view used by both repo / global settings """
43 43
44 44 def __init__(self, context, request):
45 45 self.context = context
46 46 self.request = request
47 47 self._load_general_context()
48 48
49 49 if not self.perm_check(request.user):
50 50 raise HTTPForbidden()
51 51
52 52 def _load_general_context(self):
53 53 """
54 54 This avoids boilerplate for repo/global+list/edit+views/templates
55 55 by doing all possible contexts at the same time however it should
56 56 be split up into separate functions once more "contexts" exist
57 57 """
58 58
59 59 self.IntegrationType = None
60 60 self.repo = None
61 61 self.integration = None
62 62 self.integrations = {}
63 63
64 64 request = self.request
65 65
66 66 if 'repo_name' in request.matchdict: # we're in a repo context
67 67 repo_name = request.matchdict['repo_name']
68 68 self.repo = Repository.get_by_repo_name(repo_name)
69 69
70 70 if 'integration' in request.matchdict: # we're in integration context
71 71 integration_type = request.matchdict['integration']
72 72 self.IntegrationType = integration_type_registry[integration_type]
73 73
74 74 if 'integration_id' in request.matchdict: # single integration context
75 75 integration_id = request.matchdict['integration_id']
76 76 self.integration = Integration.get(integration_id)
77 77 else: # list integrations context
78 78 for integration in IntegrationModel().get_integrations(self.repo):
79 79 self.integrations.setdefault(integration.integration_type, []
80 80 ).append(integration)
81 81
82 82 self.settings = self.integration and self.integration.settings or {}
83 83
84 84 def _template_c_context(self):
85 85 # TODO: dan: this is a stopgap in order to inherit from current pylons
86 86 # based admin/repo settings templates - this should be removed entirely
87 87 # after port to pyramid
88 88
89 89 c = pylons.tmpl_context
90 90 c.active = 'integrations'
91 91 c.rhodecode_user = self.request.user
92 92 c.repo = self.repo
93 93 c.repo_name = self.repo and self.repo.repo_name or None
94 94 if self.repo:
95 95 c.repo_info = self.repo
96 96 c.rhodecode_db_repo = self.repo
97 97 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
98 98 else:
99 99 c.navlist = navigation_list(self.request)
100 100
101 101 return c
102 102
103 103 def _form_schema(self):
104 104 return self.IntegrationType.settings_schema()
105 105
106 106 def settings_get(self, defaults=None, errors=None):
107 107 """
108 108 View that displays the plugin settings as a form.
109 109 """
110 110 defaults = defaults or {}
111 111 errors = errors or {}
112 112
113 113 schema = self._form_schema()
114 114
115 115 if not defaults:
116 116 if self.integration:
117 117 defaults['enabled'] = self.integration.enabled
118 118 defaults['name'] = self.integration.name
119 119 else:
120 120 if self.repo:
121 121 scope = self.repo.repo_name
122 122 else:
123 123 scope = _('Global')
124 124
125 125 defaults['name'] = '{} {} integration'.format(scope,
126 126 self.IntegrationType.display_name)
127 127 defaults['enabled'] = True
128 128
129 129 for node in schema:
130 130 setting = self.settings.get(node.name)
131 131 if setting is not None:
132 132 defaults.setdefault(node.name, setting)
133 133 else:
134 134 if node.default:
135 135 defaults.setdefault(node.name, node.default)
136 136
137 137 template_context = {
138 138 'defaults': defaults,
139 139 'errors': errors,
140 140 'schema': schema,
141 141 'current_IntegrationType': self.IntegrationType,
142 142 'integration': self.integration,
143 143 'settings': self.settings,
144 144 'resource': self.context,
145 145 'c': self._template_c_context(),
146 146 }
147 147
148 148 return template_context
149 149
150 150 @auth.CSRFRequired()
151 151 def settings_post(self):
152 152 """
153 153 View that validates and stores the plugin settings.
154 154 """
155 155 if self.request.params.get('delete'):
156 156 Session().delete(self.integration)
157 157 Session().commit()
158 158 self.request.session.flash(
159 159 _('Integration {integration_name} deleted successfully.').format(
160 160 integration_name=self.integration.name),
161 161 queue='success')
162 162 if self.repo:
163 163 redirect_to = self.request.route_url(
164 164 'repo_integrations_home', repo_name=self.repo.repo_name)
165 165 else:
166 166 redirect_to = self.request.route_url('global_integrations_home')
167 167 raise HTTPFound(redirect_to)
168 168
169 169 schema = self._form_schema()
170 170
171 171 params = {}
172 172 for node in schema.children:
173 173 if type(node.typ) in (colander.Set, colander.List):
174 174 val = self.request.params.getall(node.name)
175 175 else:
176 176 val = self.request.params.get(node.name)
177 177 if val:
178 178 params[node.name] = val
179 179
180 180 try:
181 181 valid_data = schema.deserialize(params)
182 182 except colander.Invalid, e:
183 183 # Display error message and display form again.
184 184 self.request.session.flash(
185 185 _('Errors exist when saving plugin settings. '
186 186 'Please check the form inputs.'),
187 187 queue='error')
188 188 return self.settings_get(errors=e.asdict(), defaults=params)
189 189
190 190 if not self.integration:
191 191 self.integration = Integration(
192 192 integration_type=self.IntegrationType.key)
193 193 if self.repo:
194 194 self.integration.repo = self.repo
195 195 Session.add(self.integration)
196 196
197 197 self.integration.enabled = valid_data.pop('enabled', False)
198 198 self.integration.name = valid_data.pop('name')
199 199 self.integration.settings = valid_data
200 200
201 201 Session.commit()
202 202
203 203 # Display success message and redirect.
204 204 self.request.session.flash(
205 205 _('Integration {integration_name} updated successfully.').format(
206 integration_name=self.IntegrationType.display_name,
207 queue='success'))
206 integration_name=self.IntegrationType.display_name),
207 queue='success')
208
208 209 if self.repo:
209 210 redirect_to = self.request.route_url(
210 211 'repo_integrations_edit', repo_name=self.repo.repo_name,
211 212 integration=self.integration.integration_type,
212 213 integration_id=self.integration.integration_id)
213 214 else:
214 215 redirect_to = self.request.route_url(
215 216 'global_integrations_edit',
216 217 integration=self.integration.integration_type,
217 218 integration_id=self.integration.integration_id)
218 219
219 220 return HTTPFound(redirect_to)
220 221
221 222 def index(self):
222 223 current_integrations = self.integrations
223 224 if self.IntegrationType:
224 225 current_integrations = {
225 226 self.IntegrationType.key: self.integrations.get(
226 227 self.IntegrationType.key, [])
227 228 }
228 229
229 230 template_context = {
230 231 'current_IntegrationType': self.IntegrationType,
231 232 'current_integrations': current_integrations,
232 233 'current_integration': 'none',
233 234 'available_integrations': integration_type_registry,
234 235 'c': self._template_c_context()
235 236 }
236 237
237 238 if self.repo:
238 239 html = render('rhodecode:templates/admin/integrations/list.html',
239 240 template_context,
240 241 request=self.request)
241 242 else:
242 243 html = render('rhodecode:templates/admin/integrations/list.html',
243 244 template_context,
244 245 request=self.request)
245 246
246 247 return Response(html)
247 248
248 249
249 250 class GlobalIntegrationsView(IntegrationSettingsViewBase):
250 251 def perm_check(self, user):
251 252 return auth.HasPermissionAll('hg.admin').check_permissions(user=user)
252 253
253 254
254 255 class RepoIntegrationsView(IntegrationSettingsViewBase):
255 256 def perm_check(self, user):
256 257 return auth.HasRepoPermissionAll('repository.admin'
257 258 )(repo_name=self.repo.repo_name, user=user)
General Comments 0
You need to be logged in to leave comments. Login now