add: provide backup archive feature

This commit is contained in:
h z
2025-01-16 14:05:19 +00:00
parent 9e0967c69e
commit e87ec256bb
2 changed files with 69 additions and 1 deletions

66
api/backup.py Normal file
View File

@@ -0,0 +1,66 @@
import shutil
import zipfile
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")
children = [c for c in paths.values() if c.parent_id == path_id]
for child in children:
traverse(child.id, paths)
cd_back()