Files
graph-requirements-planner/backend/app/routers/links.py
2026-03-18 06:40:53 -05:00

56 lines
1.8 KiB
Python

from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import or_
from sqlalchemy.orm import Session
from ..auth import verify_token
from ..database import get_db
from ..models import CrossPillarLink, RequirementNode
from ..schemas import LinkCreate, LinkResponse
router = APIRouter(prefix="/api/links", tags=["links"], dependencies=[Depends(verify_token)])
@router.get("", response_model=list[LinkResponse])
def list_links(
node_id: Optional[str] = Query(None, description="Filter links involving this node"),
db: Session = Depends(get_db),
):
q = db.query(CrossPillarLink)
if node_id:
q = q.filter(
or_(
CrossPillarLink.source_id == node_id,
CrossPillarLink.target_id == node_id,
)
)
return q.all()
@router.post("", response_model=LinkResponse, status_code=201)
def create_link(data: LinkCreate, db: Session = Depends(get_db)):
if not db.get(RequirementNode, data.source_id):
raise HTTPException(404, f"Source {data.source_id} not found")
if not db.get(RequirementNode, data.target_id):
raise HTTPException(404, f"Target {data.target_id} not found")
existing = db.get(CrossPillarLink, (data.source_id, data.target_id))
if existing:
raise HTTPException(409, "Link already exists")
link = CrossPillarLink(**data.model_dump())
db.add(link)
db.commit()
db.refresh(link)
return link
@router.delete("/{source_id}/{target_id}", status_code=204)
def delete_link(source_id: str, target_id: str, db: Session = Depends(get_db)):
link = db.get(CrossPillarLink, (source_id, target_id))
if not link:
raise HTTPException(404, "Link not found")
db.delete(link)
db.commit()