##// END OF EJS Templates
integrations: fixed missing template variable for fork reference checks.
marcink -
r3611:37100ede stable
parent child Browse files
Show More
@@ -1,316 +1,310 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2019 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 logging
22 22
23 23 from pyramid.view import view_config
24 24 from pyramid.httpexceptions import HTTPFound
25 25
26 26 from rhodecode import events
27 27 from rhodecode.apps._base import RepoAppView
28 28 from rhodecode.lib import helpers as h
29 29 from rhodecode.lib import audit_logger
30 30 from rhodecode.lib.auth import (
31 31 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired,
32 32 HasRepoPermissionAny)
33 33 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError
34 34 from rhodecode.lib.utils2 import safe_int
35 35 from rhodecode.lib.vcs import RepositoryError
36 36 from rhodecode.model.db import Session, UserFollowing, User, Repository
37 37 from rhodecode.model.repo import RepoModel
38 38 from rhodecode.model.scm import ScmModel
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 43 class RepoSettingsView(RepoAppView):
44 44
45 45 def load_default_context(self):
46 46 c = self._get_local_tmpl_context()
47 47 return c
48 48
49 49 def _get_users_with_permissions(self):
50 50 user_permissions = {}
51 51 for perm in self.db_repo.permissions():
52 52 user_permissions[perm.user_id] = perm
53 53
54 54 return user_permissions
55 55
56 56 @LoginRequired()
57 57 @HasRepoPermissionAnyDecorator('repository.admin')
58 58 @view_config(
59 59 route_name='edit_repo_advanced', request_method='GET',
60 60 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
61 61 def edit_advanced(self):
62 62 c = self.load_default_context()
63 63 c.active = 'advanced'
64 64
65 65 c.default_user_id = User.get_default_user().user_id
66 66 c.in_public_journal = UserFollowing.query() \
67 67 .filter(UserFollowing.user_id == c.default_user_id) \
68 68 .filter(UserFollowing.follows_repository == self.db_repo).scalar()
69 69
70 c.has_origin_repo_read_perm = False
71 if self.db_repo.fork:
72 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
73 'repository.write', 'repository.read', 'repository.admin')(
74 self.db_repo.fork.repo_name, 'repo set as fork page')
75
76 70 c.ver_info_dict = self.rhodecode_vcs_repo.get_hooks_info()
77 71
78 72 return self._get_template_context(c)
79 73
80 74 @LoginRequired()
81 75 @HasRepoPermissionAnyDecorator('repository.admin')
82 76 @CSRFRequired()
83 77 @view_config(
84 78 route_name='edit_repo_advanced_archive', request_method='POST',
85 79 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
86 80 def edit_advanced_archive(self):
87 81 """
88 82 Archives the repository. It will become read-only, and not visible in search
89 83 or other queries. But still visible for super-admins.
90 84 """
91 85
92 86 _ = self.request.translate
93 87
94 88 try:
95 89 old_data = self.db_repo.get_api_data()
96 90 RepoModel().archive(self.db_repo)
97 91
98 92 repo = audit_logger.RepoWrap(repo_id=None, repo_name=self.db_repo.repo_name)
99 93 audit_logger.store_web(
100 94 'repo.archive', action_data={'old_data': old_data},
101 95 user=self._rhodecode_user, repo=repo)
102 96
103 97 ScmModel().mark_for_invalidation(self.db_repo_name, delete=True)
104 98 h.flash(
105 99 _('Archived repository `%s`') % self.db_repo_name,
106 100 category='success')
107 101 Session().commit()
108 102 except Exception:
109 103 log.exception("Exception during archiving of repository")
110 104 h.flash(_('An error occurred during archiving of `%s`')
111 105 % self.db_repo_name, category='error')
112 106 # redirect to advanced for more deletion options
113 107 raise HTTPFound(
114 108 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name,
115 109 _anchor='advanced-archive'))
116 110
117 111 # flush permissions for all users defined in permissions
118 112 affected_user_ids = self._get_users_with_permissions().keys()
119 113 events.trigger(events.UserPermissionsChange(affected_user_ids))
120 114
121 115 raise HTTPFound(h.route_path('home'))
122 116
123 117 @LoginRequired()
124 118 @HasRepoPermissionAnyDecorator('repository.admin')
125 119 @CSRFRequired()
126 120 @view_config(
127 121 route_name='edit_repo_advanced_delete', request_method='POST',
128 122 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
129 123 def edit_advanced_delete(self):
130 124 """
131 125 Deletes the repository, or shows warnings if deletion is not possible
132 126 because of attached forks or other errors.
133 127 """
134 128 _ = self.request.translate
135 129 handle_forks = self.request.POST.get('forks', None)
136 130 if handle_forks == 'detach_forks':
137 131 handle_forks = 'detach'
138 132 elif handle_forks == 'delete_forks':
139 133 handle_forks = 'delete'
140 134
141 135 try:
142 136 old_data = self.db_repo.get_api_data()
143 137 RepoModel().delete(self.db_repo, forks=handle_forks)
144 138
145 139 _forks = self.db_repo.forks.count()
146 140 if _forks and handle_forks:
147 141 if handle_forks == 'detach_forks':
148 142 h.flash(_('Detached %s forks') % _forks, category='success')
149 143 elif handle_forks == 'delete_forks':
150 144 h.flash(_('Deleted %s forks') % _forks, category='success')
151 145
152 146 repo = audit_logger.RepoWrap(repo_id=None, repo_name=self.db_repo.repo_name)
153 147 audit_logger.store_web(
154 148 'repo.delete', action_data={'old_data': old_data},
155 149 user=self._rhodecode_user, repo=repo)
156 150
157 151 ScmModel().mark_for_invalidation(self.db_repo_name, delete=True)
158 152 h.flash(
159 153 _('Deleted repository `%s`') % self.db_repo_name,
160 154 category='success')
161 155 Session().commit()
162 156 except AttachedForksError:
163 157 repo_advanced_url = h.route_path(
164 158 'edit_repo_advanced', repo_name=self.db_repo_name,
165 159 _anchor='advanced-delete')
166 160 delete_anchor = h.link_to(_('detach or delete'), repo_advanced_url)
167 161 h.flash(_('Cannot delete `{repo}` it still contains attached forks. '
168 162 'Try using {delete_or_detach} option.')
169 163 .format(repo=self.db_repo_name, delete_or_detach=delete_anchor),
170 164 category='warning')
171 165
172 166 # redirect to advanced for forks handle action ?
173 167 raise HTTPFound(repo_advanced_url)
174 168
175 169 except AttachedPullRequestsError:
176 170 repo_advanced_url = h.route_path(
177 171 'edit_repo_advanced', repo_name=self.db_repo_name,
178 172 _anchor='advanced-delete')
179 173 attached_prs = len(self.db_repo.pull_requests_source +
180 174 self.db_repo.pull_requests_target)
181 175 h.flash(
182 176 _('Cannot delete `{repo}` it still contains {num} attached pull requests. '
183 177 'Consider archiving the repository instead.').format(
184 178 repo=self.db_repo_name, num=attached_prs), category='warning')
185 179
186 180 # redirect to advanced for forks handle action ?
187 181 raise HTTPFound(repo_advanced_url)
188 182
189 183 except Exception:
190 184 log.exception("Exception during deletion of repository")
191 185 h.flash(_('An error occurred during deletion of `%s`')
192 186 % self.db_repo_name, category='error')
193 187 # redirect to advanced for more deletion options
194 188 raise HTTPFound(
195 189 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name,
196 190 _anchor='advanced-delete'))
197 191
198 192 raise HTTPFound(h.route_path('home'))
199 193
200 194 @LoginRequired()
201 195 @HasRepoPermissionAnyDecorator('repository.admin')
202 196 @CSRFRequired()
203 197 @view_config(
204 198 route_name='edit_repo_advanced_journal', request_method='POST',
205 199 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
206 200 def edit_advanced_journal(self):
207 201 """
208 202 Set's this repository to be visible in public journal,
209 203 in other words making default user to follow this repo
210 204 """
211 205 _ = self.request.translate
212 206
213 207 try:
214 208 user_id = User.get_default_user().user_id
215 209 ScmModel().toggle_following_repo(self.db_repo.repo_id, user_id)
216 210 h.flash(_('Updated repository visibility in public journal'),
217 211 category='success')
218 212 Session().commit()
219 213 except Exception:
220 214 h.flash(_('An error occurred during setting this '
221 215 'repository in public journal'),
222 216 category='error')
223 217
224 218 raise HTTPFound(
225 219 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name))
226 220
227 221 @LoginRequired()
228 222 @HasRepoPermissionAnyDecorator('repository.admin')
229 223 @CSRFRequired()
230 224 @view_config(
231 225 route_name='edit_repo_advanced_fork', request_method='POST',
232 226 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
233 227 def edit_advanced_fork(self):
234 228 """
235 229 Mark given repository as a fork of another
236 230 """
237 231 _ = self.request.translate
238 232
239 233 new_fork_id = safe_int(self.request.POST.get('id_fork_of'))
240 234
241 235 # valid repo, re-check permissions
242 236 if new_fork_id:
243 237 repo = Repository.get(new_fork_id)
244 238 # ensure we have at least read access to the repo we mark
245 239 perm_check = HasRepoPermissionAny(
246 240 'repository.read', 'repository.write', 'repository.admin')
247 241
248 242 if repo and perm_check(repo_name=repo.repo_name):
249 243 new_fork_id = repo.repo_id
250 244 else:
251 245 new_fork_id = None
252 246
253 247 try:
254 248 repo = ScmModel().mark_as_fork(
255 249 self.db_repo_name, new_fork_id, self._rhodecode_user.user_id)
256 250 fork = repo.fork.repo_name if repo.fork else _('Nothing')
257 251 Session().commit()
258 252 h.flash(
259 253 _('Marked repo %s as fork of %s') % (self.db_repo_name, fork),
260 254 category='success')
261 255 except RepositoryError as e:
262 256 log.exception("Repository Error occurred")
263 257 h.flash(str(e), category='error')
264 258 except Exception:
265 259 log.exception("Exception while editing fork")
266 260 h.flash(_('An error occurred during this operation'),
267 261 category='error')
268 262
269 263 raise HTTPFound(
270 264 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name))
271 265
272 266 @LoginRequired()
273 267 @HasRepoPermissionAnyDecorator('repository.admin')
274 268 @CSRFRequired()
275 269 @view_config(
276 270 route_name='edit_repo_advanced_locking', request_method='POST',
277 271 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
278 272 def edit_advanced_locking(self):
279 273 """
280 274 Toggle locking of repository
281 275 """
282 276 _ = self.request.translate
283 277 set_lock = self.request.POST.get('set_lock')
284 278 set_unlock = self.request.POST.get('set_unlock')
285 279
286 280 try:
287 281 if set_lock:
288 282 Repository.lock(self.db_repo, self._rhodecode_user.user_id,
289 283 lock_reason=Repository.LOCK_WEB)
290 284 h.flash(_('Locked repository'), category='success')
291 285 elif set_unlock:
292 286 Repository.unlock(self.db_repo)
293 287 h.flash(_('Unlocked repository'), category='success')
294 288 except Exception as e:
295 289 log.exception("Exception during unlocking")
296 290 h.flash(_('An error occurred during unlocking'), category='error')
297 291
298 292 raise HTTPFound(
299 293 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name))
300 294
301 295 @LoginRequired()
302 296 @HasRepoPermissionAnyDecorator('repository.admin')
303 297 @view_config(
304 298 route_name='edit_repo_advanced_hooks', request_method='GET',
305 299 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
306 300 def edit_advanced_install_hooks(self):
307 301 """
308 302 Install Hooks for repository
309 303 """
310 304 _ = self.request.translate
311 305 self.load_default_context()
312 306 self.rhodecode_vcs_repo.install_hooks(force=True)
313 307 h.flash(_('installed updated hooks into this repository'),
314 308 category='success')
315 309 raise HTTPFound(
316 310 h.route_path('edit_repo_advanced', repo_name=self.db_repo_name))
@@ -1,459 +1,463 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2019 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 deform
22 22 import logging
23 23 import peppercorn
24 24 import webhelpers.paginate
25 25
26 26 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
27 27
28 28 from rhodecode.integrations import integration_type_registry
29 29 from rhodecode.apps._base import BaseAppView
30 30 from rhodecode.apps._base.navigation import navigation_list
31 31 from rhodecode.lib.auth import (
32 32 LoginRequired, CSRFRequired, HasPermissionAnyDecorator,
33 33 HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
34 34 from rhodecode.lib.utils2 import safe_int
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.model.db import Repository, RepoGroup, Session, Integration
37 37 from rhodecode.model.scm import ScmModel
38 38 from rhodecode.model.integration import IntegrationModel
39 39 from rhodecode.model.validation_schema.schemas.integration_schema import (
40 40 make_integration_schema, IntegrationScopeType)
41 41
42 42 log = logging.getLogger(__name__)
43 43
44 44
45 45 class IntegrationSettingsViewBase(BaseAppView):
46 46 """
47 47 Base Integration settings view used by both repo / global settings
48 48 """
49 49
50 50 def __init__(self, context, request):
51 51 super(IntegrationSettingsViewBase, self).__init__(context, request)
52 52 self._load_view_context()
53 53
54 54 def _load_view_context(self):
55 55 """
56 56 This avoids boilerplate for repo/global+list/edit+views/templates
57 57 by doing all possible contexts at the same time however it should
58 58 be split up into separate functions once more "contexts" exist
59 59 """
60 60
61 61 self.IntegrationType = None
62 62 self.repo = None
63 63 self.repo_group = None
64 64 self.integration = None
65 65 self.integrations = {}
66 66
67 67 request = self.request
68 68
69 69 if 'repo_name' in request.matchdict: # in repo settings context
70 70 repo_name = request.matchdict['repo_name']
71 71 self.repo = Repository.get_by_repo_name(repo_name)
72 72
73 73 if 'repo_group_name' in request.matchdict: # in group settings context
74 74 repo_group_name = request.matchdict['repo_group_name']
75 75 self.repo_group = RepoGroup.get_by_group_name(repo_group_name)
76 76
77 77 if 'integration' in request.matchdict: # integration type context
78 78 integration_type = request.matchdict['integration']
79 79 if integration_type not in integration_type_registry:
80 80 raise HTTPNotFound()
81 81
82 82 self.IntegrationType = integration_type_registry[integration_type]
83 83 if self.IntegrationType.is_dummy:
84 84 raise HTTPNotFound()
85 85
86 86 if 'integration_id' in request.matchdict: # single integration context
87 87 integration_id = request.matchdict['integration_id']
88 88 self.integration = Integration.get(integration_id)
89 89
90 90 # extra perms check just in case
91 91 if not self._has_perms_for_integration(self.integration):
92 92 raise HTTPForbidden()
93 93
94 94 self.settings = self.integration and self.integration.settings or {}
95 95 self.admin_view = not (self.repo or self.repo_group)
96 96
97 97 def _has_perms_for_integration(self, integration):
98 98 perms = self.request.user.permissions
99 99
100 100 if 'hg.admin' in perms['global']:
101 101 return True
102 102
103 103 if integration.repo:
104 104 return perms['repositories'].get(
105 105 integration.repo.repo_name) == 'repository.admin'
106 106
107 107 if integration.repo_group:
108 108 return perms['repositories_groups'].get(
109 109 integration.repo_group.group_name) == 'group.admin'
110 110
111 111 return False
112 112
113 113 def _get_local_tmpl_context(self, include_app_defaults=True):
114 114 _ = self.request.translate
115 115 c = super(IntegrationSettingsViewBase, self)._get_local_tmpl_context(
116 116 include_app_defaults=include_app_defaults)
117
118 117 c.active = 'integrations'
119 118
120 119 return c
121 120
122 121 def _form_schema(self):
123 122 schema = make_integration_schema(IntegrationType=self.IntegrationType,
124 123 settings=self.settings)
125 124
126 125 # returns a clone, important if mutating the schema later
127 126 return schema.bind(
128 127 permissions=self.request.user.permissions,
129 128 no_scope=not self.admin_view)
130 129
131 130 def _form_defaults(self):
132 131 _ = self.request.translate
133 132 defaults = {}
134 133
135 134 if self.integration:
136 135 defaults['settings'] = self.integration.settings or {}
137 136 defaults['options'] = {
138 137 'name': self.integration.name,
139 138 'enabled': self.integration.enabled,
140 139 'scope': {
141 140 'repo': self.integration.repo,
142 141 'repo_group': self.integration.repo_group,
143 142 'child_repos_only': self.integration.child_repos_only,
144 143 },
145 144 }
146 145 else:
147 146 if self.repo:
148 147 scope = _('{repo_name} repository').format(
149 148 repo_name=self.repo.repo_name)
150 149 elif self.repo_group:
151 150 scope = _('{repo_group_name} repo group').format(
152 151 repo_group_name=self.repo_group.group_name)
153 152 else:
154 153 scope = _('Global')
155 154
156 155 defaults['options'] = {
157 156 'enabled': True,
158 157 'name': _('{name} integration').format(
159 158 name=self.IntegrationType.display_name),
160 159 }
161 160 defaults['options']['scope'] = {
162 161 'repo': self.repo,
163 162 'repo_group': self.repo_group,
164 163 }
165 164
166 165 return defaults
167 166
168 167 def _delete_integration(self, integration):
169 168 _ = self.request.translate
170 169 Session().delete(integration)
171 170 Session().commit()
172 171 h.flash(
173 172 _('Integration {integration_name} deleted successfully.').format(
174 173 integration_name=integration.name),
175 174 category='success')
176 175
177 176 if self.repo:
178 177 redirect_to = self.request.route_path(
179 178 'repo_integrations_home', repo_name=self.repo.repo_name)
180 179 elif self.repo_group:
181 180 redirect_to = self.request.route_path(
182 181 'repo_group_integrations_home',
183 182 repo_group_name=self.repo_group.group_name)
184 183 else:
185 184 redirect_to = self.request.route_path('global_integrations_home')
186 185 raise HTTPFound(redirect_to)
187 186
188 187 def _integration_list(self):
189 188 """ List integrations """
190 189
191 190 c = self.load_default_context()
192 191 if self.repo:
193 192 scope = self.repo
194 193 elif self.repo_group:
195 194 scope = self.repo_group
196 195 else:
197 196 scope = 'all'
198 197
199 198 integrations = []
200 199
201 200 for IntType, integration in IntegrationModel().get_integrations(
202 201 scope=scope, IntegrationType=self.IntegrationType):
203 202
204 203 # extra permissions check *just in case*
205 204 if not self._has_perms_for_integration(integration):
206 205 continue
207 206
208 207 integrations.append((IntType, integration))
209 208
210 209 sort_arg = self.request.GET.get('sort', 'name:asc')
211 210 sort_dir = 'asc'
212 211 if ':' in sort_arg:
213 212 sort_field, sort_dir = sort_arg.split(':')
214 213 else:
215 214 sort_field = sort_arg, 'asc'
216 215
217 216 assert sort_field in ('name', 'integration_type', 'enabled', 'scope')
218 217
219 218 integrations.sort(
220 219 key=lambda x: getattr(x[1], sort_field),
221 220 reverse=(sort_dir == 'desc'))
222 221
223 222 page_url = webhelpers.paginate.PageURL(
224 223 self.request.path, self.request.GET)
225 224 page = safe_int(self.request.GET.get('page', 1), 1)
226 225
227 226 integrations = h.Page(
228 227 integrations, page=page, items_per_page=10, url=page_url)
229 228
230 229 c.rev_sort_dir = sort_dir != 'desc' and 'desc' or 'asc'
231 230
232 231 c.current_IntegrationType = self.IntegrationType
233 232 c.integrations_list = integrations
234 233 c.available_integrations = integration_type_registry
235 234
236 235 return self._get_template_context(c)
237 236
238 237 def _settings_get(self, defaults=None, form=None):
239 238 """
240 239 View that displays the integration settings as a form.
241 240 """
242 241 c = self.load_default_context()
243 242
244 243 defaults = defaults or self._form_defaults()
245 244 schema = self._form_schema()
246 245
247 246 if self.integration:
248 247 buttons = ('submit', 'delete')
249 248 else:
250 249 buttons = ('submit',)
251 250
252 251 form = form or deform.Form(schema, appstruct=defaults, buttons=buttons)
253 252
254 253 c.form = form
255 254 c.current_IntegrationType = self.IntegrationType
256 255 c.integration = self.integration
257 256
258 257 return self._get_template_context(c)
259 258
260 259 def _settings_post(self):
261 260 """
262 261 View that validates and stores the integration settings.
263 262 """
264 263 _ = self.request.translate
265 264
266 265 controls = self.request.POST.items()
267 266 pstruct = peppercorn.parse(controls)
268 267
269 268 if self.integration and pstruct.get('delete'):
270 269 return self._delete_integration(self.integration)
271 270
272 271 schema = self._form_schema()
273 272
274 273 skip_settings_validation = False
275 274 if self.integration and 'enabled' not in pstruct.get('options', {}):
276 275 skip_settings_validation = True
277 276 schema['settings'].validator = None
278 277 for field in schema['settings'].children:
279 278 field.validator = None
280 279 field.missing = ''
281 280
282 281 if self.integration:
283 282 buttons = ('submit', 'delete')
284 283 else:
285 284 buttons = ('submit',)
286 285
287 286 form = deform.Form(schema, buttons=buttons)
288 287
289 288 if not self.admin_view:
290 289 # scope is read only field in these cases, and has to be added
291 290 options = pstruct.setdefault('options', {})
292 291 if 'scope' not in options:
293 292 options['scope'] = IntegrationScopeType().serialize(None, {
294 293 'repo': self.repo,
295 294 'repo_group': self.repo_group,
296 295 })
297 296
298 297 try:
299 298 valid_data = form.validate_pstruct(pstruct)
300 299 except deform.ValidationFailure as e:
301 300 h.flash(
302 301 _('Errors exist when saving integration settings. '
303 302 'Please check the form inputs.'),
304 303 category='error')
305 304 return self._settings_get(form=e)
306 305
307 306 if not self.integration:
308 307 self.integration = Integration()
309 308 self.integration.integration_type = self.IntegrationType.key
310 309 Session().add(self.integration)
311 310
312 311 scope = valid_data['options']['scope']
313 312
314 313 IntegrationModel().update_integration(self.integration,
315 314 name=valid_data['options']['name'],
316 315 enabled=valid_data['options']['enabled'],
317 316 settings=valid_data['settings'],
318 317 repo=scope['repo'],
319 318 repo_group=scope['repo_group'],
320 319 child_repos_only=scope['child_repos_only'],
321 320 )
322 321
323 322 self.integration.settings = valid_data['settings']
324 323 Session().commit()
325 324 # Display success message and redirect.
326 325 h.flash(
327 326 _('Integration {integration_name} updated successfully.').format(
328 327 integration_name=self.IntegrationType.display_name),
329 328 category='success')
330 329
331 330 # if integration scope changes, we must redirect to the right place
332 331 # keeping in mind if the original view was for /repo/ or /_admin/
333 332 admin_view = not (self.repo or self.repo_group)
334 333
335 334 if self.integration.repo and not admin_view:
336 335 redirect_to = self.request.route_path(
337 336 'repo_integrations_edit',
338 337 repo_name=self.integration.repo.repo_name,
339 338 integration=self.integration.integration_type,
340 339 integration_id=self.integration.integration_id)
341 340 elif self.integration.repo_group and not admin_view:
342 341 redirect_to = self.request.route_path(
343 342 'repo_group_integrations_edit',
344 343 repo_group_name=self.integration.repo_group.group_name,
345 344 integration=self.integration.integration_type,
346 345 integration_id=self.integration.integration_id)
347 346 else:
348 347 redirect_to = self.request.route_path(
349 348 'global_integrations_edit',
350 349 integration=self.integration.integration_type,
351 350 integration_id=self.integration.integration_id)
352 351
353 352 return HTTPFound(redirect_to)
354 353
355 354 def _new_integration(self):
356 355 c = self.load_default_context()
357 356 c.available_integrations = integration_type_registry
358 357 return self._get_template_context(c)
359 358
360 359 def load_default_context(self):
361 360 raise NotImplementedError()
362 361
363 362
364 363 class GlobalIntegrationsView(IntegrationSettingsViewBase):
365 364 def load_default_context(self):
366 365 c = self._get_local_tmpl_context()
367 366 c.repo = self.repo
368 367 c.repo_group = self.repo_group
369 368 c.navlist = navigation_list(self.request)
370 369
371 370 return c
372 371
373 372 @LoginRequired()
374 373 @HasPermissionAnyDecorator('hg.admin')
375 374 def integration_list(self):
376 375 return self._integration_list()
377 376
378 377 @LoginRequired()
379 378 @HasPermissionAnyDecorator('hg.admin')
380 379 def settings_get(self):
381 380 return self._settings_get()
382 381
383 382 @LoginRequired()
384 383 @HasPermissionAnyDecorator('hg.admin')
385 384 @CSRFRequired()
386 385 def settings_post(self):
387 386 return self._settings_post()
388 387
389 388 @LoginRequired()
390 389 @HasPermissionAnyDecorator('hg.admin')
391 390 def new_integration(self):
392 391 return self._new_integration()
393 392
394 393
395 394 class RepoIntegrationsView(IntegrationSettingsViewBase):
396 395 def load_default_context(self):
397 396 c = self._get_local_tmpl_context()
398 397
399 398 c.repo = self.repo
400 399 c.repo_group = self.repo_group
401 400
402 401 self.db_repo = self.repo
403 402 c.rhodecode_db_repo = self.repo
404 403 c.repo_name = self.db_repo.repo_name
405 404 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
406 405
406 c.has_origin_repo_read_perm = False
407 if self.db_repo.fork:
408 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
409 'repository.write', 'repository.read', 'repository.admin')(
410 self.db_repo.fork.repo_name, 'summary fork link')
407 411 return c
408 412
409 413 @LoginRequired()
410 414 @HasRepoPermissionAnyDecorator('repository.admin')
411 415 def integration_list(self):
412 416 return self._integration_list()
413 417
414 418 @LoginRequired()
415 419 @HasRepoPermissionAnyDecorator('repository.admin')
416 420 def settings_get(self):
417 421 return self._settings_get()
418 422
419 423 @LoginRequired()
420 424 @HasRepoPermissionAnyDecorator('repository.admin')
421 425 @CSRFRequired()
422 426 def settings_post(self):
423 427 return self._settings_post()
424 428
425 429 @LoginRequired()
426 430 @HasRepoPermissionAnyDecorator('repository.admin')
427 431 def new_integration(self):
428 432 return self._new_integration()
429 433
430 434
431 435 class RepoGroupIntegrationsView(IntegrationSettingsViewBase):
432 436 def load_default_context(self):
433 437 c = self._get_local_tmpl_context()
434 438 c.repo = self.repo
435 439 c.repo_group = self.repo_group
436 440 c.navlist = navigation_list(self.request)
437 441
438 442 return c
439 443
440 444 @LoginRequired()
441 445 @HasRepoGroupPermissionAnyDecorator('group.admin')
442 446 def integration_list(self):
443 447 return self._integration_list()
444 448
445 449 @LoginRequired()
446 450 @HasRepoGroupPermissionAnyDecorator('group.admin')
447 451 def settings_get(self):
448 452 return self._settings_get()
449 453
450 454 @LoginRequired()
451 455 @HasRepoGroupPermissionAnyDecorator('group.admin')
452 456 @CSRFRequired()
453 457 def settings_post(self):
454 458 return self._settings_post()
455 459
456 460 @LoginRequired()
457 461 @HasRepoGroupPermissionAnyDecorator('group.admin')
458 462 def new_integration(self):
459 463 return self._new_integration()
General Comments 0
You need to be logged in to leave comments. Login now