2 * @file deviceDiscovery.js
3 * @module routes/deviceDiscovery
4 * @description Network device discovery endpoint for agent scanner plugin.
5 * Receives network scan results (SNMP, ARP, etc.) from agents and stores in Redis/database.
6 * Enables automatic device inventory and network mapping.
8 * @requires middleware/auth
9 * @requires services/db
11 * @author RMM-PSA Development Team
12 * @copyright 2026 RMM-PSA Platform
13 * @license Proprietary
17 * @apiDefine DeviceDiscovery Network Device Discovery
18 * Network scanner results from agent plugins
21const express = require('express');
22const router = express.Router();
23const authenticateToken = require('../middleware/auth');
24const pool = require('../services/db');
27 * @api {post} /api/device-discovery Submit discovered devices
28 * @apiName SubmitDeviceDiscovery
29 * @apiGroup DeviceDiscovery
30 * @apiDescription Agent network scanner plugin submits discovered devices (SNMP/ARP scan results).
31 * Data stored in Redis queue for processing. SNMP devices with sysDescr auto-inserted into database.
32 * Supports network topology mapping and automatic device inventory.
33 * @apiParam {string} agent_uuid Agent UUID performing scan
34 * @apiParam {string} [type="network"] Discovery type ("network", "snmp")
35 * @apiParam {object[]} data Array of discovered devices
36 * @apiParam {string} data.ip Device IP address
37 * @apiParam {string} [data.mac] Device MAC address
38 * @apiParam {string} [data.sysDescr] SNMP system description (sysDescr OID)
39 * @apiParam {string} [data.sysName] SNMP system name (sysName OID)
40 * @apiParam {string} [data.sysLocation] SNMP system location (sysLocation OID)
41 * @apiParam {DateTime} [ts] Discovery timestamp (default: now)
42 * @apiSuccess {string} status="ok" Success status
43 * @apiSuccess {number} devices Number of devices received
44 * @apiSuccess {number} dbAdded Number of devices auto-inserted to database (SNMP only)
45 * @apiError (400) {String} error="Missing agent_uuid or device data" Required parameters missing
46 * @apiError (500) {String} error="Failed to save device data" Redis or database error
47 * @apiExample {curl} Example (SNMP scan):
48 * curl -X POST http://localhost:3000/api/device-discovery \\\\
49 * -H "Authorization: Bearer YOUR_TOKEN" \\\\
50 * -H "Content-Type: application/json" \\\\
52 * "agent_uuid": "abc-123-uuid",
54 * "ts": "2026-03-12T10:00:00.000Z",
57 * "ip": "192.168.1.1",
58 * "mac": "00:11:22:33:44:55",
59 * "sysDescr": "Cisco IOS Software",
60 * "sysName": "CORE-SWITCH-01",
61 * "sysLocation": "Server Room"
65 * @apiSuccessExample {json} Success-Response:
73router.post('/', authenticateToken, async (req, res) => {
75 const { agent_uuid, type, data, ts } = req.body;
76 if (!agent_uuid || !Array.isArray(data)) {
77 return res.status(400).json({ error: 'Missing agent_uuid or device data' });
79 // Use Redis for storing detected endpoints for later processing
80 const Redis = require('ioredis');
81 const redisConfig = require('../config/redis');
82 const redis = new Redis(redisConfig);
83 const key = `deviceDiscovery:${agent_uuid}`;
85 for (const device of data) {
86 await redis.rpush(key, JSON.stringify({
89 type: type || 'network',
90 discovered_at: ts || new Date().toISOString(),
91 sysDescr: device.sysDescr || '',
92 sysName: device.sysName || '',
93 sysLocation: device.sysLocation || '',
94 discovered_by: agent_uuid
96 // If SNMP fingerprint present, auto-add to DB
97 if (type === 'snmp' && device.sysDescr) {
100 `INSERT INTO devices (ip, mac, sys_descr, sys_name, sys_location, discovered_by, discovered_at)
101 VALUES ($1, $2, $3, $4, $5, $6, $7)
102 ON CONFLICT (ip, mac) DO UPDATE SET sys_descr = $3, sys_name = $4, sys_location = $5, discovered_by = $6, discovered_at = $7`,
103 [device.ip, device.mac, device.sysDescr, device.sysName, device.sysLocation, agent_uuid, ts || new Date().toISOString()]
107 console.error('[DeviceDiscovery] DB insert error:', e);
111 await redis.expire(key, 86400);
112 res.json({ status: 'ok', devices: data.length, dbAdded });
114 console.error('[DeviceDiscovery] Error:', err);
115 res.status(500).json({ error: 'Failed to save device data' });
119module.exports = router;