Files
gongxue-base/scripts/bootstrap-platform-admin-test.js
2026-07-12 19:26:57 +08:00

244 lines
9.1 KiB
JavaScript

import assert from 'node:assert/strict';
import {
APPLY_CONFIRMATION,
BOOTSTRAP_LOCK_KEY,
bootstrapPlatformAdmin,
buildConfig,
helpText,
publicResult,
sanitizeErrorMessage,
} from './bootstrap-platform-admin.js';
const AUTH_USER_ID = '11111111-1111-4111-8111-111111111111';
const PLATFORM_USER_ID = '22222222-2222-4222-8222-222222222222';
const LEGACY_USER_ID = '33333333-3333-4333-8333-333333333333';
function result(rows = []) {
return { rows, rowCount: rows.length };
}
function mockPool(responses) {
const queries = [];
const client = {
async query(sql, params = []) {
const normalized = String(sql).replace(/\s+/g, ' ').trim();
queries.push({ sql: normalized, params });
if (normalized === 'begin' || normalized === 'commit' || normalized === 'rollback') return result();
const response = responses.shift();
if (response instanceof Error) throw response;
if (!response) throw new Error(`Unexpected query: ${normalized}`);
return response;
},
release() {},
};
return {
queries,
pool: { async connect() { return client; } },
assertExhausted() { assert.equal(responses.length, 0, 'all expected database queries should run'); },
};
}
function config(overrides = {}) {
return {
databaseUrl: 'test-database-url',
authUserId: AUTH_USER_ID,
apply: false,
confirmation: APPLY_CONFIRMATION,
username: 'owner.admin',
email: 'owner@example.test',
phone: '13800001234',
name: 'Owner Admin',
...overrides,
};
}
const parsed = buildConfig({
DATABASE_URL: 'test-database-url',
BOOTSTRAP_PLATFORM_ADMIN_AUTH_USER_ID: AUTH_USER_ID,
BOOTSTRAP_PLATFORM_ADMIN_USERNAME: 'owner.admin',
BOOTSTRAP_PLATFORM_ADMIN_NAME: 'Owner Admin',
}, []);
assert.equal(parsed.apply, false, 'bootstrap should default to dry-run');
assert.throws(
() => buildConfig({
DATABASE_URL: 'test-database-url',
BOOTSTRAP_PLATFORM_ADMIN_AUTH_USER_ID: AUTH_USER_ID,
}, ['--apply']),
new RegExp(APPLY_CONFIRMATION),
'apply must require the exact confirmation phrase',
);
assert.equal(
buildConfig({
DATABASE_URL: 'test-database-url',
BOOTSTRAP_PLATFORM_ADMIN_AUTH_USER_ID: AUTH_USER_ID,
}, ['--apply', '--confirm', APPLY_CONFIRMATION]).apply,
true,
);
await assert.rejects(
() => bootstrapPlatformAdmin(config({ apply: true, confirmation: '' }), { pool: mockPool([]).pool }),
new RegExp(APPLY_CONFIRMATION),
'direct callers must not bypass the apply confirmation gate',
);
assert.match(helpText(), /active, Auth-bound platform admin exists/);
assert.match(helpText(), /exactly one unbound legacy platform_admin/);
const sensitiveDatabaseUrl = ['postgresql:', '', 'bootstrap_user:bootstrap_password@db.internal:5432/tiku'].join('/');
const safeError = sanitizeErrorMessage(
new Error(`connection failed for ${sensitiveDatabaseUrl}`),
sensitiveDatabaseUrl,
);
assert.equal(safeError.includes(sensitiveDatabaseUrl), false, 'failure output must redact the configured database URL');
assert.equal(safeError.includes('bootstrap_password'), false, 'failure output must not expose database credentials');
{
const mock = mockPool([
result(),
result([{ exists: true }]),
result(),
result(),
result([{ id: LEGACY_USER_ID, username: 'legacy.admin', email: null, phone: null, name: 'Legacy Admin' }]),
]);
const dryRun = await bootstrapPlatformAdmin(config(), { pool: mock.pool });
mock.assertExhausted();
assert.equal(dryRun.dryRun, true);
assert.equal(dryRun.action, 'bind_legacy');
assert.equal(dryRun.platformUserId, LEGACY_USER_ID);
assert.equal(mock.queries[0].sql, 'begin');
assert.match(mock.queries[1].sql, /pg_advisory_xact_lock/);
assert.deepEqual(mock.queries[1].params, [BOOTSTRAP_LOCK_KEY]);
assert.equal(mock.queries.at(-1).sql, 'commit', 'dry-run should retain its transaction lock through normal commit');
assert.equal(mock.queries.some(query => query.sql === 'rollback'), false, 'successful dry-run should not break the transaction abstraction');
assert.equal(
mock.queries.some(query => /^(insert|update|delete)\b/i.test(query.sql)),
false,
'dry-run must execute no write statement',
);
assert.match(mock.queries[2].sql, /app\.auth_user_exists/);
assert.doesNotMatch(mock.queries[2].sql, /auth\.users/);
}
{
const saved = {
id: PLATFORM_USER_ID,
authUserId: AUTH_USER_ID,
username: 'owner.admin',
email: 'owner@example.test',
phone: '13800001234',
};
const mock = mockPool([
result(),
result([{ exists: true }]),
result(),
result(),
result(),
result([saved]),
result(),
]);
const applied = await bootstrapPlatformAdmin(config({ apply: true }), { pool: mock.pool });
mock.assertExhausted();
assert.equal(applied.action, 'create');
assert.equal(applied.auditAction, 'platform.admin.bootstrapped');
assert.equal(mock.queries.at(-1).sql, 'commit');
const userWrite = mock.queries.find(query => query.sql.includes('insert into public.platform_users'));
assert.ok(userWrite, 'apply should create the platform user inside the transaction');
assert.match(userWrite.sql, /platform_permissions/);
assert.match(userWrite.sql, /'\{"\*":true\}'::jsonb/);
const auditWrite = mock.queries.find(query => query.sql.includes('insert into public.audit_logs'));
assert.ok(auditWrite, 'apply should write an audit event in the same transaction');
assert.deepEqual(auditWrite.params, [PLATFORM_USER_ID, 'platform.admin.bootstrapped', 'create']);
assert.match(auditWrite.sql, /values \( null, null, \$2, 'platform_user', \$1::text/);
assert.match(auditWrite.sql, /'invokedBy', 'system_cli'/);
const auditPayload = JSON.stringify(auditWrite);
assert.equal(auditPayload.includes('owner@example.test'), false, 'audit must not contain email');
assert.equal(auditPayload.includes('13800001234'), false, 'audit must not contain phone');
assert.equal(auditPayload.includes(AUTH_USER_ID), false, 'audit must not contain the Supabase Auth user ID');
const output = JSON.stringify(publicResult(applied));
assert.equal(output.includes(AUTH_USER_ID), false, 'CLI output must mask Auth user ID');
assert.equal(output.includes(PLATFORM_USER_ID), false, 'CLI output must mask platform user ID');
assert.equal(output.includes('owner@example.test'), false, 'CLI output must mask email');
assert.equal(output.includes('13800001234'), false, 'CLI output must mask phone');
assert.equal(output.includes('owner.admin'), false, 'CLI output must mask username');
const emailUsernameOutput = JSON.stringify(publicResult({ ...applied, username: 'owner@example.test' }));
assert.equal(emailUsernameOutput.includes('owner@example.test'), false, 'email-shaped username must be masked');
const phoneUsernameOutput = JSON.stringify(publicResult({ ...applied, username: '13800001234' }));
assert.equal(phoneUsernameOutput.includes('13800001234'), false, 'phone-shaped username must be masked');
}
{
const mock = mockPool([
result(),
result([{ exists: true }]),
result([{ id: PLATFORM_USER_ID }]),
]);
await assert.rejects(
() => bootstrapPlatformAdmin(config({ apply: true }), { pool: mock.pool }),
/active, Auth-bound platform admin already exists/,
);
mock.assertExhausted();
assert.equal(mock.queries.at(-1).sql, 'rollback');
assert.equal(mock.queries.some(query => query.sql.startsWith('insert into')), false);
}
{
const mock = mockPool([
result(),
result([{ exists: true }]),
result(),
result(),
result([
{ id: LEGACY_USER_ID, username: 'legacy.one' },
{ id: PLATFORM_USER_ID, username: 'legacy.two' },
]),
]);
await assert.rejects(
() => bootstrapPlatformAdmin(config({ apply: true }), { pool: mock.pool }),
/Multiple unbound legacy platform admins/,
);
mock.assertExhausted();
assert.equal(mock.queries.at(-1).sql, 'rollback');
}
{
const mock = mockPool([
result(),
result([{ exists: true }]),
result(),
result(),
result([{ id: LEGACY_USER_ID, username: 'legacy.admin', email: null, phone: null, name: 'Legacy Admin' }]),
result([{
id: LEGACY_USER_ID,
authUserId: AUTH_USER_ID,
username: 'legacy.admin',
email: null,
phone: null,
}]),
result(),
]);
const applied = await bootstrapPlatformAdmin(config({ apply: true }), { pool: mock.pool });
mock.assertExhausted();
assert.equal(applied.action, 'bind_legacy');
const userWrite = mock.queries.find(query => query.sql.includes('insert into public.platform_users'));
assert.equal(userWrite.params[0], LEGACY_USER_ID, 'unique legacy row should be bound instead of creating a duplicate');
const auditWrite = mock.queries.find(query => query.sql.includes('insert into public.audit_logs'));
assert.deepEqual(auditWrite.params, [LEGACY_USER_ID, 'platform.admin.bootstrapped', 'bind_legacy']);
}
{
const mock = mockPool([
result(),
result([{ exists: false }]),
]);
await assert.rejects(
() => bootstrapPlatformAdmin(config({ apply: true }), { pool: mock.pool }),
/Supabase Auth user not found/,
);
mock.assertExhausted();
assert.equal(mock.queries.at(-1).sql, 'rollback');
assert.equal(mock.queries.some(query => /^(insert|update|delete)\b/i.test(query.sql)), false);
}
console.log('[PASS] first platform admin bootstrap safety contract');