mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-14 15:24:52 +09:00
Drop subscriptions when a user loses permission for them
The permission for a subscription was only checked when subscribing, so a control connection kept receiving events after the user's roles or role permissions changed to no longer allow it. Add SubscriptionController.unsubscribeUnpermitted which rechecks every subscription of a link and removes the ones the user is no longer permitted, and call it for the affected control connections from userPermissionsUpdated and rolesUpdated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ce6bfe282f
commit
beec2f523a
4 files changed
+103
No files matched your search
@@ -261,6 +261,31 @@ describe("controller/src/Controller", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("permission changes", function() {
|
||||
let role, connection, checked, originalWsServer;
|
||||
beforeEach(function() {
|
||||
role = new Role(1, "Test", "", new Set());
|
||||
const user = { roles: new Set([role]) };
|
||||
connection = { user, send() {} };
|
||||
originalWsServer = controller.wsServer;
|
||||
controller.wsServer = { controlConnections: new Map([[1, connection]]) };
|
||||
checked = [];
|
||||
controller.subscriptions.unsubscribeUnpermitted = (link, linkUser) => checked.push([link, linkUser]);
|
||||
});
|
||||
afterEach(function() {
|
||||
controller.wsServer = originalWsServer;
|
||||
delete controller.subscriptions.unsubscribeUnpermitted;
|
||||
});
|
||||
it("should recheck subscriptions when a user's permissions change", function() {
|
||||
controller.userPermissionsUpdated(connection.user);
|
||||
assert.deepEqual(checked, [[connection, connection.user]]);
|
||||
});
|
||||
it("should recheck subscriptions of users with an updated role", function() {
|
||||
controller.rolesUpdated([role]);
|
||||
assert.deepEqual(checked, [[connection, connection.user]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".instances", function() {
|
||||
it("should set the dirty flag if the config is updated", function() {
|
||||
controller.instances.records.dirty = false;
|
||||
|
||||
@@ -552,6 +552,57 @@ describe("lib/subscriptions", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe(".unsubscribeUnpermitted()", function() {
|
||||
class DenyingUser {
|
||||
constructor(denied) {
|
||||
this.denied = denied;
|
||||
}
|
||||
|
||||
checkPermission(permission) {
|
||||
if (permission === this.denied) {
|
||||
throw new lib.PermissionError("Permission denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
beforeEach(async function() {
|
||||
subscriptions.handle(StringPermissionEvent);
|
||||
subscriptions.handle(FunctionPermissionEvent);
|
||||
for (const connectorData of connectorSetupDate) {
|
||||
for (const Event of [StringPermissionEvent, FunctionPermissionEvent]) {
|
||||
const request = new lib.SubscriptionRequest(Event.name, "subscribe");
|
||||
await subscriptions.handleRequest(getLink(connectorData.id), request, connectorData.dst);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("should remove subscriptions with a string permission the user lost", async function() {
|
||||
subscriptions.unsubscribeUnpermitted(getLink(0), new DenyingUser("StringPermission"));
|
||||
subscriptions.broadcast(new StringPermissionEvent());
|
||||
await onceConnectorSend(1);
|
||||
assertNoEvent(0);
|
||||
subscriptions.broadcast(new FunctionPermissionEvent());
|
||||
await onceConnectorSend(0);
|
||||
assertLastEvent(0, FunctionPermissionEvent);
|
||||
});
|
||||
|
||||
it("should remove subscriptions with a function permission the user lost", async function() {
|
||||
subscriptions.unsubscribeUnpermitted(getLink(0), new DenyingUser("FunctionPermission"));
|
||||
subscriptions.broadcast(new FunctionPermissionEvent());
|
||||
await onceConnectorSend(1);
|
||||
assertNoEvent(0);
|
||||
subscriptions.broadcast(new StringPermissionEvent());
|
||||
await onceConnectorSend(0);
|
||||
assertLastEvent(0, StringPermissionEvent);
|
||||
});
|
||||
|
||||
it("should keep subscriptions the user still has permission for", async function() {
|
||||
subscriptions.unsubscribeUnpermitted(getLink(0), new DenyingUser(null));
|
||||
subscriptions.broadcast(new StringPermissionEvent());
|
||||
await onceConnectorSend(0);
|
||||
assertLastEvent(0, StringPermissionEvent);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".handleRequest()", function() {
|
||||
beforeEach(function() {
|
||||
subscriptions.handle(RegisteredEvent);
|
||||
|
||||
Reference in new issue
Block a user