Skip to content

Commit 7593d2d

Browse files
committed
implement username
1 parent 222fdb3 commit 7593d2d

File tree

10 files changed

+296
-65
lines changed

10 files changed

+296
-65
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.idea
2+
benchmark
3+
commands.json
4+
dist
5+
docs/build
6+
init.sh
7+
*__pycache__*
8+
python_redis.egg-info/

pyredis/client.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ class ClusterClient(
202202
:param read_timeout:
203203
Read Timeout.
204204
:type read_timeout: float
205+
206+
:param username:
207+
Username used for acl scl authentication. If not set, fall back use legacy auth.
208+
:type username: str
205209
"""
206210
def __init__(
207211
self,
@@ -212,7 +216,9 @@ def __init__(
212216
slave_ok=False,
213217
conn_timeout=2,
214218
read_timeout=2,
215-
cluster_map=None):
219+
cluster_map=None,
220+
username=None
221+
):
216222
super().__init__()
217223
if not bool(seeds) != bool(cluster_map):
218224
raise PyRedisError('Ether seeds or cluster_map has to be provided')
@@ -229,6 +235,7 @@ def __init__(
229235
else:
230236
self._map = ClusterMap(seeds=seeds)
231237
self._map_id = self._map.id
238+
self._username = username
232239

233240
def _cleanup_conns(self):
234241
hosts = self._map.hosts(slave=self._slave_ok)
@@ -250,7 +257,8 @@ def _connect(self, sock):
250257
read_only=self._slave_ok,
251258
encoding=self._encoding,
252259
password=self._password,
253-
database=self._database
260+
database=self._database,
261+
username=self._username
254262
)
255263
self._conns[sock] = client
256264

@@ -364,7 +372,16 @@ class HashClient(
364372
- commands.String,
365373
- commands.Transaction
366374
"""
367-
def __init__(self, buckets, database=0, password=None, encoding=None, conn_timeout=2, read_timeout=2):
375+
def __init__(
376+
self,
377+
buckets,
378+
database=None,
379+
password=None,
380+
encoding=None,
381+
conn_timeout=2,
382+
read_timeout=2,
383+
username=None
384+
):
368385

369386
super().__init__()
370387
self._conns = dict()
@@ -378,7 +395,15 @@ def __init__(self, buckets, database=0, password=None, encoding=None, conn_timeo
378395
self._closed = False
379396
self._cluster = True
380397
self._map = dict()
381-
self._init_conns(buckets, database, password, encoding, conn_timeout, read_timeout)
398+
self._init_conns(
399+
buckets=buckets,
400+
database=database,
401+
password=password,
402+
encoding=encoding,
403+
conn_timeout=conn_timeout,
404+
read_timeout=read_timeout,
405+
username=username
406+
)
382407
self._init_map()
383408

384409
def _bulk_fetch(self):
@@ -401,14 +426,20 @@ def _execute_bulk(self, *args, conn):
401426
if self._bulk_size_current == self._bulk_size:
402427
self._bulk_fetch()
403428

404-
def _init_conns(self, buckets, database, password, encoding, conn_timeout, read_timeout):
429+
def _init_conns(self, buckets, database, password, encoding, conn_timeout, read_timeout, username):
405430
for bucket in buckets:
406431
host, port = bucket
407432
bucketname = '{0}_{1}'.format(host, port)
408433
self._conn_names.append(bucketname)
409434
self._conns[bucketname] = Connection(
410-
host=host, port=port, database=database, password=password,
411-
encoding=encoding, conn_timeout=conn_timeout, read_timeout=read_timeout
435+
host=host,
436+
port=port,
437+
database=database,
438+
password=password,
439+
encoding=encoding,
440+
conn_timeout=conn_timeout,
441+
read_timeout=read_timeout,
442+
username=username
412443
)
413444

414445
def _init_map(self):
@@ -576,15 +607,27 @@ class SentinelClient(object):
576607
Password used for authentication of Sentinel instance itself. If None, no authentication is done.
577608
Only available starting with Redis 5.0.1.
578609
:type password: str
610+
611+
:param username:
612+
Username used for acl scl authentication. If not set, fall back use legacy auth.
613+
:type username: str
579614
"""
580-
def __init__(self, sentinels, password=None):
615+
def __init__(self, sentinels, password=None, username=None):
581616
self._conn = None
582617
self._sentinels = deque(sentinels)
583618
self._password = password
619+
self._username = username
584620

585621
def _sentinel_connect(self, sentinel):
586622
host, port = sentinel
587-
self._conn = Connection(host=host, port=port, conn_timeout=0.1, sentinel=True, password=self._password)
623+
self._conn = Connection(
624+
host=host,
625+
port=port,
626+
conn_timeout=0.1,
627+
sentinel=True,
628+
password=self._password,
629+
username=self._username
630+
)
588631
try:
589632
self.execute('PING')
590633
return True

pyredis/connection.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Connection(object):
3333
:type unix_sock: str
3434
3535
:param database:
36-
Select which db should be used for this connection
36+
Select which db should be used for this connection, defaults to None, so we use the default database 0
3737
:type database: int
3838
3939
:param password:
@@ -56,19 +56,25 @@ class Connection(object):
5656
If True, authentication and database selection is skipped.
5757
:type sentinel: bool
5858
59+
:param username:
60+
Username used for acl scl authentication. If not set, fall back use legacy auth.
61+
:type username: str
62+
5963
"""
6064
def __init__(
6165
self,
6266
host=None,
6367
port=6379,
6468
unix_sock=None,
65-
database=0,
69+
database=None,
6670
password=None,
6771
encoding=None,
6872
conn_timeout=2,
6973
read_only=False,
7074
read_timeout=2,
71-
sentinel=False):
75+
sentinel=False,
76+
username=None
77+
):
7278

7379
if not bool(host) != bool(unix_sock):
7480
raise PyRedisError('Ether host or unix_sock has to be provided')
@@ -85,10 +91,18 @@ def __init__(
8591
self.port = port
8692
self.unix_sock = unix_sock
8793
self.password = password
94+
self.username = username
8895
self.database = database
8996

9097
def _authenticate(self):
91-
if self.password:
98+
if self.username and self.password:
99+
self.write('AUTH', self.username, self.password)
100+
try:
101+
self.read()
102+
except ReplyError as err:
103+
self.close()
104+
raise err
105+
elif self.password:
92106
self.write('AUTH', self.password)
93107
try:
94108
self.read()
@@ -163,6 +177,8 @@ def _connect_unix(self):
163177
def _setdb(self):
164178
if self._sentinel:
165179
return
180+
if self.database is None:
181+
return
166182
self._sock.settimeout(0.1)
167183
self.write('SELECT', self.database)
168184
try:

pyredis/helper.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,23 @@ def slot_from_key(key):
3838

3939

4040
class ClusterMap(object):
41-
def __init__(self, seeds, password=None, lock=Lock()):
41+
def __init__(
42+
self,
43+
seeds,
44+
password=None,
45+
lock=None,
46+
username=None,
47+
48+
):
4249
self._id = uuid4()
43-
self._lock = lock
50+
if not lock:
51+
self._lock = Lock()
52+
else:
53+
self._lock = lock
4454
self._map = {}
4555
self._seeds = deque(seeds)
4656
self._password = password
57+
self._username = username
4758

4859
@property
4960
def id(self):
@@ -55,7 +66,13 @@ def _make_str(endpoint):
5566

5667
def _fetch_map(self):
5768
for seed in self._seeds:
58-
conn = Connection(host=seed[0], port=seed[1], encoding='utf-8', password=self._password)
69+
conn = Connection(
70+
host=seed[0],
71+
port=seed[1],
72+
encoding='utf-8',
73+
password=self._password,
74+
username=self._username
75+
)
5976
try:
6077
conn.write(b'CLUSTER', b'SLOTS')
6178
return conn.read()

0 commit comments

Comments
 (0)