Files
CIAgent/apps/api/app/api/v1/sources.py
T
saksham 1a4c80958f Initial commit: CI Agent competitive-intelligence monitoring app
FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring,
source collection, LLM-based change analysis, enrichment, and account
security (Turnstile, escalating lockout, email verification).
2026-08-05 10:48:20 -04:00

84 lines
2.8 KiB
Python

"""Source routes. Mixes `/companies/{company_id}/sources` and
`/sources/{source_id}` paths per the spec - kept in one router since both
share the same schemas/service."""
from __future__ import annotations
import uuid
from fastapi import APIRouter, Depends, Request, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth.dependencies import get_current_user
from app.core.config import Settings, get_settings
from app.core.rate_limit import limiter
from app.db.session import get_db
from app.models.user import User
from app.schemas.source import SourceCreate, SourceResponse, SourceTestResult, SourceUpdate
from app.services import source_service
router = APIRouter(tags=["sources"])
@router.get("/companies/{company_id}/sources", response_model=list[SourceResponse])
async def list_sources(
company_id: uuid.UUID,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> list[SourceResponse]:
sources = await source_service.list_sources(db, user.id, company_id)
return [SourceResponse.model_validate(s) for s in sources]
@router.post(
"/companies/{company_id}/sources",
response_model=SourceResponse,
status_code=status.HTTP_201_CREATED,
)
@limiter.limit("30/minute")
async def create_source(
request: Request,
company_id: uuid.UUID,
payload: SourceCreate,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> SourceResponse:
source = await source_service.create_source(db, user.id, company_id, payload)
return SourceResponse.model_validate(source)
@router.patch("/sources/{source_id}", response_model=SourceResponse)
async def update_source(
source_id: uuid.UUID,
payload: SourceUpdate,
user: User = Depends(get_current_user),
settings: Settings = Depends(get_settings),
db: AsyncSession = Depends(get_db),
) -> SourceResponse:
source = await source_service.update_source(db, settings, user.id, source_id, payload)
return SourceResponse.model_validate(source)
@router.delete("/sources/{source_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_source(
source_id: uuid.UUID,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> None:
await source_service.delete_source(db, user.id, source_id)
@router.post("/sources/{source_id}/test", response_model=SourceTestResult)
@limiter.limit("20/minute")
async def test_source(
request: Request,
source_id: uuid.UUID,
user: User = Depends(get_current_user),
settings: Settings = Depends(get_settings),
db: AsyncSession = Depends(get_db),
) -> SourceTestResult:
result = await source_service.test_source(db, settings, user.id, source_id)
return SourceTestResult(
status=result.status, documents_found=len(result.documents), error=result.error
)