Skip to content

Commit b4c8c76

Browse files
committed
fix: allow no-op updates to locked flows
1 parent aa41e5a commit b4c8c76

2 files changed

Lines changed: 21 additions & 4 deletions

File tree

src/backend/base/langflow/services/database/models/flow/guards.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ def ensure_flow_unlocked(flow: Flow) -> None:
3030

3131

3232
def ensure_flow_update_allowed(flow: Flow, update_data: Mapping[str, Any]) -> None:
33-
"""Allow updates to unlocked flows and unlock-only updates to locked flows.
33+
"""Allow updates to unlocked flows and safe updates to locked flows.
3434
3535
API clients commonly send the full current flow when toggling the lock. We
36-
therefore compare payload values with the persisted row and allow the
37-
request when ``locked=False`` is the only effective change.
36+
therefore compare payload values with the persisted row and allow no-op
37+
requests or requests where ``locked=False`` is the only effective change.
3838
"""
3939
if getattr(flow, "locked", False) is not True:
4040
return
4141

4242
changed_fields = {
4343
field_name for field_name, new_value in update_data.items() if getattr(flow, field_name, None) != new_value
4444
}
45-
if changed_fields == {"locked"} and update_data.get("locked") is False:
45+
if not changed_fields or (changed_fields == {"locked"} and update_data.get("locked") is False):
4646
return
4747

4848
raise LockedFlowError(LOCKED_FLOW_DETAIL)

src/backend/tests/unit/api/v1/test_flows.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,23 @@ async def test_locked_flow_rejects_api_updates_until_unlocked(client: AsyncClien
218218
created = create_response.json()
219219
flow_id = created["id"]
220220

221+
# Navigation can submit the full current flow even when nothing changed.
222+
# A no-op save must succeed so the UI can leave a locked flow cleanly.
223+
no_op_response = await client.patch(
224+
f"api/v1/flows/{flow_id}",
225+
json={
226+
"name": created["name"],
227+
"description": created["description"],
228+
"data": created["data"],
229+
"folder_id": created["folder_id"],
230+
"endpoint_name": created["endpoint_name"],
231+
"locked": True,
232+
},
233+
headers=logged_in_headers,
234+
)
235+
assert no_op_response.status_code == status.HTTP_200_OK
236+
assert no_op_response.json()["locked"] is True
237+
221238
patch_response = await client.patch(
222239
f"api/v1/flows/{flow_id}",
223240
json={"description": "changed via PATCH"},

0 commit comments

Comments
 (0)