173 lines
6.0 KiB
Python
173 lines
6.0 KiB
Python
from flask import Blueprint, jsonify, request, abort
|
|
from flask_login import login_required, current_user
|
|
from models import db, Room, RoomFile, TrashedFile, UserStarredFile
|
|
from utils import user_has_permission, clean_path, log_event
|
|
import os
|
|
from datetime import datetime
|
|
|
|
trash_bp = Blueprint('trash', __name__)
|
|
|
|
@trash_bp.route('/<int:room_id>/trash', methods=['GET'])
|
|
@login_required
|
|
def list_trashed_files(room_id):
|
|
room = Room.query.get_or_404(room_id)
|
|
if not user_has_permission(room, 'can_view'):
|
|
abort(403)
|
|
|
|
# Get all trashed files in the room
|
|
files = TrashedFile.query.filter_by(room_id=room_id).order_by(TrashedFile.deleted_at.desc()).all()
|
|
|
|
result = []
|
|
for f in files:
|
|
uploader_full_name = None
|
|
uploader_profile_pic = None
|
|
if f.uploader:
|
|
uploader_full_name = f.uploader.username
|
|
if getattr(f.uploader, 'last_name', None):
|
|
uploader_full_name += ' ' + f.uploader.last_name
|
|
uploader_profile_pic = f.uploader.profile_picture if getattr(f.uploader, 'profile_picture', None) else None
|
|
|
|
deleter_full_name = None
|
|
if f.deleter:
|
|
deleter_full_name = f.deleter.username
|
|
if getattr(f.deleter, 'last_name', None):
|
|
deleter_full_name += ' ' + f.deleter.last_name
|
|
|
|
result.append({
|
|
'id': f.id,
|
|
'name': f.name,
|
|
'type': f.type,
|
|
'size': f.size if f.type == 'file' else '-',
|
|
'modified': f.modified,
|
|
'uploaded_by': uploader_full_name,
|
|
'uploader_profile_pic': uploader_profile_pic,
|
|
'uploaded_at': f.uploaded_at.isoformat() if f.uploaded_at else None,
|
|
'original_path': f.original_path,
|
|
'deleted_by': deleter_full_name,
|
|
'deleted_at': f.deleted_at.isoformat()
|
|
})
|
|
|
|
return jsonify(result)
|
|
|
|
@trash_bp.route('/<int:room_id>/trash/<int:trash_id>/restore', methods=['POST'])
|
|
@login_required
|
|
def restore_file(room_id, trash_id):
|
|
room = Room.query.get_or_404(room_id)
|
|
if not user_has_permission(room, 'can_upload'):
|
|
abort(403)
|
|
|
|
trashed_file = TrashedFile.query.get_or_404(trash_id)
|
|
if trashed_file.room_id != room_id:
|
|
abort(404)
|
|
|
|
# Create new RoomFile entry
|
|
rf = RoomFile(
|
|
room_id=room_id,
|
|
name=trashed_file.name,
|
|
path=trashed_file.original_path,
|
|
type=trashed_file.type,
|
|
size=trashed_file.size,
|
|
modified=trashed_file.modified,
|
|
uploaded_by=trashed_file.uploaded_by,
|
|
uploaded_at=trashed_file.uploaded_at
|
|
)
|
|
db.session.add(rf)
|
|
|
|
# Delete the trashed file entry
|
|
db.session.delete(trashed_file)
|
|
db.session.commit()
|
|
|
|
log_event(
|
|
event_type='file_restore',
|
|
details={
|
|
'filename': trashed_file.name,
|
|
'room_id': room_id,
|
|
'room_name': room.name,
|
|
'original_path': trashed_file.original_path,
|
|
'restored_by': f"{current_user.username} {current_user.last_name}",
|
|
'file_type': trashed_file.type,
|
|
'file_size': trashed_file.size if trashed_file.type == 'file' else None
|
|
},
|
|
user_id=current_user.id
|
|
)
|
|
|
|
return jsonify({'success': True})
|
|
|
|
@trash_bp.route('/<int:room_id>/trash/<int:trash_id>', methods=['DELETE'])
|
|
@login_required
|
|
def permanently_delete_file(room_id, trash_id):
|
|
room = Room.query.get_or_404(room_id)
|
|
if not user_has_permission(room, 'can_delete'):
|
|
abort(403)
|
|
|
|
trashed_file = TrashedFile.query.get_or_404(trash_id)
|
|
if trashed_file.room_id != room_id:
|
|
abort(404)
|
|
|
|
# Delete the trashed file entry
|
|
db.session.delete(trashed_file)
|
|
db.session.commit()
|
|
|
|
log_event(
|
|
event_type='file_delete_permanent',
|
|
details={
|
|
'filename': trashed_file.name,
|
|
'room_id': room_id,
|
|
'room_name': room.name,
|
|
'original_path': trashed_file.original_path,
|
|
'deleted_by': f"{current_user.username} {current_user.last_name}",
|
|
'file_type': trashed_file.type,
|
|
'file_size': trashed_file.size if trashed_file.type == 'file' else None,
|
|
'was_in_trash': True
|
|
},
|
|
user_id=current_user.id
|
|
)
|
|
|
|
return jsonify({'success': True})
|
|
|
|
@trash_bp.route('/<int:room_id>/trash/empty', methods=['POST'])
|
|
@login_required
|
|
def empty_trash(room_id):
|
|
"""Empty the trash for a specific room."""
|
|
try:
|
|
room = Room.query.get_or_404(room_id)
|
|
# Get all trashed files
|
|
trashed_files = TrashedFile.query.filter_by(room_id=room_id).all()
|
|
|
|
# Delete physical files first
|
|
for file in trashed_files:
|
|
try:
|
|
file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], str(room_id), file.name)
|
|
if os.path.exists(file_path):
|
|
os.remove(file_path)
|
|
except Exception as e:
|
|
print(f"Error deleting physical file {file.name}: {str(e)}")
|
|
continue
|
|
|
|
# Delete all starred file references for the trashed files
|
|
room_files = RoomFile.query.filter_by(room_id=room_id, deleted=True).all()
|
|
for file in room_files:
|
|
UserStarredFile.query.filter_by(file_id=file.id).delete()
|
|
|
|
# Delete all trashed files from both tables
|
|
TrashedFile.query.filter_by(room_id=room_id).delete()
|
|
RoomFile.query.filter_by(room_id=room_id, deleted=True).delete()
|
|
|
|
db.session.commit()
|
|
|
|
log_event(
|
|
event_type='trash_empty',
|
|
details={
|
|
'room_id': room_id,
|
|
'room_name': room.name,
|
|
'emptied_by': f"{current_user.username} {current_user.last_name}",
|
|
'files_deleted_count': len(trashed_files)
|
|
},
|
|
user_id=current_user.id
|
|
)
|
|
|
|
return jsonify({'success': True})
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
print(f"Error emptying trash: {str(e)}")
|
|
return jsonify({'success': False, 'error': str(e)}), 500 |