56 lines
1.8 KiB
Python
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()
|