docker upload directories fixes
This commit is contained in:
@@ -22,7 +22,7 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Create necessary directories and set permissions
|
# Create necessary directories and set permissions
|
||||||
RUN mkdir -p /app/uploads/rooms /app/static/uploads && \
|
RUN mkdir -p /app/uploads/rooms /app/uploads/profile_pics /app/static/uploads && \
|
||||||
chown -R celery:celery /app && \
|
chown -R celery:celery /app && \
|
||||||
chmod -R 755 /app/uploads
|
chmod -R 755 /app/uploads
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
2
app.py
2
app.py
@@ -136,7 +136,7 @@ app = create_app()
|
|||||||
|
|
||||||
@app.route('/uploads/profile_pics/<filename>')
|
@app.route('/uploads/profile_pics/<filename>')
|
||||||
def profile_pic(filename):
|
def profile_pic(filename):
|
||||||
return send_from_directory(os.path.join(os.getcwd(), 'uploads', 'profile_pics'), filename)
|
return send_from_directory('/app/uploads/profile_pics', filename)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ def sync_files():
|
|||||||
return jsonify({'error': 'Unauthorized'}), 403
|
return jsonify({'error': 'Unauthorized'}), 403
|
||||||
|
|
||||||
try:
|
try:
|
||||||
DATA_ROOT = '/data/rooms'
|
DATA_ROOT = '/app/uploads/rooms'
|
||||||
admin_user = User.query.filter_by(is_admin=True).first()
|
admin_user = User.query.filter_by(is_admin=True).first()
|
||||||
if not admin_user:
|
if not admin_user:
|
||||||
return jsonify({'error': 'No admin user found'}), 500
|
return jsonify({'error': 'No admin user found'}), 500
|
||||||
@@ -73,7 +73,7 @@ def verify_db_state():
|
|||||||
return jsonify({'error': 'Unauthorized'}), 403
|
return jsonify({'error': 'Unauthorized'}), 403
|
||||||
|
|
||||||
try:
|
try:
|
||||||
DATA_ROOT = '/data/rooms'
|
DATA_ROOT = '/app/uploads/rooms'
|
||||||
verification_results = {
|
verification_results = {
|
||||||
'rooms_checked': 0,
|
'rooms_checked': 0,
|
||||||
'files_in_db_not_fs': [],
|
'files_in_db_not_fs': [],
|
||||||
@@ -208,7 +208,7 @@ def cleanup_orphaned_records():
|
|||||||
return jsonify({'error': 'Unauthorized'}), 403
|
return jsonify({'error': 'Unauthorized'}), 403
|
||||||
|
|
||||||
try:
|
try:
|
||||||
DATA_ROOT = '/data/rooms'
|
DATA_ROOT = '/app/uploads/rooms'
|
||||||
rooms = Room.query.all()
|
rooms = Room.query.all()
|
||||||
cleaned_records = []
|
cleaned_records = []
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import string
|
|||||||
|
|
||||||
contacts_bp = Blueprint('contacts', __name__, url_prefix='/contacts')
|
contacts_bp = Blueprint('contacts', __name__, url_prefix='/contacts')
|
||||||
|
|
||||||
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'uploads', 'profile_pics')
|
UPLOAD_FOLDER = '/app/uploads/profile_pics'
|
||||||
if not os.path.exists(UPLOAD_FOLDER):
|
if not os.path.exists(UPLOAD_FOLDER):
|
||||||
os.makedirs(UPLOAD_FOLDER)
|
os.makedirs(UPLOAD_FOLDER)
|
||||||
|
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ def init_routes(main_bp):
|
|||||||
is_admin=current_user.is_admin
|
is_admin=current_user.is_admin
|
||||||
)
|
)
|
||||||
|
|
||||||
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'uploads', 'profile_pics')
|
UPLOAD_FOLDER = '/app/uploads/profile_pics'
|
||||||
if not os.path.exists(UPLOAD_FOLDER):
|
if not os.path.exists(UPLOAD_FOLDER):
|
||||||
os.makedirs(UPLOAD_FOLDER)
|
os.makedirs(UPLOAD_FOLDER)
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ def upload_room_file(room_id):
|
|||||||
|
|
||||||
# If we are overwriting, delete the trashed file record
|
# If we are overwriting, delete the trashed file record
|
||||||
db.session.delete(trashed_file)
|
db.session.delete(trashed_file)
|
||||||
db.session.commit()
|
|
||||||
existing_file = None
|
existing_file = None
|
||||||
|
|
||||||
file.save(file_path)
|
file.save(file_path)
|
||||||
@@ -347,6 +346,19 @@ def delete_file(room_id, filename):
|
|||||||
if not rf:
|
if not rf:
|
||||||
return jsonify({'error': 'File not found'}), 404
|
return jsonify({'error': 'File not found'}), 404
|
||||||
|
|
||||||
|
# If it's a folder, mark all contained items as deleted
|
||||||
|
if rf.type == 'folder':
|
||||||
|
folder_path = os.path.join(rf.path, rf.name) if rf.path else rf.name
|
||||||
|
contained_items = RoomFile.query.filter(
|
||||||
|
RoomFile.room_id == room_id,
|
||||||
|
RoomFile.path.like(f"{folder_path}%")
|
||||||
|
).all()
|
||||||
|
|
||||||
|
for item in contained_items:
|
||||||
|
item.deleted = True
|
||||||
|
item.deleted_by = current_user.id
|
||||||
|
item.deleted_at = datetime.utcnow()
|
||||||
|
|
||||||
# Mark as deleted and record who deleted it and when
|
# Mark as deleted and record who deleted it and when
|
||||||
rf.deleted = True
|
rf.deleted = True
|
||||||
rf.deleted_by = current_user.id
|
rf.deleted_by = current_user.id
|
||||||
@@ -1053,6 +1065,9 @@ def delete_permanent(room_id):
|
|||||||
for item in contained_items:
|
for item in contained_items:
|
||||||
db.session.delete(item)
|
db.session.delete(item)
|
||||||
|
|
||||||
|
# Delete the database record
|
||||||
|
db.session.delete(rf)
|
||||||
|
|
||||||
log_event(
|
log_event(
|
||||||
event_type='file_delete_permanent',
|
event_type='file_delete_permanent',
|
||||||
details={
|
details={
|
||||||
@@ -1066,10 +1081,15 @@ def delete_permanent(room_id):
|
|||||||
user_id=current_user.id
|
user_id=current_user.id
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error deleting {rf.type} from storage: {e}")
|
print(f"Error deleting file {rf.name}: {str(e)}")
|
||||||
|
continue
|
||||||
|
|
||||||
# Delete the database record
|
# Commit all changes
|
||||||
db.session.delete(rf)
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error committing changes: {str(e)}")
|
||||||
|
db.session.rollback()
|
||||||
|
return jsonify({'error': 'Failed to delete files'}), 500
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
return jsonify({'success': True})
|
return jsonify({'success': True})
|
||||||
@@ -346,7 +346,7 @@ def delete_room(room_id):
|
|||||||
print(f"Attempting to delete room {room_id} ({room_name})")
|
print(f"Attempting to delete room {room_id} ({room_name})")
|
||||||
|
|
||||||
# Delete physical files
|
# Delete physical files
|
||||||
room_dir = os.path.join('/data/rooms', str(room_id))
|
room_dir = os.path.join('/app/uploads/rooms', str(room_id))
|
||||||
if os.path.exists(room_dir):
|
if os.path.exists(room_dir):
|
||||||
shutil.rmtree(room_dir)
|
shutil.rmtree(room_dir)
|
||||||
print(f"Deleted room directory: {room_dir}")
|
print(f"Deleted room directory: {room_dir}")
|
||||||
|
|||||||
@@ -348,13 +348,32 @@ export class ViewManager {
|
|||||||
renderFileActions(file, index) {
|
renderFileActions(file, index) {
|
||||||
const actions = [];
|
const actions = [];
|
||||||
|
|
||||||
// Add details button
|
// Check if file can be previewed
|
||||||
actions.push(`
|
const extension = file.name.split('.').pop().toLowerCase();
|
||||||
<button class="btn btn-sm file-action-btn" title="Details" onclick="window.roomManager.modalManager.showDetailsModal('${file.name}', '${file.path || ''}')"
|
const previewableExtensions = [
|
||||||
style="background-color:var(--primary-opacity-8);color:var(--primary-color);">
|
'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
|
||||||
<i class="fas fa-info-circle"></i>
|
'txt', 'md', 'csv', 'py', 'js', 'html', 'css', 'json', 'xml', 'sql', 'sh', 'bat',
|
||||||
</button>
|
'jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'tiff',
|
||||||
`);
|
'mp3', 'mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (previewableExtensions.includes(extension)) {
|
||||||
|
// Add preview button for previewable files
|
||||||
|
actions.push(`
|
||||||
|
<button class="btn btn-sm file-action-btn" title="Preview" onclick="window.roomManager.viewManager.previewFile(${index})"
|
||||||
|
style="background-color:var(--primary-opacity-8);color:var(--primary-color);">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</button>
|
||||||
|
`);
|
||||||
|
} else {
|
||||||
|
// Add details button for non-previewable files
|
||||||
|
actions.push(`
|
||||||
|
<button class="btn btn-sm file-action-btn" title="Details" onclick="window.roomManager.modalManager.showDetailsModal('${file.name}', '${file.path || ''}')"
|
||||||
|
style="background-color:var(--primary-opacity-8);color:var(--primary-color);">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
</button>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
// Add download button if user has permission
|
// Add download button if user has permission
|
||||||
if (this.roomManager.canDownload) {
|
if (this.roomManager.canDownload) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from datetime import datetime
|
|||||||
from app import create_app
|
from app import create_app
|
||||||
from models import db, Room, RoomFile, User
|
from models import db, Room, RoomFile, User
|
||||||
|
|
||||||
DATA_ROOT = '/data/rooms'
|
DATA_ROOT = '/app/uploads/rooms'
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
|
|||||||
2
tasks.py
2
tasks.py
@@ -20,7 +20,7 @@ def cleanup_trash():
|
|||||||
try:
|
try:
|
||||||
# Delete the file from storage if it's a file
|
# Delete the file from storage if it's a file
|
||||||
if file.type == 'file':
|
if file.type == 'file':
|
||||||
file_path = os.path.join('/data/rooms', str(file.room_id), file.path, file.name)
|
file_path = os.path.join('/app/uploads/rooms', str(file.room_id), file.path, file.name)
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
os.remove(file_path)
|
os.remove(file_path)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user