import shutil from datetime import datetime from flask import Blueprint, send_file, jsonify import os from api import require_auth from db import get_db from db.models.Markdown import Markdown from db.models.Path import Path import logging logger = logging.getLogger(__name__) backup_bp = Blueprint('backup', __name__, url_prefix='/api/backup') @backup_bp.route('/', methods=['GET']) @require_auth(roles=['admin']) def get_backup(): try: paths = {} with get_db() as session: pths = session.query(Path).all() paths = {p.id : p for p in pths} traverse(1, paths) timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') archive = shutil.make_archive(base_name=timestamp, format='zip', root_dir='Root') shutil.rmtree('Root') return send_file( archive, as_attachment=True, download_name=timestamp + '.zip', ) except Exception as e: logger.error(f"Failed to get backup: {e}") return jsonify({"error": "failed to get backup"}), 500 def create_and_cd(path_name): if not os.path.exists(path_name) or not os.path.isdir(path_name): os.makedirs(path_name) os.chdir(path_name) def cd_back(): os.chdir('..') def traverse(path_id, paths): current_path = paths[path_id] if path_id == 1: create_and_cd("Root") else: create_and_cd(current_path.name) with open(".meta", "w") as meta_file: meta_file.write(f"order: {current_path.order}\n") with get_db() as session: mds = session.query(Markdown).filter(Markdown.path_id == path_id).all() for md in mds: with open(f"{md.title}.md", "w") as md_file: md_file.write(md.content) with open(f"{md.title}.mdmeta", "w") as meta_file: meta_file.write(f"created_at: {md.created_at}\n") meta_file.write(f"order: {md.order}\n") meta_file.write(f"shortcut: {md.shortcut}\n") children = [c for c in paths.values() if c.parent_id == path_id] for child in children: traverse(child.id, paths) cd_back()