UNPKG

@panoptic-it-solutions/n8n-nodes-datto-rmm

Version:

n8n node for Datto RMM integration

648 lines 33 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.executeActivityLogOperation = executeActivityLogOperation; const n8n_workflow_1 = require("n8n-workflow"); async function executeActivityLogOperation() { const items = this.getInputData(); const returnData = []; const operation = this.getNodeParameter('operation', 0); const { dattoRmmApiRequest, dattoRmmApiRequestAllItems } = await Promise.resolve().then(() => __importStar(require('../../helpers/api.helper'))); for (let i = 0; i < items.length; i++) { try { let responseData; switch (operation) { case 'getAll': responseData = await handleGetAllDeviceStatus.call(this, i); break; case 'search': responseData = await handleSearchDeviceEvents.call(this, i); break; case 'getByDevice': responseData = await handleGetDeviceActivity.call(this, i); break; case 'getBySite': responseData = await handleGetSiteActivity.call(this, i); break; case 'getByUser': responseData = await handleGetUserActivity.call(this, i); break; default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not supported for Activity monitoring!`, { itemIndex: i }); } if (Array.isArray(responseData)) { returnData.push(...responseData.map((item) => ({ json: item }))); } else { returnData.push({ json: responseData }); } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message }, error, }); continue; } throw error; } } return [returnData]; } async function handleGetAllDeviceStatus(itemIndex) { const { dattoRmmApiRequest, dattoRmmApiRequestAllItems } = await Promise.resolve().then(() => __importStar(require('../../helpers/api.helper'))); const returnAll = this.getNodeParameter('returnAll', itemIndex, false); const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}); const options = this.getNodeParameter('options', itemIndex, {}); try { let devices = await dattoRmmApiRequestAllItems.call(this, 'GET', '/api/v2/account/devices'); if (additionalFields.siteId) { devices = devices.filter((device) => device.siteUid === additionalFields.siteId); } if (additionalFields.deviceId) { devices = devices.filter((device) => device.uid === additionalFields.deviceId); } let alerts = []; try { const openAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', '/api/v2/account/alerts/open'); alerts = [...alerts, ...openAlerts]; const resolvedAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', '/api/v2/account/alerts/resolved'); alerts = [...alerts, ...resolvedAlerts]; } catch (error) { console.warn('Could not fetch alerts:', error.message); } const deviceActivitiesPromises = devices.map(async (device) => { const deviceActivities = []; try { const queryParams = {}; if (additionalFields.dateFrom || additionalFields.dateTo) { queryParams.includeArchived = true; if (additionalFields.dateFrom) { queryParams.startDate = new Date(additionalFields.dateFrom) .toISOString() .split('T')[0]; } if (additionalFields.dateTo) { queryParams.endDate = new Date(additionalFields.dateTo) .toISOString() .split('T')[0]; } } const auditData = await dattoRmmApiRequest.call(this, 'GET', `/api/v2/audit/device/${device.uid}`, {}, queryParams); if (auditData && auditData.changeLog && Array.isArray(auditData.changeLog)) { auditData.changeLog.forEach((change) => { const changeDesc = change.description || change.item || 'Hardware/Software modification'; const changeType = change.changeType || 'System Change'; let activityType = 'audit_change'; let severity = 'low'; let priority = 'low'; let message = `Audit Change: ${changeType} - ${changeDesc}`; const loginIndicators = [ /user.*log(in|on|ged)/i, /session.*start/i, /authentication.*success/i, /rdp.*connect/i, /terminal.*service.*connect/i, /event.*4624/i, /interactive.*logon/i, ]; const logoutIndicators = [ /user.*log(out|off)/i, /session.*(end|terminat|close)/i, /rdp.*disconnect/i, /terminal.*service.*disconnect/i, /event.*4634/i, /event.*4647/i, /interactive.*logoff/i, ]; if (loginIndicators.some((pattern) => pattern.test(changeDesc) || pattern.test(changeType))) { activityType = 'user_login'; severity = 'low'; priority = 'low'; message = `User Login Detected: ${changeDesc}`; } else if (logoutIndicators.some((pattern) => pattern.test(changeDesc) || pattern.test(changeType))) { activityType = 'user_logout'; severity = 'low'; priority = 'low'; message = `User Logout Detected: ${changeDesc}`; } else if (/user.*account|account.*user/i.test(changeDesc) || /user.*creat|user.*delet|user.*modif/i.test(changeDesc)) { activityType = 'user_account_change'; severity = 'medium'; priority = 'medium'; message = `User Account Activity: ${changeDesc}`; } deviceActivities.push({ id: `audit-${device.uid}-${change.id || Math.random()}`, activityTime: change.changeDate || change.auditDate || new Date().toISOString(), activityType: activityType, deviceName: device.hostname || device.displayName, deviceId: device.uid, siteName: device.siteName, siteId: device.siteUid, message: message, severity: severity, status: 'completed', activityResult: 'success', priority: priority, data: { changeType: change.changeType, item: change.item, description: change.description, auditDate: change.auditDate, changeDate: change.changeDate, deviceType: device.deviceType, operatingSystem: device.operatingSystem, originalMessage: `${changeType} - ${changeDesc}`, }, }); }); } } catch (auditError) { console.warn(`Could not fetch audit data for device ${device.uid}:`, auditError.message); } deviceActivities.push({ id: `${device.uid}-status`, activityTime: device.lastSeen || new Date().toISOString(), activityType: 'device_status', deviceName: device.hostname || device.displayName, deviceId: device.uid, siteName: device.siteName, siteId: device.siteUid, message: `Device ${device.hostname || device.displayName} - Status: ${device.online ? 'Online' : 'Offline'}`, severity: device.online ? 'low' : 'high', status: device.online ? 'online' : 'offline', activityResult: device.online ? 'success' : 'pending', priority: device.online ? 'low' : 'high', data: { deviceType: device.deviceType, operatingSystem: device.operatingSystem, lastSeen: device.lastSeen, ipAddress: device.intIpAddress, extIpAddress: device.extIpAddress, domain: device.domain, workgroup: device.workgroup, }, }); return deviceActivities; }); const allDeviceActivities = await Promise.all(deviceActivitiesPromises); let deviceActivities = allDeviceActivities.flat(); alerts.forEach((alert) => { const alertMessage = alert.alertMessage || alert.message || 'Alert activity'; const diagnostics = alert.diagnostics || ''; const alertType = alert.alertType || ''; let activityType = 'alert'; let enhancedMessage = alertMessage; const loginPatterns = [ /login|logon|sign.?in|authentication.*success|logged.?in/i, /user.*(start|begin|connect)/i, /session.*(start|creat|establish)/i, /event.?4624|successful.*logon/i, /rdp.*(connect|login|establish)/i, /terminal.?services.*(login|connect)/i, /interactive.*logon/i, ]; const logoutPatterns = [ /logout|logoff|sign.?out|disconnect.*user/i, /user.*(end|terminat|close.*session)/i, /session.*(end|terminat|close|expire)/i, /event.?4634|event.?4647|user.*logoff/i, /rdp.*(disconnect|close)/i, /terminal.?services.*(disconnect|close)/i, /interactive.*logoff/i, ]; const failedLoginPatterns = [ /login.*fail|logon.*fail|authentication.*fail/i, /event.?4625|failed.*logon/i, /invalid.*credential|incorrect.*password/i, /access.*denied.*login/i, /authentication.*error/i, ]; if (loginPatterns.some((pattern) => pattern.test(alertMessage) || pattern.test(diagnostics) || pattern.test(alertType))) { activityType = 'user_login'; enhancedMessage = `User Login Activity: ${alertMessage}`; } else if (logoutPatterns.some((pattern) => pattern.test(alertMessage) || pattern.test(diagnostics) || pattern.test(alertType))) { activityType = 'user_logout'; enhancedMessage = `User Logout Activity: ${alertMessage}`; } else if (failedLoginPatterns.some((pattern) => pattern.test(alertMessage) || pattern.test(diagnostics) || pattern.test(alertType))) { activityType = 'failed_login'; enhancedMessage = `Failed Login Attempt: ${alertMessage}`; } else if (/device.*(online|connect|available)/i.test(alertMessage) || /network.*connect/i.test(alertMessage)) { activityType = 'device_online'; enhancedMessage = `Device Online: ${alertMessage}`; } else if (/device.*(offline|disconnect|unavailable)/i.test(alertMessage) || /network.*disconnect/i.test(alertMessage)) { activityType = 'device_offline'; enhancedMessage = `Device Offline: ${alertMessage}`; } deviceActivities.push({ id: alert.alertUid || `alert-${Math.random()}`, activityTime: alert.alertSourceTime || alert.alertDate || alert.created || new Date().toISOString(), activityType: activityType, deviceName: alert.deviceName, deviceId: alert.deviceUid, siteName: alert.siteName, siteId: alert.siteUid, message: enhancedMessage, severity: (alert.priority || 'medium').toLowerCase(), status: alert.alertStatus || 'active', activityResult: alert.alertStatus === 'resolved' ? 'success' : 'pending', priority: (alert.priority || 'medium').toLowerCase(), data: { alertType: alert.alertType, alertCategory: alert.alertCategory, diagnostics: alert.diagnostics, resolution: alert.resolution, ticketNumber: alert.ticketNumber, muted: alert.muted, created: alert.created, resolved: alert.resolved, originalMessage: alertMessage, }, }); }); let filteredActivities = deviceActivities; if (additionalFields.dateFrom) { const fromDate = new Date(additionalFields.dateFrom); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) >= fromDate); } if (additionalFields.dateTo) { const toDate = new Date(additionalFields.dateTo); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) <= toDate); } if (additionalFields.severity) { filteredActivities = filteredActivities.filter((activity) => activity.severity === additionalFields.severity); } if (additionalFields.activityType && Array.isArray(additionalFields.activityType)) { filteredActivities = filteredActivities.filter((activity) => additionalFields.activityType.includes(activity.activityType)); } const sortBy = options.sortBy || 'activityTime'; const sortOrder = options.sortOrder || 'desc'; filteredActivities.sort((a, b) => { let aValue = a[sortBy]; let bValue = b[sortBy]; if (sortBy === 'activityTime') { aValue = new Date(aValue || 0).getTime(); bValue = new Date(bValue || 0).getTime(); } if (sortOrder === 'desc') { return bValue - aValue; } else { return aValue - bValue; } }); if (!returnAll) { const limit = this.getNodeParameter('limit', itemIndex, 100); filteredActivities = filteredActivities.slice(0, limit); } return filteredActivities; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to get device status information: ${error.message}`, { itemIndex }); } } async function handleSearchDeviceEvents(itemIndex) { const { dattoRmmApiRequest, dattoRmmApiRequestAllItems } = await Promise.resolve().then(() => __importStar(require('../../helpers/api.helper'))); const searchQuery = this.getNodeParameter('searchQuery', itemIndex); const returnAll = this.getNodeParameter('returnAll', itemIndex, false); const searchOptions = this.getNodeParameter('searchOptions', itemIndex, {}); try { const openAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', '/api/v2/account/alerts/open'); const resolvedAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', '/api/v2/account/alerts/resolved'); const allAlerts = [...openAlerts, ...resolvedAlerts]; const caseSensitive = searchOptions.caseSensitive || false; const searchRegex = new RegExp(searchQuery, caseSensitive ? 'g' : 'gi'); const loginPatterns = [ /login|logon|sign.?in|authentication|logged.?in/gi, /user.*(start|begin|initiat)/gi, /session.*(start|creat|establish)/gi, /event.?id.?4624/gi, /event.?id.?4625/gi, /rdp.*(connect|login)/gi, /terminal.?services.*(login|connect)/gi, ]; const logoutPatterns = [ /logout|logoff|sign.?out|disconnect/gi, /user.*(end|terminat|close)/gi, /session.*(end|terminat|close|expire)/gi, /event.?id.?4634/gi, /event.?id.?4647/gi, /rdp.*(disconnect|close)/gi, /terminal.?services.*(disconnect|close)/gi, ]; let matchingAlerts = allAlerts.filter((alert) => { const message = alert.alertMessage || ''; const deviceName = alert.deviceName || ''; const siteName = alert.siteName || ''; const alertType = alert.alertType || ''; const diagnostics = alert.diagnostics || ''; const basicMatch = searchRegex.test(message) || searchRegex.test(deviceName) || searchRegex.test(siteName) || searchRegex.test(alertType) || searchRegex.test(diagnostics); const searchForLogins = /login|logon|sign|session|user|auth/gi.test(searchQuery); let loginMatch = false; if (searchForLogins) { loginMatch = loginPatterns.some((pattern) => pattern.test(message) || pattern.test(diagnostics) || pattern.test(alertType)) || logoutPatterns.some((pattern) => pattern.test(message) || pattern.test(diagnostics) || pattern.test(alertType)); } return basicMatch || loginMatch; }); if (searchOptions.dateFrom) { const fromDate = new Date(searchOptions.dateFrom); matchingAlerts = matchingAlerts.filter((alert) => new Date(alert.alertSourceTime || alert.alertDate) >= fromDate); } if (searchOptions.dateTo) { const toDate = new Date(searchOptions.dateTo); matchingAlerts = matchingAlerts.filter((alert) => new Date(alert.alertSourceTime || alert.alertDate) <= toDate); } const searchResults = matchingAlerts.map((alert) => { var _a, _b; return ({ id: alert.alertUid, activityTime: alert.alertSourceTime || alert.alertDate, activityType: 'alert', deviceName: alert.deviceName, deviceId: alert.deviceUid, siteName: alert.siteName, siteId: alert.siteUid, message: alert.alertMessage, severity: ((_a = alert.priority) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'medium', status: alert.alertStatus || 'active', activityResult: alert.alertStatus === 'resolved' ? 'success' : 'pending', priority: ((_b = alert.priority) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || 'medium', alertType: alert.alertType, alertCategory: alert.alertCategory, diagnostics: alert.diagnostics, resolution: alert.resolution, ticketNumber: alert.ticketNumber, muted: alert.muted, }); }); if (!returnAll) { const limit = this.getNodeParameter('limit', itemIndex, 100); return searchResults.slice(0, limit); } return searchResults; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to search device events: ${error.message}`, { itemIndex }); } } async function handleGetDeviceActivity(itemIndex) { const { dattoRmmApiRequest, dattoRmmApiRequestAllItems } = await Promise.resolve().then(() => __importStar(require('../../helpers/api.helper'))); const deviceUid = this.getNodeParameter('deviceUid', itemIndex); const deviceOptions = this.getNodeParameter('deviceOptions', itemIndex, {}); try { const device = await dattoRmmApiRequest.call(this, 'GET', `/api/v2/device/${deviceUid}`); const auditData = await dattoRmmApiRequest.call(this, 'GET', `/api/v2/audit/device/${deviceUid}`); const deviceAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', `/api/v2/device/${deviceUid}/alerts/open`); const resolvedAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', `/api/v2/device/${deviceUid}/alerts/resolved`); const activities = []; activities.push({ id: `${deviceUid}-status`, activityTime: device.lastSeen || new Date().toISOString(), activityType: 'device_status', deviceName: device.hostname || device.displayName, deviceId: deviceUid, siteName: device.siteName, siteId: device.siteUid, message: `Device ${device.hostname || device.displayName} is ${device.online ? 'online' : 'offline'}`, severity: device.online ? 'low' : 'high', status: device.online ? 'online' : 'offline', activityResult: 'success', priority: device.online ? 'low' : 'high', data: { deviceType: device.deviceType, operatingSystem: device.operatingSystem, lastSeen: device.lastSeen, ipAddress: device.intIpAddress, }, }); if (auditData && auditData.changeLog) { auditData.changeLog.forEach((change) => { activities.push({ id: `audit-${change.id || Math.random()}`, activityTime: change.changeDate || change.auditDate, activityType: 'audit_change', deviceName: device.hostname || device.displayName, deviceId: deviceUid, siteName: device.siteName, siteId: device.siteUid, message: `Audit change: ${change.changeType} - ${change.description || change.item}`, severity: 'low', status: 'completed', activityResult: 'success', priority: 'low', data: change, }); }); } [...deviceAlerts, ...resolvedAlerts].forEach((alert) => { var _a, _b; activities.push({ id: alert.alertUid, activityTime: alert.alertSourceTime || alert.alertDate, activityType: 'alert', deviceName: device.hostname || device.displayName, deviceId: deviceUid, siteName: device.siteName, siteId: device.siteUid, message: alert.alertMessage, severity: ((_a = alert.priority) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'medium', status: alert.alertStatus || 'active', activityResult: alert.alertStatus === 'resolved' ? 'success' : 'pending', priority: ((_b = alert.priority) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || 'medium', data: { alertType: alert.alertType, alertCategory: alert.alertCategory, diagnostics: alert.diagnostics, resolution: alert.resolution, ticketNumber: alert.ticketNumber, muted: alert.muted, }, }); }); let filteredActivities = activities; if (deviceOptions.dateFrom) { const fromDate = new Date(deviceOptions.dateFrom); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) >= fromDate); } if (deviceOptions.dateTo) { const toDate = new Date(deviceOptions.dateTo); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) <= toDate); } if (deviceOptions.activityType && Array.isArray(deviceOptions.activityType)) { filteredActivities = filteredActivities.filter((activity) => deviceOptions.activityType.includes(activity.activityType)); } filteredActivities.sort((a, b) => new Date(b.activityTime).getTime() - new Date(a.activityTime).getTime()); const returnAll = deviceOptions.returnAll; if (!returnAll) { const limit = deviceOptions.limit || 100; filteredActivities = filteredActivities.slice(0, limit); } return filteredActivities; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to get device activity: ${error.message}`, { itemIndex }); } } async function handleGetSiteActivity(itemIndex) { const { dattoRmmApiRequest, dattoRmmApiRequestAllItems } = await Promise.resolve().then(() => __importStar(require('../../helpers/api.helper'))); const siteUid = this.getNodeParameter('siteUid', itemIndex); const siteOptions = this.getNodeParameter('siteOptions', itemIndex, {}); try { const site = await dattoRmmApiRequest.call(this, 'GET', `/api/v2/site/${siteUid}`); const siteDevices = await dattoRmmApiRequestAllItems.call(this, 'GET', `/api/v2/site/${siteUid}/devices`); const siteAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', `/api/v2/site/${siteUid}/alerts/open`); const resolvedSiteAlerts = await dattoRmmApiRequestAllItems.call(this, 'GET', `/api/v2/site/${siteUid}/alerts/resolved`); const activities = []; if (siteOptions.includeDevices !== false) { siteDevices.forEach((device) => { activities.push({ id: `${device.uid}-status`, activityTime: device.lastSeen || new Date().toISOString(), activityType: 'device_status', deviceName: device.hostname || device.displayName, deviceId: device.uid, siteName: site.name, siteId: siteUid, message: `Device ${device.hostname || device.displayName} is ${device.online ? 'online' : 'offline'}`, severity: device.online ? 'low' : 'high', status: device.online ? 'online' : 'offline', activityResult: 'success', priority: device.online ? 'low' : 'high', data: { deviceType: device.deviceType, operatingSystem: device.operatingSystem, lastSeen: device.lastSeen, ipAddress: device.intIpAddress, }, }); }); } [...siteAlerts, ...resolvedSiteAlerts].forEach((alert) => { var _a, _b; activities.push({ id: alert.alertUid, activityTime: alert.alertSourceTime || alert.alertDate, activityType: 'alert', deviceName: alert.deviceName, deviceId: alert.deviceUid, siteName: site.name, siteId: siteUid, message: alert.alertMessage, severity: ((_a = alert.priority) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'medium', status: alert.alertStatus || 'active', activityResult: alert.alertStatus === 'resolved' ? 'success' : 'pending', priority: ((_b = alert.priority) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || 'medium', data: { alertType: alert.alertType, alertCategory: alert.alertCategory, diagnostics: alert.diagnostics, resolution: alert.resolution, ticketNumber: alert.ticketNumber, muted: alert.muted, }, }); }); let filteredActivities = activities; if (siteOptions.dateFrom) { const fromDate = new Date(siteOptions.dateFrom); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) >= fromDate); } if (siteOptions.dateTo) { const toDate = new Date(siteOptions.dateTo); filteredActivities = filteredActivities.filter((activity) => new Date(activity.activityTime) <= toDate); } if (siteOptions.activityType && Array.isArray(siteOptions.activityType)) { filteredActivities = filteredActivities.filter((activity) => siteOptions.activityType.includes(activity.activityType)); } filteredActivities.sort((a, b) => new Date(b.activityTime).getTime() - new Date(a.activityTime).getTime()); const returnAll = siteOptions.returnAll; if (!returnAll) { const limit = siteOptions.limit || 100; filteredActivities = filteredActivities.slice(0, limit); } return filteredActivities; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to get site activity: ${error.message}`, { itemIndex, }); } } async function handleGetUserActivity(itemIndex) { const userId = this.getNodeParameter('userId', itemIndex); const userOptions = this.getNodeParameter('userOptions', itemIndex, {}); const userActivities = [ { id: `user-${userId}-note`, activityTime: new Date().toISOString(), activityType: 'info', userId: userId, message: 'User activity monitoring is limited in Datto RMM API. Consider using alerts and audit logs to track user-related changes.', severity: 'low', status: 'info', activityResult: 'success', priority: 'low', data: { note: 'For comprehensive user activity tracking, monitor device activities, alerts, and audit logs where user actions may be recorded.', suggestions: [ 'Monitor alerts for user-related activities', 'Check audit logs on devices for user login/logout events', 'Use device status monitoring to track when users are active', 'Implement webhook monitoring for real-time user activity notifications', ], }, }, ]; return userActivities; } //# sourceMappingURL=execute.js.map