user-groups: added info, and new panel to control user group synchronization.
- allows to check status of user-group and if it's going to be sync-ed via external plugins. - allows to set manual synchronization for already existing RhodeCode Groups.
This commit is contained in:
parent
19511543cf
commit
98f97b18fd
6 changed files with 128 additions and 9 deletions
|
|
@ -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']})
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class UserGroupsController(BaseController):
|
|||
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(BaseController):
|
|||
"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(BaseController):
|
|||
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'),
|
||||
|
|
@ -458,6 +458,36 @@ class UserGroupsController(BaseController):
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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 @@
|
|||
<div class="panel-body">
|
||||
${base.dt_info_panel(elems)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">${_('Group members sync')}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<% sync_type = c.user_group.group_data.get('extern_type') %>
|
||||
|
||||
% if sync_type:
|
||||
<p>
|
||||
${_('This group is set to be automatically synchronised.')}<br/>
|
||||
${_('Each member will be added or removed from this groups once they interact with RhodeCode system.')}<br/>
|
||||
${_('This group synchronization was set by')}: <strong>${sync_type}</strong>
|
||||
</p>
|
||||
% else:
|
||||
<p>
|
||||
${_('This group is not set to be automatically synchronised')}
|
||||
</p>
|
||||
% endif
|
||||
|
||||
<div>
|
||||
${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')}
|
||||
<div class="field">
|
||||
<button class="btn btn-default" type="submit">
|
||||
%if sync_type:
|
||||
${_('Disable synchronization')}
|
||||
%else:
|
||||
${_('Enable synchronization')}
|
||||
%endif
|
||||
</button>
|
||||
</div>
|
||||
<div class="field">
|
||||
<span class="help-block">
|
||||
%if sync_type:
|
||||
${_('User group will no longer synchronize membership')}
|
||||
%else:
|
||||
${_('User group will start to synchronize membership')}
|
||||
%endif
|
||||
</span>
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">${_('Delete User Group')}</h3>
|
||||
|
|
|
|||
|
|
@ -58,8 +58,10 @@ $(document).ready(function() {
|
|||
{ 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",
|
||||
|
|
|
|||
|
|
@ -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(TestController):
|
|||
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(TestController):
|
|||
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})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue