Spaces:
Running
Running
| """admin/routers/dashboard.py — Sessions, transcripts, and message moderation. | |
| Routes: | |
| GET /{slug}/dashboard | |
| GET /{slug}/sessions | |
| GET /{slug}/sessions/search | |
| POST /{slug}/sessions/{id}/block | |
| POST /{slug}/sessions/{id}/unblock | |
| GET /{slug}/sessions/{id}/transcript | |
| POST /{slug}/sessions/{id}/messages/{mid}/annotate | |
| POST /{slug}/sessions/{id}/messages/{mid}/flag | |
| """ | |
| from fastapi import APIRouter, Depends, HTTPException, Query | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.dependencies import get_db, get_current_author_scoped | |
| from app.schemas.admin import AnnotateRequest, FlagRequest | |
| from app.services.dashboard_service import DashboardService | |
| router = APIRouter() | |
| async def dashboard( | |
| author_slug: str, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Return high-level dashboard stats for the author.""" | |
| return await DashboardService(db).get_dashboard_stats(current_user.id) | |
| async def list_sessions( | |
| author_slug: str, | |
| limit: int = Query(50, ge=1, le=200), | |
| offset: int = 0, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """List reader sessions with pagination.""" | |
| return await DashboardService(db).list_sessions(current_user.id, limit, offset) | |
| async def search_sessions( | |
| author_slug: str, | |
| q: str = Query("", min_length=0, max_length=200), | |
| page: int = Query(1, ge=1), | |
| per_page: int = Query(20, ge=1, le=100), | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Full-text search across chat messages for the author.""" | |
| return await DashboardService(db).search_sessions(current_user.id, q, page, per_page) | |
| async def block_session( | |
| author_slug: str, | |
| session_id: str, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Block a visitor session.""" | |
| if not await DashboardService(db).block_session(current_user.id, session_id): | |
| raise HTTPException(404, "Session not found") | |
| return {"message": "Session blocked"} | |
| async def unblock_session( | |
| author_slug: str, | |
| session_id: str, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Unblock a visitor session.""" | |
| if not await DashboardService(db).unblock_session(current_user.id, session_id): | |
| raise HTTPException(404, "Session not found") | |
| return {"message": "Session unblocked"} | |
| async def get_transcript( | |
| author_slug: str, | |
| session_id: str, | |
| page: int = Query(1, ge=1), | |
| per_page: int = Query(50, ge=1, le=200), | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Return paginated message transcript for a session.""" | |
| result = await DashboardService(db).get_transcript( | |
| current_user.id, session_id, page, per_page, | |
| ) | |
| if result is None: | |
| raise HTTPException(404, "Session not found") | |
| return result | |
| async def annotate_message( | |
| author_slug: str, | |
| session_id: str, | |
| message_id: str, | |
| body: AnnotateRequest, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Add admin annotation to a chat message (append-only). R-029: Schema validated.""" | |
| result = await DashboardService(db).annotate_message( | |
| current_user.id, session_id, message_id, body.annotation, | |
| ) | |
| if result is None: | |
| raise HTTPException(404, "Message not found") | |
| return result | |
| async def flag_message( | |
| author_slug: str, | |
| session_id: str, | |
| message_id: str, | |
| body: FlagRequest, | |
| current_user=Depends(get_current_author_scoped), | |
| db: AsyncSession = Depends(get_db), | |
| ): | |
| """Flag a message as spam, quality issue, or escalation. R-029: Schema validated.""" | |
| result = await DashboardService(db).flag_message( | |
| current_user.id, session_id, message_id, body.flag_type, | |
| ) | |
| if result is None: | |
| raise HTTPException(404, "Message not found") | |
| return result | |