mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
feat(meds): scope the advanced-settings export to the single medication
The advanced sheet sits on one medication and its import already loads that medication's intake history, but the co-located export streamed every medication. Pass the medication id through to the export route, which narrows both the medication row and the intake history by it (always alongside userId, so a foreign id 404s rather than leaking).
This commit is contained in:
1 parent
8363db4146
commit
24ffca7220
4 files changed
+82
-5
No files matched your search
@@ -203,6 +203,59 @@ describe("GET /api/export/medications", () => {
|
||||
expect(body).not.toContain("# Intake history");
|
||||
expect(prisma.medicationIntakeEvent.findMany).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("scopes both queries to a single medication when medicationId is set", async () => {
|
||||
vi.mocked(getSession).mockResolvedValue(SESSION_OK as never);
|
||||
vi.mocked(checkRateLimit).mockResolvedValue({
|
||||
allowed: true,
|
||||
remaining: 9,
|
||||
resetAt: Date.now() + 3600_000,
|
||||
});
|
||||
vi.mocked(prisma.medication.findMany).mockResolvedValue([
|
||||
{ name: "Aspirin", dose: "100mg", active: true, schedules: [] },
|
||||
] as never);
|
||||
vi.mocked(prisma.medicationIntakeEvent.findMany).mockResolvedValue(
|
||||
[] as never,
|
||||
);
|
||||
|
||||
const { GET } = await import("../medications/route");
|
||||
const res = await GET(
|
||||
mkReq(
|
||||
"http://localhost/api/export/medications?intake=true&medicationId=med-9",
|
||||
),
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
// The medication list is narrowed by id AND userId (IDOR-safe).
|
||||
expect(prisma.medication.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { userId: "user-1", id: "med-9" },
|
||||
}),
|
||||
);
|
||||
// The intake history is filtered to the same medication.
|
||||
expect(prisma.medicationIntakeEvent.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: expect.objectContaining({ medicationId: "med-9" }),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("404s a scoped export when the medication is not the caller's", async () => {
|
||||
vi.mocked(getSession).mockResolvedValue(SESSION_OK as never);
|
||||
vi.mocked(checkRateLimit).mockResolvedValue({
|
||||
allowed: true,
|
||||
remaining: 9,
|
||||
resetAt: Date.now() + 3600_000,
|
||||
});
|
||||
// userId-narrowed query resolves to no row for a foreign id.
|
||||
vi.mocked(prisma.medication.findMany).mockResolvedValue([] as never);
|
||||
|
||||
const { GET } = await import("../medications/route");
|
||||
const res = await GET(
|
||||
mkReq("http://localhost/api/export/medications?medicationId=not-mine"),
|
||||
);
|
||||
expect(res.status).toBe(404);
|
||||
expect(prisma.medicationIntakeEvent.findMany).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /api/export/mood", () => {
|
||||
|
||||
Reference in new issue
Block a user