Files
stapler/tests/test_token_manager.py
T
2026-04-21 16:10:20 +02:00

140 lines
5.0 KiB
Python

import logging
import typing
import unittest
import unittest.mock
from stapler.page import Page
from stapler.params import Parameters
from stapler.token_manager import TokenManager
from . import BaseTestCase
class TestTokenManager(BaseTestCase):
EMPTY_SALT_HASH = "a04ca803c9fd73c21b721ece14b8b30cd3d9ca1bff752904a46982b881e152d0cdaa463a32e6bce71408de611953bc304ca8000d40d4b06b3f2a70769f69fecc"
SALT_HASH = "a5f2d8785eb4f064eae60f94e6025f93be32c2c93d2bbd73a982ee5c7ebcc484536487a4f60cfdfcb9ba72da7cebe0ce11afa91f191272e51d8c14be6874824b"
SECRET_HASH = "9901847ff8c76bd5fb473b7bd2e4f4ddd110332a52a888fd69deb276613885ddf382e5cf1210ed0decdb8010ae3994331a9e0639c3ca7e9e8b110dd50978ce76" # noqa: S105
@typing.override
def setUp(self) -> None:
self.registry = self.new_mock()
self.token_manager = TokenManager(
Parameters(data_dir=self.get_tmp_dir(), token_salt="salt"), # noqa: S106
self.registry,
)
self.token_manager.logger = unittest.mock.Mock(logging.Logger)
self.tmp_tokens_file = self.tmp_path / TokenManager.FILE
super().setUp()
def test_init_no_hashes(self) -> None:
self.seal_mocks()
self.token_manager.init()
self.assert_file_content(self.tmp_tokens_file, self.SALT_HASH)
self.assertEqual(self.tmp_tokens_file.stat().st_mode, 0o100600)
self.assertListEqual(self.token_manager.token_hashes, [])
def test_init_weak_salt(self) -> None:
self.token_manager.token_salt = ""
self.seal_mocks()
self.token_manager.init()
self.assert_file_content(
self.tmp_tokens_file,
self.EMPTY_SALT_HASH,
)
self.assertListEqual(self.token_manager.token_hashes, [])
def test_init_load_hashes(self) -> None:
with self.tmp_tokens_file.open(mode="w") as file:
file.write(self.SALT_HASH + "\n" + self.SECRET_HASH)
self.seal_mocks()
self.token_manager.init()
self.assertListEqual(self.token_manager.token_hashes, [self.SECRET_HASH])
def test_init_invalid_salt(self) -> None:
with self.tmp_tokens_file.open(mode="w") as file:
file.write(self.EMPTY_SALT_HASH + "\n" + self.SECRET_HASH)
self.seal_mocks()
self.token_manager.init()
self.assertListEqual(self.token_manager.token_hashes, [])
def test_is_valid(self) -> None:
self.seal_mocks()
self.token_manager.token_hashes = [self.SECRET_HASH]
assert self.token_manager.is_valid("secret")
def test_is_valid_fail(self) -> None:
self.seal_mocks()
assert not self.token_manager.is_valid("secret")
def test_is_valid_for_path(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1", token_hash=self.SECRET_HASH),
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_no_token(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1"),
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_no_page(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_fail(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1", token_hash=self.SALT_HASH),
),
self.seal_mocks(),
):
assert not self.token_manager.is_valid_for_path("secret", "test_1")
def test_set_token(self) -> None:
with (
self.mock_call(
self.registry.set_token_hash,
["test_1", self.SECRET_HASH],
),
self.seal_mocks(),
):
self.token_manager.set_token("test_1", "secret")
def test_detect_file_change(self) -> None:
self.tmp_tokens_file.touch()
self.seal_mocks()
assert self.token_manager.detect_file_change()
def test_detect_file_change_nothing(self) -> None:
self.tmp_tokens_file.touch()
self.token_manager.last_file_change = self.tmp_tokens_file.stat().st_mtime
self.seal_mocks()
assert not self.token_manager.detect_file_change()
@unittest.mock.patch("secrets.token_hex")
def test_new_token(self, mock_token_hex: unittest.mock.Mock) -> None:
mock_token_hex.return_value = "secret"
self.seal_mocks()
self.token_manager.new_token()
self.assertListEqual(self.token_manager.token_hashes, [self.SECRET_HASH])
self.assert_file_content(self.tmp_tokens_file, self.SALT_HASH, self.SECRET_HASH)