Asma-yaseen commited on
Commit
c965d09
·
verified ·
1 Parent(s): 80fbbf5

Upload routes/tasks.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. routes/tasks.py +347 -0
routes/tasks.py ADDED
@@ -0,0 +1,347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Task CRUD API endpoints.
3
+
4
+ Task: 1.7, 1.8, 1.9
5
+ Spec: specs/api/rest-endpoints.md
6
+ """
7
+ from fastapi import APIRouter, Depends, HTTPException, status, Query
8
+ from sqlmodel import Session, select
9
+ from typing import Optional
10
+ from datetime import datetime
11
+ from pydantic import BaseModel, Field
12
+ from models import Task
13
+ from db import get_session
14
+ from middleware.auth import verify_token
15
+
16
+ router = APIRouter(prefix="/api", tags=["tasks"])
17
+
18
+
19
+ # Request/Response Models
20
+ class TaskCreate(BaseModel):
21
+ """Request model for creating a task."""
22
+ title: str = Field(min_length=1, max_length=200)
23
+ description: Optional[str] = None
24
+
25
+
26
+ class TaskUpdate(BaseModel):
27
+ """Request model for updating a task."""
28
+ title: Optional[str] = Field(None, min_length=1, max_length=200)
29
+ description: Optional[str] = None
30
+ completed: Optional[bool] = None
31
+
32
+
33
+ class TaskResponse(BaseModel):
34
+ """Response model for task operations."""
35
+ id: int
36
+ user_id: str
37
+ title: str
38
+ description: Optional[str]
39
+ completed: bool
40
+ created_at: datetime
41
+ updated_at: datetime
42
+
43
+
44
+ @router.get("/{user_id}/tasks")
45
+ async def get_tasks(
46
+ user_id: str,
47
+ status_filter: Optional[str] = Query(None, alias="status"),
48
+ session: Session = Depends(get_session),
49
+ authenticated_user_id: str = Depends(verify_token)
50
+ ):
51
+ """
52
+ Get all tasks for a user with optional status filtering.
53
+
54
+ Args:
55
+ user_id: User ID from URL path
56
+ status_filter: Filter tasks by status (all, pending, completed)
57
+ session: Database session
58
+ authenticated_user_id: User ID from JWT token
59
+
60
+ Returns:
61
+ Object with tasks array and counts
62
+
63
+ Raises:
64
+ HTTPException: 403 if user_id doesn't match authenticated user
65
+ """
66
+ # Verify user_id matches authenticated user
67
+ if user_id != authenticated_user_id:
68
+ raise HTTPException(
69
+ status_code=status.HTTP_403_FORBIDDEN,
70
+ detail="Cannot access other users' tasks"
71
+ )
72
+
73
+ # Build query
74
+ query = select(Task).where(Task.user_id == user_id)
75
+
76
+ # Apply status filter
77
+ if status_filter == "pending":
78
+ query = query.where(Task.completed == False)
79
+ elif status_filter == "completed":
80
+ query = query.where(Task.completed == True)
81
+ # 'all' or None - no filter needed
82
+
83
+ # Sort by created_at descending (newest first)
84
+ query = query.order_by(Task.created_at.desc())
85
+
86
+ # Execute query
87
+ tasks = session.exec(query).all()
88
+
89
+ # Calculate counts
90
+ total = len(tasks)
91
+ pending = sum(1 for t in tasks if not t.completed)
92
+ completed = sum(1 for t in tasks if t.completed)
93
+
94
+ return {
95
+ "tasks": tasks,
96
+ "count": {
97
+ "total": total,
98
+ "pending": pending,
99
+ "completed": completed
100
+ }
101
+ }
102
+
103
+
104
+ @router.post("/{user_id}/tasks", status_code=status.HTTP_201_CREATED, response_model=TaskResponse)
105
+ async def create_task(
106
+ user_id: str,
107
+ task_data: TaskCreate,
108
+ session: Session = Depends(get_session),
109
+ authenticated_user_id: str = Depends(verify_token)
110
+ ):
111
+ """
112
+ Create a new task for a user.
113
+
114
+ Args:
115
+ user_id: User ID from URL path
116
+ task_data: Task creation data (title, description)
117
+ session: Database session
118
+ authenticated_user_id: User ID from JWT token
119
+
120
+ Returns:
121
+ Created task object
122
+
123
+ Raises:
124
+ HTTPException: 403 if user_id doesn't match authenticated user
125
+ HTTPException: 400 if validation fails
126
+ """
127
+ # Verify user_id matches authenticated user
128
+ if user_id != authenticated_user_id:
129
+ raise HTTPException(
130
+ status_code=status.HTTP_403_FORBIDDEN,
131
+ detail="Cannot create tasks for other users"
132
+ )
133
+
134
+ # Create new task
135
+ new_task = Task(
136
+ user_id=user_id,
137
+ title=task_data.title,
138
+ description=task_data.description,
139
+ completed=False,
140
+ created_at=datetime.utcnow(),
141
+ updated_at=datetime.utcnow()
142
+ )
143
+
144
+ # Save to database
145
+ session.add(new_task)
146
+ session.commit()
147
+ session.refresh(new_task)
148
+
149
+ return new_task
150
+
151
+
152
+ @router.get("/{user_id}/tasks/{task_id}", response_model=TaskResponse)
153
+ async def get_task(
154
+ user_id: str,
155
+ task_id: int,
156
+ session: Session = Depends(get_session),
157
+ authenticated_user_id: str = Depends(verify_token)
158
+ ):
159
+ """
160
+ Get a specific task by ID.
161
+
162
+ Args:
163
+ user_id: User ID from URL path
164
+ task_id: Task ID from URL path
165
+ session: Database session
166
+ authenticated_user_id: User ID from JWT token
167
+
168
+ Returns:
169
+ Task object
170
+
171
+ Raises:
172
+ HTTPException: 403 if user_id doesn't match authenticated user
173
+ HTTPException: 404 if task not found
174
+ """
175
+ # Verify user_id matches authenticated user
176
+ if user_id != authenticated_user_id:
177
+ raise HTTPException(
178
+ status_code=status.HTTP_403_FORBIDDEN,
179
+ detail="Cannot access other users' tasks"
180
+ )
181
+
182
+ # Find task
183
+ task = session.get(Task, task_id)
184
+
185
+ if not task or task.user_id != user_id:
186
+ raise HTTPException(
187
+ status_code=status.HTTP_404_NOT_FOUND,
188
+ detail="Task not found"
189
+ )
190
+
191
+ return task
192
+
193
+
194
+ @router.put("/{user_id}/tasks/{task_id}", response_model=TaskResponse)
195
+ async def update_task(
196
+ user_id: str,
197
+ task_id: int,
198
+ task_data: TaskUpdate,
199
+ session: Session = Depends(get_session),
200
+ authenticated_user_id: str = Depends(verify_token)
201
+ ):
202
+ """
203
+ Update a task.
204
+
205
+ Args:
206
+ user_id: User ID from URL path
207
+ task_id: Task ID from URL path
208
+ task_data: Task update data (title, description, completed)
209
+ session: Database session
210
+ authenticated_user_id: User ID from JWT token
211
+
212
+ Returns:
213
+ Updated task object
214
+
215
+ Raises:
216
+ HTTPException: 403 if user_id doesn't match authenticated user
217
+ HTTPException: 404 if task not found
218
+ """
219
+ # Verify user_id matches authenticated user
220
+ if user_id != authenticated_user_id:
221
+ raise HTTPException(
222
+ status_code=status.HTTP_403_FORBIDDEN,
223
+ detail="Cannot update other users' tasks"
224
+ )
225
+
226
+ # Find task
227
+ task = session.get(Task, task_id)
228
+
229
+ if not task or task.user_id != user_id:
230
+ raise HTTPException(
231
+ status_code=status.HTTP_404_NOT_FOUND,
232
+ detail="Task not found"
233
+ )
234
+
235
+ # Update fields if provided
236
+ if task_data.title is not None:
237
+ task.title = task_data.title
238
+ if task_data.description is not None:
239
+ task.description = task_data.description
240
+ if task_data.completed is not None:
241
+ task.completed = task_data.completed
242
+
243
+ task.updated_at = datetime.utcnow()
244
+
245
+ # Save changes
246
+ session.add(task)
247
+ session.commit()
248
+ session.refresh(task)
249
+
250
+ return task
251
+
252
+
253
+ @router.delete("/{user_id}/tasks/{task_id}", status_code=status.HTTP_204_NO_CONTENT)
254
+ async def delete_task(
255
+ user_id: str,
256
+ task_id: int,
257
+ session: Session = Depends(get_session),
258
+ authenticated_user_id: str = Depends(verify_token)
259
+ ):
260
+ """
261
+ Delete a task.
262
+
263
+ Args:
264
+ user_id: User ID from URL path
265
+ task_id: Task ID from URL path
266
+ session: Database session
267
+ authenticated_user_id: User ID from JWT token
268
+
269
+ Returns:
270
+ None (204 No Content)
271
+
272
+ Raises:
273
+ HTTPException: 403 if user_id doesn't match authenticated user
274
+ HTTPException: 404 if task not found
275
+ """
276
+ # Verify user_id matches authenticated user
277
+ if user_id != authenticated_user_id:
278
+ raise HTTPException(
279
+ status_code=status.HTTP_403_FORBIDDEN,
280
+ detail="Cannot delete other users' tasks"
281
+ )
282
+
283
+ # Find task
284
+ task = session.get(Task, task_id)
285
+
286
+ if not task or task.user_id != user_id:
287
+ raise HTTPException(
288
+ status_code=status.HTTP_404_NOT_FOUND,
289
+ detail="Task not found"
290
+ )
291
+
292
+ # Delete task
293
+ session.delete(task)
294
+ session.commit()
295
+
296
+ return None
297
+
298
+
299
+ @router.patch("/{user_id}/tasks/{task_id}/complete", response_model=TaskResponse)
300
+ async def toggle_task_completion(
301
+ user_id: str,
302
+ task_id: int,
303
+ session: Session = Depends(get_session),
304
+ authenticated_user_id: str = Depends(verify_token)
305
+ ):
306
+ """
307
+ Toggle task completion status.
308
+
309
+ Args:
310
+ user_id: User ID from URL path
311
+ task_id: Task ID from URL path
312
+ session: Database session
313
+ authenticated_user_id: User ID from JWT token
314
+
315
+ Returns:
316
+ Updated task object
317
+
318
+ Raises:
319
+ HTTPException: 403 if user_id doesn't match authenticated user
320
+ HTTPException: 404 if task not found
321
+ """
322
+ # Verify user_id matches authenticated user
323
+ if user_id != authenticated_user_id:
324
+ raise HTTPException(
325
+ status_code=status.HTTP_403_FORBIDDEN,
326
+ detail="Cannot update other users' tasks"
327
+ )
328
+
329
+ # Find task
330
+ task = session.get(Task, task_id)
331
+
332
+ if not task or task.user_id != user_id:
333
+ raise HTTPException(
334
+ status_code=status.HTTP_404_NOT_FOUND,
335
+ detail="Task not found"
336
+ )
337
+
338
+ # Toggle completion status
339
+ task.completed = not task.completed
340
+ task.updated_at = datetime.utcnow()
341
+
342
+ # Save changes
343
+ session.add(task)
344
+ session.commit()
345
+ session.refresh(task)
346
+
347
+ return task