Files
Jyotisha/frontend/tests/database-report-worker-subject.test.ts
T
jesse-uxandGrok (agent loop) fca62fda43 给别人出报告能读到档案,对话和报告标明 AI 生成
BUG-1063:后台按列只读档案,授权前数据库拒绝读表,授权后通过。对话输入框下和报告标题下加上 AI 生成说明。状态板按已部署提交改措辞,不标 resolved。下载文件元数据没有做。

自测:tsc 退出码 0;lint 0 error;定向测试 51 通过;test:db 82 项里 13 项为 Windows 已知失败,无新增;隐私标记退出码 0。

Co-Authored-By: Grok (agent loop)
2026-10-14 09:30:51 +08:00

84 lines
3.5 KiB
TypeScript

import assert from "node:assert/strict";
import { randomUUID } from "node:crypto";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import test from "node:test";
import { closeLocalPostgresDataPool, createLocalPostgresDataClient } from "../src/lib/db/local-postgres-client-core.ts";
import { loadReportWorkerProfile } from "../src/lib/personal-report-worker-subject.ts";
import { CHART_SUBJECT_SELECT } from "../src/lib/subject-birth.ts";
import { startPostgresFixture, type PostgresFixture } from "./helpers/postgres-fixture.ts";
// BUG-1063: the report worker reads another person's archive through
// service_role. Fictional rows only.
const runner = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url));
const docker = spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], { stdio: "ignore" }).status === 0;
const SERVICE_URL_ROLE = ["service_runtime", "service-runtime-test-password"] as const;
function applyMigrations(fixture: PostgresFixture): void {
const result = spawnSync(process.execPath, [runner], {
encoding: "utf8",
env: {
...process.env,
SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password"),
},
});
assert.equal(result.status, 0, result.stderr || result.stdout);
}
test("service_role can read another person's chart profile for a report", {
skip: docker ? false : "docker unavailable",
}, async () => {
const fixture = startPostgresFixture();
const serviceUrl = fixture.connectionUrl(...SERVICE_URL_ROLE);
try {
applyMigrations(fixture);
const owner = randomUUID();
const subjectId = randomUUID();
fixture.psql(`insert into identity.users (id, name, email, email_verified, email_verified_at)
values ('${owner}', 'Fictional owner', '${owner}@example.invalid', true, now());`);
fixture.psql(`insert into public.chart_profiles (
id, user_id, role, profile, updated_at, name, birth_date, reported_birth_time,
birth_time_source, latitude, longitude, timezone_id, timezone_offset,
birth_place_label, ayanamsa, birth_time_status
) values (
'${subjectId}', '${owner}', 'other', '{"name":"虚构乙"}'::jsonb, now(),
'虚构乙', '1990-01-01', '08:00', 'family_exact', 22.3, 114.1,
'Asia/Shanghai', 8, '虚构港', 'lahiri', 'reported'
);`);
const admin = createLocalPostgresDataClient(serviceUrl, null, "service_role");
const probe = await admin
.from("chart_profiles")
.select(CHART_SUBJECT_SELECT)
.eq("id", subjectId)
.maybeSingle();
assert.equal(probe.error, null, probe.error?.message ?? "chart_profiles select failed");
const loaded = await loadReportWorkerProfile(admin, owner, subjectId) as { name?: string };
assert.equal(loaded.name, "虚构乙");
for (const column of CHART_SUBJECT_SELECT.split(",")) {
assert.equal(
fixture.psql(`select has_column_privilege('service_role', 'public.chart_profiles', '${column}', 'select')`),
"t",
column,
);
}
for (const privilege of ["insert", "update", "delete"]) {
assert.equal(
fixture.psql(`select has_table_privilege('service_role', 'public.chart_profiles', '${privilege}')`),
"f",
privilege,
);
}
assert.equal(
fixture.psql("select has_table_privilege('authenticated', 'public.chart_profiles', 'select')"),
"t",
);
} finally {
await closeLocalPostgresDataPool(serviceUrl);
fixture.stop();
}
});