Add a printer through the gateway without the cloud keeping its credential
POST /farms/:id/printers (owner) is the console's add-printer call. It needs a connected gateway and relays the printer's access code to it in a single provision_printer frame; the gateway connects to the printer to prove the code, saves it in its own database, and only then does the cloud create the printer row. A refused or timed-out add leaves no row, and a row insert that fails after the gateway said yes tells the gateway to forget the printer. The access code is held in the request and the one frame and nowhere else: not in any table, not in a log line, not in a response or an error (the gateway's error text is scrubbed of it as a second line of defence). Deleting a printer now also tells the gateway to forget it and its stored credential, best effort, so an unplugged gateway cannot block an owner. Only Bambu is accepted, because it is the only vendor with a working driver; the rest are found by discovery but cannot yet be driven. e2e-provision.sh drives a stand-in gateway over the real socket and, after adding a printer, searches every table of the database and the backend's log for the code (checked to fail when the code is logged).
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { gatewayIdFor, safeGatewayError } from "../src/provision/plan";
|
||||
|
||||
describe("gatewayIdFor", () => {
|
||||
const accepted = /^[A-Za-z0-9_-]{1,64}$/;
|
||||
|
||||
test("makes a readable id the gateway will accept", () => {
|
||||
expect(gatewayIdFor("Bench P1P", () => 0)).toBe("bench-p1p-0000");
|
||||
expect(gatewayIdFor("Bench P1P", () => 0.999999)).toMatch(accepted);
|
||||
});
|
||||
|
||||
test("survives names with nothing usable in them", () => {
|
||||
expect(gatewayIdFor("***", () => 0.5)).toMatch(/^printer-[0-9a-f]{4}$/);
|
||||
expect(gatewayIdFor("Принтер", () => 0.5)).toMatch(accepted);
|
||||
});
|
||||
|
||||
test("never exceeds what the gateway accepts, whatever the name", () => {
|
||||
expect(gatewayIdFor("x".repeat(500))).toMatch(accepted);
|
||||
expect(gatewayIdFor("../../etc/passwd")).toMatch(accepted);
|
||||
});
|
||||
|
||||
test("two printers with the same name get different ids", () => {
|
||||
const ids = new Set(Array.from({ length: 50 }, () => gatewayIdFor("Same name")));
|
||||
expect(ids.size).toBeGreaterThan(30);
|
||||
});
|
||||
});
|
||||
|
||||
describe("safeGatewayError", () => {
|
||||
test("passes an ordinary message through", () => {
|
||||
expect(safeGatewayError("could not connect to the printer", ["12345678"])).toBe(
|
||||
"could not connect to the printer",
|
||||
);
|
||||
});
|
||||
test("removes a credential that somehow got into the message", () => {
|
||||
expect(safeGatewayError("bad login 12345678 for host", ["12345678"])).toBe("bad login <hidden> for host");
|
||||
});
|
||||
test("has an answer when the gateway gave none", () => {
|
||||
expect(safeGatewayError(undefined, [])).toBe("the gateway did not say why");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user