Fix W1/W2 webhook loop (skip-if-already-synced guard) + fix W2 link API alist_path bug

This commit is contained in:
2026-08-22 22:34:27 +08:00
parent 71acb88078
commit 160169e6f2
2 changed files with 139 additions and 7 deletions
+70 -4
View File
@@ -77,7 +77,7 @@
},
{
"parameters": {
"jsCode": "const cust = $input.item.json;\nconst username = cust.username; const password = cust.password;\nif (!username) throw new Error('Customer missing username');\nreturn { json: { customerId: cust.Id ?? cust.id, username, password, displayName: cust.display_name ?? username, basePath: cust.base_path ?? '/Class', alistUserId: cust.alist_user_id ?? null, alistRoleId: cust.alist_role_id ?? null, isCreate: !(cust.alist_user_id) } };\n"
"jsCode": "const cust = $input.item.json;\nconst username = cust.username; const password = cust.password;\nif (!username) throw new Error('Customer missing username');\nconst newUserId = cust.alist_user_id ?? null;\nconst newRoleId = cust.alist_role_id ?? null;\nconst isCreate = !newUserId;\n// Break loop: only write back if semantic fields would actually change.\n// If the record already has alist_user_id + role_id + sync_status=synced,\n// this webhook was fired by our own write-back (echo) -> skip.\nconst skipWriteBack = (!isCreate) && (cust.sync_status === 'synced');\nreturn { json: {\n customerId: cust.Id ?? cust.id,\n username, password,\n displayName: cust.display_name ?? username,\n basePath: cust.base_path ?? '/Class',\n alistUserId: newUserId,\n alistRoleId: newRoleId,\n isCreate,\n skipWriteBack,\n} };\n"
},
"id": "prepare",
"name": "Prepare Provision Payload",
@@ -333,7 +333,7 @@
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify([{ Id: $('Prepare Provision Payload').item.json.customerId, alist_user_id: $('Find New User Id').item.json.alistUserId, alist_role_id: $('Find New Role Id').item.json.alistRoleId, sync_status: 'synced', last_sync: new Date().toISOString(), last_sync_error: null }]) }}",
"jsonBody": "={{ JSON.stringify([{ Id: $('Prepare Provision Payload').item.json.customerId, alist_user_id: $('Find New User Id').item.json.alistUserId, alist_role_id: $('Find New Role Id').item.json.alistRoleId, sync_status: 'synced', last_sync_error: null }]) }}",
"options": {}
},
"id": "nocodb-writeback-create",
@@ -395,7 +395,7 @@
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify([{ Id: $('Prepare Provision Payload').item.json.customerId, sync_status: 'synced', last_sync: new Date().toISOString(), last_sync_error: null }]) }}",
"jsonBody": "={{ JSON.stringify([{ Id: $('Prepare Provision Payload').item.json.customerId, sync_status: 'synced', last_sync_error: null }]) }}",
"options": {}
},
"id": "nocodb-writeback-update",
@@ -406,6 +406,54 @@
1760,
0
]
},
{
"parameters": {
"jsCode": "// Loop guard: echo webhook already synced -> stop here, no login, no write-back.\nreturn { json: { skipped: true, customerId: $('Prepare Provision Payload').item.json.customerId } };"
},
"id": "skip-echo-end",
"name": "Skip Echo (No-op)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1540,
-520
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeName": "boolean",
"ignoreCase": true
},
"conditions": [
{
"id": "cond-skip",
"leftValue": "={{ $('Prepare Provision Payload').item.json.skipWriteBack }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals",
"singleValue": true,
"rightType": "boolean"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-skip",
"name": "Skip if already synced",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1320,
0
]
}
],
"connections": {
@@ -446,7 +494,7 @@
"main": [
[
{
"node": "AList Admin Login",
"node": "Skip if already synced",
"type": "main",
"index": 0
}
@@ -586,6 +634,24 @@
}
]
]
},
"Skip if already synced": {
"main": [
[
{
"node": "Skip Echo (No-op)",
"type": "main",
"index": 0
}
],
[
{
"node": "AList Admin Login",
"type": "main",
"index": 0
}
]
]
}
}
}