summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy McCurdy <andy@andymccurdy.com>2019-10-03 09:25:53 -0700
committerAndy McCurdy <andy@andymccurdy.com>2019-12-28 22:23:43 -0800
commita6bfef091ee22090280542f7ec21a18e244ee090 (patch)
tree4b62a36fc15201892259d7826494b94532910090
parent902093ce547252a71a0e751d14b0f9dc73ed77c2 (diff)
downloadredis-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-xredis/client.py41
-rw-r--r--tests/test_commands.py18
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):