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:
bbassieandClaude Opus 5.5 committed 2026-10-08 11:11:28 +00:00
1 parent ce6bfe282f
commit beec2f523a
4 files changed
+103

No files matched your search

+25
View File
@@ -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;