Add explicit database import UI and harden SQL restore.

This commit is contained in:
orohi
2026-08-09 16:22:38 +03:00
parent bf1c6761fd
commit 58aad90dee
9 changed files with 107 additions and 45 deletions
+23 -2
View File
@@ -2,12 +2,13 @@
from __future__ import annotations
import gzip
import logging
import os
import subprocess
from datetime import datetime, timezone
from .connection import get_pg_connection_params
from .connection import close_pool, get_pg_connection_params
from .store import invalidate_data_cache
logger = logging.getLogger(__name__)
@@ -25,6 +26,18 @@ def backup_filename() -> str:
return f'amnezia_panel_backup_{stamp}.sql'
def _decode_backup_bytes(data: bytes) -> bytes:
"""Accept plain .sql or gzip-compressed dumps (.sql.gz / gzip magic)."""
if not data:
return data
if data[:2] == b'\x1f\x8b':
try:
return gzip.decompress(data)
except OSError as e:
raise ValueError(f'Invalid gzip backup: {e}') from e
return data
def export_database_sql() -> bytes:
"""Create a plain SQL dump of the panel PostgreSQL database."""
params = get_pg_connection_params()
@@ -54,8 +67,16 @@ def export_database_sql() -> bytes:
def restore_database_sql(data: bytes) -> None:
"""Restore panel data from a plain SQL dump produced by pg_dump."""
data = _decode_backup_bytes(data)
if not data or not data.strip():
raise ValueError('Empty backup file')
# Drop live pool connections so --clean DROP TABLE is not blocked.
try:
close_pool()
except Exception as e:
logger.warning('close_pool before restore failed: %s', e)
params = get_pg_connection_params()
proc = subprocess.run(
[
@@ -72,9 +93,9 @@ def restore_database_sql(data: bytes) -> None:
check=False,
env=_pg_cli_env(params['password']),
)
invalidate_data_cache()
if proc.returncode != 0:
err = proc.stderr.decode('utf-8', errors='replace').strip()
out = proc.stdout.decode('utf-8', errors='replace').strip()
raise RuntimeError(err or out or 'psql restore failed')
invalidate_data_cache()
logger.info('PostgreSQL backup restored successfully')