mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2025-08-14 18:58:10 +08:00
124 lines
3.6 KiB
Python
124 lines
3.6 KiB
Python
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
|
|
from fastapi_users.authentication.strategy import RedisStrategy
|
|
from tests.conftest import IDType, UserModel
|
|
|
|
|
|
class RedisMock:
|
|
store: dict[str, tuple[str, Optional[int]]]
|
|
|
|
def __init__(self):
|
|
self.store = {}
|
|
|
|
async def get(self, key: str) -> Optional[str]:
|
|
try:
|
|
value, expiration = self.store[key]
|
|
if expiration is not None and expiration < datetime.now().timestamp():
|
|
return None
|
|
except KeyError:
|
|
return None
|
|
else:
|
|
return value
|
|
|
|
async def set(self, key: str, value: str, ex: Optional[int] = None):
|
|
expiration = None
|
|
if ex is not None:
|
|
expiration = int(datetime.now().timestamp() + ex)
|
|
self.store[key] = (value, expiration)
|
|
|
|
async def delete(self, key: str):
|
|
try:
|
|
del self.store[key]
|
|
except KeyError:
|
|
pass
|
|
|
|
|
|
@pytest.fixture
|
|
def redis() -> RedisMock:
|
|
return RedisMock()
|
|
|
|
|
|
@pytest.fixture
|
|
def redis_strategy(redis):
|
|
return RedisStrategy(redis, 3600)
|
|
|
|
|
|
@pytest.mark.authentication
|
|
class TestReadToken:
|
|
@pytest.mark.asyncio
|
|
async def test_missing_token(
|
|
self, redis_strategy: RedisStrategy[UserModel, IDType], user_manager
|
|
):
|
|
authenticated_user = await redis_strategy.read_token(None, user_manager)
|
|
assert authenticated_user is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_invalid_token(
|
|
self, redis_strategy: RedisStrategy[UserModel, IDType], user_manager
|
|
):
|
|
authenticated_user = await redis_strategy.read_token("TOKEN", user_manager)
|
|
assert authenticated_user is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_valid_token_invalid_uuid(
|
|
self,
|
|
redis_strategy: RedisStrategy[UserModel, IDType],
|
|
redis: RedisMock,
|
|
user_manager,
|
|
):
|
|
await redis.set(f"{redis_strategy.key_prefix}TOKEN", "bar")
|
|
authenticated_user = await redis_strategy.read_token("TOKEN", user_manager)
|
|
assert authenticated_user is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_valid_token_not_existing_user(
|
|
self,
|
|
redis_strategy: RedisStrategy[UserModel, IDType],
|
|
redis: RedisMock,
|
|
user_manager,
|
|
):
|
|
await redis.set(
|
|
f"{redis_strategy.key_prefix}TOKEN", "d35d213e-f3d8-4f08-954a-7e0d1bea286f"
|
|
)
|
|
authenticated_user = await redis_strategy.read_token("TOKEN", user_manager)
|
|
assert authenticated_user is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_valid_token(
|
|
self,
|
|
redis_strategy: RedisStrategy[UserModel, IDType],
|
|
redis: RedisMock,
|
|
user_manager,
|
|
user,
|
|
):
|
|
await redis.set(f"{redis_strategy.key_prefix}TOKEN", str(user.id))
|
|
authenticated_user = await redis_strategy.read_token("TOKEN", user_manager)
|
|
assert authenticated_user is not None
|
|
assert authenticated_user.id == user.id
|
|
|
|
|
|
@pytest.mark.authentication
|
|
@pytest.mark.asyncio
|
|
async def test_write_token(
|
|
redis_strategy: RedisStrategy[UserModel, IDType], redis: RedisMock, user
|
|
):
|
|
token = await redis_strategy.write_token(user)
|
|
|
|
value = await redis.get(f"{redis_strategy.key_prefix}{token}")
|
|
assert value == str(user.id)
|
|
|
|
|
|
@pytest.mark.authentication
|
|
@pytest.mark.asyncio
|
|
async def test_destroy_token(
|
|
redis_strategy: RedisStrategy[UserModel, IDType], redis: RedisMock, user
|
|
):
|
|
await redis.set(f"{redis_strategy.key_prefix}TOKEN", str(user.id))
|
|
|
|
await redis_strategy.destroy_token("TOKEN", user)
|
|
|
|
assert await redis.get(f"{redis_strategy.key_prefix}TOKEN") is None
|