n8n
This commit is contained in:
parent
0afa69d8ca
commit
984d4488c0
2
.env
2
.env
@ -103,4 +103,4 @@ MICROSOFT_CLIENT_ID="afaffea5-4e10-462a-aa64-e73baf642c57"
|
|||||||
MICROSOFT_CLIENT_SECRET="eIx8Q~N3ZnXTjTsVM3ECZio4G7t.BO6AYlD1-b2h"
|
MICROSOFT_CLIENT_SECRET="eIx8Q~N3ZnXTjTsVM3ECZio4G7t.BO6AYlD1-b2h"
|
||||||
MICROSOFT_REDIRECT_URI="https://lab.slm-lab.net/ms"
|
MICROSOFT_REDIRECT_URI="https://lab.slm-lab.net/ms"
|
||||||
MICROSOFT_TENANT_ID="cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2"
|
MICROSOFT_TENANT_ID="cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2"
|
||||||
N8N_WEBHOOK_URL=https://brain.slm-lab.net/webhook-test/mission-created
|
N8N_WEBHOOK_URL="https://brain.slm-lab.net/webhook-test/mission-created"
|
||||||
|
|||||||
420
Missions.json
420
Missions.json
@ -1,420 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Missions",
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Process and sanitize mission data\nconst missionData = $input.item.json;\n\n// Sanitize mission name for use in various APIs\nconst sanitizeName = (name) => {\n if (!name || typeof name !== 'string') return 'unnamed-mission';\n\n return name.toLowerCase()\n .replace(/[^\\w\\s-]/g, '') // Remove special characters\n .replace(/\\s+/g, '-') // Replace whitespace with hyphens\n .trim();\n};\n\n// Format dates for Leantime API (YYYY-MM-DD)\nconst formatDate = (date) => {\n if (!date) return '';\n const d = new Date(date);\n return d.toISOString().split('T')[0];\n};\n\n// Construct processed mission data\nconst output = {\n missionOriginal: missionData,\n missionProcessed: {\n name: missionData?.name || 'Unnamed Mission',\n sanitizedName: sanitizeName(missionData?.name),\n intention: missionData?.intention || '',\n description: missionData?.intention || 'Mission documentation',\n startDate: formatDate(new Date()),\n endDate: formatDate(new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)), // +30 days\n missionType: missionData?.missionType || 'default',\n guardians: missionData?.guardians || {},\n volunteers: missionData?.volunteers || [],\n profils: missionData?.profils || [],\n services: missionData?.services || [],\n clientId: missionData?.missionType === 'interne' ? 1 : 2,\n rocketChatUsernames: []\n },\n config: {\n GITEA_API_URL: \"https://gite.slm-lab.net/api/v1\",\n GITEA_API_TOKEN: \"310645d564cbf752be1fe3b42582a3d5f5d0bddd\",\n GITEA_OWNER: \"alma\",\n LEANTIME_API_URL: \"https://agilite.slm-lab.net\",\n LEANTIME_API_TOKEN: \"lt_lsdShQdoYHaPUWuL07XZR1Rf3GeySsIs_UDlll3VJPk5EwAuILpMC4BwzJ9MZFRrb\",\n ROCKETCHAT_API_URL: \"https://parole.slm-lab.net/\",\n ROCKETCHAT_AUTH_TOKEN: \"w91TYgkH-Z67Oz72usYdkW5TZLLRwnre7qyAhp7aHJB\",\n ROCKETCHAT_USER_ID: \"Tpuww59PJKsrGNQJB\",\n OUTLINE_API_URL: \"https://chapitre.slm-lab.net/api\",\n OUTLINE_API_TOKEN: \"ol_api_tlLlANBfcoJ4l7zA8GOcpduAeL6QyBTcYvEnlN\",\n MISSION_API_URL: \"https://brain.slm-lab.net/webhook-test/mission-created\"\n }\n};\n\n// Populate RocketChat usernames from guardians and volunteers\nif (missionData?.guardians) {\n for (const role in missionData.guardians) {\n const user = missionData.guardians[role];\n if (user) output.missionProcessed.rocketChatUsernames.push(user);\n }\n}\n\nif (Array.isArray(missionData?.volunteers)) {\n output.missionProcessed.rocketChatUsernames.push(...missionData.volunteers);\n}\n\n// Deduplicate usernames\noutput.missionProcessed.rocketChatUsernames = [...new Set(output.missionProcessed.rocketChatUsernames)];\n\nreturn output;\n"
|
|
||||||
},
|
|
||||||
"name": "Process Mission Data",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
260,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"id": "900e5ca6-b081-4f80-a7c5-ecde88c4ee3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "={{ $node['Process Mission Data'].json.config.GITEA_API_URL + '/user/repos' }}",
|
|
||||||
"sendHeaders": true,
|
|
||||||
"headerParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Authorization",
|
|
||||||
"value": "={{ 'Bearer ' + $node['Process Mission Data'].json.config.GITEA_API_TOKEN }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sendBody": true,
|
|
||||||
"bodyParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.sanitizedName }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "private",
|
|
||||||
"value": "={{ true }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "auto_init",
|
|
||||||
"value": "={{ true }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Create Git Repository",
|
|
||||||
"type": "n8n-nodes-base.httpRequest",
|
|
||||||
"typeVersion": 3,
|
|
||||||
"position": [
|
|
||||||
460,
|
|
||||||
460
|
|
||||||
],
|
|
||||||
"id": "71eea3d3-2a75-4a14-9bc6-c23ca49be59a",
|
|
||||||
"continueOnFail": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "={{ $node['Process Mission Data'].json.config.LEANTIME_API_URL + '/api/jsonrpc' }}",
|
|
||||||
"sendHeaders": true,
|
|
||||||
"headerParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "X-API-Key",
|
|
||||||
"value": "={{ $node['Process Mission Data'].json.config.LEANTIME_API_TOKEN }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sendBody": true,
|
|
||||||
"bodyParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "method",
|
|
||||||
"value": "leantime.rpc.Projects.Projects.addProject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "jsonrpc",
|
|
||||||
"value": "2.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "params",
|
|
||||||
"value": "={{ { \n \"values\": {\n \"name\": $node[\"Process Mission Data\"].json.missionProcessed.name,\n \"clientId\": $node[\"Process Mission Data\"].json.missionProcessed.clientId,\n \"details\": $node[\"Process Mission Data\"].json.missionProcessed.intention,\n \"type\": \"project\",\n \"start\": $node[\"Process Mission Data\"].json.missionProcessed.startDate,\n \"end\": $node[\"Process Mission Data\"].json.missionProcessed.endDate,\n \"status\": \"open\",\n \"psettings\": \"restricted\"\n }\n} }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Create Leantime Project",
|
|
||||||
"type": "n8n-nodes-base.httpRequest",
|
|
||||||
"typeVersion": 3,
|
|
||||||
"position": [
|
|
||||||
460,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"id": "0cb15b0b-f718-4455-8e52-6ad8ceb563eb",
|
|
||||||
"continueOnFail": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_API_URL + '/api/v1/channels.create' }}",
|
|
||||||
"sendHeaders": true,
|
|
||||||
"headerParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "X-Auth-Token",
|
|
||||||
"value": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_AUTH_TOKEN }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "X-User-Id",
|
|
||||||
"value": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_USER_ID }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sendBody": true,
|
|
||||||
"bodyParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.sanitizedName }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "members",
|
|
||||||
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.rocketChatUsernames }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "readOnly",
|
|
||||||
"value": "false"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Create RocketChat Channel",
|
|
||||||
"type": "n8n-nodes-base.httpRequest",
|
|
||||||
"typeVersion": 3,
|
|
||||||
"position": [
|
|
||||||
460,
|
|
||||||
660
|
|
||||||
],
|
|
||||||
"id": "73934ba8-8ea0-4f15-bf5e-3aa2a64ae57f",
|
|
||||||
"continueOnFail": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "={{ $node['Process Mission Data'].json.config.OUTLINE_API_URL + '/collections.create' }}",
|
|
||||||
"sendHeaders": true,
|
|
||||||
"headerParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Authorization",
|
|
||||||
"value": "={{ 'Bearer ' + $node['Process Mission Data'].json.config.OUTLINE_API_TOKEN }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sendBody": true,
|
|
||||||
"bodyParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.name }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.description }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"value": "#4f46e5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "permission",
|
|
||||||
"value": "read"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "private",
|
|
||||||
"value": "={{ true }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Create Documentation Collection",
|
|
||||||
"type": "n8n-nodes-base.httpRequest",
|
|
||||||
"typeVersion": 3,
|
|
||||||
"position": [
|
|
||||||
460,
|
|
||||||
760
|
|
||||||
],
|
|
||||||
"id": "ed034321-54b1-4e59-b204-c93619561fec",
|
|
||||||
"continueOnFail": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "={{ $node['Process Mission Data'].json.config.MISSION_API_URL+ '/api/missions' }}",
|
|
||||||
"sendHeaders": true,
|
|
||||||
"headerParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sendBody": true,
|
|
||||||
"bodyParameters": {
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "body",
|
|
||||||
"value": "={{ {\n \"name\": $node[\"Process Mission Data\"].json.missionOriginal.name,\n \"logo\": $node[\"Process Mission Data\"].json.missionOriginal.logo || \"\",\n \"oddScope\": $node[\"Process Mission Data\"].json.missionOriginal.oddScope || [],\n \"niveau\": $node[\"Process Mission Data\"].json.missionOriginal.niveau || \"\",\n \"intention\": $node[\"Process Mission Data\"].json.missionOriginal.intention || \"\",\n \"missionType\": $node[\"Process Mission Data\"].json.missionOriginal.missionType || \"\",\n \"donneurDOrdre\": $node[\"Process Mission Data\"].json.missionOriginal.donneurDOrdre || \"\",\n \"projection\": $node[\"Process Mission Data\"].json.missionOriginal.projection || \"\",\n \"services\": $node[\"Process Mission Data\"].json.missionOriginal.services || [],\n \"participation\": $node[\"Process Mission Data\"].json.missionOriginal.participation || \"\",\n \"profils\": $node[\"Process Mission Data\"].json.missionOriginal.profils || [],\n \"guardians\": $node[\"Process Mission Data\"].json.missionOriginal.guardians || {\n \"gardien-temps\": \"\",\n \"gardien-parole\": \"\",\n \"gardien-memoire\": \"\"\n },\n \"volunteers\": $node[\"Process Mission Data\"].json.missionOriginal.volunteers || [],\n \"integrations\": {\n \"gitRepoUrl\": $node[\"Create Git Repository\"].json.html_url || \"\",\n \"leantimeProjectId\": $node[\"Create Leantime Project\"].json.result || \"\",\n \"rocketChatChannelId\": $node[\"Create RocketChat Channel\"].json.channel._id || \"\",\n \"documentationCollectionId\": $node[\"Create Documentation Collection\"].json.id || \"\"\n }\n} }}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Save Mission To API",
|
|
||||||
"type": "n8n-nodes-base.httpRequest",
|
|
||||||
"typeVersion": 3,
|
|
||||||
"position": [
|
|
||||||
660,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"id": "f74f61e2-f487-42a5-828b-3c040b6471c6",
|
|
||||||
"continueOnFail": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Collect all integration results\nconst results = {\n webhook: $input.item.json || {},\n gitRepo: $node[\"Create Git Repository\"].json || { error: 'Failed or not executed' },\n leantimeProject: $node[\"Create Leantime Project\"].json || { error: 'Failed or not executed' },\n rocketChatChannel: $node[\"Create RocketChat Channel\"].json || { error: 'Failed or not executed' },\n docCollection: $node[\"Create Documentation Collection\"].json || { error: 'Failed or not executed' },\n missionApi: $node[\"Save Mission To API\"].json || { error: 'Failed or not executed' }\n};\n\n// Check for errors\nconst errors = [];\n\nif (!results.gitRepo.html_url) {\n errors.push('Git repository creation failed');\n}\n\nif (!results.leantimeProject.result) {\n errors.push('Leantime project creation failed');\n}\n\nif (!results.rocketChatChannel.success) {\n errors.push('RocketChat channel creation failed');\n}\n\nif (!results.docCollection.id) {\n errors.push('Documentation collection creation failed');\n}\n\nif (!results.missionApi.id) {\n errors.push('Mission API registration failed');\n}\n\n// Prepare response\nconst output = {\n success: errors.length === 0,\n errors: errors,\n results: results,\n message: errors.length === 0 ? \n 'Mission integration complete: All systems updated successfully' : \n `Mission integration partial: ${errors.join(', ')}`\n};\n\nreturn output;"
|
|
||||||
},
|
|
||||||
"name": "Process Results",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
860,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"id": "aedea1af-dcfc-4361-bb66-f25dcce10b98"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"respondWith": "json",
|
|
||||||
"responseBody": "={{ $node[\"Process Results\"].json }}",
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"name": "Respond To Webhook",
|
|
||||||
"type": "n8n-nodes-base.respondToWebhook",
|
|
||||||
"typeVersion": 1,
|
|
||||||
"position": [
|
|
||||||
1060,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"id": "fcecf6cc-52c3-4989-8fad-0cf6e3508601"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"httpMethod": "POST",
|
|
||||||
"path": "mission-created",
|
|
||||||
"options": {
|
|
||||||
"responseData": "allEntries"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "Mission Created Webhook",
|
|
||||||
"type": "n8n-nodes-base.webhook",
|
|
||||||
"typeVersion": 1,
|
|
||||||
"position": [
|
|
||||||
-160,
|
|
||||||
560
|
|
||||||
],
|
|
||||||
"webhookId": "mission-created-webhook",
|
|
||||||
"id": "11274a5b-b20f-4180-8611-3690dc9a8722"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"pinData": {},
|
|
||||||
"connections": {
|
|
||||||
"Process Mission Data": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Create Leantime Project",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"node": "Create RocketChat Channel",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"node": "Create Documentation Collection",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"node": "Create Git Repository",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Create Git Repository": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Save Mission To API",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"node": "Create Leantime Project",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Create Leantime Project": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Save Mission To API",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Create RocketChat Channel": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Save Mission To API",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Create Documentation Collection": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Save Mission To API",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Save Mission To API": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Process Results",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Process Results": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Respond To Webhook",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Mission Created Webhook": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Process Mission Data",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"active": false,
|
|
||||||
"settings": {
|
|
||||||
"executionOrder": "v1"
|
|
||||||
},
|
|
||||||
"versionId": "ab79ce0c-8778-4103-bfb8-7ccf99bc6ea6",
|
|
||||||
"meta": {
|
|
||||||
"templateCredsSetupCompleted": true,
|
|
||||||
"instanceId": "575d8de48bd511243817deebddae0cc97d73be64c6c4737e5d4e9caddec881d8"
|
|
||||||
},
|
|
||||||
"id": "Mxg5cbQzEUgTEFNd",
|
|
||||||
"tags": []
|
|
||||||
}
|
|
||||||
584
Missionspre.json
Normal file
584
Missionspre.json
Normal file
@ -0,0 +1,584 @@
|
|||||||
|
{
|
||||||
|
"name": "Missions",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "const missionData = $input.item.json; console.log('Raw input:', JSON.stringify($input.item, null, 2)); console.log('Mission data:', JSON.stringify(missionData, null, 2)); const sanitizeName = (name) => { console.log('Sanitizing name:', name); if (!name || typeof name !== 'string') { console.log('Invalid name, using default'); return 'unnamed-mission'; } const timestamp = new Date().getTime(); const uniqueSuffix = `-${timestamp}`; const sanitized = name.toLowerCase().replace(/[^\\w\\s-]/g, '').replace(/\\s+/g, '-').trim() + uniqueSuffix; console.log('Sanitized result:', sanitized); return sanitized; }; const formatDate = (date) => { if (!date) return ''; const d = new Date(date); return d.toISOString().split('T')[0]; }; const missionName = missionData?.missionOriginal?.body?.name || missionData?.body?.name || missionData?.name || 'Unnamed Mission'; console.log('Extracted mission name:', missionName); const output = { missionOriginal: missionData, missionProcessed: { name: missionName, sanitizedName: sanitizeName(missionName), intention: missionData?.missionOriginal?.body?.intention || missionData?.body?.intention || missionData?.intention || '', description: missionData?.missionOriginal?.body?.intention || missionData?.body?.intention || missionData?.intention || 'Mission documentation', startDate: formatDate(new Date()), endDate: formatDate(new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)), missionType: missionData?.missionOriginal?.body?.missionType || missionData?.body?.missionType || missionData?.missionType || 'default', guardians: missionData?.missionOriginal?.body?.guardians || missionData?.body?.guardians || missionData?.guardians || {}, volunteers: missionData?.missionOriginal?.body?.volunteers || missionData?.body?.volunteers || missionData?.volunteers || [], profils: missionData?.missionOriginal?.body?.profils || missionData?.body?.profils || missionData?.profils || [], services: missionData?.missionOriginal?.body?.services || missionData?.body?.services || missionData?.services || [], clientId: (missionData?.missionOriginal?.body?.missionType === 'interne' || missionData?.body?.missionType === 'interne' || missionData?.missionType === 'interne') ? 1 : 2, rocketChatUsernames: [] }, config: { GITEA_API_URL: \"https://gite.slm-lab.net/api/v1\", GITEA_API_TOKEN: \"310645d564cbf752be1fe3b42582a3d5f5d0bddd\", GITEA_OWNER: \"alma\", LEANTIME_API_URL: \"https://agilite.slm-lab.net\", LEANTIME_API_TOKEN: \"lt_lsdShQdoYHaPUWuL07XZR1Rf3GeySsIs_UDlll3VJPk5EwAuILpMC4BwzJ9MZFRrb\", ROCKETCHAT_API_URL: \"https://parole.slm-lab.net/\", ROCKETCHAT_AUTH_TOKEN: \"w91TYgkH-Z67Oz72usYdkW5TZLLRwnre7qyAhp7aHJB\", ROCKETCHAT_USER_ID: \"Tpuww59PJKsrGNQJB\", OUTLINE_API_URL: \"https://chapitre.slm-lab.net/api\", OUTLINE_API_TOKEN: \"ol_api_tlLlANBfcoJ4l7zA8GOcpduAeL6QyBTcYvEnlN\", MISSION_API_URL: \"https://hub.slm-lab.net\", N8N_API_KEY: \"LwgeE1ntADD20OuWC88S3pR0EaO7FtO4\", KEYCLOAK_BASE_URL: \"https://connect.slm-lab.net\", KEYCLOAK_REALM: \"cercle\", KEYCLOAK_CLIENT_ID: \"lab\", KEYCLOAK_CLIENT_SECRET: \"LwgeE1ntADD20OuWC88S3pR0EaO7FtO4\" } }; const guardians = missionData?.missionOriginal?.body?.guardians || missionData?.body?.guardians || missionData?.guardians || {}; if (guardians) { for (const role in guardians) { const user = guardians[role]; if (user) output.missionProcessed.rocketChatUsernames.push(user); } } const volunteers = missionData?.missionOriginal?.body?.volunteers || missionData?.body?.volunteers || missionData?.volunteers || []; if (Array.isArray(volunteers)) { output.missionProcessed.rocketChatUsernames.push(...volunteers); } output.missionProcessed.rocketChatUsernames = [...new Set(output.missionProcessed.rocketChatUsernames)]; console.log('Final processed data:', { name: output.missionProcessed.name, sanitizedName: output.missionProcessed.sanitizedName, rocketChatUsernames: output.missionProcessed.rocketChatUsernames }); return output;"
|
||||||
|
},
|
||||||
|
"name": "Process Mission Data",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
260,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"id": "900e5ca6-b081-4f80-a7c5-ecde88c4ee3d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.GITEA_API_URL + '/user/repos' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Authorization",
|
||||||
|
"value": "={{ 'Bearer ' + $node['Process Mission Data'].json.config.GITEA_API_TOKEN }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.name }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "private",
|
||||||
|
"value": "={{ true }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "auto_init",
|
||||||
|
"value": "={{ true }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"name": "Create Git Repository",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
460,
|
||||||
|
460
|
||||||
|
],
|
||||||
|
"id": "71eea3d3-2a75-4a14-9bc6-c23ca49be59a",
|
||||||
|
"continueOnFail": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.LEANTIME_API_URL + '/api/jsonrpc' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "X-API-Key",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.LEANTIME_API_TOKEN }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"value": "leantime.rpc.Projects.Projects.addProject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jsonrpc",
|
||||||
|
"value": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "params",
|
||||||
|
"value": "={{ { \n \"values\": {\n \"name\": $node[\"Process Mission Data\"].json.missionProcessed.name,\n \"clientId\": $node[\"Process Mission Data\"].json.missionProcessed.clientId,\n \"details\": $node[\"Process Mission Data\"].json.missionProcessed.intention,\n \"type\": \"project\",\n \"start\": $node[\"Process Mission Data\"].json.missionProcessed.startDate,\n \"end\": $node[\"Process Mission Data\"].json.missionProcessed.endDate,\n \"status\": \"open\",\n \"psettings\": \"restricted\"\n }\n} }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"fullResponse": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "Create Leantime Project",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
460,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"id": "0cb15b0b-f718-4455-8e52-6ad8ceb563eb",
|
||||||
|
"continueOnFail": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.OUTLINE_API_URL + '/collections.create' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Authorization",
|
||||||
|
"value": "={{ 'Bearer ' + $node['Process Mission Data'].json.config.OUTLINE_API_TOKEN }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.name }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.description }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"value": "#4f46e5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission",
|
||||||
|
"value": "read"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "private",
|
||||||
|
"value": "={{ true }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"name": "Create Documentation Collection",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
460,
|
||||||
|
760
|
||||||
|
],
|
||||||
|
"id": "ed034321-54b1-4e59-b204-c93619561fec",
|
||||||
|
"continueOnFail": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.KEYCLOAK_BASE_URL + '/realms/' + $node['Process Mission Data'].json.config.KEYCLOAK_REALM + '/protocol/openid-connect/token' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/x-www-form-urlencoded"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "grant_type",
|
||||||
|
"value": "client_credentials"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "client_id",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.KEYCLOAK_CLIENT_ID }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "client_secret",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.KEYCLOAK_CLIENT_SECRET }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scope",
|
||||||
|
"value": "openid profile email"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"bodyContentType": "form-urlencoded",
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"fullResponse": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timeout": 30000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "Get Keycloak Token",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
460,
|
||||||
|
460
|
||||||
|
],
|
||||||
|
"id": "get-keycloak-token",
|
||||||
|
"continueOnFail": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"functionCode": "const input = $input.item.json;\nconsole.log('KEYCLOAK RESPONSE:', JSON.stringify(input, null, 2));\n\n// Extract the access token from the response body\nconst access_token = input.body?.access_token;\nif (!access_token) {\n throw new Error('No access token received from Keycloak');\n}\n\nreturn {\n json: {\n access_token: access_token\n }\n};"
|
||||||
|
},
|
||||||
|
"name": "Process Token",
|
||||||
|
"type": "n8n-nodes-base.function",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
580,
|
||||||
|
460
|
||||||
|
],
|
||||||
|
"id": "process-token"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"functionCode": "// Get all inputs\nconst inputs = $input.item.json;\n\n// Initialize results object\nconst results = {\n gitRepo: null,\n leantimeProject: null,\n docCollection: null,\n rocketChatChannel: null\n};\n\n// Process each input\nif (Array.isArray(inputs)) {\n // First input is gitRepo\n if (inputs[0] && typeof inputs[0] === 'object') {\n results.gitRepo = inputs[0];\n }\n \n // Second input is leantimeProject\n if (inputs[1] && typeof inputs[1] === 'object') {\n // Extract project ID from Leantime response\n const leantimeResponse = inputs[1];\n if (leantimeResponse && leantimeResponse.result) {\n results.leantimeProject = {\n id: leantimeResponse.result,\n name: leantimeResponse.name || ''\n };\n }\n }\n \n // Third input is docCollection\n if (inputs[2] && typeof inputs[2] === 'object') {\n results.docCollection = inputs[2];\n }\n \n // Fourth input is rocketChatChannel\n if (inputs[3] && typeof inputs[3] === 'object') {\n results.rocketChatChannel = inputs[3];\n }\n}\n\n// If we got a single object, it's the gitRepo\nif (!Array.isArray(inputs) && inputs && typeof inputs === 'object') {\n results.gitRepo = inputs;\n}\n\nconsole.log('Input:', JSON.stringify(inputs, null, 2));\nconsole.log('Combined results:', JSON.stringify(results, null, 2));\nreturn results;"
|
||||||
|
},
|
||||||
|
"name": "Combine Results",
|
||||||
|
"type": "n8n-nodes-base.function",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
560,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"id": "combine-results"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.MISSION_API_URL + '/api/missions' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x-api-key",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.N8N_API_KEY }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.name }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "niveau",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.niveau || 'default' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "intention",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.intention }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.description }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gitRepoUrl",
|
||||||
|
"value": "={{ $node['Combine Results'].json.gitRepo?.html_url || '' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leantimeProjectId",
|
||||||
|
"value": "={{ $node['Combine Results'].json.leantimeProject?.id || '' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "documentationCollectionId",
|
||||||
|
"value": "={{ $node['Combine Results'].json.docCollection?.id || '' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rocketchatChannelId",
|
||||||
|
"value": "={{ $node['Combine Results'].json.rocketChatChannel?.channel?._id || '' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "donneurDOrdre",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.donneurDOrdre || 'default' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "projection",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.projection || 'default' }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "missionType",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.missionProcessed.missionType || 'default' }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"fullResponse": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timeout": 30000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "Save Mission To API",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
780,
|
||||||
|
460
|
||||||
|
],
|
||||||
|
"id": "save-mission-to-api"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "// Defensive access to all nodes\nconst missionData = $node['Process Mission Data']?.json?.missionProcessed || {};\nconst integrationResults = $node['Combine Results']?.json || {};\nconst saveMissionResult = $node['Save Mission To API']?.json || {};\n\nconst errors = [];\n\nif (saveMissionResult.error) {\n errors.push(`Failed to save mission: ${saveMissionResult.error.message || 'Unknown error'}`);\n}\nif (!integrationResults.gitRepo?.html_url) {\n errors.push('Git repository creation failed');\n}\nif (!integrationResults.leantimeProject?.id) {\n errors.push('Leantime project creation failed');\n}\nif (!integrationResults.rocketChatChannel?.channel?._id) {\n errors.push('RocketChat channel creation failed');\n}\nif (!integrationResults.docCollection?.id) {\n errors.push('Documentation collection creation failed');\n}\n\nconst output = {\n success: errors.length === 0,\n error: errors.length > 0 ? errors.join('; ') : null,\n errors: errors,\n missionData: missionData,\n integrationResults: integrationResults,\n saveMissionResult: saveMissionResult,\n message: errors.length === 0 ?\n 'Mission integration complete: All systems updated successfully' :\n `Mission integration failed: ${errors.join('; ')}`\n};\n\nconsole.log('Process Results output:', JSON.stringify(output, null, 2));\nreturn output;"
|
||||||
|
},
|
||||||
|
"name": "Process Results",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
860,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"id": "aedea1af-dcfc-4361-bb66-f25dcce10b98"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"respondWith": "json",
|
||||||
|
"responseBody": "={{ $node[\"Process Results\"].json }}",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"name": "Respond To Webhook",
|
||||||
|
"type": "n8n-nodes-base.respondToWebhook",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1060,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"id": "fcecf6cc-52c3-4989-8fad-0cf6e3508601"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"httpMethod": "POST",
|
||||||
|
"path": "mission-created",
|
||||||
|
"options": {
|
||||||
|
"responseData": "lastNodeJson"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "Mission Created Webhook",
|
||||||
|
"type": "n8n-nodes-base.webhook",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
-160,
|
||||||
|
560
|
||||||
|
],
|
||||||
|
"webhookId": "mission-created",
|
||||||
|
"id": "11274a5b-b20f-4180-8611-3690dc9a8722"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_API_URL + '/api/v1/channels.create' }}",
|
||||||
|
"sendHeaders": true,
|
||||||
|
"headerParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "X-Auth-Token",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_AUTH_TOKEN }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "X-User-Id",
|
||||||
|
"value": "={{ $node['Process Mission Data'].json.config.ROCKETCHAT_USER_ID }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.name }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "members",
|
||||||
|
"value": "={{ $node[\"Process Mission Data\"].json.missionProcessed.rocketChatUsernames }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "readOnly",
|
||||||
|
"value": "false"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"name": "Create RocketChat Channel",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
460,
|
||||||
|
660
|
||||||
|
],
|
||||||
|
"id": "90b1482e-6455-4c75-a7ae-297393c7aa63",
|
||||||
|
"continueOnFail": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pinData": {},
|
||||||
|
"connections": {
|
||||||
|
"Mission Created Webhook": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Process Mission Data",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Process Mission Data": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Keycloak Token",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Get Keycloak Token": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Process Token",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Process Token": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Create Git Repository",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Create Leantime Project",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Create Documentation Collection",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Create RocketChat Channel",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Create Git Repository": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Combine Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Create Leantime Project": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Combine Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Create Documentation Collection": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Combine Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Create RocketChat Channel": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Combine Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Combine Results": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Save Mission To API",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Save Mission To API": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Process Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Process Results": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Respond To Webhook",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": false,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"versionId": "45981b34-113c-428c-85fd-fdc5e22afce4",
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true,
|
||||||
|
"instanceId": "575d8de48bd511243817deebddae0cc97d73be64c6c4737e5d4e9caddec881d8"
|
||||||
|
},
|
||||||
|
"id": "Mxg5cbQzEUgTEFNd",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
@ -9,6 +9,17 @@ import { N8nService } from '@/lib/services/n8n-service';
|
|||||||
|
|
||||||
// Helper function to check authentication
|
// Helper function to check authentication
|
||||||
async function checkAuth(request: Request) {
|
async function checkAuth(request: Request) {
|
||||||
|
// Check for service account API key first
|
||||||
|
const apiKey = request.headers.get('x-api-key');
|
||||||
|
console.log('API key from header:', apiKey);
|
||||||
|
console.log('API key from env:', process.env.N8N_API_KEY);
|
||||||
|
console.log('Keys match:', apiKey === process.env.N8N_API_KEY);
|
||||||
|
if (apiKey === process.env.N8N_API_KEY) {
|
||||||
|
// For service account, use a default system user ID
|
||||||
|
return { authorized: true, userId: process.env.SYSTEM_USER_ID || 'system' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to NextAuth session for regular users
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
if (!session?.user?.id) {
|
if (!session?.user?.id) {
|
||||||
console.error('Unauthorized access attempt:', {
|
console.error('Unauthorized access attempt:', {
|
||||||
@ -217,17 +228,31 @@ export async function POST(request: Request) {
|
|||||||
creatorId: userId
|
creatorId: userId
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update mission with integration results
|
// Update mission with integration results, even if some failed
|
||||||
if (workflowResult.results) {
|
if (workflowResult.results) {
|
||||||
await prisma.mission.update({
|
const updateData: any = {};
|
||||||
where: { id: mission.id },
|
|
||||||
data: {
|
// Only update fields that were successfully created
|
||||||
giteaRepositoryUrl: workflowResult.results.gitRepo?.html_url,
|
if (workflowResult.results.gitRepo?.html_url) {
|
||||||
leantimeProjectId: workflowResult.results.leantimeProject?.result?.toString(),
|
updateData.giteaRepositoryUrl = workflowResult.results.gitRepo.html_url;
|
||||||
rocketChatChannelId: workflowResult.results.rocketChatChannel?.channel?._id,
|
}
|
||||||
outlineCollectionId: workflowResult.results.docCollection?.id
|
if (workflowResult.results.leantimeProject?.result) {
|
||||||
}
|
updateData.leantimeProjectId = workflowResult.results.leantimeProject.result.toString();
|
||||||
});
|
}
|
||||||
|
if (workflowResult.results.rocketChatChannel?.channel?._id) {
|
||||||
|
updateData.rocketChatChannelId = workflowResult.results.rocketChatChannel.channel._id;
|
||||||
|
}
|
||||||
|
if (workflowResult.results.docCollection?.id) {
|
||||||
|
updateData.outlineCollectionId = workflowResult.results.docCollection.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update if we have any successful integrations
|
||||||
|
if (Object.keys(updateData).length > 0) {
|
||||||
|
await prisma.mission.update({
|
||||||
|
where: { id: mission.id },
|
||||||
|
data: updateData
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
@ -238,12 +263,13 @@ export async function POST(request: Request) {
|
|||||||
createdAt: mission.createdAt
|
createdAt: mission.createdAt
|
||||||
},
|
},
|
||||||
workflow: {
|
workflow: {
|
||||||
status: 'success',
|
status: workflowResult.success ? 'success' : 'partial_success',
|
||||||
data: workflowResult
|
data: workflowResult,
|
||||||
|
errors: workflowResult.errors || []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (workflowError) {
|
} catch (workflowError) {
|
||||||
// If workflow fails, delete the mission and report failure
|
// If workflow fails completely, delete the mission and report failure
|
||||||
console.error('Workflow error:', workflowError);
|
console.error('Workflow error:', workflowError);
|
||||||
await prisma.mission.delete({ where: { id: mission.id } });
|
await prisma.mission.delete({ where: { id: mission.id } });
|
||||||
|
|
||||||
|
|||||||
@ -410,13 +410,12 @@ export function MissionsAdminPanel() {
|
|||||||
body: JSON.stringify(missionSubmitData),
|
body: JSON.stringify(missionSubmitData),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorData = await response.json();
|
|
||||||
throw new Error(errorData.error || 'Failed to create mission');
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(data.error || data.message || 'Failed to create mission');
|
||||||
|
}
|
||||||
|
|
||||||
// Check workflow status
|
// Check workflow status
|
||||||
if (data.workflow?.status === 'success') {
|
if (data.workflow?.status === 'success') {
|
||||||
toast({
|
toast({
|
||||||
@ -427,7 +426,7 @@ export function MissionsAdminPanel() {
|
|||||||
// Redirect to missions list
|
// Redirect to missions list
|
||||||
router.push('/missions');
|
router.push('/missions');
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.workflow?.data?.message || 'Workflow execution failed');
|
throw new Error(data.workflow?.data?.message || data.error || 'Workflow execution failed');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating mission:', error);
|
console.error('Error creating mission:', error);
|
||||||
|
|||||||
@ -27,8 +27,13 @@ export class N8nService {
|
|||||||
|
|
||||||
console.log('n8n workflow response:', response.data);
|
console.log('n8n workflow response:', response.data);
|
||||||
|
|
||||||
|
if (response.data.errors && response.data.errors.length > 0) {
|
||||||
|
console.warn('Workflow completed with partial success:', response.data.errors);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
if (!response.data.success) {
|
if (!response.data.success) {
|
||||||
throw new Error(`Workflow execution failed: ${response.data.message}`);
|
throw new Error(`Workflow execution failed: ${response.data.message || 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
@ -37,4 +42,4 @@ export class N8nService {
|
|||||||
throw new Error(`Failed to trigger mission creation workflow: ${error instanceof Error ? error.message : String(error)}`);
|
throw new Error(`Failed to trigger mission creation workflow: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user