UNPKG

@kaia-team/n8n-nodes-kaia

Version:

n8n node to interact with Kaia API for signal capture and security gating

178 lines (177 loc) 7.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SecurityGate = void 0; const n8n_workflow_1 = require("n8n-workflow"); class SecurityGate { constructor() { this.description = { displayName: 'KAIA Security Gate', name: 'securityGate', icon: 'file:kaia.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["entityId"]}}', description: 'Check entity context and block workflow if conditions are not met', defaults: { name: 'KAIA Security Gate', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'kaiaApi', required: true, }, ], properties: [ { displayName: 'Entity ID', name: 'entityId', type: 'string', default: '', required: true, description: 'Entity identifier to check in the knowledge graph', placeholder: 'user-123', }, { displayName: 'Condition', name: 'condition', type: 'collection', placeholder: 'Add Condition', default: {}, description: 'Optional condition to evaluate. If not provided, gate will check if entity exists.', options: [ { displayName: 'Relation', name: 'relation', type: 'string', default: '', required: true, description: 'Relation name to check (e.g., "status", "role", "permission")', placeholder: 'status', }, { displayName: 'Operator', name: 'operator', type: 'options', options: [ { name: 'Equals', value: '==', description: 'Check if relation equals value (proceed if true, block if false)', }, { name: 'Not Equals', value: '!=', description: 'Check if relation does not equal value (block if true, proceed if false)', }, { name: 'Exists', value: 'exists', description: 'Check if relation exists (proceed if exists, block if not)', }, { name: 'Not Exists', value: 'not_exists', description: 'Check if relation does not exist (block if exists, proceed if not)', }, ], default: 'exists', required: true, description: 'Comparison operator', }, { displayName: 'Value', name: 'value', type: 'string', default: '', required: false, description: 'Value to compare against (required for == and != operators)', displayOptions: { show: { operator: ['==', '!='], }, }, }, ], }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { // Get credentials const credentials = await this.getCredentials('kaiaApi'); const baseUrl = credentials?.baseUrl || ''; const token = credentials?.token || ''; if (!baseUrl || !token) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Kaia API credentials are required'); } // Get parameters const entityId = this.getNodeParameter('entityId', i); const condition = this.getNodeParameter('condition', i); if (!entityId) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Entity ID is required'); } // Build request body const body = { entity_id: entityId, }; // Add condition if provided if (condition.relation && condition.operator) { const conditionObj = { relation: condition.relation, operator: condition.operator, }; // Add value for == and != operators if ((condition.operator === '==' || condition.operator === '!=') && condition.value) { conditionObj.value = condition.value; } body.condition = conditionObj; } // Make API request const requestUrl = `${baseUrl}/api/kaia/context/gate`; const options = { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, method: 'POST', body, url: requestUrl, json: true, }; const response = await this.helpers.httpRequest(options); // Check decision if (response.decision === 'block') { const reason = response.reason || 'Entity context check failed'; const confidence = response.confidence || 0; throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Security Gate blocked: ${reason} (confidence: ${confidence})`, { description: 'The workflow execution was blocked by the Security Gate node based on entity context evaluation.', itemIndex: i, }); } // Decision is "proceed" - continue with output returnData.push(response); } catch (error) { // If it's a NodeOperationError (block decision), re-throw it if (error instanceof n8n_workflow_1.NodeOperationError) { throw error; } // For other errors, handle based on continueOnFail setting if (this.continueOnFail()) { const errorMessage = error instanceof Error ? error.message : String(error); returnData.push({ error: errorMessage }); continue; } throw error; } } return [this.helpers.returnJsonArray(returnData)]; } } exports.SecurityGate = SecurityGate;