#!/usr/bin/env python """Seed demo users into the PostgreSQL users table. Run from the repo root: PYTHONPATH=backend python scripts/seed_users.py Creates four demo accounts (one per role). Safe to run multiple times — existing usernames are left unchanged (ON CONFLICT DO NOTHING). """ import os import sys # Allow running from repo root without installing the package. sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "backend")) import psycopg2 from passlib.context import CryptContext from app.config.settings import settings _PWD_CTX = CryptContext(schemes=["bcrypt"], deprecated="auto") DEMO_USERS = [ {"username": "admin", "password": "Admin@2026!", "role": "admin"}, {"username": "legal", "password": "Legal@2026!", "role": "legal"}, {"username": "ehs", "password": "EHS@2026!", "role": "ehs"}, {"username": "readonly", "password": "Read@2026!", "role": "readonly"}, ] _CREATE_TABLE_SQL = """ CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), username VARCHAR(100) UNIQUE NOT NULL, hashed_pw TEXT NOT NULL, role VARCHAR(50) NOT NULL DEFAULT 'readonly', is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); """ def seed() -> None: """Insert demo users. Skips any username that already exists.""" conn = psycopg2.connect( host=settings.postgres_host, port=settings.postgres_port, user=settings.postgres_user, password=settings.postgres_password, dbname=settings.postgres_db, ) conn.autocommit = True with conn.cursor() as cur: # Enable pgcrypto for gen_random_uuid() if not already enabled, or use uuid-ossp fallback. try: cur.execute("CREATE EXTENSION IF NOT EXISTS pgcrypto;") except Exception: conn.rollback() cur.execute(_CREATE_TABLE_SQL) inserted = 0 with conn.cursor() as cur: for user in DEMO_USERS: hashed = _PWD_CTX.hash(user["password"]) cur.execute( """ INSERT INTO users (username, hashed_pw, role) VALUES (%s, %s, %s) ON CONFLICT (username) DO NOTHING """, (user["username"], hashed, user["role"]), ) if cur.rowcount > 0: print(f" Created user: {user['username']} (role={user['role']})") inserted += 1 else: print(f" Skipped (already exists): {user['username']}") print(f"\nDone. {inserted} user(s) created.") conn.close() if __name__ == "__main__": seed()