network/gaiia/sync_all_radius_groups_workflow.json
2026-07-19 14:42:02 -05:00

154 lines
6.2 KiB
JSON

{
"name": "Sync All RADIUS Groups",
"description": "MANUAL: Syncs RADIUS usergroups for ALL accounts (2 pages x 250 = 500 accounts). Passes actual account status through — ACTIVE, SUSPENDED, INACTIVE, etc.",
"trigger": {
"type": "MANUAL",
"nextSteps": [{ "slug": "fetch-page-1" }]
},
"steps": [
{
"name": "Fetch accounts page 1",
"slug": "fetch-page-1",
"type": "GAIIA_API_GATEWAY_V1_GRAPHQL_REQUEST",
"nodeSlug": "gaiia-public-api-gateway-graphql-request",
"allowSkipExecution": false,
"outputMapper": "({ output }) => {\n const data = output.response.accounts;\n return {\n accounts: data.nodes.map((a) => ({\n accountId: a.id,\n status: (a.status?.name || '').toUpperCase(),\n products: (a.billingSubscriptions?.nodes || [])\n .map((s) => s.productVersion?.product?.id)\n .filter(Boolean)\n .filter((id, i, arr) => arr.indexOf(id) === i)\n })),\n hasNextPage: data.pageInfo.hasNextPage,\n endCursor: data.pageInfo.endCursor\n };\n}",
"inputs": [
{
"key": "query",
"type": "LITERAL",
"value": "string:query {\n accounts(first: 250) {\n nodes {\n id\n status { name }\n billingSubscriptions {\n nodes { productVersion { product { id } } }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n}"
},
{
"key": "variables",
"type": "FUNCTION",
"value": "({ secrets, state, utils, variables }) => ({})"
}
],
"nextSteps": [{ "slug": "sync-page-1" }]
},
{
"name": "Sync page 1",
"slug": "sync-page-1",
"type": "PARALLEL_LOOP",
"nodeSlug": "parallel-loop",
"maxConcurrentIterations": 10,
"inputs": [
{
"key": "iterable",
"type": "FUNCTION",
"value": "({ state }) => state.steps['fetch-page-1'].output.accounts"
}
],
"initialSteps": [{ "slug": "call-update-page1" }],
"nextSteps": [{ "slug": "need-page-2" }]
},
{
"name": "Call Update RADIUS Account Groups",
"slug": "call-update-page1",
"type": "GAIIA_START_WORKFLOW_EXECUTION",
"nodeSlug": "start-workflow-execution",
"parentParallelLoopSlug": "sync-page-1",
"allowSkipExecution": false,
"inputs": [
{
"key": "workflowId",
"type": "LITERAL",
"value": "string:workflow_fLXTNCvridPqwEEXxf3CK1"
},
{
"key": "input",
"type": "FUNCTION",
"value": "({ state }) => {\n const acct = state.currentParallelLoopIterations['sync-page-1'];\n return { accountId: acct.accountId, status: acct.status, productIds: acct.products };\n}"
},
{
"key": "fireAndForget",
"type": "LITERAL",
"value": "boolean:true"
}
],
"nextSteps": [{ "slug": "sync-page-1-end" }]
},
{
"name": "Need page 2?",
"slug": "need-page-2",
"type": "CONDITION",
"nodeSlug": "condition",
"condition": "({ secrets, state, utils, variables }) => {\n return state.steps['fetch-page-1'].output.hasNextPage;\n}",
"elseSteps": [{ "slug": "end" }],
"thenSteps": [{ "slug": "fetch-page-2" }]
},
{
"name": "Fetch accounts page 2",
"slug": "fetch-page-2",
"type": "GAIIA_API_GATEWAY_V1_GRAPHQL_REQUEST",
"nodeSlug": "gaiia-public-api-gateway-graphql-request",
"allowSkipExecution": false,
"outputMapper": "({ output }) => {\n const nodes = output.response.accounts.nodes;\n if (!nodes || nodes.length === 0) return [];\n return nodes.map((a) => ({\n accountId: a.id,\n status: (a.status?.name || '').toUpperCase(),\n products: (a.billingSubscriptions?.nodes || [])\n .map((s) => s.productVersion?.product?.id)\n .filter(Boolean)\n .filter((id, i, arr) => arr.indexOf(id) === i)\n }));\n}",
"inputs": [
{
"key": "query",
"type": "LITERAL",
"value": "string:query($after: String) {\n accounts(first: 250, after: $after) {\n nodes {\n id\n status { name }\n billingSubscriptions {\n nodes { productVersion { product { id } } }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n}"
},
{
"key": "variables",
"type": "FUNCTION",
"value": "({ state }) => {\n const p1 = state.steps['fetch-page-1'].output;\n return p1.hasNextPage ? { after: p1.endCursor } : {};\n}"
}
],
"nextSteps": [{ "slug": "if-page-2-has-data" }]
},
{
"name": "Page 2 has data?",
"slug": "if-page-2-has-data",
"type": "CONDITION",
"nodeSlug": "condition",
"condition": "({ secrets, state, utils, variables }) => {\n const data = state.steps['fetch-page-2'].output;\n return Array.isArray(data) && data.length > 0;\n}",
"elseSteps": [{ "slug": "end" }],
"thenSteps": [{ "slug": "sync-page-2" }]
},
{
"name": "Sync page 2",
"slug": "sync-page-2",
"type": "PARALLEL_LOOP",
"nodeSlug": "parallel-loop",
"maxConcurrentIterations": 10,
"inputs": [
{
"key": "iterable",
"type": "FUNCTION",
"value": "({ state }) => state.steps['fetch-page-2'].output"
}
],
"initialSteps": [{ "slug": "call-update-page2" }],
"nextSteps": [{ "slug": "end" }]
},
{
"name": "Call Update RADIUS Account Groups (page 2)",
"slug": "call-update-page2",
"type": "GAIIA_START_WORKFLOW_EXECUTION",
"nodeSlug": "start-workflow-execution",
"parentParallelLoopSlug": "sync-page-2",
"allowSkipExecution": false,
"inputs": [
{
"key": "workflowId",
"type": "LITERAL",
"value": "string:workflow_fLXTNCvridPqwEEXxf3CK1"
},
{
"key": "input",
"type": "FUNCTION",
"value": "({ state }) => {\n const acct = state.currentParallelLoopIterations['sync-page-2'];\n return { accountId: acct.accountId, status: acct.status, productIds: acct.products };\n}"
},
{
"key": "fireAndForget",
"type": "LITERAL",
"value": "boolean:true"
}
],
"nextSteps": [{ "slug": "sync-page-2-end" }]
}
]
}