updated backups solution

This commit is contained in:
Quality System Admin
2025-11-03 22:18:56 +02:00
parent 1ade0b5681
commit 9c19379810
17 changed files with 3105 additions and 50 deletions

View File

@@ -3711,4 +3711,106 @@ def api_backup_restore(filename):
return jsonify({
'success': False,
'message': f'Restore failed: {str(e)}'
}), 500
}), 500
@bp.route('/api/backup/upload', methods=['POST'])
@superadmin_only
def api_backup_upload():
"""Upload an external backup file (superadmin only)"""
try:
from app.database_backup import DatabaseBackupManager
from werkzeug.utils import secure_filename
import os
from datetime import datetime
# Check if file was uploaded
if 'backup_file' not in request.files:
return jsonify({
'success': False,
'message': 'No file uploaded'
}), 400
file = request.files['backup_file']
# Check if file was selected
if file.filename == '':
return jsonify({
'success': False,
'message': 'No file selected'
}), 400
# Validate file extension
if not file.filename.lower().endswith('.sql'):
return jsonify({
'success': False,
'message': 'Invalid file format. Only .sql files are allowed.'
}), 400
# Get backup manager and backup path
backup_manager = DatabaseBackupManager()
backup_path = backup_manager.backup_path
# Ensure backup_path is a Path object
from pathlib import Path
if not isinstance(backup_path, Path):
backup_path = Path(backup_path)
# Create backup directory if it doesn't exist
backup_path.mkdir(parents=True, exist_ok=True)
# Generate secure filename with timestamp to avoid conflicts
original_filename = secure_filename(file.filename)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# If filename already starts with "backup_", keep it; otherwise add prefix
if original_filename.startswith('backup_'):
new_filename = f"{original_filename.rsplit('.', 1)[0]}_{timestamp}.sql"
else:
new_filename = f"backup_uploaded_{timestamp}_{original_filename}"
# Save file to backup directory
file_path = backup_path / new_filename
file.save(str(file_path))
# Get file size
file_size = file_path.stat().st_size
size_mb = round(file_size / (1024 * 1024), 2)
# Validate the uploaded file for integrity and compatibility
validation_result = backup_manager.validate_backup_file(new_filename)
if not validation_result['success']:
# Validation failed - remove the uploaded file
file_path.unlink() # Delete the invalid file
return jsonify({
'success': False,
'message': f'Validation failed: {validation_result["message"]}',
'validation_details': validation_result.get('details', {}),
'warnings': validation_result.get('warnings', [])
}), 400
# Build response with validation details
response = {
'success': True,
'message': 'Backup file uploaded and validated successfully',
'filename': new_filename,
'size': f'{size_mb} MB',
'path': str(file_path),
'validation': {
'status': 'passed',
'message': validation_result['message'],
'details': validation_result.get('details', {}),
'warnings': validation_result.get('warnings', [])
}
}
# Add warning flag if there are warnings
if validation_result.get('warnings'):
response['message'] = f'Backup uploaded with warnings: {"; ".join(validation_result["warnings"])}'
return jsonify(response)
except Exception as e:
return jsonify({
'success': False,
'message': f'Upload failed: {str(e)}'
}), 500