#!/usr/bin/env python3 """ Simplified Ground Zero Database Purge Script Deletes ALL test users and lets database cascade constraints handle the rest. """ import asyncio import sys from sqlalchemy import text from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker # Import settings sys.path.insert(0, '/app') from app.core.config import settings async def purge_test_data_simple(): """Simple purge function using cascade delete""" # Create async engine engine = create_async_engine( str(settings.SQLALCHEMY_DATABASE_URI), echo=False, pool_size=5, max_overflow=10, ) async_session = sessionmaker( engine, class_=AsyncSession, expire_on_commit=False ) async with async_session() as session: try: print("šŸ” Starting Ground Zero database purge (simplified)...") print("=" * 60) # 1. First, identify test users to delete test_email_patterns = [ '%test%', '%noreply%', '%profibot%', 'tester_pro@profibot.hu', 'test@example.com', '%example.com', '%@gmail.com' # Also delete gmail test users ] # Build WHERE clause for test users where_conditions = [] for pattern in test_email_patterns: where_conditions.append(f"email ILIKE '{pattern}'") where_clause = " OR ".join(where_conditions) # 2. Get count of test users count_query = text(f""" SELECT COUNT(*) FROM identity.users WHERE {where_clause} AND is_deleted = false """) result = await session.execute(count_query) test_user_count = result.scalar() if test_user_count == 0: print("āœ… No test users found to delete.") return # 3. Get list of test users list_query = text(f""" SELECT id, email FROM identity.users WHERE {where_clause} AND is_deleted = false LIMIT 20 """) result = await session.execute(list_query) test_users = result.fetchall() print(f"šŸ“‹ Found {test_user_count} test users to delete:") for user in test_users: print(f" - {user[1]} (ID: {user[0]})") if test_user_count > 20: print(f" ... and {test_user_count - 20} more") # 4. Delete users (cascade will handle related records) delete_query = text(f""" DELETE FROM identity.users WHERE {where_clause} AND is_deleted = false RETURNING id, email """) print("\nšŸ—‘ļø Deleting test users (cascade delete will handle related records)...") result = await session.execute(delete_query) deleted_users = result.fetchall() # 5. Also delete any orphaned persons cleanup_persons_query = text(""" DELETE FROM identity.persons WHERE NOT EXISTS ( SELECT 1 FROM identity.users WHERE users.person_id = persons.id ) RETURNING id """) result = await session.execute(cleanup_persons_query) orphaned_persons = result.rowcount # Commit transaction await session.commit() print("=" * 60) print("āœ… Ground Zero purge completed successfully!") print(f"\nšŸ“Š Deletion Summary:") print(f" Test users deleted: {len(deleted_users)}") print(f" Orphaned persons cleaned up: {orphaned_persons}") # 6. Verify cleanup verify_query = text(f""" SELECT COUNT(*) FROM identity.users WHERE {where_clause} AND is_deleted = false """) result = await session.execute(verify_query) remaining = result.scalar() if remaining == 0: print(f"\nāœ… Verification: All test users have been removed.") else: print(f"\nāš ļø Verification: {remaining} test users still remain.") return len(deleted_users) except Exception as e: await session.rollback() print(f"āŒ Error during purge: {e}") raise if __name__ == "__main__": asyncio.run(purge_test_data_simple())