Files
serv_benchmark/backend/app/api/links.py
gilles soulier c6a8e8e83d feat: Complete MVP implementation of Linux BenchTools
 Features:
- Backend FastAPI complete (25 Python files)
  - 5 SQLAlchemy models (Device, HardwareSnapshot, Benchmark, Link, Document)
  - Pydantic schemas for validation
  - 4 API routers (benchmark, devices, links, docs)
  - Authentication with Bearer token
  - Automatic score calculation
  - File upload support

- Frontend web interface (13 files)
  - 4 HTML pages (Dashboard, Devices, Device Detail, Settings)
  - 7 JavaScript modules
  - Monokai dark theme CSS
  - Responsive design
  - Complete CRUD operations

- Client benchmark script (500+ lines Bash)
  - Hardware auto-detection
  - CPU, RAM, Disk, Network benchmarks
  - JSON payload generation
  - Robust error handling

- Docker deployment
  - Optimized Dockerfile
  - docker-compose with 2 services
  - Persistent volumes
  - Environment variables

- Documentation & Installation
  - Automated install.sh script
  - README, QUICKSTART, DEPLOYMENT guides
  - Complete API documentation
  - Project structure documentation

📊 Stats:
- ~60 files created
- ~5000 lines of code
- Full MVP feature set implemented

🚀 Ready for production deployment!

🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 14:46:10 +01:00

108 lines
2.7 KiB
Python

"""
Linux BenchTools - Links API
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List
from app.db.session import get_db
from app.schemas.link import LinkCreate, LinkUpdate, LinkResponse
from app.models.manufacturer_link import ManufacturerLink
from app.models.device import Device
router = APIRouter()
@router.get("/devices/{device_id}/links", response_model=List[LinkResponse])
async def get_device_links(
device_id: int,
db: Session = Depends(get_db)
):
"""Get all links for a device"""
device = db.query(Device).filter(Device.id == device_id).first()
if not device:
raise HTTPException(status_code=404, detail="Device not found")
links = db.query(ManufacturerLink).filter(ManufacturerLink.device_id == device_id).all()
return [
LinkResponse(
id=link.id,
device_id=link.device_id,
label=link.label,
url=link.url
)
for link in links
]
@router.post("/devices/{device_id}/links", response_model=LinkResponse, status_code=status.HTTP_201_CREATED)
async def create_device_link(
device_id: int,
link_data: LinkCreate,
db: Session = Depends(get_db)
):
"""Add a link to a device"""
device = db.query(Device).filter(Device.id == device_id).first()
if not device:
raise HTTPException(status_code=404, detail="Device not found")
link = ManufacturerLink(
device_id=device_id,
label=link_data.label,
url=link_data.url
)
db.add(link)
db.commit()
db.refresh(link)
return LinkResponse(
id=link.id,
device_id=link.device_id,
label=link.label,
url=link.url
)
@router.put("/links/{link_id}", response_model=LinkResponse)
async def update_link(
link_id: int,
link_data: LinkUpdate,
db: Session = Depends(get_db)
):
"""Update a link"""
link = db.query(ManufacturerLink).filter(ManufacturerLink.id == link_id).first()
if not link:
raise HTTPException(status_code=404, detail="Link not found")
link.label = link_data.label
link.url = link_data.url
db.commit()
db.refresh(link)
return LinkResponse(
id=link.id,
device_id=link.device_id,
label=link.label,
url=link.url
)
@router.delete("/links/{link_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_link(
link_id: int,
db: Session = Depends(get_db)
):
"""Delete a link"""
link = db.query(ManufacturerLink).filter(ManufacturerLink.id == link_id).first()
if not link:
raise HTTPException(status_code=404, detail="Link not found")
db.delete(link)
db.commit()
return None