Files
HealthLog/tests/integration/record-settings-authorization.test.ts
T
Marc-André Bombeck 6a1d1dd6e8 fix: preserve managed target defaults
- Return effective threshold ranges after managed updates\n- Localize closed Coach and Insights display inventories
2026-08-06 03:52:49 +02:00

95 lines
3.7 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import { resolveGuardianRecordSettingsAccess } from "@/lib/record-settings/access";
import {
classifySettingsDestination,
SETTINGS_DESTINATION_INVENTORY,
} from "@/lib/record-settings/classification";
import { MANAGED_RECORD_SETTINGS_FIELD_ALLOWLIST } from "@/lib/record-settings";
const fromRoot = (...segments: string[]) => resolve(process.cwd(), ...segments);
describe("record settings authorization", () => {
it("keeps actor and record separation", async () => {
const [authMeRoute, recordSettingsRoute] = await Promise.all([
readFile(fromRoot("src/app/api/auth/me/route.ts"), "utf8"),
readFile(fromRoot("src/app/api/record-settings/route.ts"), "utf8"),
]);
const access = resolveGuardianRecordSettingsAccess({
actor: { id: "guardian-1" },
grantId: "grant-1",
user: { id: "managed-record-1", managedProfileAt: new Date() },
});
expect(access).toMatchObject({
actorId: "guardian-1",
recordId: "managed-record-1",
recordKind: "managed",
relationship: "guardian",
});
expect(authMeRoute).toContain("requireAuth");
expect(authMeRoute).not.toContain("requireGuardianAuth");
expect(authMeRoute).not.toContain("requireRecordAuth");
expect(recordSettingsRoute).toContain("requireGuardianAuth");
expect(recordSettingsRoute).toContain("toRecordSettingsDto");
});
it("keeps settings classification exhaustive and fail closed", () => {
expect(Object.keys(SETTINGS_DESTINATION_INVENTORY)).not.toHaveLength(0);
expect(classifySettingsDestination("integrations")).toMatchObject({
kind: "managed-guardian",
guardianWritable: false,
});
expect(classifySettingsDestination("ai").kind).toBe("unavailable");
expect(classifySettingsDestination("unknown-settings-path").kind).toBe(
"unavailable",
);
});
it("uses one guardian-only record resolver for every writable DTO family", async () => {
const route = await readFile(
fromRoot("src/app/api/record-settings/[family]/route.ts"),
"utf8",
);
const guardian = resolveGuardianRecordSettingsAccess({
actor: { id: "guardian-1" },
grantId: "grant-1",
user: { id: "managed-record-1", managedProfileAt: new Date() },
});
const adultManager = resolveGuardianRecordSettingsAccess({
actor: { id: "adult-manager" },
grantId: "grant-1",
user: { id: "adult-record-1", managedProfileAt: null },
});
expect(guardian?.recordId).toBe("managed-record-1");
expect(adultManager).toBeNull();
expect(route).toContain("requireGuardianAuth");
expect(route).toContain("resolveGuardianRecordSettingsAccess");
for (const family of Object.keys(MANAGED_RECORD_SETTINGS_FIELD_ALLOWLIST)) {
expect(route).toContain(`case \"${family}\"`);
}
expect(route).toContain("record-settings.${family}.update");
expect(route).toContain("userId: access.recordId");
expect(route).toContain("actorUserId: access.actorId");
expect(route).toContain("details: { changed }");
expect(route).not.toContain("details: { recordId:");
expect(route).toContain("invalidateUserMedications(access.recordId, {");
expect(route).toContain("invalidateUserHealthScore(access.recordId)");
expect(route).toContain("getAllEffectiveRanges(record, overrides)");
expect(route).toContain(
"effective: getAllEffectiveRanges(record, overrides)",
);
expect(route).toContain("invalidateUserProfile(access.recordId)");
expect(
route.lastIndexOf("invalidateUserProfile(access.recordId)"),
).toBeGreaterThan(
route.indexOf("data: { thresholdsJson: toJson(overrides) }"),
);
});
});