40 lines
1.4 KiB
TypeScript
40 lines
1.4 KiB
TypeScript
/** Seeds the two accounts requested for this first slice: `admin` (role
|
|
* admin, unlocks /admin) and `demo` (role user, the "logged-in doctor"
|
|
* persona). Idempotent (ON CONFLICT DO NOTHING) — safe to run on every
|
|
* deploy alongside migrate.ts.
|
|
*
|
|
* SECURITY: both passwords are "1", set explicitly for local/dev use. Do
|
|
* not run this against a deployment `/admin` is actually reachable from
|
|
* without rotating them first — see docs/operations.md and the plan this
|
|
* was built from.
|
|
*/
|
|
import * as bcrypt from "bcrypt";
|
|
import { createPool } from "./db";
|
|
import { loadSettings } from "./config";
|
|
|
|
const SEED_USERS: Array<{ username: string; password: string; role: "user" | "admin" }> = [
|
|
{ username: "admin", password: "1", role: "admin" },
|
|
{ username: "demo", password: "1", role: "user" },
|
|
];
|
|
|
|
async function main() {
|
|
const settings = loadSettings();
|
|
const pool = createPool(settings.postgresDsn);
|
|
for (const seed of SEED_USERS) {
|
|
const passwordHash = await bcrypt.hash(seed.password, 12);
|
|
await pool.query(
|
|
`INSERT INTO auth_user (username, password_hash, role)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (username) DO NOTHING`,
|
|
[seed.username, passwordHash, seed.role]
|
|
);
|
|
console.log(`Seeded ${seed.username} (${seed.role})`);
|
|
}
|
|
await pool.end();
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|