##// END OF EJS Templates
user-groups-audit: properly register add/delete members on main...
marcink -
r2106:44a92162 default
parent child Browse files
Show More
@@ -1,529 +1,543 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 import peppercorn
24 24 import formencode
25 25 import formencode.htmlfill
26 26 from pyramid.httpexceptions import HTTPFound
27 27 from pyramid.view import view_config
28 28 from pyramid.response import Response
29 29 from pyramid.renderers import render
30 30
31 31 from rhodecode.lib.exceptions import (
32 32 RepoGroupAssignmentError, UserGroupAssignedException)
33 33 from rhodecode.model.forms import (
34 34 UserGroupPermsForm, UserGroupForm, UserIndividualPermissionsForm,
35 35 UserPermissionsForm)
36 36 from rhodecode.model.permission import PermissionModel
37 37
38 38 from rhodecode.apps._base import UserGroupAppView
39 39 from rhodecode.lib.auth import (
40 40 LoginRequired, HasUserGroupPermissionAnyDecorator, CSRFRequired)
41 41 from rhodecode.lib import helpers as h, audit_logger
42 42 from rhodecode.lib.utils2 import str2bool
43 43 from rhodecode.model.db import (
44 44 joinedload, User, UserGroupRepoToPerm, UserGroupRepoGroupToPerm)
45 45 from rhodecode.model.meta import Session
46 46 from rhodecode.model.user_group import UserGroupModel
47 47
48 48 log = logging.getLogger(__name__)
49 49
50 50
51 51 class UserGroupsView(UserGroupAppView):
52 52
53 53 def load_default_context(self):
54 54 c = self._get_local_tmpl_context()
55 55
56 56 PermissionModel().set_global_permission_choices(
57 57 c, gettext_translator=self.request.translate)
58 58
59 59 self._register_global_c(c)
60 60 return c
61 61
62 62 def _get_perms_summary(self, user_group_id):
63 63 permissions = {
64 64 'repositories': {},
65 65 'repositories_groups': {},
66 66 }
67 67 ugroup_repo_perms = UserGroupRepoToPerm.query()\
68 68 .options(joinedload(UserGroupRepoToPerm.permission))\
69 69 .options(joinedload(UserGroupRepoToPerm.repository))\
70 70 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
71 71 .all()
72 72
73 73 for gr in ugroup_repo_perms:
74 74 permissions['repositories'][gr.repository.repo_name] \
75 75 = gr.permission.permission_name
76 76
77 77 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
78 78 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
79 79 .options(joinedload(UserGroupRepoGroupToPerm.group))\
80 80 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
81 81 .all()
82 82
83 83 for gr in ugroup_group_perms:
84 84 permissions['repositories_groups'][gr.group.group_name] \
85 85 = gr.permission.permission_name
86 86 return permissions
87 87
88 88 @LoginRequired()
89 89 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
90 90 @view_config(
91 91 route_name='user_group_members_data', request_method='GET',
92 92 renderer='json_ext', xhr=True)
93 93 def user_group_members(self):
94 94 """
95 95 Return members of given user group
96 96 """
97 97 user_group = self.db_user_group
98 98 group_members_obj = sorted((x.user for x in user_group.members),
99 99 key=lambda u: u.username.lower())
100 100
101 101 group_members = [
102 102 {
103 103 'id': user.user_id,
104 104 'first_name': user.first_name,
105 105 'last_name': user.last_name,
106 106 'username': user.username,
107 107 'icon_link': h.gravatar_url(user.email, 30),
108 108 'value_display': h.person(user.email),
109 109 'value': user.username,
110 110 'value_type': 'user',
111 111 'active': user.active,
112 112 }
113 113 for user in group_members_obj
114 114 ]
115 115
116 116 return {
117 117 'members': group_members
118 118 }
119 119
120 120 @LoginRequired()
121 121 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
122 122 @view_config(
123 123 route_name='edit_user_group_perms_summary', request_method='GET',
124 124 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
125 125 def user_group_perms_summary(self):
126 126 c = self.load_default_context()
127 127 c.user_group = self.db_user_group
128 128 c.active = 'perms_summary'
129 129 c.permissions = self._get_perms_summary(c.user_group.users_group_id)
130 130 return self._get_template_context(c)
131 131
132 132 @LoginRequired()
133 133 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
134 134 @view_config(
135 135 route_name='edit_user_group_perms_summary_json', request_method='GET',
136 136 renderer='json_ext')
137 137 def user_group_perms_summary_json(self):
138 138 self.load_default_context()
139 139 user_group = self.db_user_group
140 140 return self._get_perms_summary(user_group.users_group_id)
141 141
142 142 def _revoke_perms_on_yourself(self, form_result):
143 143 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
144 144 form_result['perm_updates'])
145 145 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
146 146 form_result['perm_additions'])
147 147 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
148 148 form_result['perm_deletions'])
149 149 admin_perm = 'usergroup.admin'
150 150 if _updates and _updates[0][1] != admin_perm or \
151 151 _additions and _additions[0][1] != admin_perm or \
152 152 _deletions and _deletions[0][1] != admin_perm:
153 153 return True
154 154 return False
155 155
156 156 @LoginRequired()
157 157 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
158 158 @CSRFRequired()
159 159 @view_config(
160 160 route_name='user_groups_update', request_method='POST',
161 161 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
162 162 def user_group_update(self):
163 163 _ = self.request.translate
164 164
165 165 user_group = self.db_user_group
166 166 user_group_id = user_group.users_group_id
167 167
168 168 c = self.load_default_context()
169 169 c.user_group = user_group
170 170 c.group_members_obj = [x.user for x in c.user_group.members]
171 171 c.group_members_obj.sort(key=lambda u: u.username.lower())
172 172 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
173 173 c.active = 'settings'
174 174
175 175 users_group_form = UserGroupForm(
176 176 edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
177 177
178 178 old_values = c.user_group.get_api_data()
179 179 user_group_name = self.request.POST.get('users_group_name')
180 180 try:
181 181 form_result = users_group_form.to_python(self.request.POST)
182 182 pstruct = peppercorn.parse(self.request.POST.items())
183 183 form_result['users_group_members'] = pstruct['user_group_members']
184 184
185 185 user_group, added_members, removed_members = \
186 186 UserGroupModel().update(c.user_group, form_result)
187 187 updated_user_group = form_result['users_group_name']
188 188
189 for user_id in added_members:
190 user = User.get(user_id)
191 user_data = user.get_api_data()
192 audit_logger.store_web(
193 'user_group.edit.member.add',
194 action_data={'user': user_data, 'old_data': old_values},
195 user=self._rhodecode_user)
196
197 for user_id in removed_members:
198 user = User.get(user_id)
199 user_data = user.get_api_data()
200 audit_logger.store_web(
201 'user_group.edit.member.delete',
202 action_data={'user': user_data, 'old_data': old_values},
203 user=self._rhodecode_user)
204
189 205 audit_logger.store_web(
190 206 'user_group.edit', action_data={'old_data': old_values},
191 207 user=self._rhodecode_user)
192 208
193 # TODO(marcink): use added/removed to set user_group.edit.member.add
194
195 209 h.flash(_('Updated user group %s') % updated_user_group,
196 210 category='success')
197 211 Session().commit()
198 212 except formencode.Invalid as errors:
199 213 defaults = errors.value
200 214 e = errors.error_dict or {}
201 215
202 216 data = render(
203 217 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
204 218 self._get_template_context(c), self.request)
205 219 html = formencode.htmlfill.render(
206 220 data,
207 221 defaults=defaults,
208 222 errors=e,
209 223 prefix_error=False,
210 224 encoding="UTF-8",
211 225 force_defaults=False
212 226 )
213 227 return Response(html)
214 228
215 229 except Exception:
216 230 log.exception("Exception during update of user group")
217 231 h.flash(_('Error occurred during update of user group %s')
218 232 % user_group_name, category='error')
219 233
220 234 raise HTTPFound(
221 235 h.route_path('edit_user_group', user_group_id=user_group_id))
222 236
223 237 @LoginRequired()
224 238 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
225 239 @CSRFRequired()
226 240 @view_config(
227 241 route_name='user_groups_delete', request_method='POST',
228 242 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
229 243 def user_group_delete(self):
230 244 _ = self.request.translate
231 245 user_group = self.db_user_group
232 246
233 247 self.load_default_context()
234 248 force = str2bool(self.request.POST.get('force'))
235 249
236 250 old_values = user_group.get_api_data()
237 251 try:
238 252 UserGroupModel().delete(user_group, force=force)
239 253 audit_logger.store_web(
240 254 'user.delete', action_data={'old_data': old_values},
241 255 user=self._rhodecode_user)
242 256 Session().commit()
243 257 h.flash(_('Successfully deleted user group'), category='success')
244 258 except UserGroupAssignedException as e:
245 259 h.flash(str(e), category='error')
246 260 except Exception:
247 261 log.exception("Exception during deletion of user group")
248 262 h.flash(_('An error occurred during deletion of user group'),
249 263 category='error')
250 264 raise HTTPFound(h.route_path('user_groups'))
251 265
252 266 @LoginRequired()
253 267 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
254 268 @view_config(
255 269 route_name='edit_user_group', request_method='GET',
256 270 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
257 271 def user_group_edit(self):
258 272 user_group = self.db_user_group
259 273
260 274 c = self.load_default_context()
261 275 c.user_group = user_group
262 276 c.group_members_obj = [x.user for x in c.user_group.members]
263 277 c.group_members_obj.sort(key=lambda u: u.username.lower())
264 278 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
265 279
266 280 c.active = 'settings'
267 281
268 282 defaults = user_group.get_dict()
269 283 # fill owner
270 284 if user_group.user:
271 285 defaults.update({'user': user_group.user.username})
272 286 else:
273 287 replacement_user = User.get_first_super_admin().username
274 288 defaults.update({'user': replacement_user})
275 289
276 290 data = render(
277 291 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
278 292 self._get_template_context(c), self.request)
279 293 html = formencode.htmlfill.render(
280 294 data,
281 295 defaults=defaults,
282 296 encoding="UTF-8",
283 297 force_defaults=False
284 298 )
285 299 return Response(html)
286 300
287 301 @LoginRequired()
288 302 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
289 303 @view_config(
290 304 route_name='edit_user_group_perms', request_method='GET',
291 305 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
292 306 def user_group_edit_perms(self):
293 307 user_group = self.db_user_group
294 308 c = self.load_default_context()
295 309 c.user_group = user_group
296 310 c.active = 'perms'
297 311
298 312 defaults = {}
299 313 # fill user group users
300 314 for p in c.user_group.user_user_group_to_perm:
301 315 defaults.update({'u_perm_%s' % p.user.user_id:
302 316 p.permission.permission_name})
303 317
304 318 for p in c.user_group.user_group_user_group_to_perm:
305 319 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
306 320 p.permission.permission_name})
307 321
308 322 data = render(
309 323 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
310 324 self._get_template_context(c), self.request)
311 325 html = formencode.htmlfill.render(
312 326 data,
313 327 defaults=defaults,
314 328 encoding="UTF-8",
315 329 force_defaults=False
316 330 )
317 331 return Response(html)
318 332
319 333 @LoginRequired()
320 334 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
321 335 @CSRFRequired()
322 336 @view_config(
323 337 route_name='edit_user_group_perms_update', request_method='POST',
324 338 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
325 339 def user_group_update_perms(self):
326 340 """
327 341 grant permission for given user group
328 342 """
329 343 _ = self.request.translate
330 344
331 345 user_group = self.db_user_group
332 346 user_group_id = user_group.users_group_id
333 347 c = self.load_default_context()
334 348 c.user_group = user_group
335 349 form = UserGroupPermsForm()().to_python(self.request.POST)
336 350
337 351 if not self._rhodecode_user.is_admin:
338 352 if self._revoke_perms_on_yourself(form):
339 353 msg = _('Cannot change permission for yourself as admin')
340 354 h.flash(msg, category='warning')
341 355 raise HTTPFound(
342 356 h.route_path('edit_user_group_perms',
343 357 user_group_id=user_group_id))
344 358
345 359 try:
346 360 changes = UserGroupModel().update_permissions(
347 361 user_group_id,
348 362 form['perm_additions'], form['perm_updates'],
349 363 form['perm_deletions'])
350 364
351 365 except RepoGroupAssignmentError:
352 366 h.flash(_('Target group cannot be the same'), category='error')
353 367 raise HTTPFound(
354 368 h.route_path('edit_user_group_perms',
355 369 user_group_id=user_group_id))
356 370
357 371 action_data = {
358 372 'added': changes['added'],
359 373 'updated': changes['updated'],
360 374 'deleted': changes['deleted'],
361 375 }
362 376 audit_logger.store_web(
363 377 'user_group.edit.permissions', action_data=action_data,
364 378 user=self._rhodecode_user)
365 379
366 380 Session().commit()
367 381 h.flash(_('User Group permissions updated'), category='success')
368 382 raise HTTPFound(
369 383 h.route_path('edit_user_group_perms', user_group_id=user_group_id))
370 384
371 385 @LoginRequired()
372 386 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
373 387 @view_config(
374 388 route_name='edit_user_group_global_perms', request_method='GET',
375 389 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
376 390 def user_group_global_perms_edit(self):
377 391 user_group = self.db_user_group
378 392 c = self.load_default_context()
379 393 c.user_group = user_group
380 394 c.active = 'global_perms'
381 395
382 396 c.default_user = User.get_default_user()
383 397 defaults = c.user_group.get_dict()
384 398 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
385 399 defaults.update(c.user_group.get_default_perms())
386 400
387 401 data = render(
388 402 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
389 403 self._get_template_context(c), self.request)
390 404 html = formencode.htmlfill.render(
391 405 data,
392 406 defaults=defaults,
393 407 encoding="UTF-8",
394 408 force_defaults=False
395 409 )
396 410 return Response(html)
397 411
398 412 @LoginRequired()
399 413 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
400 414 @CSRFRequired()
401 415 @view_config(
402 416 route_name='edit_user_group_global_perms_update', request_method='POST',
403 417 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
404 418 def user_group_global_perms_update(self):
405 419 _ = self.request.translate
406 420 user_group = self.db_user_group
407 421 user_group_id = self.db_user_group.users_group_id
408 422
409 423 c = self.load_default_context()
410 424 c.user_group = user_group
411 425 c.active = 'global_perms'
412 426
413 427 try:
414 428 # first stage that verifies the checkbox
415 429 _form = UserIndividualPermissionsForm()
416 430 form_result = _form.to_python(dict(self.request.POST))
417 431 inherit_perms = form_result['inherit_default_permissions']
418 432 user_group.inherit_default_permissions = inherit_perms
419 433 Session().add(user_group)
420 434
421 435 if not inherit_perms:
422 436 # only update the individual ones if we un check the flag
423 437 _form = UserPermissionsForm(
424 438 [x[0] for x in c.repo_create_choices],
425 439 [x[0] for x in c.repo_create_on_write_choices],
426 440 [x[0] for x in c.repo_group_create_choices],
427 441 [x[0] for x in c.user_group_create_choices],
428 442 [x[0] for x in c.fork_choices],
429 443 [x[0] for x in c.inherit_default_permission_choices])()
430 444
431 445 form_result = _form.to_python(dict(self.request.POST))
432 446 form_result.update(
433 447 {'perm_user_group_id': user_group.users_group_id})
434 448
435 449 PermissionModel().update_user_group_permissions(form_result)
436 450
437 451 Session().commit()
438 452 h.flash(_('User Group global permissions updated successfully'),
439 453 category='success')
440 454
441 455 except formencode.Invalid as errors:
442 456 defaults = errors.value
443 457
444 458 data = render(
445 459 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
446 460 self._get_template_context(c), self.request)
447 461 html = formencode.htmlfill.render(
448 462 data,
449 463 defaults=defaults,
450 464 errors=errors.error_dict or {},
451 465 prefix_error=False,
452 466 encoding="UTF-8",
453 467 force_defaults=False
454 468 )
455 469 return Response(html)
456 470 except Exception:
457 471 log.exception("Exception during permissions saving")
458 472 h.flash(_('An error occurred during permissions saving'),
459 473 category='error')
460 474
461 475 raise HTTPFound(
462 476 h.route_path('edit_user_group_global_perms',
463 477 user_group_id=user_group_id))
464 478
465 479 @LoginRequired()
466 480 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
467 481 @view_config(
468 482 route_name='edit_user_group_advanced', request_method='GET',
469 483 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
470 484 def user_group_edit_advanced(self):
471 485 user_group = self.db_user_group
472 486
473 487 c = self.load_default_context()
474 488 c.user_group = user_group
475 489 c.active = 'advanced'
476 490 c.group_members_obj = sorted(
477 491 (x.user for x in c.user_group.members),
478 492 key=lambda u: u.username.lower())
479 493
480 494 c.group_to_repos = sorted(
481 495 (x.repository for x in c.user_group.users_group_repo_to_perm),
482 496 key=lambda u: u.repo_name.lower())
483 497
484 498 c.group_to_repo_groups = sorted(
485 499 (x.group for x in c.user_group.users_group_repo_group_to_perm),
486 500 key=lambda u: u.group_name.lower())
487 501
488 502 c.group_to_review_rules = sorted(
489 503 (x.users_group for x in c.user_group.user_group_review_rules),
490 504 key=lambda u: u.users_group_name.lower())
491 505
492 506 return self._get_template_context(c)
493 507
494 508 @LoginRequired()
495 509 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
496 510 @CSRFRequired()
497 511 @view_config(
498 512 route_name='edit_user_group_advanced_sync', request_method='POST',
499 513 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
500 514 def user_group_edit_advanced_set_synchronization(self):
501 515 _ = self.request.translate
502 516 user_group = self.db_user_group
503 517 user_group_id = user_group.users_group_id
504 518
505 519 existing = user_group.group_data.get('extern_type')
506 520
507 521 if existing:
508 522 new_state = user_group.group_data
509 523 new_state['extern_type'] = None
510 524 else:
511 525 new_state = user_group.group_data
512 526 new_state['extern_type'] = 'manual'
513 527 new_state['extern_type_set_by'] = self._rhodecode_user.username
514 528
515 529 try:
516 530 user_group.group_data = new_state
517 531 Session().add(user_group)
518 532 Session().commit()
519 533
520 534 h.flash(_('User Group synchronization updated successfully'),
521 535 category='success')
522 536 except Exception:
523 537 log.exception("Exception during sync settings saving")
524 538 h.flash(_('An error occurred during synchronization update'),
525 539 category='error')
526 540
527 541 raise HTTPFound(
528 542 h.route_path('edit_user_group_advanced',
529 543 user_group_id=user_group_id))
General Comments 0
You need to be logged in to leave comments. Login now