Update main.py
Browse files
main.py
CHANGED
|
@@ -369,6 +369,91 @@ def get_sozo_project(project_id):
|
|
| 369 |
logger.error(f"Error fetching project {project_id}: {str(e)}")
|
| 370 |
return jsonify({'error': str(e)}), 500
|
| 371 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
@app.route('/api/sozo/projects/<string:project_id>/markdown', methods=['PUT'])
|
| 373 |
def update_sozo_markdown(project_id):
|
| 374 |
try:
|
|
|
|
| 369 |
logger.error(f"Error fetching project {project_id}: {str(e)}")
|
| 370 |
return jsonify({'error': str(e)}), 500
|
| 371 |
|
| 372 |
+
@app.route('/api/sozo/projects/<string:project_id>', methods=['DELETE'])
|
| 373 |
+
def delete_sozo_project(project_id):
|
| 374 |
+
logger.info(f"DELETE /api/sozo/projects/{project_id} - Deleting project")
|
| 375 |
+
|
| 376 |
+
try:
|
| 377 |
+
token = request.headers.get('Authorization', '').split(' ')[1]
|
| 378 |
+
uid = verify_token(token)
|
| 379 |
+
if not uid:
|
| 380 |
+
logger.warning(f"Unauthorized access attempt to delete project {project_id}")
|
| 381 |
+
return jsonify({'error': 'Unauthorized'}), 401
|
| 382 |
+
|
| 383 |
+
logger.info(f"User {uid} attempting to delete project {project_id}")
|
| 384 |
+
|
| 385 |
+
# Get project data first to verify ownership and get file paths
|
| 386 |
+
project_ref = db.reference(f'sozo_projects/{project_id}')
|
| 387 |
+
project_data = project_ref.get()
|
| 388 |
+
|
| 389 |
+
if not project_data:
|
| 390 |
+
logger.warning(f"Project {project_id} not found for deletion")
|
| 391 |
+
return jsonify({'error': 'Project not found'}), 404
|
| 392 |
+
|
| 393 |
+
if project_data.get('uid') != uid:
|
| 394 |
+
logger.warning(f"User {uid} unauthorized to delete project {project_id}")
|
| 395 |
+
return jsonify({'error': 'Unauthorized to delete this project'}), 403
|
| 396 |
+
|
| 397 |
+
logger.info(f"Project {project_id} verified for deletion by user {uid}")
|
| 398 |
+
|
| 399 |
+
# Delete files from storage
|
| 400 |
+
deleted_files = []
|
| 401 |
+
try:
|
| 402 |
+
# Delete original data file
|
| 403 |
+
if 'originalDataUrl' in project_data:
|
| 404 |
+
blob_path = "/".join(project_data['originalDataUrl'].split('/')[4:])
|
| 405 |
+
blob = bucket.blob(blob_path)
|
| 406 |
+
if blob.exists():
|
| 407 |
+
blob.delete()
|
| 408 |
+
deleted_files.append(blob_path)
|
| 409 |
+
logger.info(f"Deleted original data file: {blob_path}")
|
| 410 |
+
|
| 411 |
+
# Delete chart files if they exist
|
| 412 |
+
chart_urls = project_data.get('chartUrls', {})
|
| 413 |
+
if isinstance(chart_urls, dict):
|
| 414 |
+
for chart_name, chart_url in chart_urls.items():
|
| 415 |
+
try:
|
| 416 |
+
chart_blob_path = "/".join(chart_url.split('/')[4:])
|
| 417 |
+
chart_blob = bucket.blob(chart_blob_path)
|
| 418 |
+
if chart_blob.exists():
|
| 419 |
+
chart_blob.delete()
|
| 420 |
+
deleted_files.append(chart_blob_path)
|
| 421 |
+
logger.info(f"Deleted chart file: {chart_blob_path}")
|
| 422 |
+
except Exception as chart_error:
|
| 423 |
+
logger.warning(f"Error deleting chart {chart_name}: {str(chart_error)}")
|
| 424 |
+
|
| 425 |
+
# Delete entire project folder if it exists
|
| 426 |
+
project_folder = f"sozo_projects/{uid}/{project_id}/"
|
| 427 |
+
blobs = bucket.list_blobs(prefix=project_folder)
|
| 428 |
+
for blob in blobs:
|
| 429 |
+
if blob.name not in deleted_files: # Avoid duplicate deletions
|
| 430 |
+
blob.delete()
|
| 431 |
+
deleted_files.append(blob.name)
|
| 432 |
+
logger.info(f"Deleted additional file: {blob.name}")
|
| 433 |
+
|
| 434 |
+
logger.info(f"Deleted {len(deleted_files)} files from storage for project {project_id}")
|
| 435 |
+
|
| 436 |
+
except Exception as storage_error:
|
| 437 |
+
logger.error(f"Error deleting storage files for project {project_id}: {str(storage_error)}")
|
| 438 |
+
# Continue with database deletion even if storage cleanup fails
|
| 439 |
+
|
| 440 |
+
# Delete project from database
|
| 441 |
+
project_ref.delete()
|
| 442 |
+
logger.info(f"Project {project_id} deleted from database")
|
| 443 |
+
|
| 444 |
+
logger.info(f"Project {project_id} successfully deleted by user {uid}")
|
| 445 |
+
|
| 446 |
+
return jsonify({
|
| 447 |
+
'success': True,
|
| 448 |
+
'message': f'Project {project_id} deleted successfully',
|
| 449 |
+
'deleted_files': len(deleted_files)
|
| 450 |
+
}), 200
|
| 451 |
+
|
| 452 |
+
except Exception as e:
|
| 453 |
+
logger.error(f"Error deleting project {project_id}: {str(e)}")
|
| 454 |
+
logger.error(f"Traceback: {traceback.format_exc()}")
|
| 455 |
+
return jsonify({'error': str(e)}), 500
|
| 456 |
+
|
| 457 |
@app.route('/api/sozo/projects/<string:project_id>/markdown', methods=['PUT'])
|
| 458 |
def update_sozo_markdown(project_id):
|
| 459 |
try:
|