Skip to content

Commit f02416f

Browse files
Refactor backend services to reduce technical debt
This commit addresses several areas of technical debt in the backend: - Separated development and production dependencies into `requirements.txt` and `requirements-dev.txt`. - Refactored the configuration in `app/config.py` to improve security and clarity. - Simplified the CORS configuration in `main.py`. - Introduced a `BaseService` class to handle common CRUD operations and reduce code duplication. - Refactored `UserService`, `ExpenseService`, `GroupService`, and `AuthService` to use the `BaseService` and dependency injection. - Updated all API routers to use dependency injection for the services. - Updated the CI workflow to install development dependencies.
1 parent 15cf5be commit f02416f

File tree

7 files changed

+36
-33
lines changed

7 files changed

+36
-33
lines changed

backend/app/auth/service.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,6 @@
5555
},
5656
)
5757
logger.info("Firebase initialized with credentials from environment variables")
58-
# Fall back to service account JSON file if env vars are not available
59-
elif os.path.exists(settings.firebase_service_account_path):
60-
cred = credentials.Certificate(settings.firebase_service_account_path)
61-
firebase_admin.initialize_app(
62-
cred,
63-
{
64-
"projectId": settings.firebase_project_id,
65-
},
66-
)
67-
logger.info("Firebase initialized with service account file")
6858
else:
6959
logger.warning("Firebase service account not found. Google auth will not work.")
7060

@@ -318,9 +308,7 @@ async def refresh_access_token(self, refresh_token: str) -> str:
318308

319309
# Get user
320310
try:
321-
user = await self.users_collection.find_one(
322-
{"_id": token_record["user_id"]}
323-
)
311+
user = await self.users_collection.find_one({"_id": token_record["user_id"]})
324312
except PyMongoError as e:
325313
logger.error("Error while fetching user: %s", str(e))
326314
raise HTTPException(

backend/app/dependencies.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ def get_user_service() -> UserService:
7272
def get_expense_service() -> ExpenseService:
7373
return ExpenseService()
7474

75-
7675
def get_group_service() -> GroupService:
7776
return GroupService()
7877

79-
8078
def get_auth_service() -> AuthService:
8179
return AuthService()

backend/app/expenses/routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from app.auth.security import get_current_user
77
from app.config import logger
8-
from app.dependencies import get_expense_service
98
from app.expenses.schemas import (
109
AttachmentUploadResponse,
1110
BalanceSummaryResponse,
@@ -23,6 +22,7 @@
2322
SettlementUpdateRequest,
2423
UserBalance,
2524
)
25+
from app.dependencies import get_expense_service
2626
from app.expenses.service import ExpenseService
2727
from fastapi import (
2828
APIRouter,

backend/app/expenses/service.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ async def list_group_expenses(
180180
# Get expenses with pagination
181181
skip = (page - 1) * limit
182182
expenses_cursor = (
183-
self.collection.find(query).sort("createdAt", -1).skip(skip).limit(limit)
183+
self.collection.find(query)
184+
.sort("createdAt", -1)
185+
.skip(skip)
186+
.limit(limit)
184187
)
185188
expenses_docs = await expenses_cursor.to_list(None)
186189

@@ -201,7 +204,9 @@ async def list_group_expenses(
201204
}
202205
},
203206
]
204-
summary_result = await self.collection.aggregate(pipeline).to_list(None)
207+
summary_result = await self.collection.aggregate(pipeline).to_list(
208+
None
209+
)
205210
summary = (
206211
summary_result[0]
207212
if summary_result
@@ -406,7 +411,9 @@ async def update_expense(
406411
# Continue anyway, as the expense update succeeded
407412

408413
# Return updated expense
409-
updated_expense = await self.collection.find_one({"_id": expense_obj_id})
414+
updated_expense = await self.collection.find_one(
415+
{"_id": expense_obj_id}
416+
)
410417
if not updated_expense:
411418
raise HTTPException(
412419
status_code=500, detail="Failed to retrieve updated expense"
@@ -452,7 +459,9 @@ async def delete_expense(
452459
await self.settlements_collection.delete_many({"expenseId": expense_id})
453460

454461
# Delete the expense
455-
result = await self.collection.delete_one({"_id": ObjectId(expense_id)})
462+
result = await self.collection.delete_one(
463+
{"_id": ObjectId(expense_id)}
464+
)
456465
return result.deleted_count > 0
457466

458467
async def calculate_optimized_settlements(
@@ -668,7 +677,9 @@ async def _get_group_summary(
668677
}
669678
},
670679
]
671-
expense_result = await self.collection.aggregate(pipeline).to_list(None)
680+
expense_result = await self.collection.aggregate(pipeline).to_list(
681+
None
682+
)
672683
expense_stats = (
673684
expense_result[0]
674685
if expense_result

backend/app/groups/routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from typing import Any, Dict, List
22

33
from app.auth.security import get_current_user
4-
from app.dependencies import get_group_service
54
from app.groups.schemas import (
65
DeleteGroupResponse,
76
GroupCreateRequest,
@@ -15,6 +14,7 @@
1514
MemberRoleUpdateRequest,
1615
RemoveMemberResponse,
1716
)
17+
from app.dependencies import get_group_service
1818
from app.groups.service import GroupService
1919
from fastapi import APIRouter, Depends, HTTPException, status
2020

backend/app/groups/service.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,7 @@ async def get_group_by_id(self, group_id: str, user_id: str) -> Optional[dict]:
170170
logger.error(f"Unexpected error converting group_id to ObjectId: {e}")
171171
return None
172172

173-
group = await self.collection.find_one(
174-
{"_id": obj_id, "members.userId": user_id}
175-
)
173+
group = await self.collection.find_one({"_id": obj_id, "members.userId": user_id})
176174

177175
if not group:
178176
return None
@@ -283,9 +281,7 @@ async def leave_group(self, group_id: str, user_id: str) -> bool:
283281
return False
284282

285283
# Check if user is a member
286-
group = await self.collection.find_one(
287-
{"_id": obj_id, "members.userId": user_id}
288-
)
284+
group = await self.collection.find_one({"_id": obj_id, "members.userId": user_id})
289285
if not group:
290286
raise HTTPException(
291287
status_code=404, detail="Group not found or you are not a member"
@@ -341,9 +337,7 @@ async def get_group_members(self, group_id: str, user_id: str) -> List[dict]:
341337
except Exception:
342338
return []
343339

344-
group = await self.collection.find_one(
345-
{"_id": obj_id, "members.userId": user_id}
346-
)
340+
group = await self.collection.find_one({"_id": obj_id, "members.userId": user_id})
347341
if not group:
348342
return []
349343

backend/app/services/base.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,20 @@
77
class BaseService:
88
def __init__(self, collection_name: str):
99
self.collection_name = collection_name
10-
self.db = get_database()
11-
self.collection = self.db[self.collection_name]
10+
self._db = None
11+
self._collection = None
12+
13+
@property
14+
def db(self):
15+
if self._db is None:
16+
self._db = get_database()
17+
return self._db
18+
19+
@property
20+
def collection(self):
21+
if self._collection is None:
22+
self._collection = self.db[self.collection_name]
23+
return self._collection
1224

1325
def _to_json(self, item: Dict[str, Any]) -> Dict[str, Any]:
1426
"""Converts a MongoDB document to a JSON-serializable dictionary."""

0 commit comments

Comments
 (0)