diff options
author | Andy McCurdy <andy@andymccurdy.com> | 2019-10-03 09:25:53 -0700 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2019-12-28 22:23:43 -0800 |
commit | a6bfef091ee22090280542f7ec21a18e244ee090 (patch) | |
tree | 4b62a36fc15201892259d7826494b94532910090 | |
parent | 902093ce547252a71a0e751d14b0f9dc73ed77c2 (diff) | |
download | redis-py-a6bfef091ee22090280542f7ec21a18e244ee090.tar.gz |
ACL SETUSER now accepts add_passwords and remove_passwords
add_passwords is a string or list of passwords to add to the user
remove_passwords is a string or list of passwords to remove from the user
-rwxr-xr-x | redis/client.py | 41 | ||||
-rw-r--r-- | tests/test_commands.py | 18 |
2 files changed, 40 insertions, 19 deletions
diff --git a/redis/client.py b/redis/client.py index 61c9778..9d51558 100755 --- a/redis/client.py +++ b/redis/client.py @@ -954,8 +954,8 @@ class Redis(object): return self.execute_command('ACL SAVE') def acl_setuser(self, username, enabled=False, nopass=False, - passwords=None, categories=None, commands=None, - keys=None, reset=False): + add_passwords=None, remove_passwords=None, categories=None, + commands=None, keys=None, reset=False): """ Create or update an ACL user. @@ -969,10 +969,15 @@ class Redis(object): ``nopass`` is a boolean indicating whether the can authenticate without a password. This cannot be True if ``passwords`` are also specified. - ``passwords`` if specified is a list of strings that this user can - authenticate with. If ``passwords`` is not specified, the special - 'nopass' flag will be used to indicate this user does not need a - password to authenticate. + ``add_passwords`` if specified is a list of new passwords that this + user can authenticate with. For convenience, the value of + ``add_passwords`` can also be a simple string when adding a single + password. Note: Do not prefix passwords with '>'. + + ``remove_passwords`` if specified is a list of passwords to remove from + this user. For convenience, the value of ``remove_passwords`` can also + be a simple string when removing a single password. Note: Do not + prefix passwords with '<'. ``categories`` if specified is a list of strings representing category permissions. Each string must be prefixed with either a "+@" or "-@" @@ -1000,14 +1005,22 @@ class Redis(object): else: pieces.append('off') - if passwords and nopass: - raise DataError('Cannot set \'nopass\' and supply \'passwords\'') - - if passwords: - # as most users will have only one password, allow passwords to be - # specified as a simple string or a list - passwords = list_or_args(passwords, []) - for password in passwords: + if add_passwords and nopass: + raise DataError('Cannot set \'nopass\' and supply ' + '\'add_passwords\'') + + if remove_passwords: + # as most users will have only one password, allow remove_passwords + # to be specified as a simple string or a list + remove_passwords = list_or_args(remove_passwords, []) + for password in remove_passwords: + pieces.append('<%s' % password) + + if add_passwords: + # as most users will have only one password, allow add_passwords + # to be specified as a simple string or a list + add_passwords = list_or_args(add_passwords, []) + for password in add_passwords: pieces.append('>%s' % password) if nopass: diff --git a/tests/test_commands.py b/tests/test_commands.py index 9b2957d..06ed0de 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -128,7 +128,7 @@ class TestRedisCommands(object): # test all args assert r.acl_setuser(username, enabled=True, reset=True, - passwords=['pass1', 'pass2'], + add_passwords=['pass1', 'pass2'], categories=['+@set', '+@hash', '-@geo'], commands=['+get', '+mget', '-hset'], keys=['cache:*', 'objects:*']) @@ -142,12 +142,12 @@ class TestRedisCommands(object): # test reset=False keeps existing ACL and applies new ACL on top assert r.acl_setuser(username, enabled=True, reset=True, - passwords=['pass1'], + add_passwords=['pass1'], categories=['+@set'], commands=['+set'], keys=['cache:*']) assert r.acl_setuser(username, enabled=True, - passwords=['pass2'], + add_passwords=['pass2'], categories=['+@hash'], commands=['+mset'], keys=['objects:*']) @@ -159,6 +159,14 @@ class TestRedisCommands(object): assert set(acl['keys']) == set([b'cache:*', b'objects:*']) assert len(acl['passwords']) == 2 + # test remove_passwords + assert r.acl_setuser(username, enabled=True, reset=True, + add_passwords=['pass1', 'pass2']) + assert len(r.acl_getuser(username)['passwords']) == 2 + assert r.acl_setuser(username, enabled=True, + remove_passwords=['pass2']) + assert len(r.acl_getuser(username)['passwords']) == 1 + @skip_if_server_version_lt('6.0.0') def test_acl_list(self, r, request): username = 'redis-py-user' @@ -194,7 +202,7 @@ class TestRedisCommands(object): r.acl_setuser(username, commands=['get']) @skip_if_server_version_lt('6.0.0') - def test_acl_setuser_passwords_and_nopass_fails(self, r, request): + def test_acl_setuser_add_passwords_and_nopass_fails(self, r, request): username = 'redis-py-user' def teardown(): @@ -202,7 +210,7 @@ class TestRedisCommands(object): request.addfinalizer(teardown) with pytest.raises(exceptions.DataError): - r.acl_setuser(username, passwords='mypass', nopass=True) + r.acl_setuser(username, add_passwords='mypass', nopass=True) @skip_if_server_version_lt('6.0.0') def test_acl_users(self, r): |