mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-27 07:52:03 +00:00
Refuse a config write with no value, and 404 a document import with no file
Two more from the routes sweep, both cases where removing the check produced a wrong answer rather than no answer. `PUT /api/v1/config/:key` with a body carrying no `value` was only refused by the explicit check. Boolean(undefined) is false, so for every boolean key — offline_mode, secret_mode_enabled — an empty body would have quietly SET the setting to false instead of refusing. The test now confirms a refused write leaves the existing value alone, which is the property that actually matters. `POST /api/v1/entry/document/import` from a path checks the file exists; without it readFile's ENOENT surfaces as 500, "the server broke" for a filename the caller got wrong. Also asserts the traversal guard applies to the import side and not only to export, which nothing covered. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
This commit is contained in:
1 parent
d8292db325
commit
5aa6d04248
1 file changed
+51
@@ -221,6 +221,34 @@ describe("what the API refuses", () => {
|
||||
expect(existsSync(inside.json.path)).toBe(true);
|
||||
});
|
||||
|
||||
it("imports a document from a path, and says 404 when there is no file", async () => {
|
||||
// Without the existence check, readFile's ENOENT surfaces as 500 — "the
|
||||
// server broke" for a filename the caller simply got wrong. Both halves
|
||||
// are asserted so the test cannot pass by the route being broken.
|
||||
const missing = await call("POST", "/api/v1/entry/document/import", {
|
||||
password: PASSWORD,
|
||||
body: { label: "nope", path: "no-such-file.txt" },
|
||||
});
|
||||
expect(missing.status).toBe(404);
|
||||
expect(missing.json.detail).toContain("file not found");
|
||||
|
||||
const path = join(app.profileDir(FINGERPRINT), "importable.txt");
|
||||
await writeFile(path, "document contents");
|
||||
const imported = await call("POST", "/api/v1/entry/document/import", {
|
||||
password: PASSWORD,
|
||||
body: { label: "imported-doc", path: "importable.txt" },
|
||||
});
|
||||
expect(imported.status).toBe(201);
|
||||
|
||||
// And the traversal guard applies to the import side too, not only export.
|
||||
expect(
|
||||
(await call("POST", "/api/v1/entry/document/import", {
|
||||
password: PASSWORD,
|
||||
body: { label: "escape", path: "../../../etc/passwd" },
|
||||
})).status,
|
||||
).toBe(400);
|
||||
});
|
||||
|
||||
it("validates optional integers at every edge, not just the obvious one", async () => {
|
||||
// optInt guards `length`, `period`, `digits`, `index`, `delay` and the
|
||||
// history `target`. Each of its three clauses was unasserted.
|
||||
@@ -303,6 +331,29 @@ describe("what the API refuses", () => {
|
||||
expect(typo.json.detail).toContain("Unknown key");
|
||||
expect((await call("GET", "/api/v1/config/inactivity_timout")).json.value).toBeNull();
|
||||
|
||||
// A body with no `value` at all. The boolean keys are where this bites:
|
||||
// Boolean(undefined) is false, so without the check `PUT
|
||||
// /api/v1/config/offline_mode` with an empty body would quietly SET
|
||||
// offline_mode to false rather than refuse.
|
||||
for (const key of ["offline_mode", "secret_mode_enabled", "relays"]) {
|
||||
const res = await call("PUT", `/api/v1/config/${key}`, {
|
||||
password: PASSWORD,
|
||||
body: {},
|
||||
});
|
||||
expect(res.status).toBe(400);
|
||||
expect(res.json.detail).toContain("value is required");
|
||||
}
|
||||
// Unchanged by the refusals above.
|
||||
expect((await call("GET", "/api/v1/config/offline_mode")).json.value).toBe(false);
|
||||
await call("PUT", "/api/v1/config/offline_mode", { body: { value: true } });
|
||||
expect((await call("GET", "/api/v1/config/offline_mode")).json.value).toBe(true);
|
||||
expect(
|
||||
(await call("PUT", "/api/v1/config/offline_mode", { body: {} })).status,
|
||||
).toBe(400);
|
||||
// Still true — the empty body did not reset it.
|
||||
expect((await call("GET", "/api/v1/config/offline_mode")).json.value).toBe(true);
|
||||
await call("PUT", "/api/v1/config/offline_mode", { body: { value: false } });
|
||||
|
||||
// Nor a key that only LOOKS like an object property.
|
||||
expect(
|
||||
(await call("PUT", "/api/v1/config/__proto__", { body: { value: {} } })).status,
|
||||
|
||||
Reference in new issue
Block a user