mirror of
https://github.com/suitenumerique/drive.git
synced 2026-08-17 20:15:40 +02:00
🐛(backend) find deleted root items when searching the trashbin
Search rebuilds the visible set from the user's accesses, skipping those whose item was soft deleted. A root item holds its own access, so deleting it made it unreachable from any location, trashbin included. Hard deleted items remain excluded, and the scope filter still keeps deleted items out of regular search results.
This commit is contained in:
@@ -16,6 +16,7 @@ and this project adheres to
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(backend) find deleted root items when searching the trashbin
|
||||
- 🐛(backend) exclude folders from file type search results
|
||||
- 🐛(frontend) keep uploaded items usable while malware analysis runs
|
||||
- 🐛(backend) stream export files from S3 without buffering
|
||||
|
||||
@@ -1356,11 +1356,14 @@ class ItemViewSet(
|
||||
|
||||
workspace = filterset.form.cleaned_data.get("workspace")
|
||||
|
||||
# First look for all top level items user has access to
|
||||
# First look for all top level items user has access to. Soft deleted items
|
||||
# are kept: a deleted root item is its own access holder and would become
|
||||
# unreachable, even from the trashbin. The scope filter excludes them from
|
||||
# the results.
|
||||
user = request.user
|
||||
item_access_queryset = models.ItemAccess.objects.select_related("item").filter(
|
||||
db.Q(user=user) | db.Q(team__in=user.teams),
|
||||
item__deleted_at__isnull=True,
|
||||
item__hard_deleted_at__isnull=True,
|
||||
)
|
||||
|
||||
# Remove items with upload_state SUSPICIOUS for non-creators
|
||||
|
||||
@@ -825,3 +825,49 @@ def test_api_items_search_filter_category_excludes_folders():
|
||||
|
||||
assert response.status_code == 200
|
||||
assert [item["id"] for item in response.json()["results"]] == [str(spreadsheet.id)]
|
||||
|
||||
|
||||
def test_api_items_search_trashbin_finds_deleted_root_item():
|
||||
"""A deleted root item should still be reachable from the trashbin location."""
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
# A root item carries its own access: deleting it removes the only access
|
||||
# pointing at it.
|
||||
item = factories.ItemFactory(
|
||||
title="ywh_export_report.pdf",
|
||||
filename="ywh_export_report.pdf",
|
||||
creator=user,
|
||||
users=[(user, models.RoleChoices.OWNER)],
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
update_upload_state=models.ItemUploadStateChoices.READY,
|
||||
)
|
||||
item.soft_delete()
|
||||
|
||||
response = client.get("/api/v1.0/items/search/?location=trashbin&title=ywh_export")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert [result["id"] for result in response.json()["results"]] == [str(item.id)]
|
||||
|
||||
|
||||
def test_api_items_search_excludes_deleted_root_item_by_default():
|
||||
"""A deleted root item should stay out of the search results without a scope."""
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
item = factories.ItemFactory(
|
||||
title="ywh_export_report.pdf",
|
||||
filename="ywh_export_report.pdf",
|
||||
creator=user,
|
||||
users=[(user, models.RoleChoices.OWNER)],
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
update_upload_state=models.ItemUploadStateChoices.READY,
|
||||
)
|
||||
item.soft_delete()
|
||||
|
||||
response = client.get("/api/v1.0/items/search/?title=ywh_export")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["results"] == []
|
||||
|
||||
Reference in New Issue
Block a user