Files
triviathang/backend/routes/export_import.py
Ryan Chen 69992f1be9 Add question ownership and sharing
Questions now have a created_by field linking to the user who created them.
Users only see questions they own or that have been shared with them.
Includes share dialog, user search, bulk sharing, and export/import
respects ownership.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 09:43:04 -04:00

109 lines
3.2 KiB
Python

"""Routes for exporting and importing trivia questions"""
import os
import tempfile
from flask import Blueprint, jsonify, Response, request, g
from werkzeug.utils import secure_filename
from backend.auth.middleware import require_auth
from backend.services.export_import_service import (
export_questions_to_zip,
import_questions_from_zip
)
bp = Blueprint('export_import', __name__, url_prefix='/api/admin')
@bp.route('/export', methods=['POST'])
@require_auth
def export_data():
"""
Export all questions and categories to a ZIP file.
Returns:
ZIP file containing manifest.json and all media files
"""
try:
# Generate export ZIP (only questions visible to current user)
zip_bytes, zip_filename = export_questions_to_zip(user_id=g.current_user.id)
# Create response with ZIP file
response = Response(
zip_bytes,
mimetype='application/zip',
headers={
'Content-Disposition': f'attachment; filename={zip_filename}',
'Content-Length': str(len(zip_bytes))
}
)
return response
except Exception as e:
return jsonify({'error': f'Export failed: {str(e)}'}), 500
@bp.route('/import', methods=['POST'])
@require_auth
def import_data():
"""
Import questions and categories from a ZIP file.
Expects:
multipart/form-data with 'file' key containing ZIP file
Returns:
JSON with import summary
"""
# Check if file was uploaded
if 'file' not in request.files:
return jsonify({'error': 'No file provided'}), 400
file = request.files['file']
# Check if filename is present
if file.filename == '':
return jsonify({'error': 'No file selected'}), 400
# Check if file is a ZIP
if not file.filename.lower().endswith('.zip'):
return jsonify({'error': 'File must be a ZIP archive'}), 400
temp_path = None
try:
# Save uploaded file to temporary location
temp_dir = tempfile.mkdtemp()
temp_path = os.path.join(temp_dir, secure_filename(file.filename))
print(f"Saving uploaded file to: {temp_path}")
file.save(temp_path)
# Verify file was saved
file_size = os.path.getsize(temp_path)
print(f"Saved file size: {file_size} bytes")
# Import from ZIP (set ownership to current user)
result = import_questions_from_zip(temp_path, user_id=g.current_user.id)
return jsonify(result), 200
except ValueError as e:
# Validation errors
return jsonify({'error': str(e)}), 400
except Exception as e:
# Other errors
return jsonify({'error': f'Import failed: {str(e)}'}), 500
finally:
# Clean up uploaded file
if temp_path and os.path.exists(temp_path):
try:
os.remove(temp_path)
# Remove temp directory if empty
temp_dir = os.path.dirname(temp_path)
if os.path.exists(temp_dir) and not os.listdir(temp_dir):
os.rmdir(temp_dir)
except Exception as e:
print(f"Warning: Failed to clean up temp file {temp_path}: {e}")