test_mfa.py
1 import hashlib 2 from unittest.mock import AsyncMock 3 4 from _pytest.monkeypatch import MonkeyPatch 5 from pytest_mock import MockerFixture 6 7 from api.settings import settings 8 from api.utils import mfa 9 10 11 async def test__check_mfa_code__blocked(mocker: MockerFixture) -> None: 12 redis_patch = mocker.patch("api.utils.mfa.redis") 13 14 code = "421337" 15 secret = "tRtD1eq5oMJydVA6zxUsohZdMIKTGgoj" 16 key = f"mfa_block:{hashlib.sha256(secret.encode()).hexdigest()}:{code}" 17 redis_patch.exists.return_value = True 18 19 assert await mfa.check_mfa_code(code, secret) is False 20 21 redis_patch.exists.assert_called_once_with(key) 22 23 24 async def test__check_mfa_code__invalid(mocker: MockerFixture, monkeypatch: MonkeyPatch) -> None: 25 redis_patch = mocker.patch("api.utils.mfa.redis", new_callable=AsyncMock) 26 totp_patch = mocker.patch("api.utils.mfa.TOTP") 27 monkeypatch.setattr(settings, "mfa_valid_window", 42) 28 29 code = "421337" 30 secret = "tRtD1eq5oMJydVA6zxUsohZdMIKTGgoj" 31 key = f"mfa_block:{hashlib.sha256(secret.encode()).hexdigest()}:{code}" 32 redis_patch.exists.return_value = False 33 totp_patch.return_value.verify.return_value = False 34 35 assert await mfa.check_mfa_code(code, secret) is False 36 37 redis_patch.exists.assert_called_once_with(key) 38 totp_patch.assert_called_once_with(secret) 39 totp_patch.return_value.verify.assert_called_once_with(code, valid_window=42) 40 41 42 async def test__check_mfa_code__valid(mocker: MockerFixture, monkeypatch: MonkeyPatch) -> None: 43 redis_patch = mocker.patch("api.utils.mfa.redis", new_callable=AsyncMock) 44 totp_patch = mocker.patch("api.utils.mfa.TOTP") 45 monkeypatch.setattr(settings, "mfa_valid_window", 42) 46 47 code = "421337" 48 secret = "tRtD1eq5oMJydVA6zxUsohZdMIKTGgoj" 49 key = f"mfa_block:{hashlib.sha256(secret.encode()).hexdigest()}:{code}" 50 redis_patch.exists.return_value = False 51 totp_patch.return_value.verify.return_value = True 52 53 assert await mfa.check_mfa_code(code, secret) is True 54 55 redis_patch.exists.assert_called_once_with(key) 56 totp_patch.assert_called_once_with(secret) 57 totp_patch.return_value.verify.assert_called_once_with(code, valid_window=42) 58 redis_patch.setex.assert_called_once_with(key, 2580, 1)