diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -374,6 +374,10 @@ def make_map(config): '/user_groups/{user_group_id}/edit/advanced', action='edit_advanced', conditions={'method': ['GET']}) + m.connect('edit_user_group_advanced_sync', + '/user_groups/{user_group_id}/edit/advanced/sync', + action='edit_advanced_set_synchronization', conditions={'method': ['POST']}) + m.connect('edit_user_group_members', '/user_groups/{user_group_id}/edit/members', jsroute=True, action='user_group_members', conditions={'method': ['GET']}) diff --git a/rhodecode/controllers/admin/user_groups.py b/rhodecode/controllers/admin/user_groups.py --- a/rhodecode/controllers/admin/user_groups.py +++ b/rhodecode/controllers/admin/user_groups.py @@ -117,7 +117,7 @@ class UserGroupsController(BaseControlle def user_group_actions(user_group_id, user_group_name): return _render("user_group_actions", user_group_id, user_group_name) - ## json generate + # json generate group_iter = UserGroupList(UserGroup.query().all(), perm_set=['usergroup.admin']) @@ -129,6 +129,7 @@ class UserGroupsController(BaseControlle "group_name_raw": user_gr.users_group_name, "desc": h.escape(user_gr.user_group_description), "members": len(user_gr.members), + "sync": user_gr.group_data.get('extern_type'), "active": h.bool2icon(user_gr.users_group_active), "owner": h.escape(h.link_to_user(user_gr.user.username)), "action": user_group_actions( @@ -431,7 +432,6 @@ class UserGroupsController(BaseControlle prefix_error=False, encoding="UTF-8", force_defaults=False) - except Exception: log.exception("Exception during permissions saving") h.flash(_('An error occurred during permissions saving'), @@ -459,6 +459,36 @@ class UserGroupsController(BaseControlle return render('admin/user_groups/user_group_edit.mako') @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit_advanced_set_synchronization(self, user_group_id): + user_group_id = safe_int(user_group_id) + user_group = UserGroup.get_or_404(user_group_id) + + existing = user_group.group_data.get('extern_type') + + if existing: + new_state = user_group.group_data + new_state['extern_type'] = None + else: + new_state = user_group.group_data + new_state['extern_type'] = 'manual' + new_state['extern_type_set_by'] = c.rhodecode_user.username + + try: + user_group.group_data = new_state + Session().add(user_group) + Session().commit() + + h.flash(_('User Group synchronization updated successfully'), + category='success') + except Exception: + log.exception("Exception during sync settings saving") + h.flash(_('An error occurred during synchronization update'), + category='error') + + return redirect( + url('edit_user_group_advanced', user_group_id=user_group_id)) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') @XHRRequired() @jsonify def user_group_members(self, user_group_id): diff --git a/rhodecode/model/user_group.py b/rhodecode/model/user_group.py --- a/rhodecode/model/user_group.py +++ b/rhodecode/model/user_group.py @@ -501,8 +501,8 @@ class UserGroupModel(BaseModel): if not existing_group: desc = 'Automatically created from plugin:%s' % extern_type # we use first admin account to set the owner of the group - existing_group = UserGroupModel().create(gr, desc, owner, - group_data={'extern_type': extern_type}) + existing_group = UserGroupModel().create( + gr, desc, owner, group_data={'extern_type': extern_type}) # we can only add users to special groups created via plugins managed = 'extern_type' in existing_group.group_data @@ -511,8 +511,7 @@ class UserGroupModel(BaseModel): UserGroupModel().add_user_to_group(existing_group, user) else: log.debug('Skipping addition to group %s since it is ' - 'not managed by auth plugins' % gr) - + 'not set to be automatically synchronized' % gr) def change_groups(self, user, groups): """ diff --git a/rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako b/rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako --- a/rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako +++ b/rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako @@ -6,6 +6,8 @@ (_('Created on'), h.format_date(c.user_group.created_on), '', '',), (_('Members'), len(c.group_members_obj),'', [x for x in c.group_members_obj]), + (_('Automatic member sync'), 'Yes' if c.user_group.group_data.get('extern_type') else 'No', '', '',), + (_('Assigned to repositories'), len(c.group_to_repos),'', [x for x in c.group_to_repos]), (_('Assigned to repo groups'), len(c.group_to_repo_groups), '', [x for x in c.group_to_repo_groups]), @@ -19,8 +21,55 @@
${base.dt_info_panel(elems)}
+ +
+
+

${_('Group members sync')}

+
+
+ <% sync_type = c.user_group.group_data.get('extern_type') %> + + % if sync_type: +

+ ${_('This group is set to be automatically synchronised.')}
+ ${_('Each member will be added or removed from this groups once they interact with RhodeCode system.')}
+ ${_('This group synchronization was set by')}: ${sync_type} +

+ % else: +

+ ${_('This group is not set to be automatically synchronised')} +

+ % endif + +
+ ${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')} +
+ +
+
+ + %if sync_type: + ${_('User group will no longer synchronize membership')} + %else: + ${_('User group will start to synchronize membership')} + %endif + +
+ ${h.end_form()} +
+ +
+
+ +

${_('Delete User Group')}

diff --git a/rhodecode/templates/admin/user_groups/user_groups.mako b/rhodecode/templates/admin/user_groups/user_groups.mako --- a/rhodecode/templates/admin/user_groups/user_groups.mako +++ b/rhodecode/templates/admin/user_groups/user_groups.mako @@ -58,8 +58,10 @@ { data: {"_": "members", "sort": "members", "type": Number}, title: "${_('Members')}", className: "td-number" }, + { data: {"_": "sync", + "sort": "sync"}, title: "${_('Sync')}", className: "td-sync" }, { data: {"_": "active", - "sort": "active"}, title: "${_('Active')}", className: "td-active", className: "td-number"}, + "sort": "active"}, title: "${_('Active')}", className: "td-active" }, { data: {"_": "owner", "sort": "owner"}, title: "${_('Owner')}", className: "td-user" }, { data: {"_": "action", diff --git a/rhodecode/tests/functional/test_admin_user_groups.py b/rhodecode/tests/functional/test_admin_user_groups.py --- a/rhodecode/tests/functional/test_admin_user_groups.py +++ b/rhodecode/tests/functional/test_admin_user_groups.py @@ -21,7 +21,7 @@ import pytest from rhodecode.tests import ( - TestController, url, assert_session_flash, link_to) + TestController, url, assert_session_flash, link_to, TEST_USER_ADMIN_LOGIN) from rhodecode.model.db import User, UserGroup from rhodecode.model.meta import Session from rhodecode.tests.fixture import Fixture @@ -56,6 +56,41 @@ class TestAdminUsersGroupsController(Tes response, 'Created user group %s' % user_group_link) + def test_set_synchronization(self): + self.log_user() + users_group_name = TEST_USER_GROUP + 'sync' + response = self.app.post(url('users_groups'), { + 'users_group_name': users_group_name, + 'user_group_description': 'DESC', + 'active': True, + 'csrf_token': self.csrf_token}) + + group = Session().query(UserGroup).filter( + UserGroup.users_group_name == users_group_name).one() + + assert group.group_data.get('extern_type') is None + + # enable + self.app.post( + url('edit_user_group_advanced_sync', user_group_id=group.users_group_id), + params={'csrf_token': self.csrf_token}, status=302) + + group = Session().query(UserGroup).filter( + UserGroup.users_group_name == users_group_name).one() + assert group.group_data.get('extern_type') == 'manual' + assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN + + # disable + self.app.post( + url('edit_user_group_advanced_sync', + user_group_id=group.users_group_id), + params={'csrf_token': self.csrf_token}, status=302) + + group = Session().query(UserGroup).filter( + UserGroup.users_group_name == users_group_name).one() + assert group.group_data.get('extern_type') is None + assert group.group_data.get('extern_type_set_by') == TEST_USER_ADMIN_LOGIN + def test_delete(self): self.log_user() users_group_name = TEST_USER_GROUP + 'another' @@ -77,7 +112,7 @@ class TestAdminUsersGroupsController(Tes group = Session().query(UserGroup).filter( UserGroup.users_group_name == users_group_name).one() - response = self.app.post( + self.app.post( url('delete_users_group', user_group_id=group.users_group_id), params={'_method': 'delete', 'csrf_token': self.csrf_token})