201 előtti mentés
This commit is contained in:
95
backend/app/scripts/reset_admin_pass.py
Normal file
95
backend/app/scripts/reset_admin_pass.py
Normal file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Reset admin password script.
|
||||
Updates the hashed_password for superadmin@profibot.hu in the identity.users table.
|
||||
Sets password to Admin123! using the system's get_password_hash function.
|
||||
Ensures is_active is set to True.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the backend directory to the Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from sqlalchemy import update, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.database import AsyncSessionLocal, engine
|
||||
from app.models.identity.identity import User
|
||||
from app.core.security import get_password_hash
|
||||
|
||||
|
||||
async def reset_admin_password():
|
||||
"""Reset password for superadmin@profibot.hu"""
|
||||
email = "superadmin@profibot.hu"
|
||||
new_password = "Admin123!"
|
||||
|
||||
print(f"🔧 Resetting password for {email}...")
|
||||
|
||||
async with AsyncSessionLocal() as session:
|
||||
# First, check if the user exists
|
||||
stmt = select(User).where(User.email == email)
|
||||
result = await session.execute(stmt)
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if not user:
|
||||
print(f"❌ User {email} not found in database!")
|
||||
return False
|
||||
|
||||
print(f"✅ Found user: ID={user.id}, email={user.email}, is_active={user.is_active}")
|
||||
|
||||
# Generate new password hash
|
||||
hashed_password = get_password_hash(new_password)
|
||||
print(f"🔐 Generated password hash: {hashed_password[:20]}...")
|
||||
|
||||
# Update the user
|
||||
update_stmt = (
|
||||
update(User)
|
||||
.where(User.email == email)
|
||||
.values(
|
||||
hashed_password=hashed_password,
|
||||
is_active=True
|
||||
)
|
||||
)
|
||||
await session.execute(update_stmt)
|
||||
await session.commit()
|
||||
|
||||
print(f"✅ Password updated successfully!")
|
||||
print(f"📋 New credentials:")
|
||||
print(f" Email: {email}")
|
||||
print(f" Password: {new_password}")
|
||||
print(f" is_active: True")
|
||||
|
||||
# Verify the update
|
||||
result = await session.execute(stmt)
|
||||
updated_user = result.scalar_one_or_none()
|
||||
if updated_user:
|
||||
print(f"✅ Verification: User is_active={updated_user.is_active}")
|
||||
if updated_user.hashed_password == hashed_password:
|
||||
print(f"✅ Password hash matches!")
|
||||
else:
|
||||
print(f"⚠️ Password hash mismatch (should not happen)")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def main():
|
||||
try:
|
||||
success = await reset_admin_password()
|
||||
if success:
|
||||
print("\n🎉 Password reset completed successfully!")
|
||||
print("You can now log in with superadmin@profibot.hu / Admin123!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("\n❌ Password reset failed!")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"💥 Error during password reset: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
355
backend/app/scripts/seed_integration_data.py
Normal file
355
backend/app/scripts/seed_integration_data.py
Normal file
@@ -0,0 +1,355 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Service Finder Integration Data Seeding Script
|
||||
Populates PostgreSQL DB with real test data for frontend integration.
|
||||
|
||||
Inserts:
|
||||
1. User: tester_pro@profibot.hu (Password: Tester123!, Role: admin)
|
||||
2. Organization: "Profibot Test Fleet" in fleet.organizations
|
||||
3. Vehicles: 4 real vehicles (BMW, Audi, Mercedes, Tesla) in vehicle.assets
|
||||
4. Logs: Initial logs in audit.process_logs
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Tuple
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import select, delete, text
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.models.identity.identity import User, Person, UserRole, Wallet
|
||||
from app.models.marketplace.organization import Organization
|
||||
from app.models.vehicle.asset import Asset
|
||||
from app.models.audit import ProcessLog
|
||||
from app.core.security import get_password_hash
|
||||
|
||||
# Environment safety check
|
||||
ENVIRONMENT = "development"
|
||||
|
||||
|
||||
async def cleanup_existing_integration_data(db):
|
||||
"""Clean up previously seeded integration data (only in non-production environments)."""
|
||||
if ENVIRONMENT == "production":
|
||||
print("⚠️ Production environment detected - skipping cleanup.")
|
||||
return
|
||||
|
||||
print("🧹 Cleaning up previously seeded integration data...")
|
||||
|
||||
# We need to delete in the correct order due to foreign key constraints:
|
||||
# There's a circular reference between User and Person:
|
||||
# - User has person_id (foreign key to Person)
|
||||
# - Person has user_id (foreign key to User, but optional)
|
||||
# So we need to break the circular reference by setting person.user_id = NULL first
|
||||
|
||||
# 1. Delete integration test vehicles (by VIN pattern)
|
||||
result = await db.execute(
|
||||
delete(Asset).where(Asset.vin.like("INTEG%"))
|
||||
)
|
||||
print(f" Deleted {result.rowcount} integration test vehicles")
|
||||
|
||||
# 2. Delete integration test organization
|
||||
result = await db.execute(
|
||||
delete(Organization).where(Organization.name == "Profibot Test Fleet")
|
||||
)
|
||||
print(f" Deleted {result.rowcount} integration test organization")
|
||||
|
||||
# 3. Find integration test users and break circular references
|
||||
user_stmt = select(User).where(
|
||||
(User.email == "tester_pro@profibot.hu") |
|
||||
(User.email == "superadmin@profibot.hu")
|
||||
)
|
||||
user_result = await db.execute(user_stmt)
|
||||
integration_users = user_result.scalars().all()
|
||||
|
||||
for user in integration_users:
|
||||
# Find the person associated with this user
|
||||
person_stmt = select(Person).where(Person.user_id == user.id)
|
||||
person_result = await db.execute(person_stmt)
|
||||
person = person_result.scalar_one_or_none()
|
||||
if person:
|
||||
# Break the circular reference: set person.user_id = NULL
|
||||
person.user_id = None
|
||||
person.active_user_account = None
|
||||
await db.flush()
|
||||
print(f" Broke circular reference for person {person.id}")
|
||||
|
||||
# 4. Delete wallets for integration test users
|
||||
for user in integration_users:
|
||||
wallet_stmt = select(Wallet).where(Wallet.user_id == user.id)
|
||||
wallet_result = await db.execute(wallet_stmt)
|
||||
wallet = wallet_result.scalar_one_or_none()
|
||||
if wallet:
|
||||
await db.execute(delete(Wallet).where(Wallet.id == wallet.id))
|
||||
print(f" Deleted wallet for user {user.email}")
|
||||
|
||||
# 5. Now delete the users
|
||||
result = await db.execute(
|
||||
delete(User).where(
|
||||
(User.email == "tester_pro@profibot.hu") |
|
||||
(User.email == "superadmin@profibot.hu")
|
||||
)
|
||||
)
|
||||
print(f" Deleted {result.rowcount} integration test users")
|
||||
|
||||
# 6. Delete the persons (now that user references are broken)
|
||||
# Find persons that were associated with the deleted users
|
||||
# We need to join with users to find persons based on user email
|
||||
person_stmt = select(Person).join(User, Person.user_id == User.id).where(
|
||||
(User.email == "tester_pro@profibot.hu") |
|
||||
(User.email == "superadmin@profibot.hu")
|
||||
)
|
||||
person_result = await db.execute(person_stmt)
|
||||
integration_persons = person_result.scalars().all()
|
||||
|
||||
for person in integration_persons:
|
||||
# Double-check that no user references this person
|
||||
user_check_stmt = select(User).where(User.person_id == person.id)
|
||||
user_check_result = await db.execute(user_check_stmt)
|
||||
remaining_users = user_check_result.scalars().all()
|
||||
|
||||
if remaining_users:
|
||||
print(f"⚠️ Person {person.id} still referenced by users: {[u.email for u in remaining_users]}")
|
||||
# Try to break the reference by setting user.person_id = NULL
|
||||
for user in remaining_users:
|
||||
user.person_id = None
|
||||
await db.flush()
|
||||
|
||||
await db.execute(delete(Person).where(Person.id == person.id))
|
||||
print(f" Deleted person {person.first_name} {person.last_name}")
|
||||
|
||||
# 7. Delete integration test logs
|
||||
result = await db.execute(
|
||||
delete(ProcessLog).where(ProcessLog.process_name == "integration_seeding")
|
||||
)
|
||||
print(f" Deleted {result.rowcount} integration test logs")
|
||||
|
||||
|
||||
async def seed_integration_data():
|
||||
"""Main seeding function for integration test data."""
|
||||
print("🚀 Starting integration data seeding...")
|
||||
|
||||
async with AsyncSessionLocal() as db:
|
||||
try:
|
||||
# Clean up old integration data first
|
||||
await cleanup_existing_integration_data(db)
|
||||
|
||||
# 1. Create Person for the tester
|
||||
print("👤 Creating Person for tester...")
|
||||
person = Person(
|
||||
first_name="Test",
|
||||
last_name="User",
|
||||
phone="+36123456789",
|
||||
is_active=True,
|
||||
lifetime_xp=1000,
|
||||
penalty_points=0,
|
||||
social_reputation=4.5
|
||||
)
|
||||
db.add(person)
|
||||
await db.flush() # Get the person ID
|
||||
|
||||
# 2. Create User with admin role (tester)
|
||||
print("👤 Creating User tester_pro@profibot.hu...")
|
||||
user = User(
|
||||
email="tester_pro@profibot.hu",
|
||||
hashed_password=get_password_hash("Tester123!"),
|
||||
role=UserRole.admin,
|
||||
person_id=person.id,
|
||||
is_active=True,
|
||||
subscription_plan="PREMIUM",
|
||||
subscription_expires_at=datetime.now() + timedelta(days=365),
|
||||
is_vip=True,
|
||||
preferred_language="hu",
|
||||
region_code="HU",
|
||||
preferred_currency="HUF",
|
||||
scope_level="organization",
|
||||
custom_permissions={},
|
||||
created_at=datetime.now()
|
||||
)
|
||||
db.add(user)
|
||||
await db.flush() # Get the user ID
|
||||
|
||||
# Update person with active user reference
|
||||
person.user_id = user.id
|
||||
person.active_user_account = user
|
||||
|
||||
# 2b. Create superadmin user (separate person)
|
||||
print("👑 Creating superadmin user superadmin@profibot.hu...")
|
||||
superadmin_person = Person(
|
||||
first_name="Super",
|
||||
last_name="Admin",
|
||||
phone="+36123456788",
|
||||
is_active=True,
|
||||
lifetime_xp=5000,
|
||||
penalty_points=0,
|
||||
social_reputation=5.0
|
||||
)
|
||||
db.add(superadmin_person)
|
||||
await db.flush()
|
||||
|
||||
superadmin_user = User(
|
||||
email="superadmin@profibot.hu",
|
||||
hashed_password=get_password_hash("Superadmin123!"),
|
||||
role=UserRole.superadmin,
|
||||
person_id=superadmin_person.id,
|
||||
is_active=True,
|
||||
subscription_plan="ENTERPRISE",
|
||||
subscription_expires_at=datetime.now() + timedelta(days=365),
|
||||
is_vip=True,
|
||||
preferred_language="hu",
|
||||
region_code="HU",
|
||||
preferred_currency="HUF",
|
||||
scope_level="system",
|
||||
custom_permissions={},
|
||||
created_at=datetime.now()
|
||||
)
|
||||
db.add(superadmin_user)
|
||||
await db.flush()
|
||||
|
||||
superadmin_person.user_id = superadmin_user.id
|
||||
superadmin_person.active_user_account = superadmin_user
|
||||
|
||||
# 3. Create Organization
|
||||
print("🏢 Creating Organization 'Profibot Test Fleet'...")
|
||||
organization = Organization(
|
||||
name="Profibot Test Fleet",
|
||||
full_name="Profibot Test Fleet Kft.",
|
||||
owner_id=user.id,
|
||||
legal_owner_id=person.id,
|
||||
default_currency="HUF",
|
||||
country_code="HU",
|
||||
language="hu",
|
||||
folder_slug="profibot",
|
||||
first_registered_at=datetime.now(),
|
||||
current_lifecycle_started_at=datetime.now(),
|
||||
subscription_plan="PREMIUM",
|
||||
base_asset_limit=10,
|
||||
purchased_extra_slots=0,
|
||||
notification_settings={"notify_owner": True, "alert_days_before": [30, 15, 7, 1]},
|
||||
external_integration_config={},
|
||||
org_type="fleet_owner",
|
||||
status="active",
|
||||
is_active=True,
|
||||
is_verified=True,
|
||||
created_at=datetime.now(),
|
||||
is_ownership_transferable=True
|
||||
)
|
||||
db.add(organization)
|
||||
await db.flush()
|
||||
|
||||
# 4. Create 4 real vehicles
|
||||
print("🚗 Creating 4 real vehicles...")
|
||||
|
||||
vehicles_data = [
|
||||
{
|
||||
"vin": "INTEGBMW123456", # 13 chars
|
||||
"license_plate": "ABC-123",
|
||||
"name": "BMW X5",
|
||||
"year_of_manufacture": 2022,
|
||||
"owner_person_id": person.id,
|
||||
"owner_org_id": organization.id,
|
||||
"current_organization_id": organization.id,
|
||||
"status": "active",
|
||||
"current_mileage": 45000,
|
||||
"currency": "EUR",
|
||||
"individual_equipment": {},
|
||||
"created_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"vin": "INTEGAUDI789012", # 14 chars
|
||||
"license_plate": "DEF-456",
|
||||
"name": "Audi A6",
|
||||
"year_of_manufacture": 2021,
|
||||
"owner_person_id": person.id,
|
||||
"owner_org_id": organization.id,
|
||||
"current_organization_id": organization.id,
|
||||
"status": "active",
|
||||
"current_mileage": 32000,
|
||||
"currency": "EUR",
|
||||
"individual_equipment": {},
|
||||
"created_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"vin": "INTEGMB345678", # 12 chars
|
||||
"license_plate": "GHI-789",
|
||||
"name": "Mercedes E-Class",
|
||||
"year_of_manufacture": 2023,
|
||||
"owner_person_id": person.id,
|
||||
"owner_org_id": organization.id,
|
||||
"current_organization_id": organization.id,
|
||||
"status": "active",
|
||||
"current_mileage": 15000,
|
||||
"currency": "EUR",
|
||||
"individual_equipment": {},
|
||||
"created_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"vin": "INTEGTESLA90123", # 15 chars
|
||||
"license_plate": "JKL-012",
|
||||
"name": "Tesla Model 3",
|
||||
"year_of_manufacture": 2023,
|
||||
"owner_person_id": person.id,
|
||||
"owner_org_id": organization.id,
|
||||
"current_organization_id": organization.id,
|
||||
"status": "active",
|
||||
"current_mileage": 25000,
|
||||
"currency": "EUR",
|
||||
"individual_equipment": {},
|
||||
"created_at": datetime.now()
|
||||
}
|
||||
]
|
||||
|
||||
for i, vehicle_data in enumerate(vehicles_data, 1):
|
||||
vehicle = Asset(**vehicle_data)
|
||||
db.add(vehicle)
|
||||
print(f" Created vehicle {i}: {vehicle_data['name']}")
|
||||
|
||||
# 5. Create initial process logs
|
||||
print("📝 Creating initial process logs...")
|
||||
|
||||
# Create a single process log for the entire seeding process
|
||||
log = ProcessLog(
|
||||
process_name="integration_seeding",
|
||||
start_time=datetime.now(),
|
||||
end_time=datetime.now(),
|
||||
items_processed=7, # 1 user + 1 org + 4 vehicles + 1 log
|
||||
items_failed=0,
|
||||
details={
|
||||
"user_email": "tester_pro@profibot.hu",
|
||||
"organization": "Profibot Test Fleet",
|
||||
"vehicle_count": 4,
|
||||
"makes": ["BMW", "Audi", "Mercedes-Benz", "Tesla"]
|
||||
}
|
||||
)
|
||||
db.add(log)
|
||||
|
||||
# Commit all changes
|
||||
await db.commit()
|
||||
print("✅ Integration data seeding completed successfully!")
|
||||
|
||||
# Print summary
|
||||
print("\n📊 Seeding Summary:")
|
||||
print(f" • User: tester_pro@profibot.hu (Password: Tester123!)")
|
||||
print(f" • Organization: Profibot Test Fleet")
|
||||
print(f" • Vehicles: 4 real vehicles (BMW X5, Audi A6, Mercedes E-Class, Tesla Model 3)")
|
||||
print(f" • Logs: 3 process logs created")
|
||||
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
print(f"❌ Error during integration data seeding: {e}")
|
||||
raise
|
||||
|
||||
|
||||
async def main():
|
||||
"""Entry point for the seeding script."""
|
||||
try:
|
||||
await seed_integration_data()
|
||||
except Exception as e:
|
||||
print(f"💥 Fatal error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user