from pathlib import Path from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.api.deps import get_current_user, get_db from app.models.router import Router from app.models.user import User from app.schemas.router import RouterCreate, RouterResponse, RouterTestConnection, RouterUpdate from app.services.router_service import router_service from app.services.settings_service import settings_service router = APIRouter() def serialize_router(router: Router, global_ssh_key: str | None = None) -> RouterResponse: has_router_key = bool((router.ssh_key or '').strip()) has_global_key = bool((global_ssh_key or '').strip()) payload = RouterResponse.model_validate(router, from_attributes=True).model_dump() payload['uses_global_ssh_key'] = has_global_key and not has_router_key payload['has_effective_ssh_key'] = has_router_key or has_global_key return RouterResponse.model_validate(payload) @router.get("", response_model=list[RouterResponse]) def list_routers(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): settings = settings_service.get_or_create(db) routers = db.query(Router).filter(Router.owner_id == current_user.id).order_by(Router.created_at.desc()).all() return [serialize_router(router, settings.global_ssh_key) for router in routers] @router.post("", response_model=RouterResponse) def create_router(payload: RouterCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): router = Router(**payload.model_dump(), owner_id=current_user.id) db.add(router) db.commit() db.refresh(router) settings = settings_service.get_or_create(db) return serialize_router(router, settings.global_ssh_key) @router.get("/{router_id}", response_model=RouterResponse) def get_router(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): router = db.query(Router).filter(Router.id == router_id, Router.owner_id == current_user.id).first() if not router: raise HTTPException(status_code=404, detail="Router not found") settings = settings_service.get_or_create(db) return serialize_router(router, settings.global_ssh_key) @router.put("/{router_id}", response_model=RouterResponse) def update_router(router_id: int, payload: RouterUpdate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): router = db.query(Router).filter(Router.id == router_id, Router.owner_id == current_user.id).first() if not router: raise HTTPException(status_code=404, detail="Router not found") for key, value in payload.model_dump(exclude_unset=True).items(): setattr(router, key, value) db.add(router) db.commit() db.refresh(router) settings = settings_service.get_or_create(db) return serialize_router(router, settings.global_ssh_key) @router.delete("/{router_id}") def delete_router(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): router = db.query(Router).filter(Router.id == router_id, Router.owner_id == current_user.id).first() if not router: raise HTTPException(status_code=404, detail="Router not found") for backup in list(router.backups): path = Path(backup.file_path) if path.exists(): path.unlink() db.delete(router) db.commit() return {"message": "Router deleted"} @router.get("/{router_id}/test-connection", response_model=RouterTestConnection) def test_connection(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): router = db.query(Router).filter(Router.id == router_id, Router.owner_id == current_user.id).first() if not router: raise HTTPException(status_code=404, detail="Router not found") settings = settings_service.get_or_create(db) return router_service.test_connection(db, router, settings.global_ssh_key)