forked from mirror/crumbs-original
fix: replace hardcoded test passwords with runtime-generated UUIDs
Generate random passwords in global-setup and share via temp file so all Playwright workers use the same credentials. Screenshot scripts use module-level crypto.randomUUID() since they run single-process. Unit test auth passwords also use randomUUID(). Eliminates security scanner alerts for passwords committed to git. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
a81d723d4f
commit
575bb7ebe8
@@ -8,11 +8,11 @@ export const MOBILE_VIEWPORT = { width: 390, height: 844 };
|
||||
export const ADMIN = {
|
||||
email: 'admin@bretzel.app',
|
||||
displayName: 'Bretzel Admin',
|
||||
password: 'bretzel2026!'
|
||||
password: crypto.randomUUID()
|
||||
};
|
||||
|
||||
export const COLLABORATOR = {
|
||||
email: 'salzig@bretzel.app',
|
||||
displayName: 'Salzig Bretzel',
|
||||
password: 'salzig2026!!'
|
||||
password: crypto.randomUUID()
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createTestDb } from './db/test-helpers.js';
|
||||
import { users, sessions } from './db/schema.js';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import * as argon2 from 'argon2';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { randomBytes, randomUUID } from 'crypto';
|
||||
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
||||
import type * as schema from './db/schema.js';
|
||||
|
||||
@@ -16,16 +16,16 @@ beforeEach(() => {
|
||||
|
||||
describe('Auth - Password Hashing', () => {
|
||||
it('should hash and verify a password correctly', async () => {
|
||||
const password = 'mysecurepassword';
|
||||
const password = randomUUID();
|
||||
const hash = await argon2.hash(password);
|
||||
|
||||
expect(hash).not.toBe(password);
|
||||
expect(await argon2.verify(hash, password)).toBe(true);
|
||||
expect(await argon2.verify(hash, 'wrongpassword')).toBe(false);
|
||||
expect(await argon2.verify(hash, randomUUID())).toBe(false);
|
||||
});
|
||||
|
||||
it('should produce different hashes for the same password', async () => {
|
||||
const password = 'mysecurepassword';
|
||||
const password = randomUUID();
|
||||
const hash1 = await argon2.hash(password);
|
||||
const hash2 = await argon2.hash(password);
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('Auth - Password Hashing', () => {
|
||||
|
||||
describe('Auth - User Setup', () => {
|
||||
it('should create a user with hashed password', async () => {
|
||||
const password = 'testpassword123';
|
||||
const password = randomUUID();
|
||||
const hash = await argon2.hash(password);
|
||||
|
||||
await db.insert(users).values({
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { test, expect, setupAndLogin } from './helpers/fixtures.js';
|
||||
import { readFileSync } from 'fs';
|
||||
import { TEST_CREDENTIALS_FILE } from './global-setup';
|
||||
|
||||
const { userPassword } = JSON.parse(readFileSync(TEST_CREDENTIALS_FILE, 'utf-8'));
|
||||
|
||||
test.describe.serial('Authentication', () => {
|
||||
test('Scenario: Unauthenticated user is prompted to set up or log in', async ({ page }) => {
|
||||
@@ -78,7 +82,7 @@ test.describe('Multi-user', () => {
|
||||
data: {
|
||||
email: 'user2@test.com',
|
||||
displayName: 'User Two',
|
||||
password: 'userpassword123',
|
||||
password: userPassword,
|
||||
role: 'user'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { existsSync, unlinkSync } from 'fs';
|
||||
import { existsSync, unlinkSync, writeFileSync } from 'fs';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
const TEST_DB = './data/test-crumbs.db';
|
||||
export const TEST_CREDENTIALS_FILE = './data/test-credentials.json';
|
||||
|
||||
export default function globalSetup() {
|
||||
// Clean test database before E2E run so each run starts fresh
|
||||
@@ -10,4 +12,14 @@ export default function globalSetup() {
|
||||
unlinkSync(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate random passwords for this test run, shared across all workers
|
||||
writeFileSync(
|
||||
TEST_CREDENTIALS_FILE,
|
||||
JSON.stringify({
|
||||
testPassword: `test-${randomUUID()}`,
|
||||
collabPassword: `collab-${randomUUID()}`,
|
||||
userPassword: `user-${randomUUID()}`
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { test as base, expect, type Page, type Locator } from '@playwright/test';
|
||||
import { readFileSync } from 'fs';
|
||||
import { collectCoverage } from './coverage';
|
||||
import { TEST_CREDENTIALS_FILE } from '../global-setup';
|
||||
|
||||
const { testPassword, collabPassword } = JSON.parse(readFileSync(TEST_CREDENTIALS_FILE, 'utf-8'));
|
||||
|
||||
const TEST_EMAIL = 'admin@test.com';
|
||||
const TEST_PASSWORD = 'testpassword123';
|
||||
const TEST_PASSWORD = testPassword;
|
||||
const TEST_DISPLAY_NAME = 'Test Admin';
|
||||
|
||||
const COLLAB_EMAIL = 'collab@test.com';
|
||||
const COLLAB_PASSWORD = 'collabpass123';
|
||||
const COLLAB_PASSWORD = collabPassword;
|
||||
const COLLAB_NAME = 'Collaborator User';
|
||||
|
||||
/** Find a specific note card by its title text */
|
||||
|
||||
Reference in New Issue
Block a user