parent
5f3694ecfe
commit
fda86ce710
6 changed files with 230 additions and 0 deletions
|
|
@ -2058,6 +2058,23 @@ def handle_disable_user(goptions, session, args):
|
|||
session.disableUser(username)
|
||||
|
||||
|
||||
def handle_edit_user(goptions, session, args):
|
||||
"[admin] Alter user information"
|
||||
usage = _("usage: %prog edit-user name [options]")
|
||||
usage += _("\n(Specify the --help global option for a list of other help options)")
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--rename", help=_("Rename the user"))
|
||||
parser.add_option("--krb", help=_("Change kerberos principal of the user"))
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) < 1:
|
||||
parser.error(_("You must specify the username of the user to edit"))
|
||||
elif len(args) > 1:
|
||||
parser.error(_("This command only accepts one argument (username)"))
|
||||
activate_session(session, goptions)
|
||||
user = args[0]
|
||||
session.editUser(user, options.rename, options.krb)
|
||||
|
||||
|
||||
def handle_list_signed(goptions, session, args):
|
||||
"[admin] List signed copies of rpms"
|
||||
usage = _("usage: %prog list-signed [options]")
|
||||
|
|
|
|||
|
|
@ -3701,6 +3701,42 @@ def get_user(userInfo=None, strict=False, krb_princs=False):
|
|||
user['krb_principals'] = list_user_krb_principals(user['id'])
|
||||
return user
|
||||
|
||||
def edit_user(userInfo, name=None, krb_principal=None):
|
||||
"""Edit information for an existing user.
|
||||
|
||||
userInfo specifies the user to edit
|
||||
fields changes are provided as keyword arguments:
|
||||
name: rename the user
|
||||
krb_principal: change user's kerberos principal
|
||||
"""
|
||||
|
||||
context.session.assertPerm('admin')
|
||||
_edit_user(userInfo, name=name, krb_principal=krb_principal)
|
||||
|
||||
|
||||
def _edit_user(userInfo, name=None, krb_principal=None):
|
||||
"""Edit information for an existing user."""
|
||||
user = get_user(userInfo, strict=True)
|
||||
if name and user['name'] != name:
|
||||
# attempt to update user name
|
||||
values = {
|
||||
'name': name,
|
||||
'userID': user['id']
|
||||
}
|
||||
q = """SELECT id FROM users WHERE name=%(name)s"""
|
||||
id = _singleValue(q, values, strict=False)
|
||||
if id is not None:
|
||||
# new name is taken
|
||||
raise koji.GenericError("Name %s already taken by user %s" % (name, id))
|
||||
update = UpdateProcessor('users', values={'userID': user['id']}, clauses=['id = %(userID)i'])
|
||||
update.set(name=name)
|
||||
update.execute()
|
||||
if krb_principal and user['krb_principal'] != krb_principal:
|
||||
# attempt to update kerberos principal
|
||||
update = UpdateProcessor('users', values={'userID': user['id']}, clauses=['id = %(userID)i'])
|
||||
update.set(krb_principal=krb_principal)
|
||||
update.execute()
|
||||
|
||||
|
||||
def list_user_krb_principals(user_info=None):
|
||||
"""Return kerberos principal list of a user.
|
||||
|
|
@ -10942,6 +10978,7 @@ class RootExports(object):
|
|||
return pkgs.get(pkg_id, None)
|
||||
|
||||
getUser = staticmethod(get_user)
|
||||
editUser = staticmethod(edit_user)
|
||||
|
||||
def grantPermission(self, userinfo, permission, create=False):
|
||||
"""Grant a permission to a user"""
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ admin commands:
|
|||
edit-tag Alter tag information
|
||||
edit-tag-inheritance Edit tag inheritance
|
||||
edit-target Set the name, build_tag, and/or dest_tag of an existing build target to new values
|
||||
edit-user Alter user information
|
||||
enable-host Mark one or more hosts as enabled
|
||||
enable-user Enable logins by a user
|
||||
free-task Free a task
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ admin commands:
|
|||
edit-tag Alter tag information
|
||||
edit-tag-inheritance Edit tag inheritance
|
||||
edit-target Set the name, build_tag, and/or dest_tag of an existing build target to new values
|
||||
edit-user Alter user information
|
||||
enable-host Mark one or more hosts as enabled
|
||||
enable-user Enable logins by a user
|
||||
free-task Free a task
|
||||
|
|
|
|||
114
tests/test_cli/test_edit_user.py
Normal file
114
tests/test_cli/test_edit_user.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
from __future__ import absolute_import
|
||||
import mock
|
||||
import os
|
||||
import six
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
from koji_cli.commands import handle_edit_user
|
||||
|
||||
progname = os.path.basename(sys.argv[0]) or 'koji'
|
||||
|
||||
|
||||
class TestEditUser(unittest.TestCase):
|
||||
# Show long diffs in error output...
|
||||
maxDiff = None
|
||||
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
def test_handle_edit_user(self, activate_session_mock, stdout):
|
||||
user = 'user'
|
||||
rename = 'user2'
|
||||
krb_principal = 'krb'
|
||||
args = [user]
|
||||
args.append('--rename=' + rename)
|
||||
args.append('--krb=' + krb_principal)
|
||||
options = mock.MagicMock()
|
||||
|
||||
# Mock out the xmlrpc server
|
||||
session = mock.MagicMock()
|
||||
|
||||
# Run it and check immediate output
|
||||
# args: user --rename=user --krb=krb
|
||||
# expected: success
|
||||
rv = handle_edit_user(options, session, args)
|
||||
actual = stdout.getvalue()
|
||||
expected = ''
|
||||
self.assertMultiLineEqual(actual, expected)
|
||||
# Finally, assert that things were called as we expected.
|
||||
activate_session_mock.assert_called_once_with(session, options)
|
||||
session.editUser.assert_called_once_with(user, rename, krb_principal)
|
||||
self.assertEqual(rv, None)
|
||||
|
||||
stdout.seek(0)
|
||||
stdout.truncate()
|
||||
session.reset_mock()
|
||||
activate_session_mock.reset_mock()
|
||||
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('sys.stderr', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
def test_handle_edit_user_help(self, activate_session_mock, stderr, stdout):
|
||||
args = ['--help']
|
||||
options = mock.MagicMock()
|
||||
|
||||
# Mock out the xmlrpc server
|
||||
session = mock.MagicMock()
|
||||
|
||||
# Run it and check immediate output
|
||||
# args: --help
|
||||
# expected: failed, help info shows
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
handle_edit_user(options, session, args)
|
||||
actual_stdout = stdout.getvalue()
|
||||
actual_stderr = stderr.getvalue()
|
||||
expected_stdout = """Usage: %s edit-user name [options]
|
||||
(Specify the --help global option for a list of other help options)
|
||||
|
||||
Options:
|
||||
-h, --help show this help message and exit
|
||||
--rename=RENAME Rename the user
|
||||
--krb=KRB Change kerberos principal of the user
|
||||
""" % progname
|
||||
expected_stderr = ''
|
||||
self.assertMultiLineEqual(actual_stdout, expected_stdout)
|
||||
self.assertMultiLineEqual(actual_stderr, expected_stderr)
|
||||
# Finally, assert that things were called as we expected.
|
||||
activate_session_mock.assert_not_called()
|
||||
session.editUser.assert_not_called()
|
||||
self.assertEqual(cm.exception.code, 0)
|
||||
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('sys.stderr', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
def test_handle_edit_user_no_arg(self, activate_session_mock, stderr, stdout):
|
||||
args = []
|
||||
options = mock.MagicMock()
|
||||
|
||||
# Mock out the xmlrpc server
|
||||
session = mock.MagicMock()
|
||||
|
||||
# Run it and check immediate output
|
||||
# args: --help
|
||||
# expected: failed, help info shows
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
handle_edit_user(options, session, args)
|
||||
actual_stdout = stdout.getvalue()
|
||||
actual_stderr = stderr.getvalue()
|
||||
expected_stdout = ''
|
||||
expected_stderr = """Usage: %(progname)s edit-user name [options]
|
||||
(Specify the --help global option for a list of other help options)
|
||||
|
||||
%(progname)s: error: You must specify the username of the user to edit
|
||||
""" % {'progname': progname}
|
||||
self.assertMultiLineEqual(actual_stdout, expected_stdout)
|
||||
self.assertMultiLineEqual(actual_stderr, expected_stderr)
|
||||
# Finally, assert that things were called as we expected.
|
||||
activate_session_mock.assert_not_called()
|
||||
session.editUser.assert_not_called()
|
||||
self.assertEqual(cm.exception.code, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
60
tests/test_hub/test_edit_user.py
Normal file
60
tests/test_hub/test_edit_user.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
class TestEditUser(unittest.TestCase):
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.updates = []
|
||||
self._singleValue = mock.patch('kojihub._singleValue').start()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
# It seems MagicMock will not automatically handle attributes that
|
||||
# start with "assert"
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_edit(self):
|
||||
self.get_user.return_value = {'id': 333,
|
||||
'name': 'user',
|
||||
'krb_principal': 'krb'}
|
||||
self._singleValue.return_value = None
|
||||
|
||||
kojihub._edit_user('user', name='newuser', krb_principal='krb')
|
||||
# check the update
|
||||
self.assertEqual(len(self.updates), 1)
|
||||
update = self.updates[0]
|
||||
self.assertEqual(update.table, 'users')
|
||||
self.assertEqual(update.data, {'name': 'newuser'})
|
||||
self.assertEqual(update.values, {'userID': 333})
|
||||
self.assertEqual(update.clauses, ['id = %(userID)i'])
|
||||
|
||||
kojihub._edit_user('user', name='user', krb_principal='newkrb')
|
||||
# check the insert/update
|
||||
self.assertEqual(len(self.updates), 2)
|
||||
update = self.updates[1]
|
||||
self.assertEqual(update.table, 'users')
|
||||
self.assertEqual(update.data, {'krb_principal': 'newkrb'})
|
||||
self.assertEqual(update.values, {'userID': 333})
|
||||
self.assertEqual(update.clauses, ['id = %(userID)i'])
|
||||
|
||||
self._singleValue.reset_mock()
|
||||
self._singleValue.return_value = 2
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub._edit_user('user', name='newuser')
|
||||
self._singleValue.assert_called_once()
|
||||
self.assertEqual(cm.exception.args[0], 'Name newuser already taken by user 2')
|
||||
Loading…
Add table
Add a link
Reference in a new issue