Show More
@@ -374,6 +374,10 b' def make_map(config):' | |||
|
374 | 374 | '/user_groups/{user_group_id}/edit/advanced', |
|
375 | 375 | action='edit_advanced', conditions={'method': ['GET']}) |
|
376 | 376 | |
|
377 | m.connect('edit_user_group_advanced_sync', | |
|
378 | '/user_groups/{user_group_id}/edit/advanced/sync', | |
|
379 | action='edit_advanced_set_synchronization', conditions={'method': ['POST']}) | |
|
380 | ||
|
377 | 381 | m.connect('edit_user_group_members', |
|
378 | 382 | '/user_groups/{user_group_id}/edit/members', jsroute=True, |
|
379 | 383 | action='user_group_members', conditions={'method': ['GET']}) |
@@ -117,7 +117,7 b' class UserGroupsController(BaseControlle' | |||
|
117 | 117 | def user_group_actions(user_group_id, user_group_name): |
|
118 | 118 | return _render("user_group_actions", user_group_id, user_group_name) |
|
119 | 119 | |
|
120 |
|
|
|
120 | # json generate | |
|
121 | 121 | group_iter = UserGroupList(UserGroup.query().all(), |
|
122 | 122 | perm_set=['usergroup.admin']) |
|
123 | 123 | |
@@ -129,6 +129,7 b' class UserGroupsController(BaseControlle' | |||
|
129 | 129 | "group_name_raw": user_gr.users_group_name, |
|
130 | 130 | "desc": h.escape(user_gr.user_group_description), |
|
131 | 131 | "members": len(user_gr.members), |
|
132 | "sync": user_gr.group_data.get('extern_type'), | |
|
132 | 133 | "active": h.bool2icon(user_gr.users_group_active), |
|
133 | 134 | "owner": h.escape(h.link_to_user(user_gr.user.username)), |
|
134 | 135 | "action": user_group_actions( |
@@ -431,7 +432,6 b' class UserGroupsController(BaseControlle' | |||
|
431 | 432 | prefix_error=False, |
|
432 | 433 | encoding="UTF-8", |
|
433 | 434 | force_defaults=False) |
|
434 | ||
|
435 | 435 | except Exception: |
|
436 | 436 | log.exception("Exception during permissions saving") |
|
437 | 437 | h.flash(_('An error occurred during permissions saving'), |
@@ -459,6 +459,36 b' class UserGroupsController(BaseControlle' | |||
|
459 | 459 | return render('admin/user_groups/user_group_edit.mako') |
|
460 | 460 | |
|
461 | 461 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') |
|
462 | def edit_advanced_set_synchronization(self, user_group_id): | |
|
463 | user_group_id = safe_int(user_group_id) | |
|
464 | user_group = UserGroup.get_or_404(user_group_id) | |
|
465 | ||
|
466 | existing = user_group.group_data.get('extern_type') | |
|
467 | ||
|
468 | if existing: | |
|
469 | new_state = user_group.group_data | |
|
470 | new_state['extern_type'] = None | |
|
471 | else: | |
|
472 | new_state = user_group.group_data | |
|
473 | new_state['extern_type'] = 'manual' | |
|
474 | new_state['extern_type_set_by'] = c.rhodecode_user.username | |
|
475 | ||
|
476 | try: | |
|
477 | user_group.group_data = new_state | |
|
478 | Session().add(user_group) | |
|
479 | Session().commit() | |
|
480 | ||
|
481 | h.flash(_('User Group synchronization updated successfully'), | |
|
482 | category='success') | |
|
483 | except Exception: | |
|
484 | log.exception("Exception during sync settings saving") | |
|
485 | h.flash(_('An error occurred during synchronization update'), | |
|
486 | category='error') | |
|
487 | ||
|
488 | return redirect( | |
|
489 | url('edit_user_group_advanced', user_group_id=user_group_id)) | |
|
490 | ||
|
491 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') | |
|
462 | 492 | @XHRRequired() |
|
463 | 493 | @jsonify |
|
464 | 494 | def user_group_members(self, user_group_id): |
@@ -501,8 +501,8 b' class UserGroupModel(BaseModel):' | |||
|
501 | 501 | if not existing_group: |
|
502 | 502 | desc = 'Automatically created from plugin:%s' % extern_type |
|
503 | 503 | # we use first admin account to set the owner of the group |
|
504 |
existing_group = UserGroupModel().create( |
|
|
505 |
|
|
|
504 | existing_group = UserGroupModel().create( | |
|
505 | gr, desc, owner, group_data={'extern_type': extern_type}) | |
|
506 | 506 | |
|
507 | 507 | # we can only add users to special groups created via plugins |
|
508 | 508 | managed = 'extern_type' in existing_group.group_data |
@@ -511,8 +511,7 b' class UserGroupModel(BaseModel):' | |||
|
511 | 511 | UserGroupModel().add_user_to_group(existing_group, user) |
|
512 | 512 | else: |
|
513 | 513 | log.debug('Skipping addition to group %s since it is ' |
|
514 |
'not |
|
|
515 | ||
|
514 | 'not set to be automatically synchronized' % gr) | |
|
516 | 515 | |
|
517 | 516 | def change_groups(self, user, groups): |
|
518 | 517 | """ |
@@ -6,6 +6,8 b'' | |||
|
6 | 6 | (_('Created on'), h.format_date(c.user_group.created_on), '', '',), |
|
7 | 7 | |
|
8 | 8 | (_('Members'), len(c.group_members_obj),'', [x for x in c.group_members_obj]), |
|
9 | (_('Automatic member sync'), 'Yes' if c.user_group.group_data.get('extern_type') else 'No', '', '',), | |
|
10 | ||
|
9 | 11 | (_('Assigned to repositories'), len(c.group_to_repos),'', [x for x in c.group_to_repos]), |
|
10 | 12 | (_('Assigned to repo groups'), len(c.group_to_repo_groups), '', [x for x in c.group_to_repo_groups]), |
|
11 | 13 | |
@@ -19,8 +21,55 b'' | |||
|
19 | 21 | <div class="panel-body"> |
|
20 | 22 | ${base.dt_info_panel(elems)} |
|
21 | 23 | </div> |
|
24 | ||
|
22 | 25 | </div> |
|
23 | 26 | |
|
27 | <div class="panel panel-default"> | |
|
28 | <div class="panel-heading"> | |
|
29 | <h3 class="panel-title">${_('Group members sync')}</h3> | |
|
30 | </div> | |
|
31 | <div class="panel-body"> | |
|
32 | <% sync_type = c.user_group.group_data.get('extern_type') %> | |
|
33 | ||
|
34 | % if sync_type: | |
|
35 | <p> | |
|
36 | ${_('This group is set to be automatically synchronised.')}<br/> | |
|
37 | ${_('Each member will be added or removed from this groups once they interact with RhodeCode system.')}<br/> | |
|
38 | ${_('This group synchronization was set by')}: <strong>${sync_type}</strong> | |
|
39 | </p> | |
|
40 | % else: | |
|
41 | <p> | |
|
42 | ${_('This group is not set to be automatically synchronised')} | |
|
43 | </p> | |
|
44 | % endif | |
|
45 | ||
|
46 | <div> | |
|
47 | ${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')} | |
|
48 | <div class="field"> | |
|
49 | <button class="btn btn-default" type="submit"> | |
|
50 | %if sync_type: | |
|
51 | ${_('Disable synchronization')} | |
|
52 | %else: | |
|
53 | ${_('Enable synchronization')} | |
|
54 | %endif | |
|
55 | </button> | |
|
56 | </div> | |
|
57 | <div class="field"> | |
|
58 | <span class="help-block"> | |
|
59 | %if sync_type: | |
|
60 | ${_('User group will no longer synchronize membership')} | |
|
61 | %else: | |
|
62 | ${_('User group will start to synchronize membership')} | |
|
63 | %endif | |
|
64 | </span> | |
|
65 | </div> | |
|
66 | ${h.end_form()} | |
|
67 | </div> | |
|
68 | ||
|
69 | </div> | |
|
70 | </div> | |
|
71 | ||
|
72 | ||
|
24 | 73 | <div class="panel panel-danger"> |
|
25 | 74 | <div class="panel-heading"> |
|
26 | 75 | <h3 class="panel-title">${_('Delete User Group')}</h3> |
@@ -58,8 +58,10 b'' | |||
|
58 | 58 | { data: {"_": "members", |
|
59 | 59 | "sort": "members", |
|
60 | 60 | "type": Number}, title: "${_('Members')}", className: "td-number" }, |
|
61 | { data: {"_": "sync", | |
|
62 | "sort": "sync"}, title: "${_('Sync')}", className: "td-sync" }, | |
|
61 | 63 | { data: {"_": "active", |
|
62 |
"sort": "active"}, title: "${_('Active')}", className: "td-active" |
|
|
64 | "sort": "active"}, title: "${_('Active')}", className: "td-active" }, | |
|
63 | 65 | { data: {"_": "owner", |
|
64 | 66 | "sort": "owner"}, title: "${_('Owner')}", className: "td-user" }, |
|
65 | 67 | { data: {"_": "action", |
@@ -21,7 +21,7 b'' | |||
|
21 | 21 | import pytest |
|
22 | 22 | |
|
23 | 23 | from rhodecode.tests import ( |
|
24 | TestController, url, assert_session_flash, link_to) | |
|
24 | TestController, url, assert_session_flash, link_to, TEST_USER_ADMIN_LOGIN) | |
|
25 | 25 | from rhodecode.model.db import User, UserGroup |
|
26 | 26 | from rhodecode.model.meta import Session |
|
27 | 27 | from rhodecode.tests.fixture import Fixture |
@@ -56,6 +56,41 b' class TestAdminUsersGroupsController(Tes' | |||
|
56 | 56 | response, |
|
57 | 57 | 'Created user group %s' % user_group_link) |
|
58 | 58 | |
|
59 | def test_set_synchronization(self): | |
|
60 | self.log_user() | |
|
61 | users_group_name = TEST_USER_GROUP + 'sync' | |
|
62 | response = self.app.post(url('users_groups'), { | |
|
63 | 'users_group_name': users_group_name, | |
|
64 | 'user_group_description': 'DESC', | |
|
65 | 'active': True, | |
|
66 | 'csrf_token': self.csrf_token}) | |
|
67 | ||
|
68 | group = Session().query(UserGroup).filter( | |
|
69 | UserGroup.users_group_name == users_group_name).one() | |
|
70 | ||
|
71 | assert group.group_data.get('extern_type') is None | |
|
72 | ||
|
73 | # enable | |
|
74 | self.app.post( | |
|
75 | url('edit_user_group_advanced_sync', user_group_id=group.users_group_id), | |
|
76 | params={'csrf_token': self.csrf_token}, status=302) | |
|
77 | ||
|
78 | group = Session().query(UserGroup).filter( | |
|
79 | UserGroup.users_group_name == users_group_name).one() | |
|
80 | assert group.group_data.get('extern_type') == 'manual' | |
|
81 | assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN | |
|
82 | ||
|
83 | # disable | |
|
84 | self.app.post( | |
|
85 | url('edit_user_group_advanced_sync', | |
|
86 | user_group_id=group.users_group_id), | |
|
87 | params={'csrf_token': self.csrf_token}, status=302) | |
|
88 | ||
|
89 | group = Session().query(UserGroup).filter( | |
|
90 | UserGroup.users_group_name == users_group_name).one() | |
|
91 | assert group.group_data.get('extern_type') is None | |
|
92 | assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN | |
|
93 | ||
|
59 | 94 | def test_delete(self): |
|
60 | 95 | self.log_user() |
|
61 | 96 | users_group_name = TEST_USER_GROUP + 'another' |
@@ -77,7 +112,7 b' class TestAdminUsersGroupsController(Tes' | |||
|
77 | 112 | group = Session().query(UserGroup).filter( |
|
78 | 113 | UserGroup.users_group_name == users_group_name).one() |
|
79 | 114 | |
|
80 |
|
|
|
115 | self.app.post( | |
|
81 | 116 | url('delete_users_group', user_group_id=group.users_group_id), |
|
82 | 117 | params={'_method': 'delete', 'csrf_token': self.csrf_token}) |
|
83 | 118 |
General Comments 0
You need to be logged in to leave comments.
Login now