Cuong2004 commited on
Commit
f9f5795
·
1 Parent(s): 455d644

handle invalid userID

Browse files
Files changed (1) hide show
  1. app/itineraries/router.py +45 -0
app/itineraries/router.py CHANGED
@@ -1,5 +1,6 @@
1
  """Itineraries Router - Multi-day trip planning with persistent storage."""
2
 
 
3
  from fastapi import APIRouter, HTTPException, Depends, Query
4
  from sqlalchemy.ext.asyncio import AsyncSession
5
  from sqlalchemy import text
@@ -14,6 +15,18 @@ from app.itineraries import (
14
  router = APIRouter(prefix="/itineraries", tags=["Itineraries"])
15
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # ==================== ITINERARY CRUD ====================
18
 
19
  @router.post(
@@ -28,6 +41,9 @@ async def create_itinerary(
28
  db: AsyncSession = Depends(get_db),
29
  ) -> ItineraryResponse:
30
  """Create a new itinerary."""
 
 
 
31
  result = await db.execute(
32
  text("""
33
  INSERT INTO itineraries (user_id, title, start_date, end_date, total_days, total_budget, currency)
@@ -76,6 +92,9 @@ async def list_itineraries(
76
  db: AsyncSession = Depends(get_db),
77
  ) -> list[ItineraryListItem]:
78
  """List all itineraries for a user."""
 
 
 
79
  result = await db.execute(
80
  text("""
81
  SELECT i.id, i.title, i.start_date, i.end_date, i.total_days, i.created_at,
@@ -116,6 +135,10 @@ async def get_itinerary(
116
  db: AsyncSession = Depends(get_db),
117
  ) -> ItineraryResponse:
118
  """Get itinerary by ID with all stops."""
 
 
 
 
119
  # Get itinerary
120
  result = await db.execute(
121
  text("""
@@ -191,6 +214,10 @@ async def update_itinerary(
191
  db: AsyncSession = Depends(get_db),
192
  ) -> ItineraryResponse:
193
  """Update itinerary."""
 
 
 
 
194
  update_fields = []
195
  params = {"id": itinerary_id, "user_id": user_id}
196
 
@@ -246,6 +273,10 @@ async def delete_itinerary(
246
  db: AsyncSession = Depends(get_db),
247
  ) -> dict:
248
  """Delete itinerary."""
 
 
 
 
249
  # Delete stops first (cascade)
250
  await db.execute(
251
  text("DELETE FROM itinerary_stops WHERE itinerary_id = :id"),
@@ -280,6 +311,10 @@ async def add_stop(
280
  db: AsyncSession = Depends(get_db),
281
  ) -> StopResponse:
282
  """Add a stop to the itinerary."""
 
 
 
 
283
  # Verify itinerary exists and belongs to user
284
  check = await db.execute(
285
  text("SELECT id FROM itineraries WHERE id = :id AND user_id = :user_id"),
@@ -357,6 +392,11 @@ async def update_stop(
357
  db: AsyncSession = Depends(get_db),
358
  ) -> StopResponse:
359
  """Update a stop."""
 
 
 
 
 
360
  # Verify ownership
361
  check = await db.execute(
362
  text("""
@@ -437,6 +477,11 @@ async def delete_stop(
437
  db: AsyncSession = Depends(get_db),
438
  ) -> dict:
439
  """Delete a stop."""
 
 
 
 
 
440
  # Verify ownership and delete
441
  result = await db.execute(
442
  text("""
 
1
  """Itineraries Router - Multi-day trip planning with persistent storage."""
2
 
3
+ from uuid import UUID
4
  from fastapi import APIRouter, HTTPException, Depends, Query
5
  from sqlalchemy.ext.asyncio import AsyncSession
6
  from sqlalchemy import text
 
15
  router = APIRouter(prefix="/itineraries", tags=["Itineraries"])
16
 
17
 
18
+ def validate_uuid(value: str, field_name: str = "ID") -> str:
19
+ """Validate that a string is a valid UUID format."""
20
+ try:
21
+ UUID(value)
22
+ return value
23
+ except ValueError:
24
+ raise HTTPException(
25
+ status_code=400,
26
+ detail=f"Invalid {field_name}: '{value}' is not a valid UUID format. Expected format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
27
+ )
28
+
29
+
30
  # ==================== ITINERARY CRUD ====================
31
 
32
  @router.post(
 
41
  db: AsyncSession = Depends(get_db),
42
  ) -> ItineraryResponse:
43
  """Create a new itinerary."""
44
+ # Validate user_id is a valid UUID
45
+ validate_uuid(user_id, "user_id")
46
+
47
  result = await db.execute(
48
  text("""
49
  INSERT INTO itineraries (user_id, title, start_date, end_date, total_days, total_budget, currency)
 
92
  db: AsyncSession = Depends(get_db),
93
  ) -> list[ItineraryListItem]:
94
  """List all itineraries for a user."""
95
+ # Validate user_id is a valid UUID
96
+ validate_uuid(user_id, "user_id")
97
+
98
  result = await db.execute(
99
  text("""
100
  SELECT i.id, i.title, i.start_date, i.end_date, i.total_days, i.created_at,
 
135
  db: AsyncSession = Depends(get_db),
136
  ) -> ItineraryResponse:
137
  """Get itinerary by ID with all stops."""
138
+ # Validate UUIDs
139
+ validate_uuid(user_id, "user_id")
140
+ validate_uuid(itinerary_id, "itinerary_id")
141
+
142
  # Get itinerary
143
  result = await db.execute(
144
  text("""
 
214
  db: AsyncSession = Depends(get_db),
215
  ) -> ItineraryResponse:
216
  """Update itinerary."""
217
+ # Validate UUIDs
218
+ validate_uuid(user_id, "user_id")
219
+ validate_uuid(itinerary_id, "itinerary_id")
220
+
221
  update_fields = []
222
  params = {"id": itinerary_id, "user_id": user_id}
223
 
 
273
  db: AsyncSession = Depends(get_db),
274
  ) -> dict:
275
  """Delete itinerary."""
276
+ # Validate UUIDs
277
+ validate_uuid(user_id, "user_id")
278
+ validate_uuid(itinerary_id, "itinerary_id")
279
+
280
  # Delete stops first (cascade)
281
  await db.execute(
282
  text("DELETE FROM itinerary_stops WHERE itinerary_id = :id"),
 
311
  db: AsyncSession = Depends(get_db),
312
  ) -> StopResponse:
313
  """Add a stop to the itinerary."""
314
+ # Validate UUIDs
315
+ validate_uuid(user_id, "user_id")
316
+ validate_uuid(itinerary_id, "itinerary_id")
317
+
318
  # Verify itinerary exists and belongs to user
319
  check = await db.execute(
320
  text("SELECT id FROM itineraries WHERE id = :id AND user_id = :user_id"),
 
392
  db: AsyncSession = Depends(get_db),
393
  ) -> StopResponse:
394
  """Update a stop."""
395
+ # Validate UUIDs
396
+ validate_uuid(user_id, "user_id")
397
+ validate_uuid(itinerary_id, "itinerary_id")
398
+ validate_uuid(stop_id, "stop_id")
399
+
400
  # Verify ownership
401
  check = await db.execute(
402
  text("""
 
477
  db: AsyncSession = Depends(get_db),
478
  ) -> dict:
479
  """Delete a stop."""
480
+ # Validate UUIDs
481
+ validate_uuid(user_id, "user_id")
482
+ validate_uuid(itinerary_id, "itinerary_id")
483
+ validate_uuid(stop_id, "stop_id")
484
+
485
  # Verify ownership and delete
486
  result = await db.execute(
487
  text("""