EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
mobileDevice.js
Go to the documentation of this file.
1/**
2 * @file mobileDevice.js
3 * @module routes/mobileDevice
4 * @description Mobile device inventory management endpoint.
5 * Provides paginated list of mobile devices with filtering and tenant isolation.
6 * @requires express
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
13 */
14
15/**
16 * @apiDefine MobileDevice Mobile Devices
17 * Mobile device inventory management
18 */
19
20const express = require('express');
21const router = express.Router();
22const pool = require('../services/db');
23const authenticateToken = require('../middleware/auth');
24const { getTenantFilter } = require('../middleware/tenant');
25
26/**
27 * @api {get} /api/mobile-device/list List mobile devices
28 * @apiName ListMobileDevices
29 * @apiGroup MobileDevice
30 * @apiDescription Retrieve paginated list of mobile devices with filtering and search.
31 * Supports filtering by customer, OS, and full-text search. Enforces tenant isolation.
32 * Returns device inventory with customer/contract associations.
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 (query parameter)
37 * @apiParam {string} [search] Search device name, hostname, customer, or OS (query parameter)
38 * @apiSuccess {object[]} devices Array of mobile 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 (e.g., "iOS", "Android")
45 * @apiSuccess {string} devices.os_version OS version
46 * @apiSuccess {string} devices.version 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)
54 *
55 * @apiError (500) {String} error="Failed to list devices" Database query failed
56 *
57 * @apiExample {curl} Example:
58 * curl -X GET "http://localhost:3000/api/mobile-device/list?page=1&limit=20&search=iPhone&customer_id=5" \\\\
59 * -H "Authorization: Bearer YOUR_TOKEN"
60 *
61 * @apiSuccessExample {json} Success-Response:
62 * HTTP/1.1 200 OK
63 * {
64 * "devices": [
65 * {
66 * "device_uuid": "mobile-abc-123",
67 * "device_id": 42,
68 * "tenant_id": 2,
69 * "customer_id": 5,
70 * "hostname": "iPhone-John",
71 * "os": "iOS",
72 * "os_version": "17.3",
73 * "version": "1.0.5",
74 * "last_seen": "2026-03-12T10:30:00.000Z",
75 * "name": "John's iPhone",
76 * "ip_address": "192.168.1.150",
77 * "user_list": "john@acme.com",
78 * "customer_name": "Acme Corp",
79 * "contract_title": "Annual Support"
80 * }
81 * ],
82 * "total": 8
83 * }
84 */
85router.get('/list', authenticateToken, async (req, res) => {
86 try {
87 const { clause: tenantClause, params: tenantParams } = getTenantFilter(req, 'm');
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(`m.customer_id = $${paramIdx++}`);
95 }
96 if (req.query.search) {
97 const search = `%${req.query.search}%`;
98 params.push(search);
99 conditions.push(`(m.name ILIKE $${paramIdx} OR m.hostname ILIKE $${paramIdx} OR c.name ILIKE $${paramIdx} OR m.os ILIKE $${paramIdx})`);
100 paramIdx++;
101 }
102 if (req.query.os) {
103 params.push(req.query.os);
104 conditions.push(`m.os = $${paramIdx++}`);
105 }
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 mobile_devices m
113 LEFT JOIN customers c ON c.customer_id = m.customer_id
114 ${whereClause}
115 `, params);
116 const total = parseInt(totalResult.rows[0]?.total || '0', 10);
117 const result = await pool.query(`
118 SELECT
119 m.device_uuid,
120 m.device_id,
121 m.tenant_id,
122 m.customer_id,
123 m.hostname,
124 m.os,
125 m.os_version,
126 m.version,
127 m.last_seen,
128 m.name,
129 m.ip_address,
130 m.user_list,
131 c.name AS customer_name,
132 ct.title AS contract_title
133 FROM mobile_devices m
134 LEFT JOIN customers c ON c.customer_id = m.customer_id
135 LEFT JOIN contracts ct ON ct.contract_id = m.contract_id
136 ${whereClause}
137 ORDER BY m.hostname
138 LIMIT $${paramIdx} OFFSET $${paramIdx + 1}
139 `, [...params, limit, offset]);
140 res.json({ devices: result.rows, total });
141 } catch (err) {
142 console.error('[MobileDevice] Failed to list devices:', err);
143 res.status(500).json({ error: 'Failed to list devices' });
144 }
145});
146
147module.exports = router;