"""This module contains endpoints for operations related to todo-items.""" from typing import Annotated from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from todo.database.engine import get_db from todo.schemas import todos as todoschema from todo.schemas import users as userschema from todo.crud import todos as todocrud from todo.utils.exceptions import NotFoundException, InvalidFilterParameterException from todo.utils.exceptions import create_exception_dict as fmt from todo.dependencies.todos import TodoItemSortablePaginationParams import todo.auth.auth as auth router = APIRouter( prefix="/todos", tags=["todo-items"] ) tag_metadata = { "name": "todo-items", "description": "Operations related to todo items." } auth_handler = auth.AuthHandler() @router.post("/user/{user_id}", response_model=todoschema.TodoItem) def create_todo( todo: todoschema.TodoItemCreate, user_id: int, db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): if not (current_user.is_admin or current_user.id == user_id): raise HTTPException(403, "You are not authorized to perform this action.") try: return todocrud.create_todo(db=db, todo=todo, user_id=user_id) except NotFoundException as e: raise HTTPException(404, fmt(str(e))) @router.get("/{todo_id}", response_model=todoschema.TodoItem) def read_todo( todo_id: int, db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): try: todo = todocrud.read_todo(db=db, todo_id=todo_id) except NotFoundException as e: raise HTTPException(404, fmt(str(e))) todo_owner = todocrud.read_user_for_todo(db=db, todo_id=todo_id) if not (current_user.is_admin or current_user.id == todo_owner.id): raise HTTPException(403, "You are not authorized to view this content.") return todo @router.get("/user/{user_id}", response_model=list[todoschema.TodoItem]) def read_todos( user_id: int, commons: Annotated[TodoItemSortablePaginationParams, Depends(TodoItemSortablePaginationParams)], db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): if not (current_user.is_admin or current_user.id == user_id): raise HTTPException(403, "You are not authorized to view this content.") try: return todocrud.read_todos_for_user( db=db, user_id=user_id, skip=commons.skip, limit=commons.limit, sortby=commons.sortby, sortorder=commons.sortorder, ) except InvalidFilterParameterException as e: raise HTTPException(400, fmt(str(e))) except NotFoundException as e: raise HTTPException(404, fmt(str(e))) @router.get("/user/{user_id}/total", response_model=dict[str, int]) def read_todos_count( user_id: int, db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): if not (current_user.is_admin or current_user.id == user_id): raise HTTPException(403, "You are not authorized to view this content.") try: return {"total": todocrud.read_todos_count_for_user(db=db, user_id=user_id)} except NotFoundException as e: raise HTTPException(404, fmt(str(e))) @router.patch("/{todo_id}", response_model=todoschema.TodoItem) def update_todo( todo_id: int, todo: todoschema.TodoItemUpdate, db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): try: todo_owner = todocrud.read_user_for_todo(db=db, todo_id=todo_id) if not (current_user.is_admin or current_user.id == todo_owner.id): raise HTTPException(403, "You are not authorized to perform this action.") return todocrud.update_todo(db=db, todo=todo, todo_id=todo_id) except NotFoundException as e: raise HTTPException(404, fmt(str(e))) @router.delete("/{todo_id}", response_model=todoschema.TodoItem) def delete_todo( todo_id: int, db: Session = Depends(get_db), current_user: userschema.User = Depends(auth_handler.get_current_user), ): try: todo_owner = todocrud.read_user_for_todo(db=db, todo_id=todo_id) if not (current_user.is_admin or current_user.id == todo_owner.id): raise HTTPException(403, "You are not authorized to perform this action.") return todocrud.delete_todo(db=db, todo_id=todo_id) except NotFoundException as e: raise HTTPException(404, fmt(str(e)))