diff --git a/app/api/routes/__init__.py b/app/api/routes/__init__.py index e69de29..4c2cf11 100644 --- a/app/api/routes/__init__.py +++ b/app/api/routes/__init__.py @@ -0,0 +1,3 @@ +from app.api.routes.api import router as api_router +from app.api.routes.health import router as health_router +from app.api.routes.messages import router as messages_router \ No newline at end of file diff --git a/app/api/routes/messages.py b/app/api/routes/messages.py new file mode 100644 index 0000000..62fb32a --- /dev/null +++ b/app/api/routes/messages.py @@ -0,0 +1,90 @@ +from typing import List, Optional +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session + +from app.db.session import get_db +from app.models.message import Message +from app.schemas.message import MessageCreate, MessageResponse + +router = APIRouter(tags=["Messages"]) + + +@router.get("/", response_model=List[MessageResponse]) +def list_messages( + sender: Optional[str] = Query(None, description="Filter messages by sender"), + recipient: Optional[str] = Query(None, description="Filter messages by recipient"), + is_read: Optional[bool] = Query(None, description="Filter messages by read status"), + skip: int = Query(0, description="Number of messages to skip"), + limit: int = Query(100, description="Maximum number of messages to return"), + db: Session = Depends(get_db), +): + """ + Get a list of messages with optional filtering. + """ + query = db.query(Message) + + if sender: + query = query.filter(Message.sender == sender) + if recipient: + query = query.filter(Message.recipient == recipient) + if is_read is not None: + query = query.filter(Message.is_read == is_read) + + messages = query.order_by(Message.timestamp.desc()).offset(skip).limit(limit).all() + return messages + + +@router.get("/{message_id}", response_model=MessageResponse) +def get_message(message_id: int, db: Session = Depends(get_db)): + """ + Get a specific message by ID. + """ + message = db.query(Message).filter(Message.id == message_id).first() + if not message: + raise HTTPException(status_code=404, detail="Message not found") + return message + + +@router.post("/", response_model=MessageResponse, status_code=201) +def create_message(message: MessageCreate, db: Session = Depends(get_db)): + """ + Create a new message. + """ + db_message = Message( + sender=message.sender, + recipient=message.recipient, + content=message.content, + ) + db.add(db_message) + db.commit() + db.refresh(db_message) + return db_message + + +@router.put("/{message_id}/read", response_model=MessageResponse) +def mark_message_as_read(message_id: int, db: Session = Depends(get_db)): + """ + Mark a message as read. + """ + message = db.query(Message).filter(Message.id == message_id).first() + if not message: + raise HTTPException(status_code=404, detail="Message not found") + + message.is_read = True + db.commit() + db.refresh(message) + return message + + +@router.delete("/{message_id}", status_code=204) +def delete_message(message_id: int, db: Session = Depends(get_db)): + """ + Delete a message. + """ + message = db.query(Message).filter(Message.id == message_id).first() + if not message: + raise HTTPException(status_code=404, detail="Message not found") + + db.delete(message) + db.commit() + return None \ No newline at end of file diff --git a/main.py b/main.py index b4e6bb0..8539789 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.utils import get_openapi -from app.api.routes import health, api +from app.api.routes import health, api, messages from app.db.session import engine from app.models import base @@ -27,6 +27,7 @@ app.add_middleware( # Include routes app.include_router(health.router) app.include_router(api.router, prefix="/api/v1") +app.include_router(messages.router, prefix="/api/v1/messages") # Custom OpenAPI schema diff --git a/migrations/env.py b/migrations/env.py index 32b6706..c455fa2 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -42,6 +42,7 @@ def run_migrations_offline(): target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, + render_as_batch=True, ) with context.begin_transaction(): @@ -63,7 +64,9 @@ def run_migrations_online(): with connectable.connect() as connection: context.configure( - connection=connection, target_metadata=target_metadata + connection=connection, + target_metadata=target_metadata, + render_as_batch=True ) with context.begin_transaction():