##// END OF EJS Templates
user-groups: rewrote the app to pyramid...
marcink -
r2068:71f5d13f default
parent child Browse files
Show More
@@ -0,0 +1,101 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 from rhodecode.apps.admin.navigation import NavigationRegistry
23 from rhodecode.config.routing import ADMIN_PREFIX
24 from rhodecode.lib.utils2 import str2bool
25
26
27 def admin_routes(config):
28 """
29 User groups /_admin prefixed routes
30 """
31
32 config.add_route(
33 name='user_group_members_data',
34 pattern='/user_groups/{user_group_id:\d+}/members',
35 user_group_route=True)
36
37 # user groups perms
38 config.add_route(
39 name='edit_user_group_perms_summary',
40 pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary',
41 user_group_route=True)
42 config.add_route(
43 name='edit_user_group_perms_summary_json',
44 pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary/json',
45 user_group_route=True)
46
47 # user groups edit
48 config.add_route(
49 name='edit_user_group',
50 pattern='/user_groups/{user_group_id:\d+}/edit',
51 user_group_route=True)
52
53 # user groups update
54 config.add_route(
55 name='user_groups_update',
56 pattern='/user_groups/{user_group_id:\d+}/update',
57 user_group_route=True)
58
59 config.add_route(
60 name='edit_user_group_global_perms',
61 pattern='/user_groups/{user_group_id:\d+}/edit/global_permissions',
62 user_group_route=True)
63
64 config.add_route(
65 name='edit_user_group_global_perms_update',
66 pattern='/user_groups/{user_group_id:\d+}/edit/global_permissions/update',
67 user_group_route=True)
68
69 config.add_route(
70 name='edit_user_group_perms',
71 pattern='/user_groups/{user_group_id:\d+}/edit/permissions',
72 user_group_route=True)
73
74 config.add_route(
75 name='edit_user_group_perms_update',
76 pattern='/user_groups/{user_group_id:\d+}/edit/permissions/update',
77 user_group_route=True)
78
79 config.add_route(
80 name='edit_user_group_advanced',
81 pattern='/user_groups/{user_group_id:\d+}/edit/advanced',
82 user_group_route=True)
83
84 config.add_route(
85 name='edit_user_group_advanced_sync',
86 pattern='/user_groups/{user_group_id:\d+}/edit/advanced/sync',
87 user_group_route=True)
88
89 # user groups delete
90 config.add_route(
91 name='user_groups_delete',
92 pattern='/user_groups/{user_group_id:\d+}/delete',
93 user_group_route=True)
94
95
96 def includeme(config):
97 # main admin routes
98 config.include(admin_routes, route_prefix=ADMIN_PREFIX)
99
100 # Scan module for configuration decorators.
101 config.scan('.views', ignore='.tests')
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/\
This diff has been collapsed as it changes many lines, (529 lines changed) Show them Hide them
@@ -0,0 +1,529 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 import peppercorn
24 import formencode
25 import formencode.htmlfill
26 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
28 from pyramid.response import Response
29 from pyramid.renderers import render
30
31 from rhodecode.lib.exceptions import (
32 RepoGroupAssignmentError, UserGroupAssignedException)
33 from rhodecode.model.forms import (
34 UserGroupPermsForm, UserGroupForm, UserIndividualPermissionsForm,
35 UserPermissionsForm)
36 from rhodecode.model.permission import PermissionModel
37
38 from rhodecode.apps._base import UserGroupAppView
39 from rhodecode.lib.auth import (
40 LoginRequired, HasUserGroupPermissionAnyDecorator, CSRFRequired)
41 from rhodecode.lib import helpers as h, audit_logger
42 from rhodecode.lib.utils2 import str2bool
43 from rhodecode.model.db import (
44 joinedload, User, UserGroupRepoToPerm, UserGroupRepoGroupToPerm)
45 from rhodecode.model.meta import Session
46 from rhodecode.model.user_group import UserGroupModel
47
48 log = logging.getLogger(__name__)
49
50
51 class UserGroupsView(UserGroupAppView):
52
53 def load_default_context(self):
54 c = self._get_local_tmpl_context()
55
56 PermissionModel().set_global_permission_choices(
57 c, gettext_translator=self.request.translate)
58
59 self._register_global_c(c)
60 return c
61
62 def _get_perms_summary(self, user_group_id):
63 permissions = {
64 'repositories': {},
65 'repositories_groups': {},
66 }
67 ugroup_repo_perms = UserGroupRepoToPerm.query()\
68 .options(joinedload(UserGroupRepoToPerm.permission))\
69 .options(joinedload(UserGroupRepoToPerm.repository))\
70 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
71 .all()
72
73 for gr in ugroup_repo_perms:
74 permissions['repositories'][gr.repository.repo_name] \
75 = gr.permission.permission_name
76
77 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
78 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
79 .options(joinedload(UserGroupRepoGroupToPerm.group))\
80 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
81 .all()
82
83 for gr in ugroup_group_perms:
84 permissions['repositories_groups'][gr.group.group_name] \
85 = gr.permission.permission_name
86 return permissions
87
88 @LoginRequired()
89 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
90 @view_config(
91 route_name='user_group_members_data', request_method='GET',
92 renderer='json_ext', xhr=True)
93 def user_group_members(self):
94 """
95 Return members of given user group
96 """
97 user_group = self.db_user_group
98 group_members_obj = sorted((x.user for x in user_group.members),
99 key=lambda u: u.username.lower())
100
101 group_members = [
102 {
103 'id': user.user_id,
104 'first_name': user.first_name,
105 'last_name': user.last_name,
106 'username': user.username,
107 'icon_link': h.gravatar_url(user.email, 30),
108 'value_display': h.person(user.email),
109 'value': user.username,
110 'value_type': 'user',
111 'active': user.active,
112 }
113 for user in group_members_obj
114 ]
115
116 return {
117 'members': group_members
118 }
119
120 @LoginRequired()
121 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
122 @view_config(
123 route_name='edit_user_group_perms_summary', request_method='GET',
124 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
125 def user_group_perms_summary(self):
126 c = self.load_default_context()
127 c.user_group = self.db_user_group
128 c.active = 'perms_summary'
129 c.permissions = self._get_perms_summary(c.user_group.users_group_id)
130 return self._get_template_context(c)
131
132 @LoginRequired()
133 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
134 @view_config(
135 route_name='edit_user_group_perms_summary_json', request_method='GET',
136 renderer='json_ext')
137 def user_group_perms_summary_json(self):
138 self.load_default_context()
139 user_group = self.db_user_group
140 return self._get_perms_summary(user_group.users_group_id)
141
142 def _revoke_perms_on_yourself(self, form_result):
143 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
144 form_result['perm_updates'])
145 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
146 form_result['perm_additions'])
147 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
148 form_result['perm_deletions'])
149 admin_perm = 'usergroup.admin'
150 if _updates and _updates[0][1] != admin_perm or \
151 _additions and _additions[0][1] != admin_perm or \
152 _deletions and _deletions[0][1] != admin_perm:
153 return True
154 return False
155
156 @LoginRequired()
157 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
158 @CSRFRequired()
159 @view_config(
160 route_name='user_groups_update', request_method='POST',
161 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
162 def user_group_update(self):
163 _ = self.request.translate
164
165 user_group = self.db_user_group
166 user_group_id = user_group.users_group_id
167
168 c = self.load_default_context()
169 c.user_group = user_group
170 c.group_members_obj = [x.user for x in c.user_group.members]
171 c.group_members_obj.sort(key=lambda u: u.username.lower())
172 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
173 c.active = 'settings'
174
175 users_group_form = UserGroupForm(
176 edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
177
178 old_values = c.user_group.get_api_data()
179 user_group_name = self.request.POST.get('users_group_name')
180 try:
181 form_result = users_group_form.to_python(self.request.POST)
182 pstruct = peppercorn.parse(self.request.POST.items())
183 form_result['users_group_members'] = pstruct['user_group_members']
184
185 user_group, added_members, removed_members = \
186 UserGroupModel().update(c.user_group, form_result)
187 updated_user_group = form_result['users_group_name']
188
189 audit_logger.store_web(
190 'user_group.edit', action_data={'old_data': old_values},
191 user=self._rhodecode_user)
192
193 # TODO(marcink): use added/removed to set user_group.edit.member.add
194
195 h.flash(_('Updated user group %s') % updated_user_group,
196 category='success')
197 Session().commit()
198 except formencode.Invalid as errors:
199 defaults = errors.value
200 e = errors.error_dict or {}
201
202 data = render(
203 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
204 self._get_template_context(c), self.request)
205 html = formencode.htmlfill.render(
206 data,
207 defaults=defaults,
208 errors=e,
209 prefix_error=False,
210 encoding="UTF-8",
211 force_defaults=False
212 )
213 return Response(html)
214
215 except Exception:
216 log.exception("Exception during update of user group")
217 h.flash(_('Error occurred during update of user group %s')
218 % user_group_name, category='error')
219
220 raise HTTPFound(
221 h.route_path('edit_user_group', user_group_id=user_group_id))
222
223 @LoginRequired()
224 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
225 @CSRFRequired()
226 @view_config(
227 route_name='user_groups_delete', request_method='POST',
228 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
229 def user_group_delete(self):
230 _ = self.request.translate
231 user_group = self.db_user_group
232
233 self.load_default_context()
234 force = str2bool(self.request.POST.get('force'))
235
236 old_values = user_group.get_api_data()
237 try:
238 UserGroupModel().delete(user_group, force=force)
239 audit_logger.store_web(
240 'user.delete', action_data={'old_data': old_values},
241 user=self._rhodecode_user)
242 Session().commit()
243 h.flash(_('Successfully deleted user group'), category='success')
244 except UserGroupAssignedException as e:
245 h.flash(str(e), category='error')
246 except Exception:
247 log.exception("Exception during deletion of user group")
248 h.flash(_('An error occurred during deletion of user group'),
249 category='error')
250 raise HTTPFound(h.route_path('user_groups'))
251
252 @LoginRequired()
253 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
254 @view_config(
255 route_name='edit_user_group', request_method='GET',
256 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
257 def user_group_edit(self):
258 user_group = self.db_user_group
259
260 c = self.load_default_context()
261 c.user_group = user_group
262 c.group_members_obj = [x.user for x in c.user_group.members]
263 c.group_members_obj.sort(key=lambda u: u.username.lower())
264 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
265
266 c.active = 'settings'
267
268 defaults = user_group.get_dict()
269 # fill owner
270 if user_group.user:
271 defaults.update({'user': user_group.user.username})
272 else:
273 replacement_user = User.get_first_super_admin().username
274 defaults.update({'user': replacement_user})
275
276 data = render(
277 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
278 self._get_template_context(c), self.request)
279 html = formencode.htmlfill.render(
280 data,
281 defaults=defaults,
282 encoding="UTF-8",
283 force_defaults=False
284 )
285 return Response(html)
286
287 @LoginRequired()
288 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
289 @view_config(
290 route_name='edit_user_group_perms', request_method='GET',
291 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
292 def user_group_edit_perms(self):
293 user_group = self.db_user_group
294 c = self.load_default_context()
295 c.user_group = user_group
296 c.active = 'perms'
297
298 defaults = {}
299 # fill user group users
300 for p in c.user_group.user_user_group_to_perm:
301 defaults.update({'u_perm_%s' % p.user.user_id:
302 p.permission.permission_name})
303
304 for p in c.user_group.user_group_user_group_to_perm:
305 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
306 p.permission.permission_name})
307
308 data = render(
309 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
310 self._get_template_context(c), self.request)
311 html = formencode.htmlfill.render(
312 data,
313 defaults=defaults,
314 encoding="UTF-8",
315 force_defaults=False
316 )
317 return Response(html)
318
319 @LoginRequired()
320 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
321 @CSRFRequired()
322 @view_config(
323 route_name='edit_user_group_perms_update', request_method='POST',
324 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
325 def user_group_update_perms(self):
326 """
327 grant permission for given user group
328 """
329 _ = self.request.translate
330
331 user_group = self.db_user_group
332 user_group_id = user_group.users_group_id
333 c = self.load_default_context()
334 c.user_group = user_group
335 form = UserGroupPermsForm()().to_python(self.request.POST)
336
337 if not self._rhodecode_user.is_admin:
338 if self._revoke_perms_on_yourself(form):
339 msg = _('Cannot change permission for yourself as admin')
340 h.flash(msg, category='warning')
341 raise HTTPFound(
342 h.route_path('edit_user_group_perms',
343 user_group_id=user_group_id))
344
345 try:
346 changes = UserGroupModel().update_permissions(
347 user_group_id,
348 form['perm_additions'], form['perm_updates'],
349 form['perm_deletions'])
350
351 except RepoGroupAssignmentError:
352 h.flash(_('Target group cannot be the same'), category='error')
353 raise HTTPFound(
354 h.route_path('edit_user_group_perms',
355 user_group_id=user_group_id))
356
357 action_data = {
358 'added': changes['added'],
359 'updated': changes['updated'],
360 'deleted': changes['deleted'],
361 }
362 audit_logger.store_web(
363 'user_group.edit.permissions', action_data=action_data,
364 user=self._rhodecode_user)
365
366 Session().commit()
367 h.flash(_('User Group permissions updated'), category='success')
368 raise HTTPFound(
369 h.route_path('edit_user_group_perms', user_group_id=user_group_id))
370
371 @LoginRequired()
372 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
373 @view_config(
374 route_name='edit_user_group_global_perms', request_method='GET',
375 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
376 def user_group_global_perms_edit(self):
377 user_group = self.db_user_group
378 c = self.load_default_context()
379 c.user_group = user_group
380 c.active = 'global_perms'
381
382 c.default_user = User.get_default_user()
383 defaults = c.user_group.get_dict()
384 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
385 defaults.update(c.user_group.get_default_perms())
386
387 data = render(
388 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
389 self._get_template_context(c), self.request)
390 html = formencode.htmlfill.render(
391 data,
392 defaults=defaults,
393 encoding="UTF-8",
394 force_defaults=False
395 )
396 return Response(html)
397
398 @LoginRequired()
399 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
400 @CSRFRequired()
401 @view_config(
402 route_name='edit_user_group_global_perms_update', request_method='POST',
403 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
404 def user_group_global_perms_update(self):
405 _ = self.request.translate
406 user_group = self.db_user_group
407 user_group_id = self.db_user_group.users_group_id
408
409 c = self.load_default_context()
410 c.user_group = user_group
411 c.active = 'global_perms'
412
413 try:
414 # first stage that verifies the checkbox
415 _form = UserIndividualPermissionsForm()
416 form_result = _form.to_python(dict(self.request.POST))
417 inherit_perms = form_result['inherit_default_permissions']
418 user_group.inherit_default_permissions = inherit_perms
419 Session().add(user_group)
420
421 if not inherit_perms:
422 # only update the individual ones if we un check the flag
423 _form = UserPermissionsForm(
424 [x[0] for x in c.repo_create_choices],
425 [x[0] for x in c.repo_create_on_write_choices],
426 [x[0] for x in c.repo_group_create_choices],
427 [x[0] for x in c.user_group_create_choices],
428 [x[0] for x in c.fork_choices],
429 [x[0] for x in c.inherit_default_permission_choices])()
430
431 form_result = _form.to_python(dict(self.request.POST))
432 form_result.update(
433 {'perm_user_group_id': user_group.users_group_id})
434
435 PermissionModel().update_user_group_permissions(form_result)
436
437 Session().commit()
438 h.flash(_('User Group global permissions updated successfully'),
439 category='success')
440
441 except formencode.Invalid as errors:
442 defaults = errors.value
443
444 data = render(
445 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
446 self._get_template_context(c), self.request)
447 html = formencode.htmlfill.render(
448 data,
449 defaults=defaults,
450 errors=errors.error_dict or {},
451 prefix_error=False,
452 encoding="UTF-8",
453 force_defaults=False
454 )
455 return Response(html)
456 except Exception:
457 log.exception("Exception during permissions saving")
458 h.flash(_('An error occurred during permissions saving'),
459 category='error')
460
461 raise HTTPFound(
462 h.route_path('edit_user_group_global_perms',
463 user_group_id=user_group_id))
464
465 @LoginRequired()
466 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
467 @view_config(
468 route_name='edit_user_group_advanced', request_method='GET',
469 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
470 def user_group_edit_advanced(self):
471 user_group = self.db_user_group
472
473 c = self.load_default_context()
474 c.user_group = user_group
475 c.active = 'advanced'
476 c.group_members_obj = sorted(
477 (x.user for x in c.user_group.members),
478 key=lambda u: u.username.lower())
479
480 c.group_to_repos = sorted(
481 (x.repository for x in c.user_group.users_group_repo_to_perm),
482 key=lambda u: u.repo_name.lower())
483
484 c.group_to_repo_groups = sorted(
485 (x.group for x in c.user_group.users_group_repo_group_to_perm),
486 key=lambda u: u.group_name.lower())
487
488 c.group_to_review_rules = sorted(
489 (x.users_group for x in c.user_group.user_group_review_rules),
490 key=lambda u: u.users_group_name.lower())
491
492 return self._get_template_context(c)
493
494 @LoginRequired()
495 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
496 @CSRFRequired()
497 @view_config(
498 route_name='edit_user_group_advanced_sync', request_method='POST',
499 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
500 def user_group_edit_advanced_set_synchronization(self):
501 _ = self.request.translate
502 user_group = self.db_user_group
503 user_group_id = user_group.users_group_id
504
505 existing = user_group.group_data.get('extern_type')
506
507 if existing:
508 new_state = user_group.group_data
509 new_state['extern_type'] = None
510 else:
511 new_state = user_group.group_data
512 new_state['extern_type'] = 'manual'
513 new_state['extern_type_set_by'] = self._rhodecode_user.username
514
515 try:
516 user_group.group_data = new_state
517 Session().add(user_group)
518 Session().commit()
519
520 h.flash(_('User Group synchronization updated successfully'),
521 category='success')
522 except Exception:
523 log.exception("Exception during sync settings saving")
524 h.flash(_('An error occurred during synchronization update'),
525 category='error')
526
527 raise HTTPFound(
528 h.route_path('edit_user_group_advanced',
529 user_group_id=user_group_id))
@@ -29,6 +29,7 b' from rhodecode.lib.utils2 import StrictA'
29 29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
30 30 from rhodecode.model import repo
31 31 from rhodecode.model import repo_group
32 from rhodecode.model import user_group
32 33 from rhodecode.model.db import User
33 34 from rhodecode.model.scm import ScmModel
34 35
@@ -259,6 +260,13 b' class RepoGroupAppView(BaseAppView):'
259 260 self.db_repo_group_name = self.db_repo_group.group_name
260 261
261 262
263 class UserGroupAppView(BaseAppView):
264 def __init__(self, context, request):
265 super(UserGroupAppView, self).__init__(context, request)
266 self.db_user_group = request.db_user_group
267 self.db_user_group_name = self.db_user_group.users_group_name
268
269
262 270 class DataGridAppView(object):
263 271 """
264 272 Common class to have re-usable grid rendering components
@@ -462,6 +470,33 b' class RepoGroupRoutePredicate(object):'
462 470 return False
463 471
464 472
473 class UserGroupRoutePredicate(object):
474 def __init__(self, val, config):
475 self.val = val
476
477 def text(self):
478 return 'user_group_route = %s' % self.val
479
480 phash = text
481
482 def __call__(self, info, request):
483 if hasattr(request, 'vcs_call'):
484 # skip vcs calls
485 return
486
487 user_group_id = info['match']['user_group_id']
488 user_group_model = user_group.UserGroup()
489 by_name_match = user_group_model.get(
490 user_group_id, cache=True)
491
492 if by_name_match:
493 # register this as request object we can re-use later
494 request.db_user_group = by_name_match
495 return True
496
497 return False
498
499
465 500 def includeme(config):
466 501 config.add_route_predicate(
467 502 'repo_route', RepoRoutePredicate)
@@ -469,3 +504,5 b' def includeme(config):'
469 504 'repo_accepted_types', RepoTypeRoutePredicate)
470 505 config.add_route_predicate(
471 506 'repo_group_route', RepoGroupRoutePredicate)
507 config.add_route_predicate(
508 'user_group_route', UserGroupRoutePredicate)
@@ -180,7 +180,7 b' def admin_routes(config):'
180 180 name='edit_user_perms_summary_json',
181 181 pattern='/users/{user_id:\d+}/edit/permissions_summary/json')
182 182
183 # user groups management
183 # user user groups management
184 184 config.add_route(
185 185 name='edit_user_groups_management',
186 186 pattern='/users/{user_id:\d+}/edit/groups_management')
@@ -194,7 +194,7 b' def admin_routes(config):'
194 194 name='edit_user_audit_logs',
195 195 pattern='/users/{user_id:\d+}/edit/audit')
196 196
197 # user groups admin
197 # user-groups admin
198 198 config.add_route(
199 199 name='user_groups',
200 200 pattern='/user_groups')
@@ -204,16 +204,12 b' def admin_routes(config):'
204 204 pattern='/user_groups_data')
205 205
206 206 config.add_route(
207 name='user_group_members_data',
208 pattern='/user_groups/{user_group_id:\d+}/members')
207 name='user_groups_new',
208 pattern='/user_groups/new')
209 209
210 # user groups perms
211 210 config.add_route(
212 name='edit_user_group_perms_summary',
213 pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary')
214 config.add_route(
215 name='edit_user_group_perms_summary_json',
216 pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary/json')
211 name='user_groups_create',
212 pattern='/user_groups/create')
217 213
218 214 # repos admin
219 215 config.add_route(
@@ -38,6 +38,9 b' def route_path(name, params=None, **kwar'
38 38 'user_groups': ADMIN_PREFIX + '/user_groups',
39 39 'user_groups_data': ADMIN_PREFIX + '/user_groups_data',
40 40 'user_group_members_data': ADMIN_PREFIX + '/user_groups/{user_group_id}/members',
41 'user_groups_new': ADMIN_PREFIX + '/user_groups/new',
42 'user_groups_create': ADMIN_PREFIX + '/user_groups/create',
43 'edit_user_group': ADMIN_PREFIX + '/user_groups/{user_group_id}/edit',
41 44 }[name].format(**kwargs)
42 45
43 46 if params:
@@ -107,7 +110,61 b' class TestAdminUserGroupsView(TestContro'
107 110 members = [u.user_id for u in User.get_all()]
108 111 ug = user_util.create_user_group(members=members)
109 112 response = self.app.get(
110 route_path('user_group_members_data', user_group_id=ug.users_group_id),
113 route_path('user_group_members_data',
114 user_group_id=ug.users_group_id),
111 115 extra_environ=xhr_header)
112 116
113 117 assert len(response.json['members']) == len(members)
118
119 def test_creation_page(self):
120 self.log_user()
121 self.app.get(route_path('user_groups_new'), status=200)
122
123 def test_create(self):
124 from rhodecode.lib import helpers as h
125
126 self.log_user()
127 users_group_name = 'test_user_group'
128 response = self.app.post(route_path('user_groups_create'), {
129 'users_group_name': users_group_name,
130 'user_group_description': 'DESC',
131 'active': True,
132 'csrf_token': self.csrf_token})
133
134 user_group_id = UserGroup.get_by_group_name(
135 users_group_name).users_group_id
136
137 user_group_link = h.link_to(
138 users_group_name,
139 route_path('edit_user_group', user_group_id=user_group_id))
140
141 assert_session_flash(
142 response,
143 'Created user group %s' % user_group_link)
144
145 fixture.destroy_user_group(users_group_name)
146
147 def test_create_with_empty_name(self):
148 self.log_user()
149
150 response = self.app.post(route_path('user_groups_create'), {
151 'users_group_name': '',
152 'user_group_description': 'DESC',
153 'active': True,
154 'csrf_token': self.csrf_token}, status=200)
155
156 response.mustcontain('Please enter a value')
157
158 def test_create_duplicate(self, user_util):
159 self.log_user()
160
161 user_group = user_util.create_user_group()
162 duplicate_name = user_group.users_group_name
163 response = self.app.post(route_path('user_groups_create'), {
164 'users_group_name': duplicate_name,
165 'user_group_description': 'DESC',
166 'active': True,
167 'csrf_token': self.csrf_token}, status=200)
168
169 response.mustcontain(
170 'User group `{}` already exists'.format(user_group.users_group_name))
@@ -20,22 +20,28 b''
20 20
21 21 import logging
22 22
23 import formencode
24 import formencode.htmlfill
25
23 26 from pyramid.httpexceptions import HTTPFound
24 27 from pyramid.view import view_config
25
26 from rhodecode.model.scm import UserGroupList
28 from pyramid.response import Response
29 from pyramid.renderers import render
27 30
28 31 from rhodecode.apps._base import BaseAppView, DataGridAppView
29 32 from rhodecode.lib.auth import (
30 LoginRequired, NotAnonymous,
31 HasUserGroupPermissionAnyDecorator)
32 from rhodecode.lib import helpers as h
33 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
34 from rhodecode.lib import helpers as h, audit_logger
33 35 from rhodecode.lib.utils import PartialRenderer
34 36 from rhodecode.lib.utils2 import safe_unicode
37
38 from rhodecode.model.forms import UserGroupForm
39 from rhodecode.model.permission import PermissionModel
40 from rhodecode.model.scm import UserGroupList
35 41 from rhodecode.model.db import (
36 joinedload, or_, count, User, UserGroup, UserGroupMember,
37 UserGroupRepoToPerm, UserGroupRepoGroupToPerm)
42 or_, count, User, UserGroup, UserGroupMember)
38 43 from rhodecode.model.meta import Session
44 from rhodecode.model.user_group import UserGroupModel
39 45
40 46 log = logging.getLogger(__name__)
41 47
@@ -44,6 +50,10 b' class AdminUserGroupsView(BaseAppView, D'
44 50
45 51 def load_default_context(self):
46 52 c = self._get_local_tmpl_context()
53
54 PermissionModel().set_global_permission_choices(
55 c, gettext_translator=self.request.translate)
56
47 57 self._register_global_c(c)
48 58 return c
49 59
@@ -168,89 +178,70 b' class AdminUserGroupsView(BaseAppView, D'
168 178 return data
169 179
170 180 @LoginRequired()
171 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
181 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
172 182 @view_config(
173 route_name='user_group_members_data', request_method='GET',
174 renderer='json_ext', xhr=True)
175 def user_group_members(self):
176 """
177 Return members of given user group
178 """
179 user_group_id = self.request.matchdict['user_group_id']
180 user_group = UserGroup.get_or_404(user_group_id)
181 group_members_obj = sorted((x.user for x in user_group.members),
182 key=lambda u: u.username.lower())
183
184 group_members = [
185 {
186 'id': user.user_id,
187 'first_name': user.first_name,
188 'last_name': user.last_name,
189 'username': user.username,
190 'icon_link': h.gravatar_url(user.email, 30),
191 'value_display': h.person(user.email),
192 'value': user.username,
193 'value_type': 'user',
194 'active': user.active,
195 }
196 for user in group_members_obj
197 ]
198
199 return {
200 'members': group_members
201 }
202
203 def _get_perms_summary(self, user_group_id):
204 permissions = {
205 'repositories': {},
206 'repositories_groups': {},
207 }
208 ugroup_repo_perms = UserGroupRepoToPerm.query()\
209 .options(joinedload(UserGroupRepoToPerm.permission))\
210 .options(joinedload(UserGroupRepoToPerm.repository))\
211 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
212 .all()
213
214 for gr in ugroup_repo_perms:
215 permissions['repositories'][gr.repository.repo_name] \
216 = gr.permission.permission_name
217
218 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
219 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
220 .options(joinedload(UserGroupRepoGroupToPerm.group))\
221 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
222 .all()
223
224 for gr in ugroup_group_perms:
225 permissions['repositories_groups'][gr.group.group_name] \
226 = gr.permission.permission_name
227 return permissions
228
229 @LoginRequired()
230 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
231 @view_config(
232 route_name='edit_user_group_perms_summary', request_method='GET',
233 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
234 def user_group_perms_summary(self):
183 route_name='user_groups_new', request_method='GET',
184 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
185 def user_groups_new(self):
235 186 c = self.load_default_context()
236
237 user_group_id = self.request.matchdict.get('user_group_id')
238 c.user_group = UserGroup.get_or_404(user_group_id)
239
240 c.active = 'perms_summary'
241
242 c.permissions = self._get_perms_summary(c.user_group.users_group_id)
243 187 return self._get_template_context(c)
244 188
245 189 @LoginRequired()
246 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
190 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
191 @CSRFRequired()
247 192 @view_config(
248 route_name='edit_user_group_perms_summary_json', request_method='GET',
249 renderer='json_ext')
250 def user_group_perms_summary_json(self):
251 self.load_default_context()
193 route_name='user_groups_create', request_method='POST',
194 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
195 def user_groups_create(self):
196 _ = self.request.translate
197 c = self.load_default_context()
198 users_group_form = UserGroupForm()()
199
200 user_group_name = self.request.POST.get('users_group_name')
201 try:
202 form_result = users_group_form.to_python(dict(self.request.POST))
203 user_group = UserGroupModel().create(
204 name=form_result['users_group_name'],
205 description=form_result['user_group_description'],
206 owner=self._rhodecode_user.user_id,
207 active=form_result['users_group_active'])
208 Session().flush()
209 creation_data = user_group.get_api_data()
210 user_group_name = form_result['users_group_name']
211
212 audit_logger.store_web(
213 'user_group.create', action_data={'data': creation_data},
214 user=self._rhodecode_user)
252 215
253 user_group_id = self.request.matchdict.get('user_group_id')
254 user_group = UserGroup.get_or_404(user_group_id)
216 user_group_link = h.link_to(
217 h.escape(user_group_name),
218 h.route_path(
219 'edit_user_group', user_group_id=user_group.users_group_id))
220 h.flash(h.literal(_('Created user group %(user_group_link)s')
221 % {'user_group_link': user_group_link}),
222 category='success')
223 Session().commit()
224 user_group_id = user_group.users_group_id
225 except formencode.Invalid as errors:
255 226
256 return self._get_perms_summary(user_group.users_group_id)
227 data = render(
228 'rhodecode:templates/admin/user_groups/user_group_add.mako',
229 self._get_template_context(c), self.request)
230 html = formencode.htmlfill.render(
231 data,
232 defaults=errors.value,
233 errors=errors.error_dict or {},
234 prefix_error=False,
235 encoding="UTF-8",
236 force_defaults=False
237 )
238 return Response(html)
239
240 except Exception:
241 log.exception("Exception creating user group")
242 h.flash(_('Error occurred during creation of user group %s') \
243 % user_group_name, category='error')
244 raise HTTPFound(h.route_path('user_groups_new'))
245
246 raise HTTPFound(
247 h.route_path('edit_user_group', user_group_id=user_group_id))
@@ -21,98 +21,83 b''
21 21 import pytest
22 22
23 23 from rhodecode.tests import (
24 TestController, url, assert_session_flash, link_to, TEST_USER_ADMIN_LOGIN)
25 from rhodecode.model.db import User, UserGroup
24 TestController, assert_session_flash, TEST_USER_ADMIN_LOGIN)
25 from rhodecode.model.db import UserGroup
26 26 from rhodecode.model.meta import Session
27 27 from rhodecode.tests.fixture import Fixture
28 28
29 TEST_USER_GROUP = 'admins_test'
30
31 29 fixture = Fixture()
32 30
33 31
34 class TestAdminUsersGroupsController(TestController):
35
36 def test_create(self):
37 self.log_user()
38 users_group_name = TEST_USER_GROUP
39 response = self.app.post(url('users_groups'), {
40 'users_group_name': users_group_name,
41 'user_group_description': 'DESC',
42 'active': True,
43 'csrf_token': self.csrf_token})
32 def route_path(name, params=None, **kwargs):
33 import urllib
34 from rhodecode.apps._base import ADMIN_PREFIX
44 35
45 user_group_link = link_to(
46 users_group_name,
47 url('edit_users_group',
48 user_group_id=UserGroup.get_by_group_name(
49 users_group_name).users_group_id))
50 assert_session_flash(
51 response,
52 'Created user group %s' % user_group_link)
36 base_url = {
37 'user_groups': ADMIN_PREFIX + '/user_groups',
38 'user_groups_data': ADMIN_PREFIX + '/user_groups_data',
39 'user_group_members_data': ADMIN_PREFIX + '/user_groups/{user_group_id}/members',
40 'user_groups_new': ADMIN_PREFIX + '/user_groups/new',
41 'user_groups_create': ADMIN_PREFIX + '/user_groups/create',
42 'edit_user_group': ADMIN_PREFIX + '/user_groups/{user_group_id}/edit',
43 'edit_user_group_advanced_sync': ADMIN_PREFIX + '/user_groups/{user_group_id}/edit/advanced/sync',
44 'edit_user_group_global_perms_update': ADMIN_PREFIX + '/user_groups/{user_group_id}/edit/global_permissions/update',
45 'user_groups_update': ADMIN_PREFIX + '/user_groups/{user_group_id}/update',
46 'user_groups_delete': ADMIN_PREFIX + '/user_groups/{user_group_id}/delete',
53 47
54 def test_set_synchronization(self):
48 }[name].format(**kwargs)
49
50 if params:
51 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
52 return base_url
53
54
55 class TestUserGroupsView(TestController):
56
57 def test_set_synchronization(self, user_util):
55 58 self.log_user()
56 users_group_name = TEST_USER_GROUP + 'sync'
57 response = self.app.post(url('users_groups'), {
58 'users_group_name': users_group_name,
59 'user_group_description': 'DESC',
60 'active': True,
61 'csrf_token': self.csrf_token})
59 user_group_name = user_util.create_user_group().users_group_name
62 60
63 61 group = Session().query(UserGroup).filter(
64 UserGroup.users_group_name == users_group_name).one()
62 UserGroup.users_group_name == user_group_name).one()
65 63
66 64 assert group.group_data.get('extern_type') is None
67 65
68 66 # enable
69 67 self.app.post(
70 url('edit_user_group_advanced_sync', user_group_id=group.users_group_id),
68 route_path('edit_user_group_advanced_sync',
69 user_group_id=group.users_group_id),
71 70 params={'csrf_token': self.csrf_token}, status=302)
72 71
73 72 group = Session().query(UserGroup).filter(
74 UserGroup.users_group_name == users_group_name).one()
73 UserGroup.users_group_name == user_group_name).one()
75 74 assert group.group_data.get('extern_type') == 'manual'
76 75 assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN
77 76
78 77 # disable
79 78 self.app.post(
80 url('edit_user_group_advanced_sync',
79 route_path('edit_user_group_advanced_sync',
81 80 user_group_id=group.users_group_id),
82 81 params={'csrf_token': self.csrf_token}, status=302)
83 82
84 83 group = Session().query(UserGroup).filter(
85 UserGroup.users_group_name == users_group_name).one()
84 UserGroup.users_group_name == user_group_name).one()
86 85 assert group.group_data.get('extern_type') is None
87 86 assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN
88 87
89 def test_delete(self):
88 def test_delete_user_group(self, user_util):
90 89 self.log_user()
91 users_group_name = TEST_USER_GROUP + 'another'
92 response = self.app.post(url('users_groups'), {
93 'users_group_name': users_group_name,
94 'user_group_description': 'DESC',
95 'active': True,
96 'csrf_token': self.csrf_token})
97
98 user_group_link = link_to(
99 users_group_name,
100 url('edit_users_group',
101 user_group_id=UserGroup.get_by_group_name(
102 users_group_name).users_group_id))
103 assert_session_flash(
104 response,
105 'Created user group %s' % user_group_link)
90 user_group_id = user_util.create_user_group().users_group_id
106 91
107 92 group = Session().query(UserGroup).filter(
108 UserGroup.users_group_name == users_group_name).one()
93 UserGroup.users_group_id == user_group_id).one()
109 94
110 95 self.app.post(
111 url('delete_users_group', user_group_id=group.users_group_id),
112 params={'_method': 'delete', 'csrf_token': self.csrf_token})
96 route_path('user_groups_delete', user_group_id=group.users_group_id),
97 params={'csrf_token': self.csrf_token})
113 98
114 99 group = Session().query(UserGroup).filter(
115 UserGroup.users_group_name == users_group_name).scalar()
100 UserGroup.users_group_id == user_group_id).scalar()
116 101
117 102 assert group is None
118 103
@@ -122,26 +107,16 b' class TestAdminUsersGroupsController(Tes'
122 107 ('hg.create.XXX', 'hg.create.write_on_repogroup.true', 'hg.usergroup.create.true', 'hg.repogroup.create.true', 'hg.fork.repository', 'hg.inherit_default_perms.false', False, True),
123 108 ('', '', '', '', '', '', True, False),
124 109 ])
125 def test_global_perms_on_group(
110 def test_global_permissions_on_user_group(
126 111 self, repo_create, repo_create_write, user_group_create,
127 112 repo_group_create, fork_create, expect_error, expect_form_error,
128 inherit_default_permissions):
129 self.log_user()
130 users_group_name = TEST_USER_GROUP + 'another2'
131 response = self.app.post(url('users_groups'),
132 {'users_group_name': users_group_name,
133 'user_group_description': 'DESC',
134 'active': True,
135 'csrf_token': self.csrf_token})
113 inherit_default_permissions, user_util):
136 114
137 ug = UserGroup.get_by_group_name(users_group_name)
138 user_group_link = link_to(
139 users_group_name,
140 url('edit_users_group', user_group_id=ug.users_group_id))
141 assert_session_flash(
142 response,
143 'Created user group %s' % user_group_link)
144 response.follow()
115 self.log_user()
116 user_group = user_util.create_user_group()
117
118 user_group_name = user_group.users_group_name
119 user_group_id = user_group.users_group_id
145 120
146 121 # ENABLE REPO CREATE ON A GROUP
147 122 perm_params = {
@@ -153,12 +128,11 b' class TestAdminUsersGroupsController(Tes'
153 128 'default_fork_create': fork_create,
154 129 'default_inherit_default_permissions': inherit_default_permissions,
155 130
156 '_method': 'put',
157 131 'csrf_token': self.csrf_token,
158 132 }
159 133 response = self.app.post(
160 url('edit_user_group_global_perms',
161 user_group_id=ug.users_group_id),
134 route_path('edit_user_group_global_perms_update',
135 user_group_id=user_group_id),
162 136 params=perm_params)
163 137
164 138 if expect_form_error:
@@ -169,21 +143,76 b' class TestAdminUsersGroupsController(Tes'
169 143 msg = 'An error occurred during permissions saving'
170 144 else:
171 145 msg = 'User Group global permissions updated successfully'
172 ug = UserGroup.get_by_group_name(users_group_name)
173 del perm_params['_method']
146 ug = UserGroup.get_by_group_name(user_group_name)
174 147 del perm_params['csrf_token']
175 148 del perm_params['inherit_default_permissions']
176 149 assert perm_params == ug.get_default_perms()
177 150 assert_session_flash(response, msg)
178 151
179 fixture.destroy_user_group(users_group_name)
180
181 def test_edit_autocomplete(self):
152 def test_edit_view(self, user_util):
182 153 self.log_user()
183 ug = fixture.create_user_group(TEST_USER_GROUP, skip_if_exists=True)
184 response = self.app.get(
185 url('edit_users_group', user_group_id=ug.users_group_id))
186 fixture.destroy_user_group(TEST_USER_GROUP)
154
155 user_group = user_util.create_user_group()
156 self.app.get(
157 route_path('edit_user_group',
158 user_group_id=user_group.users_group_id),
159 status=200)
160
161 def test_update_user_group(self, user_util):
162 user = self.log_user()
163
164 user_group = user_util.create_user_group()
165 users_group_id = user_group.users_group_id
166 new_name = user_group.users_group_name + '_CHANGE'
167
168 params = [
169 ('users_group_active', False),
170 ('user_group_description', 'DESC'),
171 ('users_group_name', new_name),
172 ('user', user['username']),
173 ('csrf_token', self.csrf_token),
174 ('__start__', 'user_group_members:sequence'),
175 ('__start__', 'member:mapping'),
176 ('member_user_id', user['user_id']),
177 ('type', 'existing'),
178 ('__end__', 'member:mapping'),
179 ('__end__', 'user_group_members:sequence'),
180 ]
181
182 self.app.post(
183 route_path('user_groups_update',
184 user_group_id=users_group_id),
185 params=params,
186 status=302)
187
188 user_group = UserGroup.get(users_group_id)
189 assert user_group
190
191 assert user_group.users_group_name == new_name
192 assert user_group.user_group_description == 'DESC'
193 assert user_group.users_group_active == False
194
195 def test_update_user_group_name_conflicts(self, user_util):
196 self.log_user()
197 user_group_old = user_util.create_user_group()
198 new_name = user_group_old.users_group_name
199
200 user_group = user_util.create_user_group()
201
202 params = dict(
203 users_group_active=False,
204 user_group_description='DESC',
205 users_group_name=new_name,
206 csrf_token=self.csrf_token)
207
208 response = self.app.post(
209 route_path('user_groups_update',
210 user_group_id=user_group.users_group_id),
211 params=params,
212 status=200)
213
214 response.mustcontain('User group `{}` already exists'.format(
215 new_name))
187 216
188 217 def test_update_members_from_user_ids(self, user_regular):
189 218 uid = user_regular.user_id
@@ -197,7 +226,6 b' class TestAdminUsersGroupsController(Tes'
197 226
198 227 form_data = [
199 228 ('csrf_token', self.csrf_token),
200 ('_method', 'put'),
201 229 ('user', username),
202 230 ('users_group_name', 'changed_name'),
203 231 ('users_group_active', expected_active_state),
@@ -211,7 +239,8 b' class TestAdminUsersGroupsController(Tes'
211 239 ('__end__', 'user_group_members:sequence'),
212 240 ]
213 241 ugid = user_group.users_group_id
214 self.app.post(url('update_users_group', user_group_id=ugid), form_data)
242 self.app.post(
243 route_path('user_groups_update', user_group_id=ugid), form_data)
215 244
216 245 user_group = UserGroup.get(ugid)
217 246 assert user_group
@@ -296,6 +296,7 b' def includeme(config):'
296 296 config.include('rhodecode.apps.journal')
297 297 config.include('rhodecode.apps.repository')
298 298 config.include('rhodecode.apps.repo_group')
299 config.include('rhodecode.apps.user_group')
299 300 config.include('rhodecode.apps.search')
300 301 config.include('rhodecode.apps.user_profile')
301 302 config.include('rhodecode.apps.my_account')
@@ -254,44 +254,6 b' def make_map(config):'
254 254 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
255 255 action='update_global_perms', conditions={'method': ['PUT']})
256 256
257 # ADMIN USER GROUPS REST ROUTES
258 with rmap.submapper(path_prefix=ADMIN_PREFIX,
259 controller='admin/user_groups') as m:
260 m.connect('users_groups', '/user_groups',
261 action='create', conditions={'method': ['POST']})
262 m.connect('new_users_group', '/user_groups/new',
263 action='new', conditions={'method': ['GET']})
264 m.connect('update_users_group', '/user_groups/{user_group_id}',
265 action='update', conditions={'method': ['PUT']})
266 m.connect('delete_users_group', '/user_groups/{user_group_id}',
267 action='delete', conditions={'method': ['DELETE']})
268 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
269 action='edit', conditions={'method': ['GET']},
270 function=check_user_group)
271
272 # EXTRAS USER GROUP ROUTES
273 m.connect('edit_user_group_global_perms',
274 '/user_groups/{user_group_id}/edit/global_permissions',
275 action='edit_global_perms', conditions={'method': ['GET']})
276 m.connect('edit_user_group_global_perms',
277 '/user_groups/{user_group_id}/edit/global_permissions',
278 action='update_global_perms', conditions={'method': ['PUT']})
279
280 m.connect('edit_user_group_perms',
281 '/user_groups/{user_group_id}/edit/permissions',
282 action='edit_perms', conditions={'method': ['GET']})
283 m.connect('edit_user_group_perms',
284 '/user_groups/{user_group_id}/edit/permissions',
285 action='update_perms', conditions={'method': ['PUT']})
286
287 m.connect('edit_user_group_advanced',
288 '/user_groups/{user_group_id}/edit/advanced',
289 action='edit_advanced', conditions={'method': ['GET']})
290
291 m.connect('edit_user_group_advanced_sync',
292 '/user_groups/{user_group_id}/edit/advanced/sync',
293 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
294
295 257 # ADMIN DEFAULTS REST ROUTES
296 258 with rmap.submapper(path_prefix=ADMIN_PREFIX,
297 259 controller='admin/defaults') as m:
@@ -1305,7 +1305,7 b' def get_csrf_token(session=None, force_n'
1305 1305 return session.get(csrf_token_key)
1306 1306
1307 1307
1308 def get_request(perm_class):
1308 def get_request(perm_class_instance):
1309 1309 from pyramid.threadlocal import get_current_request
1310 1310 pyramid_request = get_current_request()
1311 1311 if not pyramid_request:
@@ -378,7 +378,6 b' class UserGroup(Base, BaseModel):'
378 378 "get_user_%s" % group_name))
379 379 return gr.scalar()
380 380
381
382 381 @classmethod
383 382 def get(cls, users_group_id, cache=False):
384 383 users_group = cls.query()
@@ -390,13 +389,13 b' class UserGroup(Base, BaseModel):'
390 389 @classmethod
391 390 def create(cls, form_data):
392 391 try:
393 new_users_group = cls()
392 new_user_group = cls()
394 393 for k, v in form_data.items():
395 setattr(new_users_group, k, v)
394 setattr(new_user_group, k, v)
396 395
397 Session.add(new_users_group)
396 Session.add(new_user_group)
398 397 Session.commit()
399 return new_users_group
398 return new_user_group
400 399 except:
401 400 log.error(traceback.format_exc())
402 401 Session.rollback()
@@ -136,22 +136,29 b' def get_repo_group_slug(request):'
136 136
137 137
138 138 def get_user_group_slug(request):
139 if isinstance(request, Request) and getattr(request, 'matchdict', None):
140 # pyramid
141 _group = request.matchdict.get('user_group_id')
142 else:
143 _group = request.environ['pylons.routes_dict'].get('user_group_id')
139 _user_group = ''
140 if isinstance(request, Request):
141
142 if hasattr(request, 'db_user_group'):
143 _user_group = request.db_user_group.users_group_name
144 elif getattr(request, 'matchdict', None):
145 # pyramid
146 _user_group = request.matchdict.get('user_group_id')
144 147
145 try:
146 _group = UserGroup.get(_group)
147 if _group:
148 _group = _group.users_group_name
149 except Exception:
150 log.exception('Failed to get user group by id')
151 # catch all failures here
152 return None
148 try:
149 _user_group = UserGroup.get(_user_group)
150 if _user_group:
151 _user_group = _user_group.users_group_name
152 except Exception:
153 log.exception('Failed to get user group by id')
154 # catch all failures here
155 return None
153 156
154 return _group
157 # TODO(marcink): remove after pylons migration...
158 if not _user_group:
159 _user_group = request.environ['pylons.routes_dict'].get('user_group_id')
160
161 return _user_group
155 162
156 163
157 164 def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
@@ -68,8 +68,8 b' class RepositoryPermissionModel(BaseMode'
68 68 .filter(UserGroupRepoToPerm.repository == repository) \
69 69 .scalar()
70 70
71 def update_users_group_permission(self, repository, users_group,
72 permission):
71 def update_user_group_permission(self, repository, users_group,
72 permission):
73 73 permission = Permission.get_by_key(permission)
74 74 current = self.get_users_group_permission(repository, users_group)
75 75 if current:
@@ -96,7 +96,7 b' class RepositoryPermissionModel(BaseMode'
96 96 def update_or_delete_users_group_permission(self, repository, user_group,
97 97 permission):
98 98 if permission:
99 self.update_users_group_permission(repository, user_group,
99 self.update_user_group_permission(repository, user_group,
100 100 permission)
101 101 else:
102 102 self.delete_users_group_permission(repository, user_group)
@@ -18,12 +18,6 b''
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
22 """
23 user group model for RhodeCode
24 """
25
26
27 21 import logging
28 22 import traceback
29 23
@@ -67,8 +61,10 b' class UserGroupModel(BaseModel):'
67 61 user_group_to_perm.user_id = def_user.user_id
68 62 return user_group_to_perm
69 63
70 def update_permissions(self, user_group, perm_additions=None, perm_updates=None,
71 perm_deletions=None, check_perms=True, cur_user=None):
64 def update_permissions(
65 self, user_group, perm_additions=None, perm_updates=None,
66 perm_deletions=None, check_perms=True, cur_user=None):
67
72 68 from rhodecode.lib.auth import HasUserGroupPermissionAny
73 69 if not perm_additions:
74 70 perm_additions = []
@@ -79,10 +75,16 b' class UserGroupModel(BaseModel):'
79 75
80 76 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
81 77
78 changes = {
79 'added': [],
80 'updated': [],
81 'deleted': []
82 }
82 83 # update permissions
83 84 for member_id, perm, member_type in perm_updates:
84 85 member_id = int(member_id)
85 86 if member_type == 'user':
87 member_name = User.get(member_id).username
86 88 # this updates existing one
87 89 self.grant_user_permission(
88 90 user_group=user_group, user=member_id, perm=perm
@@ -90,38 +92,49 b' class UserGroupModel(BaseModel):'
90 92 else:
91 93 # check if we have permissions to alter this usergroup
92 94 member_name = UserGroup.get(member_id).users_group_name
93 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
95 if not check_perms or HasUserGroupPermissionAny(
96 *req_perms)(member_name, user=cur_user):
94 97 self.grant_user_group_permission(
95 target_user_group=user_group, user_group=member_id, perm=perm
96 )
98 target_user_group=user_group, user_group=member_id, perm=perm)
99
100 changes['updated'].append({'type': member_type, 'id': member_id,
101 'name': member_name, 'new_perm': perm})
97 102
98 103 # set new permissions
99 104 for member_id, perm, member_type in perm_additions:
100 105 member_id = int(member_id)
101 106 if member_type == 'user':
107 member_name = User.get(member_id).username
102 108 self.grant_user_permission(
103 user_group=user_group, user=member_id, perm=perm
104 )
109 user_group=user_group, user=member_id, perm=perm)
105 110 else:
106 111 # check if we have permissions to alter this usergroup
107 112 member_name = UserGroup.get(member_id).users_group_name
108 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
113 if not check_perms or HasUserGroupPermissionAny(
114 *req_perms)(member_name, user=cur_user):
109 115 self.grant_user_group_permission(
110 target_user_group=user_group, user_group=member_id, perm=perm
111 )
116 target_user_group=user_group, user_group=member_id, perm=perm)
117
118 changes['added'].append({'type': member_type, 'id': member_id,
119 'name': member_name, 'new_perm': perm})
112 120
113 121 # delete permissions
114 122 for member_id, perm, member_type in perm_deletions:
115 123 member_id = int(member_id)
116 124 if member_type == 'user':
125 member_name = User.get(member_id).username
117 126 self.revoke_user_permission(user_group=user_group, user=member_id)
118 127 else:
119 128 # check if we have permissions to alter this usergroup
120 129 member_name = UserGroup.get(member_id).users_group_name
121 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
130 if not check_perms or HasUserGroupPermissionAny(
131 *req_perms)(member_name, user=cur_user):
122 132 self.revoke_user_group_permission(
123 target_user_group=user_group, user_group=member_id
124 )
133 target_user_group=user_group, user_group=member_id)
134
135 changes['deleted'].append({'type': member_type, 'id': member_id,
136 'name': member_name, 'new_perm': perm})
137 return changes
125 138
126 139 def get(self, user_group_id, cache=False):
127 140 return UserGroup.get(user_group_id)
@@ -247,6 +260,9 b' class UserGroupModel(BaseModel):'
247 260 :param force:
248 261 """
249 262 user_group = self._get_user_group(user_group)
263 if not user_group:
264 return
265
250 266 try:
251 267 # check if this group is not assigned to repo
252 268 assigned_to_repo = [x.repository for x in UserGroupRepoToPerm.query()\
@@ -527,7 +543,6 b' class UserGroupModel(BaseModel):'
527 543 This method changes user group assignment
528 544 :param user: User
529 545 :param groups: array of UserGroupModel
530 :return:
531 546 """
532 547 user = self._get_user(user)
533 548 log.debug('Changing user(%s) assignment to groups(%s)', user, groups)
@@ -542,11 +557,14 b' class UserGroupModel(BaseModel):'
542 557 groups_to_add = groups - current_groups
543 558
544 559 for gr in groups_to_remove:
545 log.debug('Removing user %s from user group %s', user.username, gr.users_group_name)
560 log.debug('Removing user %s from user group %s',
561 user.username, gr.users_group_name)
546 562 self.remove_user_from_group(gr.users_group_name, user.username)
547 563 for gr in groups_to_add:
548 log.debug('Adding user %s to user group %s', user.username, gr.users_group_name)
549 UserGroupModel().add_user_to_group(gr.users_group_name, user.username)
564 log.debug('Adding user %s to user group %s',
565 user.username, gr.users_group_name)
566 UserGroupModel().add_user_to_group(
567 gr.users_group_name, user.username)
550 568
551 569 def _serialize_user_group(self, user_group):
552 570 import rhodecode.lib.helpers as h
@@ -617,7 +635,3 b' class UserGroupModel(BaseModel):'
617 635 'owner_icon': h.gravatar_url(user_group.user.email, 30)}
618 636 }
619 637 return data
620
621
622
623
@@ -221,7 +221,7 b' def ValidUserGroup(edit=False, old_data='
221 221 class _validator(formencode.validators.FancyValidator):
222 222 messages = {
223 223 'invalid_group': _(u'Invalid user group name'),
224 'group_exist': _(u'User group "%(usergroup)s" already exists'),
224 'group_exist': _(u'User group `%(usergroup)s` already exists'),
225 225 'invalid_usergroup_name':
226 226 _(u'user group name may only contain alphanumeric '
227 227 u'characters underscores, periods or dashes and must begin '
@@ -81,9 +81,8 b' function registerRCRoutes() {'
81 81 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
82 82 pyroutes.register('user_groups', '/_admin/user_groups', []);
83 83 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
84 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
85 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
86 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
84 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
85 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
87 86 pyroutes.register('repos', '/_admin/repos', []);
88 87 pyroutes.register('repo_new', '/_admin/repos/new', []);
89 88 pyroutes.register('repo_create', '/_admin/repos/create', []);
@@ -210,6 +209,18 b' function registerRCRoutes() {'
210 209 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
211 210 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
212 211 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
212 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
213 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
214 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
215 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
216 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
217 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
218 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
219 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
220 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
221 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
222 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
223 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
213 224 pyroutes.register('search', '/_admin/search', []);
214 225 pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']);
215 226 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
@@ -96,7 +96,7 b''
96 96 <td class="td-componentname">
97 97 <i class="icon-group" ></i>
98 98 %if h.HasPermissionAny('hg.admin')():
99 <a href="${h.url('edit_users_group',user_group_id=_user_group.users_group_id)}">
99 <a href="${h.route_path('edit_user_group',user_group_id=_user_group.users_group_id)}">
100 100 ${_user_group.users_group_name}
101 101 </a>
102 102 %else:
@@ -85,7 +85,7 b''
85 85 <td class="td-componentname">
86 86 <i class="icon-group" ></i>
87 87 %if h.HasPermissionAny('hg.admin')():
88 <a href="${h.url('edit_users_group',user_group_id=_user_group.users_group_id)}">
88 <a href="${h.route_path('edit_user_group',user_group_id=_user_group.users_group_id)}">
89 89 ${_user_group.users_group_name}
90 90 </a>
91 91 %else:
@@ -10,7 +10,7 b''
10 10 <%def name="breadcrumbs_links()">
11 11 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
12 12 &raquo;
13 ${h.link_to(_('User groups'),h.url('users_groups'))}
13 ${h.link_to(_('User groups'),h.route_path('user_groups'))}
14 14 &raquo;
15 15 ${_('Add User Group')}
16 16 </%def>
@@ -26,7 +26,7 b''
26 26 ${self.breadcrumbs()}
27 27 </div>
28 28 <!-- end box / title -->
29 ${h.secure_form(h.url('users_groups'))}
29 ${h.secure_form(h.route_path('user_groups_create'), method='POST', request=request)}
30 30 <div class="form">
31 31 <!-- fields -->
32 32 <div class="fields">
@@ -11,7 +11,7 b''
11 11 <%def name="breadcrumbs_links()">
12 12 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
13 13 &raquo;
14 ${h.link_to(_('User Groups'),h.url('users_groups'))}
14 ${h.link_to(_('User Groups'),h.route_path('user_groups'))}
15 15 &raquo;
16 16 ${c.user_group.users_group_name}
17 17 </%def>
@@ -30,10 +30,10 b''
30 30 <div class="sidebar-col-wrapper">
31 31 <div class="sidebar">
32 32 <ul class="nav nav-pills nav-stacked">
33 <li class="${'active' if c.active=='settings' else ''}"><a href="${h.url('edit_users_group', user_group_id=c.user_group.users_group_id)}">${_('Settings')}</a></li>
34 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.url('edit_user_group_perms', user_group_id=c.user_group.users_group_id)}">${_('Permissions')}</a></li>
35 <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_group_advanced', user_group_id=c.user_group.users_group_id)}">${_('Advanced')}</a></li>
36 <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id)}">${_('Global permissions')}</a></li>
33 <li class="${'active' if c.active=='settings' else ''}"><a href="${h.route_path('edit_user_group', user_group_id=c.user_group.users_group_id)}">${_('Settings')}</a></li>
34 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.route_path('edit_user_group_perms', user_group_id=c.user_group.users_group_id)}">${_('Permissions')}</a></li>
35 <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.route_path('edit_user_group_advanced', user_group_id=c.user_group.users_group_id)}">${_('Advanced')}</a></li>
36 <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.route_path('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id)}">${_('Global permissions')}</a></li>
37 37 <li class="${'active' if c.active=='perms_summary' else ''}"><a href="${h.route_path('edit_user_group_perms_summary', user_group_id=c.user_group.users_group_id)}">${_('Permissions summary')}</a></li>
38 38 </ul>
39 39 </div>
@@ -44,7 +44,7 b''
44 44 % endif
45 45
46 46 <div>
47 ${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')}
47 ${h.secure_form(h.route_path('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='POST', request=request)}
48 48 <div class="field">
49 49 <button class="btn btn-default" type="submit">
50 50 %if sync_type:
@@ -72,7 +72,7 b''
72 72 <h3 class="panel-title">${_('Delete User Group')}</h3>
73 73 </div>
74 74 <div class="panel-body">
75 ${h.secure_form(h.url('delete_users_group', user_group_id=c.user_group.users_group_id),method='delete')}
75 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=c.user_group.users_group_id), method='POST', request=request)}
76 76 ${h.hidden('force', 1)}
77 77 <button class="btn btn-small btn-danger" type="submit"
78 78 onclick="return confirm('${_('Confirm to delete user group `%(ugroup)s` with all permission assignments') % {'ugroup': c.user_group.users_group_name}}');">
@@ -1,3 +1,3 b''
1 1 <%namespace name="dpb" file="/base/default_perms_box.mako"/>
2 ${dpb.default_perms_box(h.url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id))}
2 ${dpb.default_perms_box(form_url=h.route_path('edit_user_group_global_perms_update', user_group_id=c.user_group.users_group_id))}
3 3
@@ -5,7 +5,7 b''
5 5 <h3 class="panel-title">${_('User Group Permissions')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 ${h.secure_form(h.url('edit_user_group_perms', user_group_id=c.user_group.users_group_id),method='put')}
8 ${h.secure_form(h.route_path('edit_user_group_perms_update', user_group_id=c.user_group.users_group_id), method='POST', request=request)}
9 9 <table id="permissions_manage" class="rctable permissions">
10 10 <tr>
11 11 <th class="td-radio">${_('None')}</th>
@@ -96,7 +96,7 b''
96 96 <td class="td-user">
97 97 <i class="icon-group" ></i>
98 98 %if h.HasPermissionAny('hg.admin')():
99 <a href="${h.url('edit_users_group',user_group_id=_user_group.users_group_id)}">
99 <a href="${h.route_path('edit_user_group',user_group_id=_user_group.users_group_id)}">
100 100 ${_user_group.users_group_name}
101 101 </a>
102 102 %else:
@@ -6,7 +6,7 b''
6 6 <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3>
7 7 </div>
8 8 <div class="panel-body">
9 ${h.secure_form(h.url('update_users_group', user_group_id=c.user_group.users_group_id),method='put', id='edit_users_group')}
9 ${h.secure_form(h.route_path('user_groups_update', user_group_id=c.user_group.users_group_id), id='edit_user_group', method='POST', request=request)}
10 10 <div class="form">
11 11 <!-- fields -->
12 12 <div class="fields">
@@ -25,7 +25,7 b''
25 25 <ul class="links">
26 26 %if h.HasPermissionAny('hg.admin', 'hg.usergroup.create.true')():
27 27 <li>
28 <a href="${h.url('new_users_group')}" class="btn btn-small btn-success">${_(u'Add User Group')}</a>
28 <a href="${h.route_path('user_groups_new')}" class="btn btn-small btn-success">${_(u'Add User Group')}</a>
29 29 </li>
30 30 %endif
31 31 </ul>
@@ -76,7 +76,7 b''
76 76 <li><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
77 77 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
78 78 <li><a href="${h.route_path('users')}">${_('Users')}</a></li>
79 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
79 <li><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
80 80 <li><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
81 81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
82 82 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
@@ -151,7 +151,7 b''
151 151 <li class="local-admin-repo-groups"><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
152 152 %endif
153 153 %if user_groups:
154 <li class="local-admin-user-groups"><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
154 <li class="local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
155 155 %endif
156 156 </ul>
157 157 </%def>
@@ -94,7 +94,7 b''
94 94 </%def>
95 95
96 96 <%def name="default_perms_box(form_url)">
97 ${h.secure_form(form_url, method='put')}
97 ${h.secure_form(form_url, method='POST', request=request)}
98 98 <div class="form">
99 99 <div class="fields">
100 100 <div class="field panel panel-default panel-body">
@@ -175,7 +175,7 b''
175 175 %elif section == 'repositories_groups':
176 176 <a href="${h.route_path('repo_group_home', repo_group_name=k)}">${k}</a>
177 177 %elif section == 'user_groups':
178 ##<a href="${h.url('edit_users_group',user_group_id=k)}">${k}</a>
178 ##<a href="${h.route_path('edit_user_group',user_group_id=k)}">${k}</a>
179 179 ${k}
180 180 %endif
181 181 </td>
@@ -211,7 +211,7 b''
211 211 %elif section == 'repositories_groups':
212 212 <a href="${h.url('edit_repo_group_perms',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
213 213 %elif section == 'user_groups':
214 ##<a href="${h.url('edit_users_group',user_group_id=k)}">${_('edit')}</a>
214 ##<a href="${h.route_path('edit_user_group',user_group_id=k)}">${_('edit')}</a>
215 215 %endif
216 216 </td>
217 217 %endif
@@ -200,10 +200,10 b''
200 200
201 201 <%def name="user_group_actions(user_group_id, user_group_name)">
202 202 <div class="grid_edit">
203 <a href="${h.url('edit_users_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
203 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
204 204 </div>
205 205 <div class="grid_delete">
206 ${h.secure_form(h.url('delete_users_group', user_group_id=user_group_id),method='delete')}
206 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), method='POST', request=request)}
207 207 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
208 208 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
209 209 ${h.end_form()}
@@ -221,7 +221,7 b''
221 221
222 222 <%def name="user_group_name(user_group_id, user_group_name)">
223 223 <div>
224 <a href="${h.url('edit_users_group', user_group_id=user_group_id)}">
224 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}">
225 225 <i class="icon-group" title="${_('User group')}"></i> ${user_group_name}</a>
226 226 </div>
227 227 </%def>
@@ -260,12 +260,6 b''
260 260 </div>
261 261 </fieldset>
262 262
263 <script>
264 $(document).ready(function(){
265 MultiSelectWidget('users_group_members2','available_members', 'edit_users_group');
266 })
267 </script>
268
269 263 <div class="buttons">
270 264 <input type="submit" value="Save" id="example_save" class="btn">
271 265 <input type="reset" value="Reset" id="example_reset" class="btn">
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now