From 0ea45364bfd68885faa1dbb855c51dbd4b65b545 Mon Sep 17 00:00:00 2001 From: gabdevele Date: Sun, 12 Apr 2026 20:25:30 +0200 Subject: [PATCH] feat: update datetime handling to use UTC and improve type annotations --- app/api/auth/router.py | 9 +++++---- app/core/security.py | 12 ++++++++---- app/db/auth.py | 7 ++++--- app/db/proxy.py | 7 ++++--- pyproject.toml | 6 +++++- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/app/api/auth/router.py b/app/api/auth/router.py index 492351e..c02379a 100644 --- a/app/api/auth/router.py +++ b/app/api/auth/router.py @@ -1,4 +1,5 @@ -from datetime import datetime, timezone +from datetime import UTC, datetime +from typing import Annotated from core.security import ( AuthContext, @@ -32,9 +33,9 @@ async def login_handler(payload: LoginInput): @router.post("/logout", status_code=status.HTTP_204_NO_CONTENT) async def logout_handler( - auth_context: AuthContext = Depends(get_auth_context), + auth_context: Annotated[AuthContext, Depends(get_auth_context)], ) -> Response: - expires_at = datetime.fromtimestamp(auth_context.payload.exp, tz=timezone.utc) - if expires_at > datetime.now(timezone.utc): + expires_at = datetime.fromtimestamp(auth_context.payload.exp, tz=UTC) + if expires_at > datetime.now(UTC): await revoke_token(jti=auth_context.payload.jti, expires_at=expires_at) return Response(status_code=status.HTTP_204_NO_CONTENT) diff --git a/app/core/security.py b/app/core/security.py index b783ba2..bb7502a 100644 --- a/app/core/security.py +++ b/app/core/security.py @@ -1,5 +1,6 @@ from dataclasses import dataclass -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta +from typing import Annotated from uuid import uuid4 from authlib.jose import jwt # type: ignore @@ -43,7 +44,7 @@ def verify_password(plain_password: str, password_hash: str) -> bool: def create_access_token(*, subject: str) -> str: - now = datetime.now(timezone.utc) + now = datetime.now(UTC) expires_delta = timedelta(minutes=settings.JWT_EXPIRE_MINUTES) expires_at = int((now + expires_delta).timestamp()) @@ -72,7 +73,10 @@ def decode_access_token(token: str) -> AccessTokenPayload: async def get_auth_context( - credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme), + credentials: Annotated[ + HTTPAuthorizationCredentials | None, + Depends(bearer_scheme), + ], ) -> AuthContext: if credentials is None or credentials.scheme.lower() != "bearer": raise token_auth_error() @@ -94,6 +98,6 @@ async def get_auth_context( async def require_authenticated_user( - auth_context: AuthContext = Depends(get_auth_context), + auth_context: Annotated[AuthContext, Depends(get_auth_context)], ) -> AuthUserDocument: return auth_context.user diff --git a/app/db/auth.py b/app/db/auth.py index 1fee971..1269e42 100644 --- a/app/db/auth.py +++ b/app/db/auth.py @@ -1,5 +1,6 @@ -from datetime import datetime, timezone -from typing import Any, Mapping +from collections.abc import Mapping +from datetime import UTC, datetime +from typing import Any from core.mongodb import get_database from models.auth import AuthUserDocument @@ -10,7 +11,7 @@ REVOKED_COLLECTION_NAME = "revoked_tokens" def utcnow() -> datetime: - return datetime.now(timezone.utc) + return datetime.now(UTC) async def users_collection() -> AsyncIOMotorCollection[dict[str, Any]]: diff --git a/app/db/proxy.py b/app/db/proxy.py index f71b4a8..ad9e9be 100644 --- a/app/db/proxy.py +++ b/app/db/proxy.py @@ -1,5 +1,6 @@ -from datetime import datetime, timezone -from typing import Any, Mapping +from collections.abc import Mapping +from datetime import UTC, datetime +from typing import Any from core.mongodb import get_database from models.proxy import ProxyDocument, ProxyUpdateInput @@ -12,7 +13,7 @@ COLLECTION_NAME = "proxies" def _utcnow() -> datetime: - return datetime.now(timezone.utc) + return datetime.now(UTC) async def _collection() -> AsyncIOMotorCollection[dict[str, Any]]: diff --git a/pyproject.toml b/pyproject.toml index 58e0b5b..0e1e0a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,8 +12,12 @@ dependencies = [ "redis>=7.4.0", ] +[tool.ruff] +target-version = "py314" +line-length = 88 + [tool.ruff.lint] -select = ["E", "F", "I"] +select = ["E", "F", "I", "B", "UP"] [tool.ruff.format] quote-style = "double"