MyFSIO v0.1.9 Release #10

Merged
kqjy merged 3 commits from next into main 2025-12-29 06:49:48 +00:00
3 changed files with 34 additions and 28 deletions
Showing only changes of commit 1cacb80dd6 - Show all commits

View File

@@ -306,6 +306,12 @@ class ReplicationManager:
if self._shutdown:
return
# Re-check if rule is still enabled (may have been paused after task was submitted)
current_rule = self.get_rule(bucket_name)
if not current_rule or not current_rule.enabled:
logger.debug(f"Replication skipped for {bucket_name}/{object_key}: rule disabled or removed")
return
if ".." in object_key or object_key.startswith("/") or object_key.startswith("\\"):
logger.error(f"Invalid object key in replication (path traversal attempt): {object_key}")
return

View File

@@ -1054,6 +1054,7 @@ class ObjectStorage:
shutil.rmtree(upload_root, ignore_errors=True)
self._invalidate_bucket_stats_cache(bucket_id)
self._invalidate_object_cache(bucket_id)
stat = destination.stat()
return ObjectMeta(

View File

@@ -3802,40 +3802,39 @@
selectAllCheckbox?.addEventListener('change', (event) => {
const shouldSelect = Boolean(event.target?.checked);
if (hasFolders()) {
// Get all file items in the current view (works with virtual scrolling)
const filesInView = visibleItems.filter(item => item.type === 'file');
const objectsInCurrentView = allObjects.filter(obj => obj.key.startsWith(currentPrefix));
objectsInCurrentView.forEach(obj => {
const checkbox = obj.element.querySelector('[data-object-select]');
if (checkbox && !checkbox.disabled) {
checkbox.checked = shouldSelect;
// Update selectedRows directly using object keys (not DOM elements)
filesInView.forEach(item => {
if (shouldSelect) {
selectedRows.set(item.data.key, item.data);
} else {
selectedRows.delete(item.data.key);
}
toggleRowSelection(obj.element, shouldSelect);
});
// Update folder checkboxes in DOM (folders are always rendered)
document.querySelectorAll('[data-folder-select]').forEach(cb => {
cb.checked = shouldSelect;
});
} else {
// Update any currently rendered object checkboxes
document.querySelectorAll('[data-object-row]').forEach((row) => {
if (row.style.display === 'none') return;
const checkbox = row.querySelector('[data-object-select]');
if (!checkbox || checkbox.disabled) {
return;
}
if (checkbox) {
checkbox.checked = shouldSelect;
toggleRowSelection(row, shouldSelect);
});
}
});
updateBulkDeleteState();
setTimeout(updateBulkDownloadState, 0);
});
bulkDownloadButton?.addEventListener('click', async () => {
if (!bulkDownloadEndpoint) return;
const selected = Array.from(document.querySelectorAll('[data-object-select]:checked')).map(
(cb) => cb.closest('tr').dataset.key
);
// Use selectedRows which tracks all selected objects (not just rendered ones)
const selected = Array.from(selectedRows.keys());
if (selected.length === 0) return;
bulkDownloadButton.disabled = true;