2 * @file networkDevice.js
3 * @module routes/networkDevice
4 * @description Network device inventory management endpoint.
5 * Provides paginated list of network devices (switches, routers, firewalls) with filtering and tenant isolation.
7 * @requires services/db
8 * @requires middleware/auth
9 * @requires middleware/tenant
10 * @author RMM-PSA Development Team
11 * @copyright 2026 RMM-PSA Platform
12 * @license Proprietary
16 * @apiDefine NetworkDevice Network Devices
17 * Network infrastructure device inventory management
20const express = require('express');
21const router = express.Router();
22const pool = require('../services/db');
23const authenticateToken = require('../middleware/auth');
24const { getTenantFilter } = require('../middleware/tenant');
27 * @api {get} /api/network-device/list List network devices
28 * @apiName ListNetworkDevices
29 * @apiGroup NetworkDevice
30 * @apiDescription Retrieve paginated list of network devices with filtering and search.
31 * Supports filtering by customer, OS, and full-text search. Enforces tenant isolation.
32 * Returns inventory of switches, routers, firewalls, and other network infrastructure.
33 * @apiParam {number} [page=1] Page number (query parameter)
34 * @apiParam {number} [limit=20] Results per page (query parameter)
35 * @apiParam {number} [customer_id] Filter by customer ID (query parameter)
36 * @apiParam {string} [os] Filter by operating system/firmware (query parameter)
37 * @apiParam {string} [search] Search device name, hostname, customer, or OS (query parameter)
38 * @apiSuccess {object[]} devices Array of network devices
39 * @apiSuccess {string} devices.device_uuid Device UUID
40 * @apiSuccess {number} devices.device_id Device ID
41 * @apiSuccess {number} devices.tenant_id Tenant ID
42 * @apiSuccess {number} devices.customer_id Customer ID
43 * @apiSuccess {string} devices.hostname Device hostname
44 * @apiSuccess {string} devices.os Operating system/firmware (e.g., "Cisco IOS", "pfSense")
45 * @apiSuccess {string} devices.os_version Firmware version
46 * @apiSuccess {string} devices.version Management app version
47 * @apiSuccess {DateTime} devices.last_seen Last contact timestamp
48 * @apiSuccess {string} devices.name Device friendly name
49 * @apiSuccess {string} devices.ip_address Device IP address
50 * @apiSuccess {string} devices.user_list Associated users (comma-separated)
51 * @apiSuccess {string} devices.customer_name Customer name
52 * @apiSuccess {String} devices.contract_title Associated contract title
53 * @apiSuccess {Number} total Total device count (for pagination)
55 * @apiError (500) {String} error="Failed to list devices" Database query failed
57 * @apiExample {curl} Example:
58 * curl -X GET "http://localhost:3000/api/network-device/list?page=1&limit=20&search=switch&customer_id=5" \\\\
59 * -H "Authorization: Bearer YOUR_TOKEN"
61 * @apiSuccessExample {json} Success-Response:
66 * "device_uuid": "net-abc-123",
70 * "hostname": "CORE-SWITCH-01",
72 * "os_version": "15.2(4)E",
74 * "last_seen": "2026-03-12T10:30:00.000Z",
75 * "name": "Core Switch - Building A",
76 * "ip_address": "192.168.1.1",
78 * "customer_name": "Acme Corp",
79 * "contract_title": "Network Monitoring"
85router.get('/list', authenticateToken, async (req, res) => {
87 const { clause: tenantClause, params: tenantParams } = getTenantFilter(req, 'n');
88 const conditions = [];
89 const params = [...tenantParams];
90 let paramIdx = tenantParams.length + 1;
91 if (tenantClause) conditions.push(tenantClause);
92 if (req.query.customer_id) {
93 params.push(req.query.customer_id);
94 conditions.push(`n.customer_id = $${paramIdx++}`);
96 if (req.query.search) {
97 const search = `%${req.query.search}%`;
99 conditions.push(`(n.name ILIKE $${paramIdx} OR n.hostname ILIKE $${paramIdx} OR c.name ILIKE $${paramIdx} OR n.os ILIKE $${paramIdx})`);
103 params.push(req.query.os);
104 conditions.push(`n.os = $${paramIdx++}`);
106 const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
107 const page = parseInt(req.query.page, 10) || 1;
108 const limit = parseInt(req.query.limit, 10) || 20;
109 const offset = (page - 1) * limit;
110 const totalResult = await pool.query(`
111 SELECT COUNT(*) AS total
112 FROM network_devices n
113 LEFT JOIN customers c ON c.customer_id = n.customer_id
116 const total = parseInt(totalResult.rows[0]?.total || '0', 10);
117 const result = await pool.query(`
131 c.name AS customer_name,
132 ct.title AS contract_title
133 FROM network_devices n
134 LEFT JOIN customers c ON c.customer_id = n.customer_id
135 LEFT JOIN contracts ct ON ct.contract_id = n.contract_id
138 LIMIT $${paramIdx} OFFSET $${paramIdx + 1}
139 `, [...params, limit, offset]);
140 res.json({ devices: result.rows, total });
142 console.error('[NetworkDevice] Failed to list devices:', err);
143 res.status(500).json({ error: 'Failed to list devices' });
147module.exports = router;