Files
Velocity-OS/core/db/seed_test_users.py

142 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
seed_test_users.py — Velocity-OS Test Credential Seeder
========================================================
FOR TESTING ONLY. Never include in production build.
Inserts 7 test broker accounts into users_and_roles.
All passwords follow the pattern: Name@Velocity26
All emails follow: name@desineuron.in
Run against the local or remote Velocity-OS PostgreSQL:
python seed_test_users.py # uses env vars
python seed_test_users.py --dsn "postgresql://..." # explicit DSN
"""
import argparse
import hashlib
import os
import sys
# ── Generate bcrypt hashes OFFLINE (no DB dep) ────────────────────────────
# Uses passlib with same config as backend/auth/dependencies.py
try:
from passlib.context import CryptContext
pwd_ctx = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(plain: str) -> str:
raw = plain.encode("utf-8")
if len(raw) > 72:
plain = raw[:72].decode("utf-8", errors="ignore")
return pwd_ctx.hash(plain)
except ImportError:
print("[ERROR] passlib not installed. Run: pip install passlib[bcrypt]")
sys.exit(1)
# ── Test user definitions ─────────────────────────────────────────────────
# Format: (full_name, email, plain_password, role)
TEST_USERS = [
("Sagnik Ghosh", "sagnik@desineuron.in", "Sagnik@Velocity26", "ADMIN"),
("Sayan Ghosh", "sayan@desineuron.in", "Sayan@Velocity26", "SALES_DIRECTOR"),
("Sourik Ghosh", "sourik@desineuron.in", "Sourik@Velocity26", "SENIOR_BROKER"),
("Abantika Das", "abantika@desineuron.in", "Abantika@Velocity26", "SENIOR_BROKER"),
("Sinjini Roy", "sinjini@desineuron.in", "Sinjini@Velocity26", "JUNIOR_BROKER"),
("Swastika Ghosh", "swastika@desineuron.in", "Swastika@Velocity26", "JUNIOR_BROKER"),
("Debargha Mukherjee","debargha@desineuron.in", "Debargha@Velocity26", "JUNIOR_BROKER"),
]
TENANT_ID = "tenant_velocity"
def build_sql() -> str:
"""Generate idempotent INSERT SQL (ON CONFLICT DO NOTHING)."""
lines = [
"-- ================================================================",
"-- Velocity-OS Test Users Seed (FOR TESTING ONLY — NOT FOR PROD)",
"-- ================================================================",
"-- Generated by seed_test_users.py",
"",
"BEGIN;",
"",
]
for full_name, email, plain, role in TEST_USERS:
pw_hash = hash_password(plain)
lines.append(f"-- {full_name} ({role})")
lines.append("INSERT INTO users_and_roles")
lines.append(" (email, password_hash, role, tenant_id, full_name, is_active)")
lines.append("VALUES")
lines.append(f" ('{email}', '{pw_hash}', '{role}', '{TENANT_ID}', '{full_name}', TRUE)")
lines.append("ON CONFLICT (email) DO UPDATE")
lines.append(" SET password_hash = EXCLUDED.password_hash,")
lines.append(" role = EXCLUDED.role,")
lines.append(" full_name = EXCLUDED.full_name,")
lines.append(" is_active = TRUE;")
lines.append("")
lines.append("COMMIT;")
lines.append("")
lines.append("-- Verify:")
lines.append("SELECT email, role, full_name FROM users_and_roles ORDER BY role DESC, email;")
return "\n".join(lines)
def run_against_db(dsn: str, sql: str) -> None:
try:
import asyncpg
import asyncio
async def _insert():
conn = await asyncpg.connect(dsn)
try:
await conn.execute(sql)
print("[OK] Test users inserted successfully.")
finally:
await conn.close()
asyncio.run(_insert())
except ImportError:
print("[WARN] asyncpg not installed — writing SQL file only.")
write_sql_file(sql)
def write_sql_file(sql: str) -> None:
out = os.path.join(os.path.dirname(__file__), "seed_test_users.sql")
with open(out, "w", encoding="utf-8") as f:
f.write(sql)
print(f"[OK] SQL written to: {out}")
print(" Apply with: psql -U velocity_user -d velocity_db -f seed_test_users.sql")
def main():
parser = argparse.ArgumentParser(description="Seed Velocity-OS test users")
parser.add_argument("--dsn", help="PostgreSQL DSN (overrides env VELOCITY_DB_DSN)")
parser.add_argument("--sql-only", action="store_true", help="Only write SQL file, don't connect")
args = parser.parse_args()
sql = build_sql()
print("Generating bcrypt hashes for test users...")
print("Users to seed:")
for full_name, email, plain, role in TEST_USERS:
print(f" [{role:16}] {email:30} / {plain}")
print()
if args.sql_only:
write_sql_file(sql)
return
dsn = args.dsn or os.getenv("VELOCITY_DB_DSN") or os.getenv("DATABASE_URL")
if dsn:
run_against_db(dsn, sql)
else:
print("[INFO] No DSN provided — writing SQL file for manual application.")
write_sql_file(sql)
if __name__ == "__main__":
main()