from __future__ import annotations from datetime import datetime from pathlib import Path import shutil from flask import current_app class BackupService: def create_backup(self): target = Path(current_app.config['BACKUP_PATH']) / f'backup_{datetime.utcnow().strftime("%Y%m%d_%H%M%S")}' target.mkdir(parents=True, exist_ok=True) base_dir = Path(current_app.root_path).parent for part in ['instance', 'storage/archive', 'storage/pdf']: src = base_dir / part if src.exists(): shutil.copytree(src, target / Path(part).name, dirs_exist_ok=True) archive = shutil.make_archive(str(target), 'zip', root_dir=target) return archive def get_database_backup_meta(self) -> dict: uri = current_app.config.get('SQLALCHEMY_DATABASE_URI', '') backup_dir = Path(current_app.config['BACKUP_PATH']) engine = 'unknown' if '://' in uri: engine = uri.split('://', 1)[0] sqlite_supported = uri.startswith('sqlite:///') and not uri.endswith(':memory:') sqlite_path = None sqlite_exists = False if sqlite_supported: sqlite_path = Path(uri.replace('sqlite:///', '', 1)) sqlite_exists = sqlite_path.exists() return { 'engine': engine, 'backup_dir': str(backup_dir), 'sqlite_supported': sqlite_supported, 'sqlite_path': str(sqlite_path) if sqlite_path else None, 'sqlite_exists': sqlite_exists, 'notes': [ 'Kopia z panelu działa plikowo dla SQLite.', 'Dla PostgreSQL, MySQL i innych silników wymagany jest natywny dump bazy poza aplikacją.', ], } def create_database_backup(self) -> str: target_dir = Path(current_app.config['BACKUP_PATH']) target_dir.mkdir(parents=True, exist_ok=True) timestamp = datetime.utcnow().strftime('%Y%m%d_%H%M%S') uri = current_app.config.get('SQLALCHEMY_DATABASE_URI', '') if uri.startswith('sqlite:///') and not uri.endswith(':memory:'): source = Path(uri.replace('sqlite:///', '', 1)) if not source.exists(): raise FileNotFoundError(f'Plik bazy nie istnieje: {source}') target = target_dir / f'db_backup_{timestamp}.sqlite3' shutil.copy2(source, target) return str(target) target = target_dir / f'db_backup_{timestamp}.txt' target.write_text( """Automatyczna kopia DB dla bieżącego silnika nie jest obsługiwana plikowo. W panelu admina kopia działa bezpośrednio tylko dla SQLite. Wykonaj backup natywnym narzędziem bazy danych. """, encoding='utf-8', ) return str(target)