mirror of
https://github.com/screentinker/screentinker.git
synced 2026-05-15 07:32:23 -06:00
ScreenTinker - open source digital signage management software. MIT License, all features included, no license gates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
92 lines
3.4 KiB
JavaScript
92 lines
3.4 KiB
JavaScript
const heartbeat = require('../services/heartbeat');
|
|
const { verifyToken } = require('../middleware/auth');
|
|
|
|
module.exports = function setupDashboardSocket(io) {
|
|
const dashboardNs = io.of('/dashboard');
|
|
const deviceNs = io.of('/device');
|
|
|
|
// Authenticate dashboard WebSocket connections
|
|
dashboardNs.use((socket, next) => {
|
|
const token = socket.handshake.auth?.token;
|
|
if (!token) return next(new Error('Authentication required'));
|
|
try {
|
|
const decoded = verifyToken(token);
|
|
socket.userId = decoded.id;
|
|
socket.userRole = decoded.role;
|
|
next();
|
|
} catch {
|
|
next(new Error('Invalid token'));
|
|
}
|
|
});
|
|
|
|
// Verify the user owns the device or is admin/superadmin
|
|
function checkDeviceOwnership(socket, device_id) {
|
|
if (['admin', 'superadmin'].includes(socket.userRole)) return true;
|
|
const { db } = require('../db/database');
|
|
const device = db.prepare('SELECT user_id FROM devices WHERE id = ?').get(device_id);
|
|
if (!device) return false;
|
|
return device.user_id === socket.userId;
|
|
}
|
|
|
|
dashboardNs.on('connection', (socket) => {
|
|
console.log(`Dashboard client connected: ${socket.id} (user: ${socket.userId})`);
|
|
|
|
// Request screenshot from a device
|
|
socket.on('dashboard:request-screenshot', (data) => {
|
|
const { device_id } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
const conn = heartbeat.getConnection(device_id);
|
|
if (conn) {
|
|
deviceNs.to(device_id).emit('device:screenshot-request', {});
|
|
}
|
|
});
|
|
|
|
// Remote control: touch forwarding
|
|
socket.on('dashboard:remote-touch', (data) => {
|
|
const { device_id, x, y, action } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
deviceNs.to(device_id).emit('device:remote-touch', { x, y, action });
|
|
});
|
|
|
|
// Remote control: key forwarding
|
|
socket.on('dashboard:remote-key', (data) => {
|
|
const { device_id, keycode } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
console.log(`Remote key: ${keycode} -> ${device_id}`);
|
|
deviceNs.to(device_id).emit('device:remote-key', { keycode });
|
|
});
|
|
|
|
// Start remote screenshot streaming
|
|
socket.on('dashboard:remote-start', (data) => {
|
|
const { device_id } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
const room = deviceNs.adapter.rooms.get(device_id);
|
|
console.log(`Remote start for ${device_id}, room has ${room?.size || 0} socket(s)`);
|
|
deviceNs.to(device_id).emit('device:remote-start', {});
|
|
console.log(`Remote session started for device ${device_id}`);
|
|
});
|
|
|
|
// Stop remote screenshot streaming
|
|
socket.on('dashboard:remote-stop', (data) => {
|
|
const { device_id } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
deviceNs.to(device_id).emit('device:remote-stop', {});
|
|
console.log(`Remote session stopped for device ${device_id}`);
|
|
});
|
|
|
|
// Send command to device (reboot, refresh, etc.)
|
|
socket.on('dashboard:device-command', (data) => {
|
|
const { device_id, type, payload } = data;
|
|
if (!checkDeviceOwnership(socket, device_id)) return;
|
|
deviceNs.to(device_id).emit('device:command', { type, payload });
|
|
console.log(`Command sent to device ${device_id}: ${type}`);
|
|
});
|
|
|
|
socket.on('disconnect', () => {
|
|
console.log(`Dashboard client disconnected: ${socket.id}`);
|
|
});
|
|
});
|
|
|
|
return dashboardNs;
|
|
};
|