From 4d79561f8dffead3693532ee59826e92ef3617b9 Mon Sep 17 00:00:00 2001 From: Jakub Miazek Date: Thu, 9 Nov 2023 21:25:40 +0100 Subject: [PATCH 1/3] instantiate logger in a standard way --- app/api/stuff.py | 2 +- app/database.py | 2 +- app/main.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/api/stuff.py b/app/api/stuff.py index 3e572f3..d6dc341 100644 --- a/app/api/stuff.py +++ b/app/api/stuff.py @@ -7,7 +7,7 @@ from app.models.stuff import Stuff from app.schemas.stuff import StuffResponse, StuffSchema from app.utils.logging import AppLogger -logger = AppLogger.__call__().get_logger() +logger = AppLogger().get_logger() router = APIRouter(prefix="/v1/stuff") diff --git a/app/database.py b/app/database.py index 914690e..24d015b 100644 --- a/app/database.py +++ b/app/database.py @@ -6,7 +6,7 @@ from sqlalchemy.ext.asyncio import async_sessionmaker from app.config import settings as global_settings from app.utils.logging import AppLogger -logger = AppLogger.__call__().get_logger() +logger = AppLogger().get_logger() engine = create_async_engine( global_settings.asyncpg_url.unicode_string(), diff --git a/app/main.py b/app/main.py index 7482c8a..5034333 100644 --- a/app/main.py +++ b/app/main.py @@ -11,7 +11,7 @@ from app.api.health import router as health_router from app.redis import get_redis from app.services.auth import AuthBearer -logger = AppLogger.__call__().get_logger() +logger = AppLogger().get_logger() @asynccontextmanager From 32367d783d0fbd1bf975dee0df804927212857df Mon Sep 17 00:00:00 2001 From: Jakub Miazek Date: Thu, 9 Nov 2023 21:32:01 +0100 Subject: [PATCH 2/3] This ensures that the Redis connection is always properly closed. --- app/main.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/main.py b/app/main.py index 5034333..c532175 100644 --- a/app/main.py +++ b/app/main.py @@ -18,9 +18,11 @@ logger = AppLogger().get_logger() async def lifespan(app: FastAPI): # Load the redis connection app.state.redis = await get_redis() - yield - # close redis connection and release the resources - app.state.redis.close() + try: + yield + finally: + # close redis connection and release the resources + app.state.redis.close() app = FastAPI(title="Stuff And Nonsense API", version="0.6", lifespan=lifespan) From a6b6725eaffb848cac8ce44babbed5d42c15091f Mon Sep 17 00:00:00 2001 From: Jakub Miazek Date: Thu, 9 Nov 2023 21:43:53 +0100 Subject: [PATCH 3/3] The Redis database operations are abstracted into separate functions --- app/services/auth.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/services/auth.py b/app/services/auth.py index 10d22f4..3db0f36 100644 --- a/app/services/auth.py +++ b/app/services/auth.py @@ -8,9 +8,17 @@ from fastapi import Request, HTTPException from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +async def get_from_redis(request: Request, key: str): + return await request.app.state.redis.get(key) + + +async def set_to_redis(request: Request, key: str, value: str, ex: int): + return await request.app.state.redis.set(key, value, ex=ex) + + async def verify_jwt(request: Request, token: str) -> bool: - _payload = await request.app.state.redis.get(token) - return bool(_payload) + payload = await get_from_redis(request, token) + return bool(payload) class AuthBearer(HTTPBearer): @@ -29,13 +37,14 @@ class AuthBearer(HTTPBearer): async def create_access_token(user: User, request: Request): - _payload = { + # sourcery skip: avoid-builtin-shadow + payload = { "email": user.email, "expiry": time.time() + global_settings.jwt_expire, "platform": request.headers.get("User-Agent"), } - _token = jwt.encode(_payload, str(user.password), algorithm=global_settings.jwt_algorithm) + token = jwt.encode(payload, str(user.password), algorithm=global_settings.jwt_algorithm) - _bool = await request.app.state.redis.set(_token, str(_payload), ex=global_settings.jwt_expire) + _bool = await set_to_redis(request, token, str(payload), ex=global_settings.jwt_expire) if _bool: - return _token + return token