From cda0c00fa07c6576e434ef9bf547d3734060d8f9 Mon Sep 17 00:00:00 2001 From: Daniel M Date: Sun, 3 Nov 2024 10:20:12 -0500 Subject: [PATCH] acl save/load --- fakeredis/commands_mixins/acl_mixin.py | 15 ++++++++- fakeredis/model/_acl.py | 15 ++++++--- test/test_internals/test_acl_save_load.py | 37 ++++++++++++++++++++++- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/fakeredis/commands_mixins/acl_mixin.py b/fakeredis/commands_mixins/acl_mixin.py index e242236c..5e1a534e 100644 --- a/fakeredis/commands_mixins/acl_mixin.py +++ b/fakeredis/commands_mixins/acl_mixin.py @@ -159,6 +159,19 @@ def acl_load(self) -> SimpleString: with open(acl_filename, "rb") as f: rules_list = f.readlines() for rule in rules_list: + if not rule.startswith(b"user "): + continue splitted = rule.split(b" ") - self._set_user_acl(splitted[0], *splitted[1:]) + components = list() + i = 1 + while i < len(splitted): + current_component = splitted[i] + if current_component.startswith(b"("): + while not current_component.endswith(b")"): + i += 1 + current_component += b" " + splitted[i] + components.append(current_component) + i += 1 + + self._set_user_acl(components[0], *components[1:]) return OK diff --git a/fakeredis/model/_acl.py b/fakeredis/model/_acl.py index 572f0dbe..6a1b4137 100644 --- a/fakeredis/model/_acl.py +++ b/fakeredis/model/_acl.py @@ -16,23 +16,28 @@ def as_array(self) -> List[bytes]: @classmethod def from_bytes(cls, data: bytes) -> "Selector": - allowed = data[0] == ord("+") - data = data[1:] - command, data = data.split(b" ", 1) keys = b"" channels = b"" + command = b"" + allowed = False data = data.split(b" ") for item in data: - if item.startswith(b"&"): + if item.startswith(b"&"): # channels channels = item continue - if item.startswith(b"%RW"): + if item.startswith(b"%RW"): # keys item = item[3:] key = item if key.startswith(b"%"): key = key[2:] if key.startswith(b"~"): keys = item + continue + # command + if item[0] == ord("+") or item[0] == ord("-"): + command = item[1:] + allowed = item[0] == ord("+") + return cls(command, allowed, keys, channels) diff --git a/test/test_internals/test_acl_save_load.py b/test/test_internals/test_acl_save_load.py index f72e81e6..2d3760e9 100644 --- a/test/test_internals/test_acl_save_load.py +++ b/test/test_internals/test_acl_save_load.py @@ -1,3 +1,5 @@ +import os + from fakeredis import FakeServer, FakeStrictRedis @@ -19,6 +21,39 @@ def test_acl_save_load(): ) r.acl_save() - with open(acl_filename, "rb") as f: + # assert acl file contains all data + with open(acl_filename, "r") as f: lines = f.readlines() assert len(lines) == 1 + user_rule = lines[0] + assert user_rule.startswith("user fakeredis-user") + assert "nopass" not in user_rule + assert "#e6c3da5b206634d7f3f3586d747ffdb36b5c675757b380c6a5fe5c570c714349" in user_rule + assert "#1ba3d16e9881959f8c9a9762854f72c6e6321cdd44358a10a4e939033117eab9" in user_rule + assert "on" in user_rule + assert "~cache:*" in user_rule + assert "~objects:*" in user_rule + assert "resetchannels &message:*" in user_rule + assert "(%W~app* resetchannels -@all +set)" in user_rule + assert "(~app* resetchannels &x -@all +get)" in user_rule + assert "(%W~app* resetchannels -@all -hset)" in user_rule + + # assert acl file is loaded correctly + server2 = FakeServer(config={b"aclfile": acl_filename}) + r2 = FakeStrictRedis(server=server2) + r2.acl_load() + rules = r2.acl_list() + user_rule = next(filter(lambda x: x.startswith(f"user {username}"), rules), None) + assert user_rule.startswith("user fakeredis-user") + assert "nopass" not in user_rule + assert "#e6c3da5b206634d7f3f3586d747ffdb36b5c675757b380c6a5fe5c570c714349" in user_rule + assert "#1ba3d16e9881959f8c9a9762854f72c6e6321cdd44358a10a4e939033117eab9" in user_rule + assert "on" in user_rule + assert "~cache:*" in user_rule + assert "~objects:*" in user_rule + assert "resetchannels &message:*" in user_rule + assert "(%W~app* resetchannels -@all +set)" in user_rule + assert "(~app* resetchannels &x -@all +get)" in user_rule + assert "(%W~app* resetchannels -@all -hset)" in user_rule + + os.remove(acl_filename)