Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ and this project adheres to
- ♿ add missing aria-label to add sub-doc button for accessib… #1480
- ♿ add missing aria-label to more options button on sub-docs #1481

### Fixed

- ⚡️(backend) improve trashbin endpoint performance

## [3.8.0] - 2025-10-14

### Added
Expand Down
19 changes: 18 additions & 1 deletion src/backend/core/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,12 +623,29 @@ def trashbin(self, request, *args, **kwargs):
The selected documents are those deleted within the cutoff period defined in the
settings (see TRASHBIN_CUTOFF_DAYS), before they are considered permanently deleted.
"""

if not request.user.is_authenticated:
return self.get_response_for_queryset(self.queryset.none())

access_documents_paths = (
models.DocumentAccess.objects.select_related("document")
.filter(
db.Q(user=self.request.user) | db.Q(team__in=self.request.user.teams),
role=models.RoleChoices.OWNER,
)
.values_list("document__path", flat=True)
)

children_clause = db.Q()
for path in access_documents_paths:
children_clause |= db.Q(path__startswith=path)

queryset = self.queryset.filter(
children_clause,
deleted_at__isnull=False,
deleted_at__gte=models.get_trashbin_cutoff(),
)
queryset = queryset.annotate_user_roles(self.request.user)
queryset = queryset.filter(user_roles__contains=[models.RoleChoices.OWNER])

return self.get_response_for_queryset(queryset)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ def test_api_documents_trashbin_authenticated_direct(django_assert_num_queries):

expected_ids = {str(document1.id), str(document2.id), str(document3.id)}

with django_assert_num_queries(10):
with django_assert_num_queries(11):
response = client.get("/api/v1.0/documents/trashbin/")

with django_assert_num_queries(4):
with django_assert_num_queries(5):
response = client.get("/api/v1.0/documents/trashbin/")

assert response.status_code == 200
Expand Down Expand Up @@ -208,10 +208,10 @@ def test_api_documents_trashbin_authenticated_via_team(

expected_ids = {str(deleted_document_team1.id), str(deleted_document_team2.id)}

with django_assert_num_queries(7):
with django_assert_num_queries(8):
response = client.get("/api/v1.0/documents/trashbin/")

with django_assert_num_queries(3):
with django_assert_num_queries(4):
response = client.get("/api/v1.0/documents/trashbin/")

assert response.status_code == 200
Expand Down
Loading