Skip to content

Commit

Permalink
chore:add redis-py 5.3.0b3 to test matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
cunla committed Dec 20, 2024
1 parent 66733fd commit c10a34b
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 49 deletions.
6 changes: 5 additions & 1 deletion fakeredis/_basefakesocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ def __init__(self, server: "FakeServer", db: int, *args: Any, **kwargs: Any) ->
self._pubsub: int
self._transaction_failed: bool
self._current_user: bytes = b"default"
self._client_info: bytes = b"" # todo pass client info from connection
# TODO fix
self._client_info: bytes = kwargs.pop(
"client_info",
b"id=3 addr=127.0.0.1:57275 laddr=127.0.0.1:6379 fd=8 name= age=16 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=48 qbuf-free=16842 argv-mem=25 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 tot-mem=18737 events=r cmd=auth user=default redir=-1 resp=2",
)

@property
def version(self) -> Tuple[int, ...]:
Expand Down
2 changes: 1 addition & 1 deletion fakeredis/_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def connect(self) -> None:
def _connect(self) -> FakeSocket:
if not self._server.connected:
raise redis.ConnectionError(msgs.CONNECTION_ERROR_MSG)
return FakeSocket(self._server, db=self.db, lua_modules=self._lua_modules)
return FakeSocket(self._server, db=self.db, lua_modules=self._lua_modules, client_info=self)

def can_read(self, timeout: Optional[float] = 0) -> bool:
if not self._server.connected:
Expand Down
6 changes: 4 additions & 2 deletions fakeredis/_fakesocket.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Set
from typing import Optional, Set, Any

from fakeredis.commands_mixins import (
BitmapCommandsMixin,
Expand Down Expand Up @@ -62,5 +62,7 @@ def __init__(
server: "FakeServer",
db: int,
lua_modules: Optional[Set[str]] = None, # noqa: F821
*args: Any,
**kwargs,
) -> None:
super(FakeSocket, self).__init__(server, db, lua_modules=lua_modules)
super(FakeSocket, self).__init__(server, db, *args, lua_modules=lua_modules, **kwargs)
2 changes: 2 additions & 0 deletions fakeredis/_msgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@

MISSING_ACLFILE_CONFIG = "ERR This Redis instance is not configured to use an ACL file. You may want to specify users via the ACL SETUSER command and then issue a CONFIG REWRITE (assuming you have a Redis configuration file set) in order to store users in the Redis configuration."

NO_PERMISSION_ERROR = "NOPERM User {} has no permissions to run the '{}' command"

# Command flags
FLAG_NO_SCRIPT = "s" # Command not allowed in scripts
FLAG_LEAVE_EMPTY_VAL = "v"
Expand Down
3 changes: 2 additions & 1 deletion fakeredis/commands_mixins/acl_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def __init(self, *args: Any, **kwargs: Any) -> None:
self.version: Tuple[int]
self._server: Any
self._current_user: bytes
self._client_info: bytes

@property
def _server_config(self) -> Dict[bytes, bytes]:
Expand Down Expand Up @@ -91,7 +92,7 @@ def auth(self, *args: bytes) -> bytes:
raise SimpleError(msgs.WRONG_ARGS_MSG6.format("AUTH"))
username = None if len(args) == 1 else args[0]
password = args[1] if len(args) == 2 else args[0]
if (username is None or username == b"default") and (password == self._server_config.get(b"requirepass", None)):
if (username is None or username == b"default") and (password == self._server_config.get(b"requirepass", b"")):
self._current_user = b"default"
return OK
if len(args) >= 1 and self._check_user_password(username, password):
Expand Down
6 changes: 5 additions & 1 deletion fakeredis/model/_acl.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import hashlib
from typing import Dict, Set, List, Union, Optional

from fakeredis import _msgs as msgs
from ._command_info import get_commands_by_category
from .._helpers import SimpleError, current_time

Expand Down Expand Up @@ -66,7 +67,7 @@ def set_nopass(self) -> None:
self._passwords.clear()

def check_password(self, password: Optional[bytes]) -> bool:
if self._nopass and not password:
if self._nopass:
return True
if not password:
return False
Expand Down Expand Up @@ -301,4 +302,7 @@ def validate_command(self, username: bytes, fields: List[bytes]):
if not user_acl.enabled:
raise SimpleError("User disabled")

command, args = fields[0], fields[1:]
if command.lower() not in user_acl._commands:
raise SimpleError(msgs.NO_PERMISSION_ERROR.format(username.decode(), command.lower().decode()))
# todo
76 changes: 38 additions & 38 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 44 additions & 5 deletions test/test_mixins/test_acl_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,45 @@ def test_acl_whoami(r: redis.Redis):
r.config_set("requirepass", "")


def test_acl_log_auth_exist(r: redis.Redis, request):
username = "fredis-py-user"

def teardown():
r.auth("", username="default")
r.acl_deluser(username)

request.addfinalizer(teardown)
r.acl_setuser(
username,
enabled=True,
reset=True,
commands=["+get", "+set", "+select"],
keys=["cache:*"],
passwords=["+pass1"],
)
r.acl_log_reset()

with pytest.raises(exceptions.AuthenticationError):
r.auth("xxx", username=username)
r.auth("pass1", username=username)

# Valid operation and key
assert r.set("cache:0", 1)
assert r.get("cache:0") == b"1"

r.auth("", "default")
log = r.acl_log()
assert isinstance(log, list)
assert len(log) == 1
assert len(r.acl_log(count=1)) == 1
assert isinstance(log[0], dict)

expected = r.acl_log(count=1)[0]
assert expected["username"] == username


@pytest.mark.usefixtures("create_redis")
def test_acl_log(r: redis.Redis, request, create_redis):
def test_acl_log_invalid_key(r: redis.Redis, request, create_redis):
username = "fredis-py-user"

def teardown():
Expand All @@ -277,14 +314,16 @@ def teardown():
assert r.set("cache:0", 1)
assert r.get("cache:0") == b"1"

# Invalid operation
with pytest.raises(exceptions.NoPermissionError) as command_not_permitted:
r.hset("cache:0", "hkey", "hval")

assert str(command_not_permitted.value) == "User fredis-py-user has no permissions to run the 'hset' command"

# Invalid key
with pytest.raises(exceptions.NoPermissionError):
r.get("violated_cache:0")

# Invalid operation
with pytest.raises(exceptions.NoPermissionError):
r.hset("cache:0", "hkey", "hval")

r.auth("", "default")
log = r.acl_log()
assert isinstance(log, list)
Expand Down

0 comments on commit c10a34b

Please sign in to comment.