mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(realtime): stop read-only members persisting block positions (#6174)
* fix(realtime): stop read-only members persisting block positions The socket operation ACL granted the `read` role block.updatePosition and blocks.batchUpdatePositions on the premise that they were ephemeral cursor sync. They are not: both are followed by persistWorkflowOperation, which UPDATEs workflow_blocks.positionX/positionY and bumps workflow.updatedAt. A member holding only `read` on a workspace could therefore permanently rewrite the coordinates of every block of every workflow in it — a write across the read/write boundary. Live cursors ride their own `cursor-update` event, and the smooth-drag broadcast is the UNCOMMITTED position path, which returns before persisting and never consults the role table — so the read role needs no grant at all. * test(realtime): assert the role ACL against production, not a fixture The shared ROLE_ALLOWED_OPERATIONS fixture still listed the two position operations for the read role, and three tests compared that fixture against itself — so they certified whatever it said, including the grants this PR removes. They now assert checkRolePermission over the protocol's complete operation list (the fixture's copy omits subblock/variable/admin-only ops), plus one test that pins the fixture to the production ACL so the two cannot drift apart again.
This commit is contained in:
@@ -307,11 +307,18 @@ export type SocketOperation = (typeof SOCKET_OPERATIONS)[number]
|
||||
|
||||
/**
|
||||
* Operations allowed for each role.
|
||||
*
|
||||
* A convenience mirror for fixtures — NOT the authority. The real ACL lives in
|
||||
* `apps/realtime/src/middleware/permissions.ts`; assert against
|
||||
* `checkRolePermission` rather than this table, or a drift between the two turns
|
||||
* into a test that certifies whatever the fixture happens to say. (`read` listed
|
||||
* the two position operations here while production had already granted them for
|
||||
* real; both are persisted writes and neither role should hold them.)
|
||||
*/
|
||||
export const ROLE_ALLOWED_OPERATIONS: Record<PermissionType, readonly SocketOperation[]> = {
|
||||
admin: SOCKET_OPERATIONS,
|
||||
write: SOCKET_OPERATIONS,
|
||||
read: [BLOCK_OPERATIONS.UPDATE_POSITION, BLOCKS_OPERATIONS.BATCH_UPDATE_POSITIONS],
|
||||
read: [],
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user