2026.06.04 frontend építés közben
This commit is contained in:
325
backend/scripts/purge_test_data_final.py
Normal file
325
backend/scripts/purge_test_data_final.py
Normal file
@@ -0,0 +1,325 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Final Ground Zero Database Purge Script
|
||||
|
||||
Deletes ALL test users in correct cascade order.
|
||||
"""
|
||||
|
||||
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_final():
|
||||
"""Final purge function with proper cascade order"""
|
||||
# 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 (final)...")
|
||||
print("=" * 60)
|
||||
|
||||
# Start transaction
|
||||
await session.begin()
|
||||
|
||||
# 1. First, identify test users to delete
|
||||
test_email_patterns = [
|
||||
'%test%',
|
||||
'%noreply%',
|
||||
'%profibot%',
|
||||
'tester_pro@profibot.hu',
|
||||
'test@example.com',
|
||||
'%example.com',
|
||||
'%@gmail.com'
|
||||
]
|
||||
|
||||
# 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 user IDs to delete
|
||||
get_users_query = text(f"""
|
||||
SELECT id, email
|
||||
FROM identity.users
|
||||
WHERE {where_clause}
|
||||
AND is_deleted = false
|
||||
ORDER BY id
|
||||
""")
|
||||
|
||||
result = await session.execute(get_users_query)
|
||||
test_users = result.fetchall()
|
||||
|
||||
if not test_users:
|
||||
print("✅ No test users found to delete.")
|
||||
await session.commit()
|
||||
return
|
||||
|
||||
user_ids = [str(user[0]) for user in test_users]
|
||||
user_emails = [user[1] for user in test_users]
|
||||
user_ids_str = ",".join(user_ids)
|
||||
|
||||
print(f"📋 Found {len(test_users)} test users to delete:")
|
||||
for email in user_emails[:10]:
|
||||
print(f" - {email}")
|
||||
if len(test_users) > 10:
|
||||
print(f" ... and {len(test_users) - 10} more")
|
||||
|
||||
# 3. Delete in correct cascade order
|
||||
|
||||
# a) First delete from tables that reference users but have no further dependencies
|
||||
print("\n🗑️ Deleting related records in cascade order...")
|
||||
|
||||
# Tables to delete (in order of dependencies)
|
||||
tables_to_clean = [
|
||||
# Gamification tables
|
||||
("gamification.user_stats", "user_id"),
|
||||
("gamification.user_badges", "user_id"),
|
||||
("gamification.points_ledger", "user_id"),
|
||||
("gamification.user_contributions", "user_id"),
|
||||
|
||||
# Social tables (skip if they don't exist)
|
||||
("identity.social_accounts", "user_id"),
|
||||
("marketplace.service_requests", "user_id"),
|
||||
|
||||
# Organization members first (before organizations)
|
||||
("marketplace.organization_members", "user_id"),
|
||||
|
||||
# Payment intents
|
||||
("marketplace.payment_intents", "payer_id"),
|
||||
("marketplace.payment_intents", "beneficiary_id"),
|
||||
|
||||
# Withdrawal requests
|
||||
("marketplace.withdrawal_requests", "user_id"),
|
||||
|
||||
# Service reviews (if table exists)
|
||||
("identity.service_reviews", "user_id"),
|
||||
|
||||
# Vehicle ratings
|
||||
("vehicle.vehicle_user_ratings", "user_id"),
|
||||
|
||||
# Vehicle ownership
|
||||
("vehicle.vehicle_ownership", "user_id"),
|
||||
]
|
||||
|
||||
deleted_counts = {}
|
||||
|
||||
for table, column in tables_to_clean:
|
||||
try:
|
||||
# Check if table exists by trying to count
|
||||
check_query = text(f"""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = '{table.split('.')[0]}'
|
||||
AND table_name = '{table.split('.')[1]}'
|
||||
)
|
||||
""")
|
||||
exists_result = await session.execute(check_query)
|
||||
exists = exists_result.scalar()
|
||||
|
||||
if not exists:
|
||||
print(f" ⚠️ Table {table} doesn't exist, skipping...")
|
||||
continue
|
||||
|
||||
delete_query = text(f"""
|
||||
DELETE FROM {table}
|
||||
WHERE {column} IN ({user_ids_str})
|
||||
""")
|
||||
result = await session.execute(delete_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts[f"{table}.{column}"] = deleted
|
||||
if deleted > 0:
|
||||
print(f" ✅ Deleted {deleted} rows from {table}")
|
||||
|
||||
except Exception as e:
|
||||
if "does not exist" in str(e) or "UndefinedTableError" in str(e):
|
||||
print(f" ⚠️ Table {table} doesn't exist, skipping...")
|
||||
continue
|
||||
else:
|
||||
print(f" ⚠️ Error deleting from {table}: {e}")
|
||||
continue
|
||||
|
||||
# b) Delete wallets (references users)
|
||||
try:
|
||||
wallet_query = text(f"""
|
||||
DELETE FROM identity.wallets
|
||||
WHERE user_id IN ({user_ids_str})
|
||||
""")
|
||||
result = await session.execute(wallet_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["identity.wallets"] = deleted
|
||||
print(f" ✅ Deleted {deleted} wallets")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Error deleting wallets: {e}")
|
||||
|
||||
# c) Delete organizations owned by these users
|
||||
try:
|
||||
# Get organization IDs
|
||||
org_query = text(f"""
|
||||
SELECT id FROM marketplace.organizations
|
||||
WHERE owner_id IN ({user_ids_str})
|
||||
""")
|
||||
org_result = await session.execute(org_query)
|
||||
org_ids = [str(row[0]) for row in org_result.fetchall()]
|
||||
|
||||
if org_ids:
|
||||
org_ids_str = ",".join(org_ids)
|
||||
|
||||
# Delete branches for these organizations
|
||||
branch_query = text(f"""
|
||||
DELETE FROM marketplace.branches
|
||||
WHERE organization_id IN ({org_ids_str})
|
||||
""")
|
||||
result = await session.execute(branch_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["marketplace.branches"] = deleted
|
||||
print(f" ✅ Deleted {deleted} branches")
|
||||
|
||||
# Delete organization members for these organizations
|
||||
org_member_query = text(f"""
|
||||
DELETE FROM marketplace.organization_members
|
||||
WHERE organization_id IN ({org_ids_str})
|
||||
""")
|
||||
result = await session.execute(org_member_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["marketplace.organization_members_org"] = deleted
|
||||
print(f" ✅ Deleted {deleted} organization members (by org)")
|
||||
|
||||
# Delete organizations
|
||||
org_delete_query = text(f"""
|
||||
DELETE FROM marketplace.organizations
|
||||
WHERE id IN ({org_ids_str})
|
||||
""")
|
||||
result = await session.execute(org_delete_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["marketplace.organizations"] = deleted
|
||||
print(f" ✅ Deleted {deleted} organizations")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Error deleting organizations: {e}")
|
||||
|
||||
# d) Delete assets owned by these users
|
||||
try:
|
||||
# Get asset IDs
|
||||
asset_query = text(f"""
|
||||
SELECT id FROM data.assets
|
||||
WHERE owner_id IN ({user_ids_str})
|
||||
""")
|
||||
asset_result = await session.execute(asset_query)
|
||||
asset_ids = [str(row[0]) for row in asset_result.fetchall()]
|
||||
|
||||
if asset_ids:
|
||||
asset_ids_str = ",".join(asset_ids)
|
||||
|
||||
# Delete asset costs
|
||||
asset_cost_query = text(f"""
|
||||
DELETE FROM data.asset_costs
|
||||
WHERE asset_id IN ({asset_ids_str})
|
||||
""")
|
||||
result = await session.execute(asset_cost_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["data.asset_costs"] = deleted
|
||||
print(f" ✅ Deleted {deleted} asset costs")
|
||||
|
||||
# Delete asset events
|
||||
asset_event_query = text(f"""
|
||||
DELETE FROM data.asset_events
|
||||
WHERE asset_id IN ({asset_ids_str})
|
||||
""")
|
||||
result = await session.execute(asset_event_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["data.asset_events"] = deleted
|
||||
print(f" ✅ Deleted {deleted} asset events")
|
||||
|
||||
# Delete assets
|
||||
asset_delete_query = text(f"""
|
||||
DELETE FROM data.assets
|
||||
WHERE id IN ({asset_ids_str})
|
||||
""")
|
||||
result = await session.execute(asset_delete_query)
|
||||
deleted = result.rowcount
|
||||
deleted_counts["data.assets"] = deleted
|
||||
print(f" ✅ Deleted {deleted} assets")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Error deleting assets: {e}")
|
||||
|
||||
# e) Finally delete users
|
||||
print("\n🗑️ Deleting test users...")
|
||||
user_delete_query = text(f"""
|
||||
DELETE FROM identity.users
|
||||
WHERE id IN ({user_ids_str})
|
||||
AND is_deleted = false
|
||||
""")
|
||||
result = await session.execute(user_delete_query)
|
||||
deleted_users = result.rowcount
|
||||
deleted_counts["identity.users"] = deleted_users
|
||||
print(f" ✅ Deleted {deleted_users} users")
|
||||
|
||||
# f) Delete orphaned persons
|
||||
person_delete_query = text("""
|
||||
DELETE FROM identity.persons
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM identity.users
|
||||
WHERE users.person_id = persons.id
|
||||
)
|
||||
""")
|
||||
result = await session.execute(person_delete_query)
|
||||
deleted_persons = result.rowcount
|
||||
deleted_counts["identity.persons"] = deleted_persons
|
||||
if deleted_persons > 0:
|
||||
print(f" ✅ Deleted {deleted_persons} orphaned persons")
|
||||
|
||||
# Commit transaction
|
||||
await session.commit()
|
||||
|
||||
print("=" * 60)
|
||||
print("✅ Ground Zero purge completed successfully!")
|
||||
print("\n📊 Deletion Summary:")
|
||||
total_deleted = 0
|
||||
for key, count in deleted_counts.items():
|
||||
print(f" {key}: {count} rows")
|
||||
total_deleted += count
|
||||
|
||||
print(f"\n📈 Total rows deleted: {total_deleted}")
|
||||
|
||||
# Verify cleanup
|
||||
print("\n🔍 Verifying 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"✅ Verification: All test users have been removed.")
|
||||
else:
|
||||
print(f"⚠️ Verification: {remaining} test users still remain.")
|
||||
|
||||
return deleted_counts
|
||||
|
||||
except Exception as e:
|
||||
await session.rollback()
|
||||
print(f"❌ Error during purge: {e}")
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(purge_test_data_final())
|
||||
Reference in New Issue
Block a user