Volver a la wiki

Endpoint: Full Backup (racks/api/export/backup.py)

Propósito

Endpoint GET que descarga un ZIP con toda la configuración de una organización (datos + uploads), scoped solo a los ficheros referenciados.

Ruta: /api/racks/backup/full/ (GET)

Acceso: Requiere ser admin de la org (check is_admin())

Comportamiento

Entrada: Request HTTP GET

Salida: FileResponse con ZIP (streaming, no carga en RAM)

Operación:

  1. Verifica que el usuario sea admin de su org
  2. Recolecta toda la configuración de la org (via serialización interna)
  3. Empaqueta uploads: solo los ficheros referenciados por stencils/blueprints
    • Via collect_org_upload_files(org_upload_image_paths(backup_data))
    • Dedup + anti-path-escape
  4. Escribe ZIP en streaming
  5. Retorna ZIP como descarga con header Content-Disposition: attachment

Seguridad

Scoping por organización:

Permisos:

Payload de datos

El ZIP contiene:

backup_data.json

{
  "organization": { ... },
  "users": [ ... ],
  "stencils": [
    {
      "id": 1,
      "name": "Stencil 1",
      "image_path": "uploads/stencils/s1.png",
      ...
    }
  ],
  "blueprints": [
    {
      "id": 1,
      "name": "Blueprint 1",
      "image_path": "uploads/blueprints/bp1.png",
      ...
    }
  ],
  "devices": [ ... ],
  "racks": [ ... ],
  ...
}

Uploads (solo referenciados)

uploads/
  stencils/
    s1.png      (referenciado por stencil.id=1)
    s2.png      (referenciado por stencil.id=2)
  blueprints/
    bp1.png     (referenciado por blueprint.id=1)

⚠️ Antes del fix s107: empaquetaba TODA la carpeta uploads/ (todos los tenants)

Implementación

Archivo: racks/api/export/backup.py

Función: backup_full(request)

Locación: línea ~35

Cambio s107:

Streaming: Usa FileResponse con archivo ZIP generado en el filesystem (no carga todo en RAM)

Flujo completo

  1. GET /api/racks/backup/full/
  2. is_admin(request) → True
  3. Serializa org + modelos → backup_data
  4. Llama generate_backup(org) que:
    • Escribe backup_data.json
    • Colecta uploads via collect_org_upload_files()
    • Escribe ZIP
  5. Retorna ZIP como FileResponse

Lado complementario

Restauración: racks/api/export/restore.py::restore_full(request, file)

Dependencias

Servicios:

Middlewares:

Utilidades:

Tests

Archivo: tests/api/test_backup.py

Cubre:

Véase también

Subir