comparison rhodecode/controllers/admin/user_groups.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl

Imported some of the GPLv3'd changes from RhodeCode v2.2.5. This imports changes between changesets 21af6c4eab3d and 6177597791c2 in RhodeCode's original repository, including only changes to Python files and HTML. RhodeCode clearly licensed its changes to these files under GPLv3 in their /LICENSE file, which states the following: The Python code and integrated HTML are licensed under the GPLv3 license. (See: https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE or http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE for an online copy of that LICENSE file) Conservancy reviewed these changes and confirmed that they can be licensed as a whole to the Kallithea project under GPLv3-only. While some of the contents committed herein are clearly licensed GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the statement above from RhodeCode indicates that they intend GPLv3-only as their license, per GPLv3ยง14 and other relevant sections of GPLv3.
author Bradley M. Kuhn <bkuhn@sfconservancy.org>
date Wed, 02 Jul 2014 19:03:13 -0400
parents
children 7e5f8c12a3fc
comparison
equal deleted inserted replaced
4115:8b7294a804a0 4116:ffd45b185016
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
15 rhodecode.controllers.admin.users_groups
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
18 User Groups crud controller for pylons
19
20 :created_on: Jan 25, 2011
21 :author: marcink
22 :copyright: (c) 2013 RhodeCode GmbH.
23 :license: GPLv3, see LICENSE for more details.
24 """
25
26 import logging
27 import traceback
28 import formencode
29
30 from formencode import htmlfill
31 from pylons import request, session, tmpl_context as c, url, config
32 from pylons.controllers.util import abort, redirect
33 from pylons.i18n.translation import _
34
35 from sqlalchemy.orm import joinedload
36 from sqlalchemy.sql.expression import func
37 from webob.exc import HTTPInternalServerError
38
39 import rhodecode
40 from rhodecode.lib import helpers as h
41 from rhodecode.lib.exceptions import UserGroupsAssignedException,\
42 RepoGroupAssignmentError
43 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
44 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator,\
45 HasUserGroupPermissionAnyDecorator, HasPermissionAnyDecorator
46 from rhodecode.lib.base import BaseController, render
47 from rhodecode.model.scm import UserGroupList
48 from rhodecode.model.user_group import UserGroupModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.db import User, UserGroup, UserGroupToPerm,\
51 UserGroupRepoToPerm, UserGroupRepoGroupToPerm
52 from rhodecode.model.forms import UserGroupForm, UserGroupPermsForm,\
53 CustomDefaultPermissionsForm
54 from rhodecode.model.meta import Session
55 from rhodecode.lib.utils import action_logger
56 from rhodecode.lib.compat import json
57
58 log = logging.getLogger(__name__)
59
60
61 class UserGroupsController(BaseController):
62 """REST Controller styled on the Atom Publishing Protocol"""
63
64 @LoginRequired()
65 def __before__(self):
66 super(UserGroupsController, self).__before__()
67 c.available_permissions = config['available_permissions']
68
69 def __load_data(self, user_group_id):
70 c.group_members_obj = sorted((x.user for x in c.user_group.members),
71 key=lambda u: u.username.lower())
72
73 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
74 c.available_members = sorted(((x.user_id, x.username) for x in
75 User.query().all()),
76 key=lambda u: u[1].lower())
77
78 def __load_defaults(self, user_group_id):
79 """
80 Load defaults settings for edit, and update
81
82 :param user_group_id:
83 """
84 user_group = UserGroup.get_or_404(user_group_id)
85 data = user_group.get_dict()
86 return data
87
88 def index(self, format='html'):
89 """GET /users_groups: All items in the collection"""
90 # url('users_groups')
91 _list = UserGroup.query()\
92 .order_by(func.lower(UserGroup.users_group_name))\
93 .all()
94 group_iter = UserGroupList(_list, perm_set=['usergroup.admin'])
95 user_groups_data = []
96 total_records = len(group_iter)
97 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
98 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
99
100 user_group_name = lambda user_group_id, user_group_name: (
101 template.get_def("user_group_name")
102 .render(user_group_id, user_group_name, _=_, h=h, c=c)
103 )
104 user_group_actions = lambda user_group_id, user_group_name: (
105 template.get_def("user_group_actions")
106 .render(user_group_id, user_group_name, _=_, h=h, c=c)
107 )
108 for user_gr in group_iter:
109
110 user_groups_data.append({
111 "raw_name": user_gr.users_group_name,
112 "group_name": user_group_name(user_gr.users_group_id,
113 user_gr.users_group_name),
114 "desc": user_gr.user_group_description,
115 "members": len(user_gr.members),
116 "active": h.boolicon(user_gr.users_group_active),
117 "owner": h.person(user_gr.user.username),
118 "action": user_group_actions(user_gr.users_group_id, user_gr.users_group_name)
119 })
120
121 c.data = json.dumps({
122 "totalRecords": total_records,
123 "startIndex": 0,
124 "sort": None,
125 "dir": "asc",
126 "records": user_groups_data
127 })
128
129 return render('admin/user_groups/user_groups.html')
130
131 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
132 def create(self):
133 """POST /users_groups: Create a new item"""
134 # url('users_groups')
135
136 users_group_form = UserGroupForm()()
137 try:
138 form_result = users_group_form.to_python(dict(request.POST))
139 UserGroupModel().create(name=form_result['users_group_name'],
140 description=form_result['user_group_description'],
141 owner=self.rhodecode_user.user_id,
142 active=form_result['users_group_active'])
143
144 gr = form_result['users_group_name']
145 action_logger(self.rhodecode_user,
146 'admin_created_users_group:%s' % gr,
147 None, self.ip_addr, self.sa)
148 h.flash(_('Created user group %s') % gr, category='success')
149 Session().commit()
150 except formencode.Invalid, errors:
151 return htmlfill.render(
152 render('admin/user_groups/user_group_add.html'),
153 defaults=errors.value,
154 errors=errors.error_dict or {},
155 prefix_error=False,
156 encoding="UTF-8")
157 except Exception:
158 log.error(traceback.format_exc())
159 h.flash(_('Error occurred during creation of user group %s') \
160 % request.POST.get('users_group_name'), category='error')
161
162 return redirect(url('users_groups'))
163
164 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
165 def new(self, format='html'):
166 """GET /user_groups/new: Form to create a new item"""
167 # url('new_users_group')
168 return render('admin/user_groups/user_group_add.html')
169
170 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
171 def update(self, id):
172 """PUT /user_groups/id: Update an existing item"""
173 # Forms posted to this method should contain a hidden field:
174 # <input type="hidden" name="_method" value="PUT" />
175 # Or using helpers:
176 # h.form(url('users_group', id=ID),
177 # method='put')
178 # url('users_group', id=ID)
179
180 c.user_group = UserGroup.get_or_404(id)
181 c.active = 'settings'
182 self.__load_data(id)
183
184 available_members = [safe_unicode(x[0]) for x in c.available_members]
185
186 users_group_form = UserGroupForm(edit=True,
187 old_data=c.user_group.get_dict(),
188 available_members=available_members)()
189
190 try:
191 form_result = users_group_form.to_python(request.POST)
192 UserGroupModel().update(c.user_group, form_result)
193 gr = form_result['users_group_name']
194 action_logger(self.rhodecode_user,
195 'admin_updated_users_group:%s' % gr,
196 None, self.ip_addr, self.sa)
197 h.flash(_('Updated user group %s') % gr, category='success')
198 Session().commit()
199 except formencode.Invalid, errors:
200 ug_model = UserGroupModel()
201 defaults = errors.value
202 e = errors.error_dict or {}
203 defaults.update({
204 'create_repo_perm': ug_model.has_perm(id,
205 'hg.create.repository'),
206 'fork_repo_perm': ug_model.has_perm(id,
207 'hg.fork.repository'),
208 '_method': 'put'
209 })
210
211 return htmlfill.render(
212 render('admin/user_groups/user_group_edit.html'),
213 defaults=defaults,
214 errors=e,
215 prefix_error=False,
216 encoding="UTF-8")
217 except Exception:
218 log.error(traceback.format_exc())
219 h.flash(_('Error occurred during update of user group %s') \
220 % request.POST.get('users_group_name'), category='error')
221
222 return redirect(url('edit_users_group', id=id))
223
224 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
225 def delete(self, id):
226 """DELETE /user_groups/id: Delete an existing item"""
227 # Forms posted to this method should contain a hidden field:
228 # <input type="hidden" name="_method" value="DELETE" />
229 # Or using helpers:
230 # h.form(url('users_group', id=ID),
231 # method='delete')
232 # url('users_group', id=ID)
233 usr_gr = UserGroup.get_or_404(id)
234 try:
235 UserGroupModel().delete(usr_gr)
236 Session().commit()
237 h.flash(_('Successfully deleted user group'), category='success')
238 except UserGroupsAssignedException, e:
239 h.flash(e, category='error')
240 except Exception:
241 log.error(traceback.format_exc())
242 h.flash(_('An error occurred during deletion of user group'),
243 category='error')
244 return redirect(url('users_groups'))
245
246 def show(self, id, format='html'):
247 """GET /user_groups/id: Show a specific item"""
248 # url('users_group', id=ID)
249
250 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
251 def edit(self, id, format='html'):
252 """GET /user_groups/id/edit: Form to edit an existing item"""
253 # url('edit_users_group', id=ID)
254
255 c.user_group = UserGroup.get_or_404(id)
256 c.active = 'settings'
257 self.__load_data(id)
258
259 defaults = self.__load_defaults(id)
260
261 return htmlfill.render(
262 render('admin/user_groups/user_group_edit.html'),
263 defaults=defaults,
264 encoding="UTF-8",
265 force_defaults=False
266 )
267
268 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
269 def edit_perms(self, id):
270 c.user_group = UserGroup.get_or_404(id)
271 c.active = 'perms'
272
273 repo_model = RepoModel()
274 c.users_array = repo_model.get_users_js()
275 c.user_groups_array = repo_model.get_user_groups_js()
276
277 defaults = {}
278 # fill user group users
279 for p in c.user_group.user_user_group_to_perm:
280 defaults.update({'u_perm_%s' % p.user.username:
281 p.permission.permission_name})
282
283 for p in c.user_group.user_group_user_group_to_perm:
284 defaults.update({'g_perm_%s' % p.user_group.users_group_name:
285 p.permission.permission_name})
286
287 return htmlfill.render(
288 render('admin/user_groups/user_group_edit.html'),
289 defaults=defaults,
290 encoding="UTF-8",
291 force_defaults=False
292 )
293
294 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
295 def update_perms(self, id):
296 """
297 grant permission for given usergroup
298
299 :param id:
300 """
301 user_group = UserGroup.get_or_404(id)
302 form = UserGroupPermsForm()().to_python(request.POST)
303
304 # set the permissions !
305 try:
306 UserGroupModel()._update_permissions(user_group, form['perms_new'],
307 form['perms_updates'])
308 except RepoGroupAssignmentError:
309 h.flash(_('Target group cannot be the same'), category='error')
310 return redirect(url('edit_user_group_perms', id=id))
311 #TODO: implement this
312 #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
313 # repo_name, self.ip_addr, self.sa)
314 Session().commit()
315 h.flash(_('User Group permissions updated'), category='success')
316 return redirect(url('edit_user_group_perms', id=id))
317
318 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
319 def delete_perms(self, id):
320 """
321 DELETE an existing repository group permission user
322
323 :param group_name:
324 """
325 try:
326 obj_type = request.POST.get('obj_type')
327 obj_id = None
328 if obj_type == 'user':
329 obj_id = safe_int(request.POST.get('user_id'))
330 elif obj_type == 'user_group':
331 obj_id = safe_int(request.POST.get('user_group_id'))
332
333 if not c.rhodecode_user.is_admin:
334 if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
335 msg = _('Cannot revoke permission for yourself as admin')
336 h.flash(msg, category='warning')
337 raise Exception('revoke admin permission on self')
338 if obj_type == 'user':
339 UserGroupModel().revoke_user_permission(user_group=id,
340 user=obj_id)
341 elif obj_type == 'user_group':
342 UserGroupModel().revoke_user_group_permission(target_user_group=id,
343 user_group=obj_id)
344 Session().commit()
345 except Exception:
346 log.error(traceback.format_exc())
347 h.flash(_('An error occurred during revoking of permission'),
348 category='error')
349 raise HTTPInternalServerError()
350
351 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
352 def edit_default_perms(self, id):
353 c.user_group = UserGroup.get_or_404(id)
354 c.active = 'default_perms'
355
356 permissions = {
357 'repositories': {},
358 'repositories_groups': {}
359 }
360 ugroup_repo_perms = UserGroupRepoToPerm.query()\
361 .options(joinedload(UserGroupRepoToPerm.permission))\
362 .options(joinedload(UserGroupRepoToPerm.repository))\
363 .filter(UserGroupRepoToPerm.users_group_id == id)\
364 .all()
365
366 for gr in ugroup_repo_perms:
367 permissions['repositories'][gr.repository.repo_name] \
368 = gr.permission.permission_name
369
370 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
371 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
372 .options(joinedload(UserGroupRepoGroupToPerm.group))\
373 .filter(UserGroupRepoGroupToPerm.users_group_id == id)\
374 .all()
375
376 for gr in ugroup_group_perms:
377 permissions['repositories_groups'][gr.group.group_name] \
378 = gr.permission.permission_name
379 c.permissions = permissions
380
381 ug_model = UserGroupModel()
382
383 defaults = c.user_group.get_dict()
384 defaults.update({
385 'create_repo_perm': ug_model.has_perm(c.user_group,
386 'hg.create.repository'),
387 'create_user_group_perm': ug_model.has_perm(c.user_group,
388 'hg.usergroup.create.true'),
389 'fork_repo_perm': ug_model.has_perm(c.user_group,
390 'hg.fork.repository'),
391 })
392
393 return htmlfill.render(
394 render('admin/user_groups/user_group_edit.html'),
395 defaults=defaults,
396 encoding="UTF-8",
397 force_defaults=False
398 )
399
400 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
401 def update_default_perms(self, id):
402 """PUT /users_perm/id: Update an existing item"""
403 # url('users_group_perm', id=ID, method='put')
404
405 user_group = UserGroup.get_or_404(id)
406
407 try:
408 form = CustomDefaultPermissionsForm()()
409 form_result = form.to_python(request.POST)
410
411 inherit_perms = form_result['inherit_default_permissions']
412 user_group.inherit_default_permissions = inherit_perms
413 Session().add(user_group)
414 usergroup_model = UserGroupModel()
415
416 defs = UserGroupToPerm.query()\
417 .filter(UserGroupToPerm.users_group == user_group)\
418 .all()
419 for ug in defs:
420 Session().delete(ug)
421
422 if form_result['create_repo_perm']:
423 usergroup_model.grant_perm(id, 'hg.create.repository')
424 else:
425 usergroup_model.grant_perm(id, 'hg.create.none')
426 if form_result['create_user_group_perm']:
427 usergroup_model.grant_perm(id, 'hg.usergroup.create.true')
428 else:
429 usergroup_model.grant_perm(id, 'hg.usergroup.create.false')
430 if form_result['fork_repo_perm']:
431 usergroup_model.grant_perm(id, 'hg.fork.repository')
432 else:
433 usergroup_model.grant_perm(id, 'hg.fork.none')
434
435 h.flash(_("Updated permissions"), category='success')
436 Session().commit()
437 except Exception:
438 log.error(traceback.format_exc())
439 h.flash(_('An error occurred during permissions saving'),
440 category='error')
441
442 return redirect(url('edit_user_group_default_perms', id=id))
443
444 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
445 def edit_advanced(self, id):
446 c.user_group = UserGroup.get_or_404(id)
447 c.active = 'advanced'
448 c.group_members_obj = sorted((x.user for x in c.user_group.members),
449 key=lambda u: u.username.lower())
450 return render('admin/user_groups/user_group_edit.html')
451
452
453 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
454 def edit_members(self, id):
455 c.user_group = UserGroup.get_or_404(id)
456 c.active = 'members'
457 c.group_members_obj = sorted((x.user for x in c.user_group.members),
458 key=lambda u: u.username.lower())
459
460 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
461 return render('admin/user_groups/user_group_edit.html')