Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions backend/app/user/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
UserProfileUpdateRequest,
)
from app.user.service import user_service
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException, Request, status
from utils.limiter import limiter
Comment on lines +10 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Remove unused import and verify limiter import path.

The status import from FastAPI is unused and should be removed as indicated by static analysis. Also, verify that the limiter import path is correct relative to the backend directory structure.

-from fastapi import APIRouter, Depends, HTTPException, Request, status
+from fastapi import APIRouter, Depends, HTTPException, Request

🏁 Script executed:

#!/bin/bash
# Verify the limiter module exists and the import path is correct
fd -t f "limiter.py" backend/

Length of output: 54


Remove unused FastAPI import

The status symbol isn’t referenced in this file, so it can be dropped. The limiter module path is correct (backend/utils/limiter.py), no change needed there.

-from fastapi import APIRouter, Depends, HTTPException, Request, status
+from fastapi import APIRouter, Depends, HTTPException, Request

— limiter import verified at backend/utils/limiter.py

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from fastapi import APIRouter, Depends, HTTPException, Request, status
from utils.limiter import limiter
-from fastapi import APIRouter, Depends, HTTPException, Request, status
+from fastapi import APIRouter, Depends, HTTPException, Request
from utils.limiter import limiter
🧰 Tools
🪛 Ruff (0.12.2)

10-10: fastapi.status imported but unused

Remove unused import: fastapi.status

(F401)

🤖 Prompt for AI Agents
In backend/app/user/routes.py at lines 10 to 11, the import of 'status' from
FastAPI is unused and should be removed to clean up the imports. Keep the import
of 'limiter' as is since it is correctly referenced. Simply delete ', status'
from the import statement on line 10.


router = APIRouter(prefix="/users", tags=["User"])


@router.get("/me", response_model=UserProfileResponse)
@limiter.limit("20/minute")
async def get_current_user_profile(
request: Request,
current_user: Dict[str, Any] = Depends(get_current_user),
):
user = await user_service.get_user_by_id(current_user["_id"])
Expand All @@ -25,7 +28,9 @@ async def get_current_user_profile(


@router.patch("/me", response_model=Dict[str, Any])
@limiter.limit("5/minute")
async def update_user_profile(
request: Request,
updates: UserProfileUpdateRequest,
current_user: Dict[str, Any] = Depends(get_current_user),
):
Expand All @@ -47,7 +52,10 @@ async def update_user_profile(


@router.delete("/me", response_model=DeleteUserResponse)
async def delete_user_account(current_user: Dict[str, Any] = Depends(get_current_user)):
@limiter.limit("2/minute")
async def delete_user_account(
request: Request, current_user: Dict[str, Any] = Depends(get_current_user)
):
deleted = await user_service.delete_user(current_user["_id"])
if not deleted:
raise HTTPException(
Expand Down
11 changes: 11 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@
from fastapi import FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
from utils.limiter import Limiter, get_remote_address, limiter

limiter = Limiter(key_func=get_remote_address)
# limiter = Limiter(key_func=get_remote_address)
Comment on lines +16 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix duplicate limiter definition.

The limiter is imported from utils.limiter and then redefined locally, creating confusion and redundancy.

-from utils.limiter import Limiter, get_remote_address, limiter
+from utils.limiter import limiter

-limiter = Limiter(key_func=get_remote_address)
-# limiter = Limiter(key_func=get_remote_address)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from utils.limiter import Limiter, get_remote_address, limiter
limiter = Limiter(key_func=get_remote_address)
# limiter = Limiter(key_func=get_remote_address)
from utils.limiter import limiter
🧰 Tools
🪛 Ruff (0.12.2)

18-18: Redefinition of unused limiter from line 16

(F811)

🤖 Prompt for AI Agents
In backend/main.py around lines 16 to 19, there is a duplicate definition of the
limiter variable: it is both imported from utils.limiter and redefined locally.
Remove the local redefinition of limiter and use the imported limiter directly
to avoid redundancy and confusion.



@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
app.state.limiter = limiter
logger.info("Lifespan: Connecting to MongoDB...")
await connect_to_mongo()
logger.info("Lifespan: MongoDB connected.")
Expand Down Expand Up @@ -77,6 +85,9 @@ async def lifespan(app: FastAPI):
)


app.add_middleware(SlowAPIMiddleware)


# Add a catch-all OPTIONS handler that should work for any path
@app.options("/{path:path}")
async def options_handler(request: Request, path: str):
Expand Down
27 changes: 14 additions & 13 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
fastapi==0.116.1
uvicorn[standard]==0.34.3
python-jose[cryptography]==3.5.0
passlib[bcrypt]==1.7.4
python-multipart==0.0.20
pydantic==2.11.7
pydantic-settings==2.1.0
pymongo==4.13.1
motor==3.7.1
firebase-admin==6.9.0
python-dotenv==1.0.0
bcrypt==4.0.1
email-validator==2.2.0
fastapi
uvicorn[standard]
python-jose[cryptography]
passlib[bcrypt]
python-multipart
pydantic
pydantic-settings
pymongo
motor
firebase-admin
python-dotenv
bcrypt
email-validator
Comment on lines +1 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Maintain version pins for production stability.

Removing version pins from all dependencies can lead to unpredictable builds and potential breaking changes when new versions are released. This affects reproducibility and production stability.

Consider maintaining version pins for critical dependencies:

-fastapi
-uvicorn[standard]
-python-jose[cryptography]
-passlib[bcrypt]
-python-multipart
-pydantic
-pydantic-settings
-pymongo
-motor
-firebase-admin
-python-dotenv
-bcrypt
-email-validator
+fastapi>=0.104.0,<1.0.0
+uvicorn[standard]>=0.24.0,<1.0.0
+python-jose[cryptography]>=3.3.0,<4.0.0
+passlib[bcrypt]>=1.7.4,<2.0.0
+python-multipart>=0.0.6,<1.0.0
+pydantic>=2.0.0,<3.0.0
+pydantic-settings>=2.0.0,<3.0.0
+pymongo>=4.5.0,<5.0.0
+motor>=3.3.0,<4.0.0
+firebase-admin>=6.2.0,<7.0.0
+python-dotenv>=1.0.0,<2.0.0
+bcrypt>=4.0.0,<5.0.0
+email-validator>=2.0.0,<3.0.0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fastapi
uvicorn[standard]
python-jose[cryptography]
passlib[bcrypt]
python-multipart
pydantic
pydantic-settings
pymongo
motor
firebase-admin
python-dotenv
bcrypt
email-validator
fastapi>=0.104.0,<1.0.0
uvicorn[standard]>=0.24.0,<1.0.0
python-jose[cryptography]>=3.3.0,<4.0.0
passlib[bcrypt]>=1.7.4,<2.0.0
python-multipart>=0.0.6,<1.0.0
pydantic>=2.0.0,<3.0.0
pydantic-settings>=2.0.0,<3.0.0
pymongo>=4.5.0,<5.0.0
motor>=3.3.0,<4.0.0
firebase-admin>=6.2.0,<7.0.0
python-dotenv>=1.0.0,<2.0.0
bcrypt>=4.0.0,<5.0.0
email-validator>=2.0.0,<3.0.0
🤖 Prompt for AI Agents
In backend/requirements.txt lines 1 to 13, the dependencies lack version pins,
which can cause unpredictable builds and instability. To fix this, specify exact
or minimum versions for each critical dependency by adding version constraints
(e.g., == or >=) to ensure reproducible and stable production environments.

pytest
pytest-asyncio
httpx
mongomock-motor
pytest-env
pytest-cov
pytest-mock
slowapi
4 changes: 4 additions & 0 deletions backend/utils/limiter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
11 changes: 11 additions & 0 deletions backend/utils/limiter_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from slowapi.util import get_remote_address
from utils.limiter import limiter


def limit_all_routes(router, rate: str):
for route in router.routes:

print(route)
if hasattr(route, "endpoint"):

route.endpoint = limiter.limit(rate)(route.endpoint)
7 changes: 4 additions & 3 deletions ui-poc/Home.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from streamlit_cookies_manager import EncryptedCookieManager
import requests
from datetime import datetime
import json
from datetime import datetime

import requests
import streamlit as st
from streamlit_cookies_manager import EncryptedCookieManager

# Configure the page – must come immediately after importing Streamlit
st.set_page_config(
Expand Down
Loading