Fix Database Restore
Browse files- app.py +30 -0
- database_manager.py +47 -1
app.py
CHANGED
|
@@ -414,6 +414,29 @@ def predict():
|
|
| 414 |
except Exception as e:
|
| 415 |
return jsonify({"error": f"Có lỗi xảy ra khi xử lý: {str(e)}"}), 500
|
| 416 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
|
| 418 |
# Khởi tạo database
|
| 419 |
with app.app_context():
|
|
@@ -422,6 +445,13 @@ with app.app_context():
|
|
| 422 |
|
| 423 |
db.create_all()
|
| 424 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 425 |
# Kiểm tra và thêm cột is_admin nếu chưa có
|
| 426 |
try:
|
| 427 |
# Thử query để kiểm tra xem cột is_admin có tồn tại không
|
|
|
|
| 414 |
except Exception as e:
|
| 415 |
return jsonify({"error": f"Có lỗi xảy ra khi xử lý: {str(e)}"}), 500
|
| 416 |
|
| 417 |
+
@app.route('/admin/backup', methods=['POST'])
|
| 418 |
+
@admin_required
|
| 419 |
+
def manual_backup():
|
| 420 |
+
"""Manual backup endpoint for admin"""
|
| 421 |
+
try:
|
| 422 |
+
if backup_database():
|
| 423 |
+
return jsonify({"success": True, "message": "Backup completed successfully"})
|
| 424 |
+
else:
|
| 425 |
+
return jsonify({"success": False, "message": "Backup failed"}), 500
|
| 426 |
+
except Exception as e:
|
| 427 |
+
return jsonify({"success": False, "message": f"Backup error: {str(e)}"}), 500
|
| 428 |
+
|
| 429 |
+
@app.route('/admin/restore', methods=['POST'])
|
| 430 |
+
@admin_required
|
| 431 |
+
def manual_restore():
|
| 432 |
+
"""Manual restore endpoint for admin"""
|
| 433 |
+
try:
|
| 434 |
+
if restore_database():
|
| 435 |
+
return jsonify({"success": True, "message": "Database restored successfully"})
|
| 436 |
+
else:
|
| 437 |
+
return jsonify({"success": False, "message": "Restore failed"}), 500
|
| 438 |
+
except Exception as e:
|
| 439 |
+
return jsonify({"success": False, "message": f"Restore error: {str(e)}"}), 500
|
| 440 |
|
| 441 |
# Khởi tạo database
|
| 442 |
with app.app_context():
|
|
|
|
| 445 |
|
| 446 |
db.create_all()
|
| 447 |
|
| 448 |
+
# Create initial backup after database setup
|
| 449 |
+
print("🔄 Creating initial backup...")
|
| 450 |
+
if db_manager.backup_database():
|
| 451 |
+
print("✅ Initial backup created successfully")
|
| 452 |
+
else:
|
| 453 |
+
print("⚠️ Initial backup failed - will retry later")
|
| 454 |
+
|
| 455 |
# Kiểm tra và thêm cột is_admin nếu chưa có
|
| 456 |
try:
|
| 457 |
# Thử query để kiểm tra xem cột is_admin có tồn tại không
|
database_manager.py
CHANGED
|
@@ -34,6 +34,48 @@ class DatabaseManager:
|
|
| 34 |
login(token=self.hf_token)
|
| 35 |
self.api = HfApi()
|
| 36 |
print("✅ Successfully logged in to Hugging Face Hub")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
except Exception as e:
|
| 38 |
print(f"❌ Failed to login to Hugging Face Hub: {e}")
|
| 39 |
self.api = None
|
|
@@ -210,7 +252,11 @@ class DatabaseManager:
|
|
| 210 |
return True
|
| 211 |
|
| 212 |
except Exception as e:
|
| 213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
return False
|
| 215 |
|
| 216 |
def check_database_exists(self) -> bool:
|
|
|
|
| 34 |
login(token=self.hf_token)
|
| 35 |
self.api = HfApi()
|
| 36 |
print("✅ Successfully logged in to Hugging Face Hub")
|
| 37 |
+
|
| 38 |
+
# Test token permissions with private repo
|
| 39 |
+
try:
|
| 40 |
+
# Test READ permission - list files
|
| 41 |
+
files = self.api.list_repo_files(repo_id=self.repo_id, repo_type="dataset")
|
| 42 |
+
print(f"✅ Token has READ access to private dataset: {self.repo_id}")
|
| 43 |
+
print(f"📁 Found {len(files)} files in dataset")
|
| 44 |
+
|
| 45 |
+
# Test WRITE permission - create a test file
|
| 46 |
+
test_content = {"test": "permission_check", "timestamp": str(datetime.now())}
|
| 47 |
+
temp_file = f"{self.backup_dir}/permission_test.json"
|
| 48 |
+
with open(temp_file, 'w') as f:
|
| 49 |
+
json.dump(test_content, f)
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
self.api.upload_file(
|
| 53 |
+
path_or_fileobj=temp_file,
|
| 54 |
+
path_in_repo='permission_test.json',
|
| 55 |
+
repo_id=self.repo_id,
|
| 56 |
+
repo_type="dataset",
|
| 57 |
+
commit_message="Testing write permissions"
|
| 58 |
+
)
|
| 59 |
+
print("✅ Token has WRITE access - can upload files")
|
| 60 |
+
|
| 61 |
+
# Clean up test file
|
| 62 |
+
self.api.delete_file(
|
| 63 |
+
path_in_repo='permission_test.json',
|
| 64 |
+
repo_id=self.repo_id,
|
| 65 |
+
repo_type="dataset",
|
| 66 |
+
commit_message="Clean up test file"
|
| 67 |
+
)
|
| 68 |
+
os.remove(temp_file)
|
| 69 |
+
print("✅ Token has DELETE access - can remove files")
|
| 70 |
+
|
| 71 |
+
except Exception as write_error:
|
| 72 |
+
print(f"⚠️ WRITE permission issue: {write_error}")
|
| 73 |
+
print("💡 Your token needs 'Write' permission for backup to work")
|
| 74 |
+
|
| 75 |
+
except Exception as perm_error:
|
| 76 |
+
print(f"⚠️ Token permission issue: {perm_error}")
|
| 77 |
+
print("💡 Make sure your token has 'Write' permission")
|
| 78 |
+
|
| 79 |
except Exception as e:
|
| 80 |
print(f"❌ Failed to login to Hugging Face Hub: {e}")
|
| 81 |
self.api = None
|
|
|
|
| 252 |
return True
|
| 253 |
|
| 254 |
except Exception as e:
|
| 255 |
+
if "404" in str(e):
|
| 256 |
+
print("ℹ️ No backup found yet. This is normal for first-time setup.")
|
| 257 |
+
print("💡 Backup will be created automatically after first data entry.")
|
| 258 |
+
else:
|
| 259 |
+
print(f"❌ Restore failed: {e}")
|
| 260 |
return False
|
| 261 |
|
| 262 |
def check_database_exists(self) -> bool:
|