| """Room management API endpoints.""" |
|
|
| from fastapi import APIRouter, Depends, HTTPException, status |
| from sqlalchemy.ext.asyncio import AsyncSession |
| from sqlalchemy import select |
| from sqlalchemy.orm import selectinload |
| from src.db.postgres.connection import get_db |
| from src.db.postgres.models import Room, ChatMessage |
| from src.middlewares.logging import get_logger, log_execution |
| from pydantic import BaseModel |
| from typing import List |
| from datetime import datetime |
| import uuid |
|
|
| logger = get_logger("room_api") |
|
|
| router = APIRouter(prefix="/api/v1", tags=["Rooms"]) |
|
|
|
|
| class ChatMessageResponse(BaseModel): |
| id: str |
| role: str |
| content: str |
| created_at: str |
|
|
|
|
| class RoomResponse(BaseModel): |
| id: str |
| title: str |
| created_at: str |
| updated_at: str | None |
| messages: List[ChatMessageResponse] = [] |
|
|
|
|
| class CreateRoomRequest(BaseModel): |
| user_id: str |
| title: str = "New Chat" |
|
|
|
|
| @router.get("/rooms/{user_id}", response_model=List[RoomResponse]) |
| @log_execution(logger) |
| async def list_rooms( |
| user_id: str, |
| db: AsyncSession = Depends(get_db) |
| ): |
| """List all rooms for a user.""" |
| result = await db.execute( |
| select(Room) |
| .where(Room.user_id == user_id, Room.status == "active") |
| .order_by(Room.updated_at.desc()) |
| ) |
| rooms = result.scalars().all() |
|
|
| return [ |
| RoomResponse( |
| id=room.id, |
| title=room.title, |
| created_at=room.created_at.isoformat(), |
| updated_at=room.updated_at.isoformat() if room.updated_at else None |
| ) |
| for room in rooms |
| ] |
|
|
|
|
| @router.get("/room/{room_id}", response_model=RoomResponse) |
| @log_execution(logger) |
| async def get_room( |
| room_id: str, |
| db: AsyncSession = Depends(get_db) |
| ): |
| """Get a specific room with its chat history.""" |
| result = await db.execute( |
| select(Room) |
| .where(Room.id == room_id) |
| .options(selectinload(Room.messages)) |
| ) |
| room = result.scalars().first() |
|
|
| if not room: |
| raise HTTPException( |
| status_code=404, |
| detail="Room not found" |
| ) |
|
|
| messages = sorted(room.messages, key=lambda m: m.created_at) |
|
|
| return RoomResponse( |
| id=room.id, |
| title=room.title, |
| created_at=room.created_at.isoformat(), |
| updated_at=room.updated_at.isoformat() if room.updated_at else None, |
| messages=[ |
| ChatMessageResponse( |
| id=msg.id, |
| role=msg.role, |
| content=msg.content, |
| created_at=msg.created_at.isoformat() |
| ) |
| for msg in messages |
| ] |
| ) |
|
|
|
|
| @router.delete("/room/{room_id}") |
| @log_execution(logger) |
| async def delete_room( |
| room_id: str, |
| user_id: str, |
| db: AsyncSession = Depends(get_db) |
| ): |
| """Soft-delete a room by setting its status to inactive.""" |
| result = await db.execute( |
| select(Room).where(Room.id == room_id) |
| ) |
| room = result.scalars().first() |
|
|
| if not room: |
| raise HTTPException(status_code=404, detail="Room not found") |
|
|
| if room.user_id != user_id: |
| raise HTTPException(status_code=403, detail="Access denied") |
|
|
| room.status = "inactive" |
| await db.commit() |
|
|
| return {"status": "success", "message": "Room deleted successfully"} |
|
|
|
|
| @router.post("/room/create") |
| @log_execution(logger) |
| async def create_room( |
| request: CreateRoomRequest, |
| db: AsyncSession = Depends(get_db) |
| ): |
| """Create a new room.""" |
| room = Room( |
| id=str(uuid.uuid4()), |
| user_id=request.user_id, |
| title=request.title |
| ) |
| db.add(room) |
| await db.commit() |
| await db.refresh(room) |
|
|
| return { |
| "status": "success", |
| "message": "Room created successfully", |
| "data": RoomResponse( |
| id=room.id, |
| title=room.title, |
| created_at=room.created_at.isoformat(), |
| updated_at=None |
| ) |
| } |
|
|