##// END OF EJS Templates
renamed repos group -> repository group
marcink -
r3931:099585ff beta
parent child Browse files
Show More
@@ -1,401 +1,401 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos_groups
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Repository groups controller for RhodeCode
7 7
8 8 :created_on: Mar 23, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29
30 30 from formencode import htmlfill
31 31
32 32 from pylons import request, tmpl_context as c, url
33 33 from pylons.controllers.util import abort, redirect
34 34 from pylons.i18n.translation import _
35 35
36 36 from sqlalchemy.exc import IntegrityError
37 37
38 38 import rhodecode
39 39 from rhodecode.lib import helpers as h
40 40 from rhodecode.lib.compat import json
41 41 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
42 42 HasReposGroupPermissionAnyDecorator, HasReposGroupPermissionAll,\
43 43 HasPermissionAll
44 44 from rhodecode.lib.base import BaseController, render
45 45 from rhodecode.model.db import RepoGroup, Repository
46 46 from rhodecode.model.scm import RepoGroupList
47 47 from rhodecode.model.repos_group import ReposGroupModel
48 48 from rhodecode.model.forms import ReposGroupForm, RepoGroupPermsForm
49 49 from rhodecode.model.meta import Session
50 50 from rhodecode.model.repo import RepoModel
51 51 from webob.exc import HTTPInternalServerError, HTTPNotFound
52 52 from rhodecode.lib.utils2 import str2bool, safe_int
53 53 from sqlalchemy.sql.expression import func
54 54
55 55
56 56 log = logging.getLogger(__name__)
57 57
58 58
59 59 class ReposGroupsController(BaseController):
60 60 """REST Controller styled on the Atom Publishing Protocol"""
61 61 # To properly map this controller, ensure your config/routing.py
62 62 # file has a resource setup:
63 63 # map.resource('repos_group', 'repos_groups')
64 64
65 65 @LoginRequired()
66 66 def __before__(self):
67 67 super(ReposGroupsController, self).__before__()
68 68
69 69 def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]):
70 70 if HasPermissionAll('hg.admin')('group edit'):
71 71 #we're global admin, we're ok and we can create TOP level groups
72 72 allow_empty_group = True
73 73
74 74 #override the choices for this form, we need to filter choices
75 75 #and display only those we have ADMIN right
76 76 groups_with_admin_rights = RepoGroupList(RepoGroup.query().all(),
77 77 perm_set=['group.admin'])
78 78 c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights,
79 79 show_empty_group=allow_empty_group)
80 80 # exclude filtered ids
81 81 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
82 82 c.repo_groups)
83 83 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
84 84 repo_model = RepoModel()
85 85 c.users_array = repo_model.get_users_js()
86 86 c.users_groups_array = repo_model.get_users_groups_js()
87 87
88 88 def __load_data(self, group_id):
89 89 """
90 90 Load defaults settings for edit, and update
91 91
92 92 :param group_id:
93 93 """
94 94 repo_group = RepoGroup.get_or_404(group_id)
95 95 data = repo_group.get_dict()
96 96 data['group_name'] = repo_group.name
97 97
98 98 # fill repository group users
99 99 for p in repo_group.repo_group_to_perm:
100 100 data.update({'u_perm_%s' % p.user.username:
101 101 p.permission.permission_name})
102 102
103 103 # fill repository group groups
104 104 for p in repo_group.users_group_to_perm:
105 105 data.update({'g_perm_%s' % p.users_group.users_group_name:
106 106 p.permission.permission_name})
107 107
108 108 return data
109 109
110 110 def _revoke_perms_on_yourself(self, form_result):
111 111 _up = filter(lambda u: c.rhodecode_user.username == u[0],
112 112 form_result['perms_updates'])
113 113 _new = filter(lambda u: c.rhodecode_user.username == u[0],
114 114 form_result['perms_new'])
115 115 if _new and _new[0][1] != 'group.admin' or _up and _up[0][1] != 'group.admin':
116 116 return True
117 117 return False
118 118
119 119 def index(self, format='html'):
120 120 """GET /repos_groups: All items in the collection"""
121 121 # url('repos_groups')
122 122 group_iter = RepoGroupList(RepoGroup.query().all(),
123 123 perm_set=['group.admin'])
124 124 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
125 125 c.groups = sorted(group_iter, key=sk)
126 126 return render('admin/repos_groups/repos_groups_show.html')
127 127
128 128 def create(self):
129 129 """POST /repos_groups: Create a new item"""
130 130 # url('repos_groups')
131 131
132 132 self.__load_defaults()
133 133
134 134 # permissions for can create group based on parent_id are checked
135 135 # here in the Form
136 136 repos_group_form = ReposGroupForm(available_groups=
137 137 map(lambda k: unicode(k[0]), c.repo_groups))()
138 138 try:
139 139 form_result = repos_group_form.to_python(dict(request.POST))
140 140 ReposGroupModel().create(
141 141 group_name=form_result['group_name'],
142 142 group_description=form_result['group_description'],
143 143 parent=form_result['group_parent_id'],
144 144 owner=self.rhodecode_user.user_id
145 145 )
146 146 Session().commit()
147 147 h.flash(_('Created repository group %s') \
148 148 % form_result['group_name'], category='success')
149 149 #TODO: in futureaction_logger(, '', '', '', self.sa)
150 150 except formencode.Invalid, errors:
151 151 return htmlfill.render(
152 152 render('admin/repos_groups/repos_groups_add.html'),
153 153 defaults=errors.value,
154 154 errors=errors.error_dict or {},
155 155 prefix_error=False,
156 156 encoding="UTF-8")
157 157 except Exception:
158 158 log.error(traceback.format_exc())
159 159 h.flash(_('Error occurred during creation of repository group %s') \
160 160 % request.POST.get('group_name'), category='error')
161 161 parent_group_id = form_result['group_parent_id']
162 162 #TODO: maybe we should get back to the main view, not the admin one
163 163 return redirect(url('repos_groups', parent_group=parent_group_id))
164 164
165 165 def new(self, format='html'):
166 166 """GET /repos_groups/new: Form to create a new item"""
167 167 # url('new_repos_group')
168 168 if HasPermissionAll('hg.admin')('group create'):
169 169 #we're global admin, we're ok and we can create TOP level groups
170 170 pass
171 171 else:
172 172 # we pass in parent group into creation form, thus we know
173 173 # what would be the group, we can check perms here !
174 174 group_id = safe_int(request.GET.get('parent_group'))
175 175 group = RepoGroup.get(group_id) if group_id else None
176 176 group_name = group.group_name if group else None
177 177 if HasReposGroupPermissionAll('group.admin')(group_name, 'group create'):
178 178 pass
179 179 else:
180 180 return abort(403)
181 181
182 182 self.__load_defaults()
183 183 return render('admin/repos_groups/repos_groups_add.html')
184 184
185 185 @HasReposGroupPermissionAnyDecorator('group.admin')
186 186 def update(self, group_name):
187 187 """PUT /repos_groups/group_name: Update an existing item"""
188 188 # Forms posted to this method should contain a hidden field:
189 189 # <input type="hidden" name="_method" value="PUT" />
190 190 # Or using helpers:
191 191 # h.form(url('repos_group', group_name=GROUP_NAME),
192 192 # method='put')
193 193 # url('repos_group', group_name=GROUP_NAME)
194 194
195 195 c.repos_group = ReposGroupModel()._get_repo_group(group_name)
196 196 if HasPermissionAll('hg.admin')('group edit'):
197 197 #we're global admin, we're ok and we can create TOP level groups
198 198 allow_empty_group = True
199 199 elif not c.repos_group.parent_group:
200 200 allow_empty_group = True
201 201 else:
202 202 allow_empty_group = False
203 203 self.__load_defaults(allow_empty_group=allow_empty_group,
204 204 exclude_group_ids=[c.repos_group.group_id])
205 205
206 206 repos_group_form = ReposGroupForm(
207 207 edit=True,
208 208 old_data=c.repos_group.get_dict(),
209 209 available_groups=c.repo_groups_choices,
210 210 can_create_in_root=allow_empty_group,
211 211 )()
212 212 try:
213 213 form_result = repos_group_form.to_python(dict(request.POST))
214 214
215 215 new_gr = ReposGroupModel().update(group_name, form_result)
216 216 Session().commit()
217 217 h.flash(_('Updated repository group %s') \
218 218 % form_result['group_name'], category='success')
219 219 # we now have new name !
220 220 group_name = new_gr.group_name
221 221 #TODO: in future action_logger(, '', '', '', self.sa)
222 222 except formencode.Invalid, errors:
223 223
224 224 return htmlfill.render(
225 225 render('admin/repos_groups/repos_groups_edit.html'),
226 226 defaults=errors.value,
227 227 errors=errors.error_dict or {},
228 228 prefix_error=False,
229 229 encoding="UTF-8")
230 230 except Exception:
231 231 log.error(traceback.format_exc())
232 232 h.flash(_('Error occurred during update of repository group %s') \
233 233 % request.POST.get('group_name'), category='error')
234 234
235 235 return redirect(url('edit_repos_group', group_name=group_name))
236 236
237 237 @HasReposGroupPermissionAnyDecorator('group.admin')
238 238 def delete(self, group_name):
239 239 """DELETE /repos_groups/group_name: Delete an existing item"""
240 240 # Forms posted to this method should contain a hidden field:
241 241 # <input type="hidden" name="_method" value="DELETE" />
242 242 # Or using helpers:
243 243 # h.form(url('repos_group', group_name=GROUP_NAME),
244 244 # method='delete')
245 245 # url('repos_group', group_name=GROUP_NAME)
246 246
247 247 gr = c.repos_group = ReposGroupModel()._get_repo_group(group_name)
248 248 repos = gr.repositories.all()
249 249 if repos:
250 250 h.flash(_('This group contains %s repositores and cannot be '
251 251 'deleted') % len(repos), category='warning')
252 252 return redirect(url('repos_groups'))
253 253
254 254 children = gr.children.all()
255 255 if children:
256 256 h.flash(_('This group contains %s subgroups and cannot be deleted'
257 257 % (len(children))), category='warning')
258 258 return redirect(url('repos_groups'))
259 259
260 260 try:
261 261 ReposGroupModel().delete(group_name)
262 262 Session().commit()
263 263 h.flash(_('Removed repository group %s') % group_name,
264 264 category='success')
265 265 #TODO: in future action_logger(, '', '', '', self.sa)
266 266 except Exception:
267 267 log.error(traceback.format_exc())
268 h.flash(_('Error occurred during deletion of repos '
269 'group %s') % group_name, category='error')
268 h.flash(_('Error occurred during deletion of repository group %s')
269 % group_name, category='error')
270 270
271 271 return redirect(url('repos_groups'))
272 272
273 273 @HasReposGroupPermissionAnyDecorator('group.admin')
274 274 def set_repo_group_perm_member(self, group_name):
275 275 c.repos_group = ReposGroupModel()._get_repo_group(group_name)
276 276 form_result = RepoGroupPermsForm()().to_python(request.POST)
277 277 if not c.rhodecode_user.is_admin:
278 278 if self._revoke_perms_on_yourself(form_result):
279 279 msg = _('Cannot revoke permission for yourself as admin')
280 280 h.flash(msg, category='warning')
281 281 return redirect(url('edit_repos_group', group_name=group_name))
282 282 recursive = form_result['recursive']
283 283 # iterate over all members(if in recursive mode) of this groups and
284 284 # set the permissions !
285 285 # this can be potentially heavy operation
286 286 ReposGroupModel()._update_permissions(c.repos_group,
287 287 form_result['perms_new'],
288 288 form_result['perms_updates'],
289 289 recursive)
290 290 #TODO: implement this
291 291 #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
292 292 # repo_name, self.ip_addr, self.sa)
293 293 Session().commit()
294 294 h.flash(_('Repository Group permissions updated'), category='success')
295 295 return redirect(url('edit_repos_group', group_name=group_name))
296 296
297 297 @HasReposGroupPermissionAnyDecorator('group.admin')
298 298 def delete_repo_group_perm_member(self, group_name):
299 299 """
300 300 DELETE an existing repository group permission user
301 301
302 302 :param group_name:
303 303 """
304 304 try:
305 305 obj_type = request.POST.get('obj_type')
306 306 obj_id = None
307 307 if obj_type == 'user':
308 308 obj_id = safe_int(request.POST.get('user_id'))
309 309 elif obj_type == 'user_group':
310 310 obj_id = safe_int(request.POST.get('user_group_id'))
311 311
312 312 if not c.rhodecode_user.is_admin:
313 313 if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
314 314 msg = _('Cannot revoke permission for yourself as admin')
315 315 h.flash(msg, category='warning')
316 316 raise Exception('revoke admin permission on self')
317 317 recursive = str2bool(request.POST.get('recursive', False))
318 318 if obj_type == 'user':
319 319 ReposGroupModel().delete_permission(
320 320 repos_group=group_name, obj=obj_id,
321 321 obj_type='user', recursive=recursive
322 322 )
323 323 elif obj_type == 'user_group':
324 324 ReposGroupModel().delete_permission(
325 325 repos_group=group_name, obj=obj_id,
326 326 obj_type='users_group', recursive=recursive
327 327 )
328 328
329 329 Session().commit()
330 330 except Exception:
331 331 log.error(traceback.format_exc())
332 332 h.flash(_('An error occurred during revoking of permission'),
333 333 category='error')
334 334 raise HTTPInternalServerError()
335 335
336 336 def show_by_name(self, group_name):
337 337 """
338 338 This is a proxy that does a lookup group_name -> id, and shows
339 339 the group by id view instead
340 340 """
341 341 group_name = group_name.rstrip('/')
342 342 id_ = RepoGroup.get_by_group_name(group_name)
343 343 if id_:
344 344 return self.show(id_.group_id)
345 345 raise HTTPNotFound
346 346
347 347 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
348 348 'group.admin')
349 349 def show(self, group_name, format='html'):
350 350 """GET /repos_groups/group_name: Show a specific item"""
351 351 # url('repos_group', group_name=GROUP_NAME)
352 352
353 353 c.group = c.repos_group = ReposGroupModel()._get_repo_group(group_name)
354 354 c.group_repos = c.group.repositories.all()
355 355
356 356 #overwrite our cached list with current filter
357 357 gr_filter = c.group_repos
358 358 c.repo_cnt = 0
359 359
360 360 groups = RepoGroup.query().order_by(RepoGroup.group_name)\
361 361 .filter(RepoGroup.group_parent_id == c.group.group_id).all()
362 362 c.groups = self.scm_model.get_repos_groups(groups)
363 363
364 364 c.repos_list = Repository.query()\
365 365 .filter(Repository.group_id == c.group.group_id)\
366 366 .order_by(func.lower(Repository.repo_name))\
367 367 .all()
368 368
369 369 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
370 370 admin=False)
371 371 #json used to render the grid
372 372 c.data = json.dumps(repos_data)
373 373
374 374 return render('admin/repos_groups/repos_groups.html')
375 375
376 376 @HasReposGroupPermissionAnyDecorator('group.admin')
377 377 def edit(self, group_name, format='html'):
378 378 """GET /repos_groups/group_name/edit: Form to edit an existing item"""
379 379 # url('edit_repos_group', group_name=GROUP_NAME)
380 380
381 381 c.repos_group = ReposGroupModel()._get_repo_group(group_name)
382 382 #we can only allow moving empty group if it's already a top-level
383 383 #group, ie has no parents, or we're admin
384 384 if HasPermissionAll('hg.admin')('group edit'):
385 385 #we're global admin, we're ok and we can create TOP level groups
386 386 allow_empty_group = True
387 387 elif not c.repos_group.parent_group:
388 388 allow_empty_group = True
389 389 else:
390 390 allow_empty_group = False
391 391
392 392 self.__load_defaults(allow_empty_group=allow_empty_group,
393 393 exclude_group_ids=[c.repos_group.group_id])
394 394 defaults = self.__load_data(c.repos_group.group_id)
395 395
396 396 return htmlfill.render(
397 397 render('admin/repos_groups/repos_groups_edit.html'),
398 398 defaults=defaults,
399 399 encoding="UTF-8",
400 400 force_defaults=False
401 401 )
General Comments 0
You need to be logged in to leave comments. Login now