video-accessibility/backend/scripts/seed_test_users.py
Vadym Samoilenko 6559ccc1f9 feat(help): in-app role-based help guides + screenshot capture pipeline
- Help.tsx: role tabs, TOC scroll-spy, search, lightbox, react-markdown renderer
- 7 markdown guides (global, client, linguist, reviewer, production, PM, admin)
  with explicit click/drag/keyboard annotations throughout
- Sidebar: Help button added at bottom of nav (all roles)
- App.tsx: /help route, no RoleGate
- frontend/public/help-screenshots/{role}/: directories ready for screenshots
- tools/capture-help-screenshots.ts: Playwright screenshot script
  - Clicks "Local login" toggle before filling credentials
  - Uses test-admin local account (not SSO)
- backend/scripts/seed_test_users.py: idempotent MongoDB seed script
  creates 6 local-auth users (admin + 5 roles) for capture + local dev
- .env.screenshots.example: template with test-admin credentials
- Removes docs/video_accessibility_user_guide_v3.md (superseded by in-app guides)
- Deps: react-markdown, remark-gfm, rehype-raw added to frontend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 13:08:13 +01:00

85 lines
2.9 KiB
Python

"""Seed test users for screenshot capture and local development.
Run from backend/ directory (with MONGODB_URI set in environment or .env):
python scripts/seed_test_users.py
Or inside a running Docker container:
docker compose exec backend python scripts/seed_test_users.py
Idempotent — skips users that already exist (case-insensitive email match).
"""
import asyncio
import os
import re
import sys
from datetime import datetime
from bson import ObjectId
from motor.motor_asyncio import AsyncIOMotorClient
from passlib.context import CryptContext
# Load .env if dotenv is available (optional convenience for local runs)
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
MONGODB_URI = os.environ.get("MONGODB_URI") or os.environ.get("MONGO_URI")
MONGODB_DB = os.environ.get("MONGODB_DB", "accessible_video")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
TEST_USERS = [
{"email": "test-admin@oliver.agency", "password": "TestAdmin2026!", "full_name": "Test Admin", "role": "admin"},
{"email": "test-client@oliver.agency", "password": "TestClient2026!", "full_name": "Test Client", "role": "client"},
{"email": "test-linguist@oliver.agency", "password": "TestLinguist2026!", "full_name": "Test Linguist", "role": "linguist"},
{"email": "test-reviewer@oliver.agency", "password": "TestReviewer2026!", "full_name": "Test Reviewer", "role": "reviewer"},
{"email": "test-production@oliver.agency", "password": "TestProduction2026!", "full_name": "Test Production", "role": "production"},
{"email": "test-pm@oliver.agency", "password": "TestPM2026!", "full_name": "Test Project Manager","role": "project_manager"},
]
async def main() -> None:
if not MONGODB_URI:
print("ERROR: MONGODB_URI env var is not set.", file=sys.stderr)
sys.exit(1)
client = AsyncIOMotorClient(MONGODB_URI)
db = client[MONGODB_DB]
created = 0
skipped = 0
for u in TEST_USERS:
pattern = re.compile(f"^{re.escape(u['email'])}$", re.IGNORECASE)
existing = await db.users.find_one({"email": pattern})
if existing:
print(f" skip {u['email']} (already exists)")
skipped += 1
continue
doc = {
"_id": str(ObjectId()),
"email": u["email"],
"hashed_password": pwd_context.hash(u["password"]),
"full_name": u["full_name"],
"role": u["role"],
"auth_provider": "local",
"is_active": True,
"created_at": datetime.utcnow(),
"updated_at": datetime.utcnow(),
}
await db.users.insert_one(doc)
print(f" created {u['email']} ({u['role']})")
created += 1
client.close()
print(f"\nDone — {created} created, {skipped} skipped.")
if __name__ == "__main__":
asyncio.run(main())