85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
|
|
#!/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()
|