2026.06.04 frontend építés közben

This commit is contained in:
Roo
2026-06-04 07:26:22 +00:00
parent 7adf6cc3e3
commit 59a30ac428
3302 changed files with 24091 additions and 1771 deletions

View File

@@ -0,0 +1,305 @@
#!/usr/bin/env python3
"""
Ground Zero Database Purge Script
Deletes ALL test users (e.g., tester_pro@profibot.hu, noreply@...),
and cascade deletes all their Organizations, Branches, and Assets.
Outputs the exact number of deleted rows for each table.
"""
import asyncio
import sys
from sqlalchemy import text, delete, select
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():
"""Main purge function"""
# 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
)
deleted_counts = {}
async with async_session() as session:
try:
# Start transaction
await session.begin()
print("🔍 Starting Ground Zero database purge...")
print("=" * 60)
# 1. First, identify test users to delete
test_email_patterns = [
'%test%',
'%noreply%',
'%profibot%',
'tester_pro@profibot.hu',
'test@example.com',
'%example.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 for cascade operations
query = text(f"""
SELECT id, email
FROM identity.users
WHERE {where_clause}
AND is_deleted = false
""")
result = await session.execute(query)
test_users = result.fetchall()
if not test_users:
print("✅ No test users found to delete.")
await session.commit()
return deleted_counts
user_ids = [str(user[0]) for user in test_users]
user_emails = [user[1] for user in test_users]
print(f"📋 Found {len(test_users)} test users to delete:")
for email in user_emails[:10]: # Show first 10
print(f" - {email}")
if len(test_users) > 10:
print(f" ... and {len(test_users) - 10} more")
user_ids_str = ",".join(user_ids)
# 3. Delete in reverse cascade order to respect foreign keys
# First, get person IDs for these users
person_query = text(f"""
SELECT DISTINCT person_id
FROM identity.users
WHERE id IN ({user_ids_str})
AND person_id IS NOT NULL
""")
person_result = await session.execute(person_query)
person_ids = [str(row[0]) for row in person_result.fetchall()]
person_ids_str = ",".join(person_ids) if person_ids else "NULL"
# Delete from tables that reference users/persons
# a) Delete from gamification tables
gamification_tables = [
("gamification.user_stats", "user_id"),
("gamification.user_badges", "user_id"),
("gamification.points_ledger", "user_id"),
("gamification.user_contributions", "user_id"),
]
for table, column in gamification_tables:
delete_query = text(f"""
DELETE FROM {table}
WHERE {column} IN ({user_ids_str})
RETURNING *
""")
result = await session.execute(delete_query)
deleted = result.rowcount
deleted_counts[table] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} rows from {table}")
# b) Delete from social tables - with error handling for missing tables
social_tables = [
("identity.social_accounts", "user_id"),
("marketplace.service_requests", "user_id"),
]
# Try to delete from service_reviews if it exists
social_tables_to_try = social_tables + [("identity.service_reviews", "user_id")]
for table, column in social_tables_to_try:
try:
delete_query = text(f"""
DELETE FROM {table}
WHERE {column} IN ({user_ids_str})
RETURNING *
""")
result = await session.execute(delete_query)
deleted = result.rowcount
deleted_counts[table] = 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:
raise
# c) Delete from organization-related tables
# First get organization IDs owned by these users
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()]
org_ids_str = ",".join(org_ids) if org_ids else "NULL"
if org_ids:
# Delete branches for these organizations
branch_query = text(f"""
DELETE FROM marketplace.branches
WHERE organization_id IN ({org_ids_str})
RETURNING *
""")
result = await session.execute(branch_query)
deleted = result.rowcount
deleted_counts["marketplace.branches"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} branches")
# Delete organization members
org_member_query = text(f"""
DELETE FROM marketplace.organization_members
WHERE organization_id IN ({org_ids_str})
RETURNING *
""")
result = await session.execute(org_member_query)
deleted = result.rowcount
deleted_counts["marketplace.organization_members"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} organization members")
# Delete organizations
org_delete_query = text(f"""
DELETE FROM marketplace.organizations
WHERE id IN ({org_ids_str})
RETURNING *
""")
result = await session.execute(org_delete_query)
deleted = result.rowcount
deleted_counts["marketplace.organizations"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} organizations")
# d) Delete from asset-related tables
# Get asset IDs owned by these users
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()]
asset_ids_str = ",".join(asset_ids) if asset_ids else "NULL"
if asset_ids:
# Delete asset costs
asset_cost_query = text(f"""
DELETE FROM data.asset_costs
WHERE asset_id IN ({asset_ids_str})
RETURNING *
""")
result = await session.execute(asset_cost_query)
deleted = result.rowcount
deleted_counts["data.asset_costs"] = deleted
if deleted > 0:
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})
RETURNING *
""")
result = await session.execute(asset_event_query)
deleted = result.rowcount
deleted_counts["data.asset_events"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} asset events")
# Delete assets
asset_delete_query = text(f"""
DELETE FROM data.assets
WHERE id IN ({asset_ids_str})
RETURNING *
""")
result = await session.execute(asset_delete_query)
deleted = result.rowcount
deleted_counts["data.assets"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} assets")
# e) Delete wallets
wallet_query = text(f"""
DELETE FROM identity.wallets
WHERE user_id IN ({user_ids_str})
RETURNING *
""")
result = await session.execute(wallet_query)
deleted = result.rowcount
deleted_counts["identity.wallets"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} wallets")
# f) Finally delete users
user_delete_query = text(f"""
DELETE FROM identity.users
WHERE id IN ({user_ids_str})
RETURNING *
""")
result = await session.execute(user_delete_query)
deleted = result.rowcount
deleted_counts["identity.users"] = deleted
print(f" 🗑️ Deleted {deleted} users")
# g) Delete persons (if they have no other users)
if person_ids:
person_delete_query = text(f"""
DELETE FROM identity.persons
WHERE id IN ({person_ids_str})
AND NOT EXISTS (
SELECT 1 FROM identity.users
WHERE person_id = persons.id
)
RETURNING *
""")
result = await session.execute(person_delete_query)
deleted = result.rowcount
deleted_counts["identity.persons"] = deleted
if deleted > 0:
print(f" 🗑️ Deleted {deleted} persons")
# Commit transaction
await session.commit()
print("=" * 60)
print("✅ Ground Zero purge completed successfully!")
print("\n📊 Deletion Summary:")
for table, count in deleted_counts.items():
print(f" {table}: {count} rows")
total_deleted = sum(deleted_counts.values())
print(f"\n📈 Total rows deleted: {total_deleted}")
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())