132 lines
6.2 KiB
Python
132 lines
6.2 KiB
Python
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel
|
|
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, RouterPingStatus, RouterResponse, RouterTestConnection, RouterUpdate
|
|
from app.services.router_service import router_service
|
|
from app.services.settings_service import settings_service
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
class RouterPingBulkResponse(BaseModel):
|
|
items: list[RouterPingStatus]
|
|
|
|
|
|
def serialize_router(router: Router, global_settings) -> RouterResponse:
|
|
has_router_key = bool((router.ssh_key or '').strip())
|
|
has_global_key = bool((global_settings.global_ssh_key or '').strip())
|
|
router_user = (router.ssh_user or '').strip() or None
|
|
router_password = (router.ssh_password or '').strip() or None
|
|
default_swos_user = (global_settings.default_switchos_username or '').strip() or None
|
|
default_swos_password = (global_settings.default_switchos_password or '').strip() or None
|
|
effective_username = router_user
|
|
uses_global_switchos_credentials = False
|
|
has_effective_password = bool(router_password)
|
|
|
|
if router.device_type == 'switchos':
|
|
effective_username = router_user or default_swos_user
|
|
uses_global_switchos_credentials = bool(
|
|
(not router_user and default_swos_user) or (not router_password and default_swos_password)
|
|
)
|
|
has_effective_password = bool(router_password or default_swos_password)
|
|
|
|
payload = RouterResponse.model_validate(router, from_attributes=True).model_dump()
|
|
payload['effective_username'] = effective_username
|
|
payload['uses_global_ssh_key'] = router.device_type == 'routeros' and has_global_key and not has_router_key
|
|
payload['has_effective_ssh_key'] = router.device_type == 'routeros' and (has_router_key or has_global_key)
|
|
payload['uses_global_switchos_credentials'] = uses_global_switchos_credentials
|
|
payload['has_effective_password'] = has_effective_password
|
|
payload['supports_export'] = router.device_type == 'routeros'
|
|
payload['supports_restore_upload'] = router.device_type == 'routeros'
|
|
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)):
|
|
global_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, global_settings) for router in routers]
|
|
|
|
|
|
@router.get('/ping-statuses', response_model=RouterPingBulkResponse)
|
|
def list_ping_statuses(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
routers = db.query(Router).filter(Router.owner_id == current_user.id).all()
|
|
return RouterPingBulkResponse(items=router_service.ping_many(routers))
|
|
|
|
|
|
@router.post('', response_model=RouterResponse)
|
|
def create_router(payload: RouterCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
router_data = payload.model_dump()
|
|
if router_data.get('device_type') == 'switchos' and router_data.get('ssh_user') is None:
|
|
router_data['ssh_user'] = ''
|
|
router = Router(**router_data, owner_id=current_user.id)
|
|
db.add(router)
|
|
db.commit()
|
|
db.refresh(router)
|
|
global_settings = settings_service.get_or_create(db)
|
|
return serialize_router(router, global_settings)
|
|
|
|
|
|
@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='Device not found')
|
|
global_settings = settings_service.get_or_create(db)
|
|
return serialize_router(router, global_settings)
|
|
|
|
|
|
@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='Device not found')
|
|
changes = payload.model_dump(exclude_unset=True)
|
|
target_device_type = changes.get('device_type', router.device_type)
|
|
if target_device_type == 'switchos':
|
|
changes['ssh_key'] = None
|
|
if 'port' not in changes:
|
|
changes['port'] = 80
|
|
if changes.get('ssh_user') is None:
|
|
changes['ssh_user'] = ''
|
|
elif target_device_type == 'routeros' and 'port' not in changes and router.device_type != 'routeros':
|
|
changes['port'] = 22
|
|
if not changes.get('ssh_user'):
|
|
changes['ssh_user'] = router.ssh_user or 'admin'
|
|
for key, value in changes.items():
|
|
setattr(router, key, value)
|
|
db.add(router)
|
|
db.commit()
|
|
db.refresh(router)
|
|
global_settings = settings_service.get_or_create(db)
|
|
return serialize_router(router, global_settings)
|
|
|
|
|
|
@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='Device 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': 'Device 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='Device not found')
|
|
global_settings = settings_service.get_or_create(db)
|
|
return router_service.test_connection(db, router, global_settings)
|