GRO-1636: seed.ts creates Better Auth credential accounts for UAT personas
CI / Lint & Typecheck (pull_request) Successful in 22s
CI / Test (pull_request) Successful in 24s
CI / Build (pull_request) Successful in 22s
CI / Build & Push Docker Images (pull_request) Has been skipped
CI / Update Infra Image Tags (pull_request) Has been skipped
CI / E2E Tests (pull_request) Failing after 40s
CI / Deploy PR to groombook-dev (pull_request) Has been cancelled
CI / Web E2E (Dev) (pull_request) Has been cancelled
CI / Lint & Typecheck (pull_request) Successful in 22s
CI / Test (pull_request) Successful in 24s
CI / Build (pull_request) Successful in 22s
CI / Build & Push Docker Images (pull_request) Has been skipped
CI / Update Infra Image Tags (pull_request) Has been skipped
CI / E2E Tests (pull_request) Failing after 40s
CI / Deploy PR to groombook-dev (pull_request) Has been cancelled
CI / Web E2E (Dev) (pull_request) Has been cancelled
After creating staff table records for UAT personas, seedKnownUsers() now reads SEED_UAT_*_PASSWORD env vars and creates Better Auth user + account rows so personas can email+password login. Uses the same scrypt hash format (N=16384, r=8, p=1, dkLen=64) as better-auth. For uat-super and uat-groomer, the staff record is linked to the Better Auth user via userId field. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -20,6 +20,7 @@ import postgres from "postgres";
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import * as schema from "./schema.js";
|
||||
import { randomBytes, scrypt } from "node:crypto";
|
||||
|
||||
// ── Seed profile configuration ─────────────────────────────────────────────
|
||||
|
||||
@@ -509,6 +510,81 @@ async function seedKnownUsers() {
|
||||
}
|
||||
console.log(`✓ Seeded ${demoSvcs.length} services`);
|
||||
|
||||
// ── Better Auth credential accounts for UAT personas ─────────────────────
|
||||
// Creates user + account rows so UAT personas can email+password login.
|
||||
// Uses the same scrypt config as better-auth (N=16384, r=8, p=1, dkLen=64).
|
||||
const uatCredAccounts: Array<{ email: string; passwordEnvKey: string; staffId: string }> = [
|
||||
{ email: "uat-super@groombook.dev", passwordEnvKey: "SEED_UAT_SUPER_PASSWORD", staffId: "00000000-0000-0000-0000-000000000003" },
|
||||
{ email: "uat-groomer@groombook.dev", passwordEnvKey: "SEED_UAT_GROOMER_PASSWORD", staffId: "00000000-0000-0000-0000-000000000004" },
|
||||
{ email: "uat-customer@groombook.dev", passwordEnvKey: "SEED_UAT_CUSTOMER_PASSWORD", staffId: "" },
|
||||
{ email: "uat-tester@groombook.dev", passwordEnvKey: "SEED_UAT_TESTER_PASSWORD", staffId: "" },
|
||||
];
|
||||
|
||||
for (const acct of uatCredAccounts) {
|
||||
const password = process.env[acct.passwordEnvKey];
|
||||
if (!password) {
|
||||
console.log(`⊘ No ${acct.passwordEnvKey} set — skipping Better Auth account for ${acct.email}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const [existingUser] = await db
|
||||
.select()
|
||||
.from(schema.user)
|
||||
.where(eq(schema.user.email, acct.email))
|
||||
.limit(1);
|
||||
|
||||
let userId: string;
|
||||
if (existingUser) {
|
||||
userId = existingUser.id;
|
||||
console.log(`✓ Better Auth user '${acct.email}' already exists — skipping`);
|
||||
} else {
|
||||
// Hash with same scrypt params as better-auth: N=16384, r=8, p=1, dkLen=64
|
||||
// Use Promise-based scrypt API (callback pattern, wrapped in Promise)
|
||||
const salt = randomBytes(16);
|
||||
const key = await new Promise<Buffer>((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
scrypt(password.normalize("NFKC"), salt, 16384, { r: 8, p: 1, dkLen: 64 } as any, (err: Error | null, derivedKey: Buffer) => {
|
||||
if (err) reject(err);
|
||||
else resolve(derivedKey);
|
||||
});
|
||||
});
|
||||
const passwordHash = `${salt.toString("hex")}:${key.toString("hex")}`;
|
||||
|
||||
const [newUser] = await db.insert(schema.user).values({
|
||||
id: uuid(),
|
||||
name: acct.email.split("@")[0]!,
|
||||
email: acct.email,
|
||||
emailVerified: true,
|
||||
}).returning();
|
||||
userId = newUser!.id;
|
||||
|
||||
await db.insert(schema.account).values({
|
||||
id: uuid(),
|
||||
accountId: userId,
|
||||
providerId: "credential",
|
||||
userId,
|
||||
password: passwordHash,
|
||||
});
|
||||
console.log(`✓ Created Better Auth credential account for '${acct.email}'`);
|
||||
}
|
||||
|
||||
// Link staff record to Better Auth user if staff exists and has no userId yet
|
||||
if (acct.staffId) {
|
||||
const [existingStaff] = await db
|
||||
.select()
|
||||
.from(schema.staff)
|
||||
.where(eq(schema.staff.id, acct.staffId))
|
||||
.limit(1);
|
||||
if (existingStaff && !existingStaff.userId) {
|
||||
await db.update(schema.staff)
|
||||
.set({ userId })
|
||||
.where(eq(schema.staff.id, acct.staffId));
|
||||
console.log(` ↳ Linked staff '${acct.email}' to Better Auth user`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Client: Demo Client ──
|
||||
const [existingClient] = await db
|
||||
.select()
|
||||
|
||||
Reference in New Issue
Block a user