From 70d4feb6f70c401e75b6d588d75ecfd30c9e0584 Mon Sep 17 00:00:00 2001 From: Mohammed Mohsin Date: Tue, 13 Jan 2026 14:01:47 +0530 Subject: [PATCH 1/2] delete cloud sync recordings on acc delete --- backend/database/users.py | 19 +++++++++++++------ backend/utils/other/storage.py | 21 +++++++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/backend/database/users.py b/backend/database/users.py index 626e6ea0dd..0aa261726d 100644 --- a/backend/database/users.py +++ b/backend/database/users.py @@ -7,6 +7,7 @@ from ._client import db, document_id_from_seed from models.users import Subscription, PlanLimits, PlanType, SubscriptionStatus from utils.subscription import get_default_basic_subscription +from utils.other.storage import delete_all_user_private_cloud_sync_data def is_exists_user(uid: str): @@ -166,10 +167,12 @@ def remove_person_speech_sample(uid: str, person_id: str, sample_path: str) -> b if not person_doc.exists: return False - person_ref.update({ - 'speech_samples': firestore.ArrayRemove([sample_path]), - 'updated_at': datetime.now(timezone.utc), - }) + person_ref.update( + { + 'speech_samples': firestore.ArrayRemove([sample_path]), + 'updated_at': datetime.now(timezone.utc), + } + ) return True @@ -252,6 +255,10 @@ def delete_user_data(uid: str): print(f"Processed all documents in {collection_ref.path}") break + # delete private cloud sync recordings from GCS + print(f"Deleting private cloud sync data for user: {uid}") + delete_all_user_private_cloud_sync_data(uid) + # delete the user document itself print(f"Deleting user document: {uid}") user_ref.delete() @@ -294,12 +301,12 @@ def get_all_ratings(rating_type: str = 'memory_summary'): def set_chat_message_rating_score(uid: str, message_id: str, value: int, reason: str = None): """ Store chat message rating/feedback. - + Args: uid: User ID message_id: Message ID being rated value: Rating value (1 = thumbs up, -1 = thumbs down, 0 = neutral/removed) - reason: Optional reason for thumbs down (e.g. 'too_verbose', 'incorrect_or_hallucination', + reason: Optional reason for thumbs down (e.g. 'too_verbose', 'incorrect_or_hallucination', 'not_helpful_or_irrelevant', 'didnt_follow_instructions', 'other') """ doc_id = document_id_from_seed('chat_message' + message_id) diff --git a/backend/utils/other/storage.py b/backend/utils/other/storage.py index 8089b9a8fa..3d08d56659 100644 --- a/backend/utils/other/storage.py +++ b/backend/utils/other/storage.py @@ -190,10 +190,10 @@ def get_speech_sample_signed_urls(paths: List[str]) -> List[str]: """ Generate signed URLs for speech samples given their GCS paths. Uses the paths stored in Firestore instead of listing GCS blobs. - + Args: paths: List of GCS paths (e.g., '{uid}/people_profiles/{person_id}/{filename}') - + Returns: List of signed URLs """ @@ -402,6 +402,23 @@ def delete_conversation_audio_files(uid: str, conversation_id: str) -> None: blob.delete() +def delete_all_user_private_cloud_sync_data(uid: str) -> None: + """Delete all private cloud sync data (chunks and merged audio) for a user.""" + if not uid: + return + bucket = storage_client.bucket(private_cloud_sync_bucket) + + # Delete all chunks for this user + chunks_prefix = f'chunks/{uid}/' + for blob in bucket.list_blobs(prefix=chunks_prefix): + blob.delete() + + # Delete all merged audio files for this user + audio_prefix = f'audio/{uid}/' + for blob in bucket.list_blobs(prefix=audio_prefix): + blob.delete() + + def download_audio_chunks_and_merge( uid: str, conversation_id: str, From 0e7ed87de50dae041b72c5a1771b4feedc429973 Mon Sep 17 00:00:00 2001 From: Mohammed Mohsin <59914433+mdmohsin7@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:29:08 +0530 Subject: [PATCH 2/2] Update backend/utils/other/storage.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- backend/utils/other/storage.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/utils/other/storage.py b/backend/utils/other/storage.py index e14d3a5a5e..b00a18acc2 100644 --- a/backend/utils/other/storage.py +++ b/backend/utils/other/storage.py @@ -408,15 +408,17 @@ def delete_all_user_private_cloud_sync_data(uid: str) -> None: return bucket = storage_client.bucket(private_cloud_sync_bucket) - # Delete all chunks for this user - chunks_prefix = f'chunks/{uid}/' - for blob in bucket.list_blobs(prefix=chunks_prefix): - blob.delete() + # Use a batch request to efficiently delete all blobs for the user. + with storage_client.batch(): + # Delete all chunks for this user + chunks_prefix = f'chunks/{uid}/' + for blob in bucket.list_blobs(prefix=chunks_prefix): + blob.delete() - # Delete all merged audio files for this user - audio_prefix = f'audio/{uid}/' - for blob in bucket.list_blobs(prefix=audio_prefix): - blob.delete() + # Delete all merged audio files for this user + audio_prefix = f'audio/{uid}/' + for blob in bucket.list_blobs(prefix=audio_prefix): + blob.delete() def download_audio_chunks_and_merge(