109 lines
3.9 KiB
Python
109 lines
3.9 KiB
Python
from bson import ObjectId
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from pymongo import ReturnDocument
|
|
|
|
from app.database import get_mongo_database
|
|
from app.models import Account
|
|
from app.routers.auth import get_current_account
|
|
from app.schemas import StickyNoteCreate, StickyNoteRead, StickyNoteUpdate, utc_now
|
|
|
|
router = APIRouter(prefix="/sticky-notes", tags=["sticky-notes"])
|
|
|
|
|
|
def serialize_note(document: dict) -> StickyNoteRead:
|
|
return StickyNoteRead(
|
|
id=str(document["_id"]),
|
|
title=document["title"],
|
|
body=document.get("body", ""),
|
|
tags=document.get("tags", []),
|
|
color=document.get("color", "yellow"),
|
|
created_at=document["created_at"],
|
|
updated_at=document["updated_at"],
|
|
)
|
|
|
|
|
|
@router.get("", response_model=list[StickyNoteRead])
|
|
async def list_sticky_notes(
|
|
database=Depends(get_mongo_database),
|
|
account: Account = Depends(get_current_account),
|
|
):
|
|
cursor = database.sticky_notes.find({"account_id": str(account.id)}).sort(
|
|
"updated_at", -1
|
|
)
|
|
return [serialize_note(document) async for document in cursor]
|
|
|
|
|
|
@router.post("", response_model=StickyNoteRead, status_code=status.HTTP_201_CREATED)
|
|
async def create_sticky_note(
|
|
payload: StickyNoteCreate,
|
|
database=Depends(get_mongo_database),
|
|
account: Account = Depends(get_current_account),
|
|
):
|
|
now = utc_now()
|
|
document = {
|
|
"account_id": str(account.id),
|
|
"title": payload.title.strip(),
|
|
"body": payload.body.strip(),
|
|
"tags": [tag.strip() for tag in payload.tags if tag.strip()],
|
|
"color": payload.color,
|
|
"created_at": now,
|
|
"updated_at": now,
|
|
}
|
|
result = await database.sticky_notes.insert_one(document)
|
|
document["_id"] = result.inserted_id
|
|
return serialize_note(document)
|
|
|
|
|
|
@router.patch("/{note_id}", response_model=StickyNoteRead)
|
|
async def update_sticky_note(
|
|
note_id: str,
|
|
payload: StickyNoteUpdate,
|
|
database=Depends(get_mongo_database),
|
|
account: Account = Depends(get_current_account),
|
|
):
|
|
if not ObjectId.is_valid(note_id):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Invalid note ID.",
|
|
)
|
|
updates = payload.model_dump(exclude_unset=True)
|
|
if "title" in updates:
|
|
updates["title"] = updates["title"].strip()
|
|
if "body" in updates:
|
|
updates["body"] = updates["body"].strip()
|
|
if "tags" in updates and updates["tags"] is not None:
|
|
updates["tags"] = [tag.strip() for tag in updates["tags"] if tag.strip()]
|
|
if not updates:
|
|
document = await database.sticky_notes.find_one(
|
|
{"_id": ObjectId(note_id), "account_id": str(account.id)}
|
|
)
|
|
if document is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")
|
|
return serialize_note(document)
|
|
updates["updated_at"] = utc_now()
|
|
document = await database.sticky_notes.find_one_and_update(
|
|
{"_id": ObjectId(note_id), "account_id": str(account.id)},
|
|
{"$set": updates},
|
|
return_document=ReturnDocument.AFTER,
|
|
)
|
|
if document is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")
|
|
return serialize_note(document)
|
|
|
|
|
|
@router.delete("/{note_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_sticky_note(
|
|
note_id: str,
|
|
database=Depends(get_mongo_database),
|
|
account: Account = Depends(get_current_account),
|
|
):
|
|
if not ObjectId.is_valid(note_id):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Invalid note ID.",
|
|
)
|
|
result = await database.sticky_notes.delete_one(
|
|
{"_id": ObjectId(note_id), "account_id": str(account.id)}
|
|
)
|
|
if result.deleted_count == 0:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")
|