From 27e8db7d9a10b158b17fc5a72b92223c68f46c86 Mon Sep 17 00:00:00 2001 From: Daniel Bernstein Date: Thu, 21 May 2026 16:49:03 -0700 Subject: [PATCH 1/2] Exclude trashed items from Google Drive folder lookup get_file was querying Google Drive without a 'trashed = false' filter, so folders that had been moved to the trash were returned as valid parents. Any report uploaded to a trashed folder is invisible to users. Add 'trashed = false' to the query and cover the behaviour with a test that inspects the raw request URI sent to the Drive API. Co-Authored-By: Claude Sonnet 4.5 --- .../service/google_drive/google_drive.py | 13 +++++- .../service/google_drive/test_google_drive.py | 40 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/palace/manager/service/google_drive/google_drive.py b/src/palace/manager/service/google_drive/google_drive.py index 0befbedaa4..7b8e41a0a8 100644 --- a/src/palace/manager/service/google_drive/google_drive.py +++ b/src/palace/manager/service/google_drive/google_drive.py @@ -17,8 +17,19 @@ def __init__(self, api_client: DriveResource) -> None: self.api_client = api_client def get_file(self, name: str, parent_folder_id: str | None = None) -> File | None: + """ + Return the first non-trashed file or folder with the given name. - query = f"name = '{name}'" + :param name: The exact name to search for. + :param parent_folder_id: If provided, restrict the search to items + whose parent is this folder/drive ID. + :return: The first matching, non-trashed ``File`` object, or ``None`` + if no match is found. + """ + # Explicitly exclude trashed items so that a folder moved to the + # Drive trash is not mistaken for a live folder, which would cause + # uploads to land inside a trashed (invisible) directory. + query = f"name = '{name}' and trashed = false" if parent_folder_id: query += f" and '{parent_folder_id}' in parents" diff --git a/tests/manager/service/google_drive/test_google_drive.py b/tests/manager/service/google_drive/test_google_drive.py index 3434b82495..dfb656b93a 100644 --- a/tests/manager/service/google_drive/test_google_drive.py +++ b/tests/manager/service/google_drive/test_google_drive.py @@ -3,6 +3,7 @@ import json from io import BytesIO from typing import TYPE_CHECKING +from urllib.parse import unquote_plus import pytest from googleapiclient.discovery import build @@ -114,6 +115,45 @@ def test_create_file(self): assert "Hello world" in body assert f"Content-Type: {mime_type}" in body + def test_get_file_excludes_trashed_items(self): + """get_file must include 'trashed = false' in its Drive query. + + If a folder has been moved to the Drive trash, it must not be treated + as a live folder — doing so would cause uploads to land inside the + trash, making them invisible to users. + """ + file_name = "some-folder" + file_id = "folder-id" + http_mock_sequence = HttpMockSequence( + [ + ( + {"status": "200"}, + json.dumps( + { + "files": [ + { + "kind": "drive#file", + "id": file_id, + "name": file_name, + "mimeType": "application/vnd.google-apps.folder", + } + ] + } + ), + ), + ] + ) + service = drive_service(http=http_mock_sequence) + + result = service.get_file(name=file_name, parent_folder_id="parent-id") + + assert result is not None + assert result["id"] == file_id + + # Verify the query sent to the Drive API contains the trashed filter. + request_uri = unquote_plus(http_mock_sequence.request_sequence[0][0]) + assert "trashed = false" in request_uri + def test_create_existing_file_fails(self): file_name = "file.txt" file_id = "file-id" From e9312d44b3efdb579aa5400a3c408c07359df454 Mon Sep 17 00:00:00 2001 From: Daniel Bernstein Date: Thu, 21 May 2026 21:57:20 -0700 Subject: [PATCH 2/2] Shorten test_get_file_excludes_trashed_items docstring to one line Co-Authored-By: Claude Sonnet 4.6 --- tests/manager/service/google_drive/test_google_drive.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/manager/service/google_drive/test_google_drive.py b/tests/manager/service/google_drive/test_google_drive.py index dfb656b93a..0eb499fecd 100644 --- a/tests/manager/service/google_drive/test_google_drive.py +++ b/tests/manager/service/google_drive/test_google_drive.py @@ -116,12 +116,7 @@ def test_create_file(self): assert f"Content-Type: {mime_type}" in body def test_get_file_excludes_trashed_items(self): - """get_file must include 'trashed = false' in its Drive query. - - If a folder has been moved to the Drive trash, it must not be treated - as a live folder — doing so would cause uploads to land inside the - trash, making them invisible to users. - """ + """get_file must include 'trashed = false' in its Drive query.""" file_name = "some-folder" file_id = "folder-id" http_mock_sequence = HttpMockSequence(