Skip to content

Commit

Permalink
Chore/maintenance (#17)
Browse files Browse the repository at this point in the history
* chore: update core libraries

* chore: add app title to openapi docs

* chore: set updated date in price prediction script

* chore: replace deprecated datetime.utcnow method where applicable

* chore: use UTC-time when updating time field for documents

* chore: read db data in consistent timezone

- set tz aware mode when connecting to db
- remove timezone conversion for refresh token expiry date during token refresh flow
  • Loading branch information
dhruv-ahuja authored Jun 23, 2024
1 parent 59a0987 commit b8c58bf
Show file tree
Hide file tree
Showing 11 changed files with 30 additions and 19 deletions.
21 changes: 16 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ anyio==3.7.1
APScheduler==3.10.4
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
beanie==1.24.0
beanie==1.26.0
billiard==4.2.0
boto3==1.34.131
boto3-stubs==1.28.85
Expand All @@ -21,7 +21,8 @@ cryptography==42.0.4
dnspython==2.6.1
ecdsa==0.18.0
email-validator==2.1.0.post1
fastapi==0.109.2
fastapi==0.111.0
fastapi-cli==0.0.4
gunicorn==22.0.0
h11==0.14.0
hiredis==2.3.2
Expand All @@ -30,11 +31,15 @@ httptools==0.6.1
httpx==0.26.0
idna==3.7
iniconfig==2.0.0
Jinja2==3.1.4
jmespath==1.0.1
joblib==1.4.2
kombu==5.3.4
lazy-model==0.2.0
loguru==0.7.2
markdown-it-py==3.0.0
MarkupSafe==2.1.5
mdurl==0.1.2
memory-profiler==0.61.0
motor==3.3.1
mypy-boto3-cloudformation==1.28.83
Expand All @@ -55,13 +60,15 @@ passlib==1.7.4
patsy==0.5.6
pluggy==1.3.0
prompt-toolkit==3.0.41
psutil==6.0.0
pyasn1==0.5.1
pycparser==2.21
pycurl==7.45.2
pydantic==2.5.0
pydantic==2.7.4
pydantic-settings==2.1.0
pydantic_core==2.14.1
pydantic_core==2.18.4
pyfakefs==5.3.2
Pygments==2.18.0
pymongo==4.6.3
pytest==7.4.3
pytest-asyncio==0.21.1
Expand All @@ -74,22 +81,26 @@ python-multipart==0.0.9
pytz==2023.3.post1
PyYAML==6.0.1
redis==5.0.1
rich==13.7.1
rsa==4.9
ruff==0.1.5
s3transfer==0.10.1
scikit-learn==1.5.0
scipy==1.13.1
shellingham==1.5.4
six==1.16.0
sniffio==1.3.0
starlette==0.36.3
starlette==0.37.2
statsmodels==0.14.2
threadpoolctl==3.5.0
toml==0.10.2
typer==0.12.3
types-awscrt==0.19.10
types-s3transfer==0.7.0
typing_extensions==4.8.0
tzdata==2023.3
tzlocal==5.2
ujson==5.10.0
urllib3==2.2.2
uvicorn==0.24.0.post1
uvloop==0.19.0
Expand Down
4 changes: 2 additions & 2 deletions src/config/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ async def setup_services(app_: FastAPI) -> t.AsyncGenerator[None, t.Any]:
scheduler.start()
async_scheduler.start()

delete_older_than = dt.datetime.utcnow() - dt.timedelta(days=1)
delete_older_than = dt.datetime.now(dt.UTC) - dt.timedelta(days=1)
jobs.schedule_tokens_deletion(delete_older_than, async_scheduler)
jobs.schedule_price_prediction_run(async_scheduler)

Expand All @@ -289,4 +289,4 @@ async def setup_services(app_: FastAPI) -> t.AsyncGenerator[None, t.Any]:

settings = generate_settings_config()
# initialize global client object for use across app
db_client = AsyncIOMotorClient(settings.db_url.get_secret_value())
db_client = AsyncIOMotorClient(settings.db_url.get_secret_value(), tz_aware=True)
5 changes: 2 additions & 3 deletions src/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import datetime as dt
import orjson
import pytz
from typing import Any, cast

from beanie import PydanticObjectId
Expand Down Expand Up @@ -80,6 +79,7 @@ async def check_refresh_token(refresh_token: str) -> dict[str, Any]:

forbidden_error = HTTPException(status.HTTP_401_UNAUTHORIZED)

breakpoint()
token_data = check_bearer_token(refresh_token, forbidden_error)
user_id = token_data["sub"]
token_expiration_time = dt.datetime.fromtimestamp(token_data["exp"], dt.UTC)
Expand All @@ -97,9 +97,8 @@ async def check_refresh_token(refresh_token: str) -> dict[str, Any]:
session_refresh_token = user_session.refresh_token

session_expiration_time = cast(dt.datetime, user_session.expiration_time)
session_token_expiration_time = pytz.utc.localize(session_expiration_time)

if session_token_expiration_time < token_expiration_time or session_refresh_token != refresh_token:
if session_expiration_time < token_expiration_time or session_refresh_token != refresh_token:
raise forbidden_error

return token_data
Expand Down
4 changes: 3 additions & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
newrelic.agent.initialize("./newrelic.ini")


app = FastAPI(lifespan=setup_services, redirect_slashes=False, default_response_class=ORJSONResponse)
app = FastAPI(
lifespan=setup_services, redirect_slashes=False, default_response_class=ORJSONResponse, title="Backend Burger"
)

app.include_router(users.router)
app.include_router(auth.router)
Expand Down
2 changes: 1 addition & 1 deletion src/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ class DateMetadataDocument(Document):

@after_event(Update, Replace, SaveChanges, ValidateOnSave)
def update_document_time(self) -> None:
self.updated_time = dt.datetime.now()
self.updated_time = dt.datetime.now(dt.UTC)
1 change: 0 additions & 1 deletion src/models/poe.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class Item(DateMetadataDocument):
"""Item represents a Path of Exile in-game item. Each item belongs to a category. It contains information such as
item type and the current, past and predicted pricing, encapsulated in the `ItemPrice` schema."""

# TODO: ensure type_ field is serialized as 'type'
poe_ninja_id: int
id_type: ItemIdType | None = None
name: str
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/price_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async def update_items_data(items: list[Item], iteration_count: int) -> None:
pymongo.UpdateOne(
{"_id": item.id},
{
"$set": {"price": item_price_json},
"$set": {"price": item_price_json, "updated_date": dt.datetime.now(dt.UTC)},
},
)
)
Expand Down
4 changes: 2 additions & 2 deletions src/services/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async def save_session_details(
"""Saves users session details, storing the issued refresh token and its expiration time in the database.
Re-uses an existing session record or creates a new one."""

now = dt.datetime.utcnow()
now = dt.datetime.now(dt.UTC)

try:
user_record = await users_service.get_user_from_database(user.id)
Expand Down Expand Up @@ -104,7 +104,7 @@ async def invalidate_refresh_token(user: User, db_session: AgnosticClientSession
if user.session is not None:
user.session.refresh_token = None
user.session.expiration_time = None
user.session.updated_time = dt.datetime.utcnow()
user.session.updated_time = dt.datetime.now(dt.UTC)
await user.replace(session=db_session) # type: ignore
except Exception as exc:
logger.error(f"error invalidating refresh token: {exc}")
Expand Down
2 changes: 1 addition & 1 deletion src/services/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async def update_user(user_id: PydanticObjectId, user_input: UserUpdateInput) ->

user.name = user_input.name
user.email = user_input.email
user.updated_time = dt.datetime.utcnow()
user.updated_time = dt.datetime.now(dt.UTC)

try:
await user.replace() # type: ignore
Expand Down
2 changes: 1 addition & 1 deletion src/tests/config/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def sample_job():
scheduler = get_scheduler

job_id = "sample_job"
trigger = DateTrigger(run_date=dt.datetime.utcnow())
trigger = DateTrigger(run_date=dt.datetime.now(dt.UTC))
misfire_grace_time = None

job = setup_job(scheduler, sample_job, job_id, trigger, misfire_grace_time)
Expand Down
2 changes: 1 addition & 1 deletion src/utils/auth_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def compare_values(value: str, hashed_value: str) -> bool:
def create_bearer_token(expiry_time: dt.timedelta, sub: str | None = None) -> Tuple[str, dt.datetime]:
"""Creates an encoded access or refresh token with the given sub and expiry time."""

token_expires_in = dt.datetime.utcnow() + expiry_time
token_expires_in = dt.datetime.now(dt.UTC) + expiry_time
token_data: dict[str, Any] = {"exp": token_expires_in}

if sub is not None:
Expand Down

0 comments on commit b8c58bf

Please sign in to comment.