Files
mikrotik_backup_system/backend/app/api/routes/backups.py
Mateusz Gruszczyński 3da6c2832c first commit
2026-04-14 11:39:46 +02:00

129 lines
5.6 KiB
Python

from datetime import date
import io
import zipfile
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import FileResponse, HTMLResponse, StreamingResponse
from sqlalchemy.orm import Session
from app.api.deps import get_current_user, get_db
from app.models.user import User
from app.schemas.backup import BackupDiffResponse, BackupResponse, BulkActionRequest
from app.services.backup_service import backup_service
router = APIRouter()
@router.get("", response_model=list[BackupResponse])
def list_backups(
search: str | None = Query(default=None),
backup_type: str | None = Query(default=None, pattern="^(export|binary)$"),
router_id: int | None = Query(default=None),
created_on: date | None = Query(default=None),
sort_by: str = Query(default="created_at"),
order: str = Query(default="desc", pattern="^(asc|desc)$"),
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
):
return backup_service.list_backups(
db,
current_user,
search=search,
backup_type=backup_type,
router_id=router_id,
created_on=created_on,
sort_by=sort_by,
order=order,
)
@router.get("/router/{router_id}", response_model=list[BackupResponse])
def list_router_backups(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.list_router_backups(db, current_user, router_id)
@router.post("/routers/export-all")
def export_all(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.export_all(db, current_user)
@router.post("/routers/binary-all")
def binary_all(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.binary_all(db, current_user)
@router.post("/router/{router_id}/export", response_model=BackupResponse)
def export_router(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.export_router(db, current_user, router_id)
@router.post("/router/{router_id}/binary", response_model=BackupResponse)
def binary_backup(router_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.binary_backup(db, current_user, router_id)
@router.post("/router/{router_id}/upload/{backup_id}")
def upload_to_router(router_id: int, backup_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backup_service.upload_backup_to_router(db, current_user, router_id, backup_id)
return {"message": "Backup uploaded to router"}
@router.delete("/{backup_id}")
def delete_backup(backup_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backup_service.delete_backup(db, current_user, backup_id)
return {"message": "Backup deleted"}
@router.get("/{backup_id}/download")
def download_backup(backup_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backup = backup_service.get_backup_for_user(db, current_user, backup_id)
return FileResponse(path=backup.file_path, filename=backup.file_name)
@router.get("/{backup_id}/view")
def view_export(backup_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backup = backup_service.get_backup_for_user(db, current_user, backup_id)
if backup.backup_type != "export":
raise HTTPException(status_code=400, detail="Only export backups can be viewed")
with open(backup.file_path, "r", encoding="utf-8", errors="ignore") as handle:
return {"content": handle.read(), "backup": BackupResponse.model_validate(backup_service._serialize_backup(backup))}
@router.post("/{backup_id}/email")
def email_backup(backup_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backup_service.email_backup(db, current_user, backup_id)
return {"message": "Backup sent by email"}
@router.get("/{left_id}/diff/{right_id}", response_model=BackupDiffResponse)
def diff_backups(left_id: int, right_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
return backup_service.diff_backups(db, current_user, left_id, right_id)
@router.get("/{left_id}/diff/{right_id}/html", response_class=HTMLResponse)
def diff_backups_html(left_id: int, right_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
result = backup_service.diff_backups(db, current_user, left_id, right_id)
return HTMLResponse(result["diff_html"])
@router.post("/bulk")
def bulk_action(payload: BulkActionRequest, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
backups = [backup_service.get_backup_for_user(db, current_user, backup_id) for backup_id in payload.backup_ids]
if payload.action == "delete":
for backup in backups:
backup_service.delete_backup(db, current_user, backup.id, commit=False)
db.commit()
return {"message": f"Deleted {len(backups)} backups"}
if payload.action == "download":
stream = io.BytesIO()
with zipfile.ZipFile(stream, "w") as archive:
for backup in backups:
archive.write(backup.file_path, backup.file_name)
stream.seek(0)
return StreamingResponse(
stream,
media_type="application/zip",
headers={"Content-Disposition": 'attachment; filename="backups.zip"'},
)
raise HTTPException(status_code=400, detail="Unsupported bulk action")