deckhearth/scripts/create-test-users.js
varutasu 5f2b234cc8
fix(scripts): require TEST_USERS_PASSWORD + purge weak literals from test-user helpers (#27)
`scripts/create-test-users.js` hardcoded `bcrypt.hash('alice123', 12)`
+ `bcrypt.hash('bob123', 12)` and echoed those literals back to stdout
both per-user and in a final summary block. `TESTING_GUIDE.md`'s Test
Accounts table documented the same `admin123` / `alice123` / `bob123`
trio. These were the last two weak-credential surfaces left in the
helper-script + manual-QA-doc tree after `drop-public-setup` (commits
`ff80753` + `b63b509`) and `fix-reset-db-script` (squash `3ab9bf8`,
PR #25) closed the `setup-neon-db.js` and `reset-db.js` halves of the
umbrella `purge-weak-creds-from-helpers` queued follow-up.

The fix mirrors the post-`drop-public-setup` `setup-neon-db.js`
pattern and the post-PR-#25 `reset-db.js` pattern verbatim, with one
deliberate simplification: a single `TEST_USERS_PASSWORD` env var
covers both alice + bob rather than per-user env vars (risk R2 in the
convoy file argues this — these are fixture users for the
collaboration demo flow, not independent identities, and per-user
sprawl would double the env-var contract for zero security benefit).
`createTestUsers()` now reads `process.env.TEST_USERS_PASSWORD` at the
top of the function body and exits with code 1 BEFORE opening any DB
connection if the var is unset or whitespace-only, with the same
helpful-error wording template the other two scripts use (names the
var, points at `.env.local`, suggests `openssl rand -base64 24`,
references README's "First-time admin setup" section). All four
password-echo `console.log` lines are deleted; the new summary
documents *where* the password comes from without ever printing it.
`TESTING_GUIDE.md`'s Test Accounts table is rewritten to show password
source per user instead of the literal value; the two inline
`Password: alice123` / `Password: bob123` workflow snippets are
replaced with placeholder text. Unlike the previous two convoys, no
CJS→ESM conversion was needed — `create-test-users.js` was already
top-level ESM.

Verification (all static — script is destructive and not live-tested):
`node --check scripts/create-test-users.js` exit 0; `npm run lint` 128
problems (baseline preserved, no regression); `npm run test:run` 21/21
pass; grep `scripts/ TESTING_GUIDE.md` for
`admin123|password123|test123|alice123|bob123` → 0 hits;
`TEST_USERS_PASSWORD` referenced 10 times total (5 script + 5 doc).
Operator caveat: anyone running `node scripts/create-test-users.js`
post-merge must add `TEST_USERS_PASSWORD=<value>` to their
`.env.local` first; existing alice + bob rows in already-seeded
environments are NOT rotated by re-running this script
(`ON CONFLICT (email) DO NOTHING` preserves the old hashes). Same
caveat that applies to the `drop-public-setup` admin row.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 22:53:24 -05:00

74 lines
2.6 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Create Test Users Script
*
* Seeds the alice + bob test-user fixtures used by the manual QA flows
* in TESTING_GUIDE.md. Both users share a single password supplied via
* the TEST_USERS_PASSWORD environment variable — this is a test-fixture
* helper, not a prod auth surface, so per-user env vars would be
* unnecessary sprawl.
*
* Required env (in .env.local):
* POSTGRES_URL — Neon connection string
* TEST_USERS_PASSWORD — strong password applied to every test user
* (generate with `openssl rand -base64 24`)
*
* Mirrors the post-`drop-public-setup` shape of `setup-neon-db.js`
* (commit b63b509) and the post-`fix-reset-db-script` shape of
* `reset-db.js` (commit 3ab9bf8) — same ESM imports, same fail-loud
* env-var check, same no-password-echo convention. Convoy:
* `purge-weak-creds-from-helpers` (2026-05-26).
*/
import { config } from 'dotenv';
import { sql } from '@vercel/postgres';
import bcrypt from 'bcryptjs';
config({ path: '.env.local' });
async function createTestUsers() {
const testUsersPassword = process.env.TEST_USERS_PASSWORD;
if (!testUsersPassword || !testUsersPassword.trim()) {
console.error(
'❌ TEST_USERS_PASSWORD environment variable is not set.\n' +
'\n' +
' Set it in .env.local before running `node scripts/create-test-users.js`.\n' +
' Generate a strong password with: openssl rand -base64 24\n' +
' See README.md → "First-time admin setup" for the env-var pattern.\n'
);
process.exit(1);
}
try {
console.log('👥 Creating test users...\n');
const hashedPassword = await bcrypt.hash(testUsersPassword, 12);
await sql`
INSERT INTO users (email, password, role)
VALUES ('alice@deckhearth.com', ${hashedPassword}, 'user')
ON CONFLICT (email) DO NOTHING
`;
console.log('✅ Created Alice (alice@deckhearth.com)');
await sql`
INSERT INTO users (email, password, role)
VALUES ('bob@deckhearth.com', ${hashedPassword}, 'user')
ON CONFLICT (email) DO NOTHING
`;
console.log('✅ Created Bob (bob@deckhearth.com)');
console.log('\n🎉 Test users created successfully!');
console.log('\n👥 Available Test Accounts (passwords from TEST_USERS_PASSWORD):');
console.log(' 1. admin@deckhearth.com (Admin — seeded by setup-neon-db.js)');
console.log(' 2. alice@deckhearth.com (User)');
console.log(' 3. bob@deckhearth.com (User)');
} catch (error) {
console.error('❌ Failed to create test users:', error.message);
process.exit(1);
}
}
createTestUsers();