From 5fbfaa73ea91fb179c8ba87fee65635d90e7819a Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Fri, 13 Jan 2023 11:41:17 +0000 Subject: [PATCH] feat(tokens-repo): add clone() method --- .../tokens/abstract_tokens_repository.py | 16 +++++++ .../test_repository/test_tokens_repository.py | 45 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/selfprivacy_api/repositories/tokens/abstract_tokens_repository.py b/selfprivacy_api/repositories/tokens/abstract_tokens_repository.py index e5daa4d..d81bd65 100644 --- a/selfprivacy_api/repositories/tokens/abstract_tokens_repository.py +++ b/selfprivacy_api/repositories/tokens/abstract_tokens_repository.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from datetime import datetime from typing import Optional @@ -172,6 +174,20 @@ class AbstractTokensRepository(ABC): self.delete_new_device_key() self._delete_recovery_key() + def clone(self, source: AbstractTokensRepository) -> None: + """Clone the state of another repository to this one""" + self.reset() + for token in source.get_tokens(): + self._store_token(token) + + recovery_key = source.get_recovery_key() + if recovery_key is not None: + self._store_recovery_key(recovery_key) + + new_device_key = source._get_stored_new_device_key() + if new_device_key is not None: + self._store_new_device_key(new_device_key) + @abstractmethod def _store_token(self, new_token: Token): """Store a token directly""" diff --git a/tests/test_graphql/test_repository/test_tokens_repository.py b/tests/test_graphql/test_repository/test_tokens_repository.py index 7eede6a..360bfa5 100644 --- a/tests/test_graphql/test_repository/test_tokens_repository.py +++ b/tests/test_graphql/test_repository/test_tokens_repository.py @@ -17,7 +17,17 @@ from selfprivacy_api.repositories.tokens.exceptions import ( NewDeviceKeyNotFound, ) -from tests.common import FIVE_MINUTES_INTO_PAST +from selfprivacy_api.repositories.tokens.json_tokens_repository import ( + JsonTokensRepository, +) +from selfprivacy_api.repositories.tokens.redis_tokens_repository import ( + RedisTokensRepository, +) +from selfprivacy_api.repositories.tokens.abstract_tokens_repository import ( + AbstractTokensRepository, +) + +from tests.common import FIVE_MINUTES_INTO_PAST, FIVE_MINUTES_INTO_FUTURE ORIGINAL_DEVICE_NAMES = [ @@ -560,3 +570,36 @@ def test_use_mnemonic_new_device_key_when_empty(empty_repo): ) is None ) + + +def assert_identical( + repo_a: AbstractTokensRepository, repo_b: AbstractTokensRepository +): + tokens_a = repo_a.get_tokens() + tokens_b = repo_b.get_tokens() + assert len(tokens_a) == len(tokens_b) + for token in tokens_a: + assert token in tokens_b + assert repo_a.get_recovery_key() == repo_b.get_recovery_key() + assert repo_a._get_stored_new_device_key() == repo_b._get_stored_new_device_key() + + +def clone_to_redis(repo: JsonTokensRepository): + other_repo = RedisTokensRepository() + other_repo.clone(repo) + assert_identical(repo, other_repo) + + +# we cannot easily parametrize this unfortunately, since some_tokens and empty_repo cannot coexist +def test_clone_json_to_redis_empty(empty_repo): + repo = empty_repo + if isinstance(repo, JsonTokensRepository): + clone_to_redis(repo) + + +def test_clone_json_to_redis_full(some_tokens_repo): + repo = some_tokens_repo + if isinstance(repo, JsonTokensRepository): + repo.get_new_device_key() + repo.create_recovery_key(FIVE_MINUTES_INTO_FUTURE, 2) + clone_to_redis(repo)