Files
factorio-clusterio/test/lib/data/messages_user.test.js
BastiaanandClaude Opus 4.8 8239a96509 Deny instead of crashing when a control permission check throws (#1033)
A permission function runs during ingress permission checking, before
the request body is validated. UserBulkImportRequest.permission read the
raw, unvalidated message.data and threw a bare Error for an unknown
importType. That error is not a PermissionError, so _processMessage
rethrew it to the connector "message" listener, which emitted "error" on
the connector. Controller-side connectors have no "error" listener, so
Node rethrew and handleUnhandledErrors exited the process.

Repro: a control client with client-side validateSent disabled sends
UserBulkImportRequest with importType "foo"; the client gets a normal
RequestError response and the controller then logs a fatal uncaught
exception and exits.

Fix both layers: _processMessage now logs and drops an unexpected error
from the permission check (control connections only, where a response
was already sent) instead of rethrowing, and UserBulkImportRequest
throws a PermissionError for an unknown importType so it is denied
cleanly. A genuine PermissionError still denies silently as before.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-13 14:51:16 +01:00

28 lines
975 B
JavaScript

import assert from "node:assert/strict";
import * as lib from "@clusterio/lib";
describe("lib/data/messages_user", function() {
describe("UserBulkImportRequest", function() {
// A user that grants every permission, so only the importType switch
// can reject the request.
function grantAllUser() {
const checked = [];
return { checked, checkPermission(permission) { checked.push(permission); } };
}
it("should deny an unknown importType with a PermissionError", function() {
const user = grantAllUser();
assert.throws(
() => lib.UserBulkImportRequest.permission(user, { data: { importType: "foo", users: [] } }),
lib.PermissionError,
);
});
it("should check permissions for a known importType", function() {
const user = grantAllUser();
lib.UserBulkImportRequest.permission(user, { data: { importType: "admins", users: [] } });
assert.deepEqual(user.checked, ["core.user.bulk_import", "core.user.set_admin"]);
});
});
});