- Improved backup/restore module

This commit is contained in:
maziggy
2025-12-09 11:04:48 +00:00
parent 957ad17825
commit cf972f42c1
4 changed files with 36 additions and 7 deletions
+31 -2
View File
@@ -504,6 +504,18 @@ async def import_backup(
"archives": [],
}
# Log what's in the backup
import logging
restore_logger = logging.getLogger(__name__)
restore_logger.info(f"Restore: Backup version={backup.get('version')}, included={backup.get('included', [])}")
restore_logger.info(f"Restore: overwrite={overwrite}")
if "printers" in backup:
restore_logger.info(f"Restore: Backup contains {len(backup['printers'])} printers")
for p in backup["printers"]:
restore_logger.info(f" - {p.get('name')}: access_code={'YES' if p.get('access_code') else 'NO'}, is_active={p.get('is_active')}")
else:
restore_logger.info("Restore: Backup does NOT contain printers")
# Restore settings (always overwrites)
if "settings" in backup:
for key, value in backup["settings"].items():
@@ -653,14 +665,19 @@ async def import_backup(
restored["smart_plugs"] += 1
# Restore printers (skip or overwrite duplicates by serial_number)
# Note: access_code is never restored for security - must be set manually
import logging
logger = logging.getLogger(__name__)
if "printers" in backup:
logger.info(f"Restore: Processing {len(backup['printers'])} printers from backup")
for printer_data in backup["printers"]:
logger.info(f"Restore: Processing printer {printer_data.get('name')} (serial: {printer_data.get('serial_number')})")
result = await db.execute(
select(Printer).where(Printer.serial_number == printer_data["serial_number"])
)
existing = result.scalar_one_or_none()
if existing:
logger.info(f"Restore: Printer already exists (id={existing.id}, is_active={existing.is_active})")
if overwrite:
existing.name = printer_data["name"]
existing.ip_address = printer_data["ip_address"]
@@ -669,11 +686,23 @@ async def import_backup(
existing.nozzle_count = printer_data.get("nozzle_count", 1)
existing.auto_archive = printer_data.get("auto_archive", True)
existing.print_hours_offset = printer_data.get("print_hours_offset", 0.0)
# Don't overwrite access_code or is_active to preserve working connection
# If backup includes access_code, also update access_code and is_active
backup_access_code = printer_data.get("access_code")
if backup_access_code and backup_access_code != "CHANGE_ME":
existing.access_code = backup_access_code
is_active_val = printer_data.get("is_active", False)
if isinstance(is_active_val, str):
is_active_val = is_active_val.lower() == "true"
existing.is_active = is_active_val
logger.info(f"Restore: Updated access_code and is_active={is_active_val} from backup")
restored["printers"] += 1
logger.info(f"Restore: Updated existing printer (overwrite=True)")
else:
skipped["printers"] += 1
skipped_details["printers"].append(f"{printer_data['name']} ({printer_data['serial_number']})")
logger.info(f"Restore: Skipped existing printer (overwrite=False)")
else:
# Use access code from backup if provided, otherwise require manual setup
access_code = printer_data.get("access_code")
+3 -3
View File
@@ -210,12 +210,12 @@ export function RestoreModal({ onClose, onRestore, onSuccess }: RestoreModalProp
) : (
<SkipForward className="w-4 h-4 text-bambu-gray" />
)}
{overwrite ? 'Overwrite existing data' : 'Skip duplicates'}
{overwrite ? 'Update existing items' : 'Add new items only'}
</p>
<p className="text-sm text-bambu-gray mt-1">
{overwrite
? 'Replace existing items with data from backup (except access codes)'
: 'Keep existing items, only add new ones from backup'}
? 'Replace data for items that already exist on this system'
: 'Items that already exist on this system will not be changed'}
</p>
</div>
<Toggle checked={overwrite} onChange={setOverwrite} />
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
<script type="module" crossorigin src="/assets/index-p0QddWWP.js"></script>
<script type="module" crossorigin src="/assets/index-C9aeLRXp.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Ob3MFXab.css">
</head>
<body>