Skip to content

Commit 6a1c52b

Browse files
waleedlatif1claude
andcommitted
fix(lock): add lock validation to block rename operations
Defense-in-depth: although the UI disables rename for locked blocks, the collaborative layer and server now also validate locks. - collaborativeUpdateBlockName: checks if block is locked or inside locked container before attempting rename - UPDATE_NAME server handler: checks lock status and parent lock before performing database update Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 36c4b22 commit 6a1c52b

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

apps/sim/hooks/use-collaborative-workflow.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,23 @@ export function useCollaborativeWorkflow() {
744744

745745
const collaborativeUpdateBlockName = useCallback(
746746
(id: string, name: string): { success: boolean; error?: string } => {
747+
const blocks = useWorkflowStore.getState().blocks
748+
const block = blocks[id]
749+
750+
if (block) {
751+
const parentId = block.data?.parentId
752+
const isParentLocked = parentId ? blocks[parentId]?.locked : false
753+
if (block.locked || isParentLocked) {
754+
logger.error('Cannot rename locked block')
755+
useNotificationStore.getState().addNotification({
756+
level: 'info',
757+
message: 'Cannot rename locked blocks',
758+
workflowId: activeWorkflowId || undefined,
759+
})
760+
return { success: false, error: 'Block is locked' }
761+
}
762+
}
763+
747764
const trimmedName = name.trim()
748765
const normalizedNewName = normalizeName(trimmedName)
749766

@@ -1021,7 +1038,6 @@ export function useCollaborativeWorkflow() {
10211038

10221039
const blocks = useWorkflowStore.getState().blocks
10231040

1024-
// Helper to check if a block is protected (locked or inside locked parent)
10251041
const isProtected = (blockId: string): boolean => {
10261042
const block = blocks[blockId]
10271043
if (!block) return false
@@ -1036,7 +1052,6 @@ export function useCollaborativeWorkflow() {
10361052

10371053
for (const id of ids) {
10381054
const block = blocks[id]
1039-
// Skip locked blocks and blocks inside locked containers
10401055
if (block && !isProtected(id)) {
10411056
previousStates[id] = block.horizontalHandles ?? false
10421057
validIds.push(id)

apps/sim/socket/database/operations.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,18 +263,51 @@ async function handleBlockOperationTx(
263263
throw new Error('Missing required fields for update name operation')
264264
}
265265

266-
const updateResult = await tx
266+
// Check if block is protected (locked or inside locked parent)
267+
const blockToRename = await tx
268+
.select({
269+
id: workflowBlocks.id,
270+
locked: workflowBlocks.locked,
271+
data: workflowBlocks.data,
272+
})
273+
.from(workflowBlocks)
274+
.where(and(eq(workflowBlocks.id, payload.id), eq(workflowBlocks.workflowId, workflowId)))
275+
.limit(1)
276+
277+
if (blockToRename.length === 0) {
278+
throw new Error(`Block ${payload.id} not found in workflow ${workflowId}`)
279+
}
280+
281+
const block = blockToRename[0]
282+
const parentId = (block.data as Record<string, unknown> | null)?.parentId as
283+
| string
284+
| undefined
285+
286+
if (block.locked) {
287+
logger.info(`Skipping rename of locked block ${payload.id}`)
288+
break
289+
}
290+
291+
if (parentId) {
292+
const parentBlock = await tx
293+
.select({ locked: workflowBlocks.locked })
294+
.from(workflowBlocks)
295+
.where(and(eq(workflowBlocks.id, parentId), eq(workflowBlocks.workflowId, workflowId)))
296+
.limit(1)
297+
298+
if (parentBlock.length > 0 && parentBlock[0].locked) {
299+
logger.info(`Skipping rename of block ${payload.id} - parent ${parentId} is locked`)
300+
break
301+
}
302+
}
303+
304+
await tx
267305
.update(workflowBlocks)
268306
.set({
269307
name: payload.name,
270308
updatedAt: new Date(),
271309
})
272310
.where(and(eq(workflowBlocks.id, payload.id), eq(workflowBlocks.workflowId, workflowId)))
273-
.returning({ id: workflowBlocks.id })
274-
275-
if (updateResult.length === 0) {
276-
throw new Error(`Block ${payload.id} not found in workflow ${workflowId}`)
277-
}
278311

279312
logger.debug(`Updated block name: ${payload.id} -> "${payload.name}"`)
280313
break

0 commit comments

Comments
 (0)