9remote 2.0.1 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1 -1
- package/dist/install.cjs +2 -0
- package/dist/ptyDaemon.cjs +1 -1
- package/dist/server.cjs +1 -1
- package/dist/ui/assets/{index-COWVKicT.css → index-BMHG73CL.css} +1 -1
- package/dist/ui/assets/index-Bg86Demx.js +8 -0
- package/dist/ui/index.html +2 -2
- package/package.json +4 -6
- package/cli/index.js +0 -1288
- package/cli/scripts/install.js +0 -19
- package/cli/utils/apiKey.js +0 -77
- package/cli/utils/assets/trayIcon.ico +0 -0
- package/cli/utils/cloudflared.js +0 -493
- package/cli/utils/machineId.js +0 -22
- package/cli/utils/permissions.js +0 -45
- package/cli/utils/pids.js +0 -114
- package/cli/utils/state.js +0 -115
- package/cli/utils/token.js +0 -32
- package/cli/utils/tray.js +0 -251
- package/cli/utils/tui.js +0 -426
- package/cli/utils/updateChecker.js +0 -358
- package/dist/ui/assets/index-njTKNAa6.js +0 -8
- package/index.js +0 -273
- package/lib/constants.js +0 -64
- package/lib/deviceApproval.js +0 -116
- package/lib/router.js +0 -134
- package/lib/socketio.js +0 -227
package/lib/socketio.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
// Main Socket.IO setup
|
|
2
|
-
import { Server } from "socket.io";
|
|
3
|
-
import { readFileSync } from "fs";
|
|
4
|
-
import { join } from "path";
|
|
5
|
-
import { homedir } from "os";
|
|
6
|
-
import { setupTerminalSocket } from "../features/terminal/terminalSocket.js";
|
|
7
|
-
import { setupRemoteSocket, checkRemoteAvailable } from "../features/remote/remoteSocket.js";
|
|
8
|
-
import { setupFileExplorerSocket } from "../features/fileExplorer/fileExplorerSocket.js";
|
|
9
|
-
import { trackConnection, untrackConnection, pushUiLog, clearOneTimeKey, pushUiEvent, setRemoteAvailable } from "../api/ui.js";
|
|
10
|
-
import {
|
|
11
|
-
loadApprovedDevices,
|
|
12
|
-
isDeviceApproved,
|
|
13
|
-
isDevicePending,
|
|
14
|
-
approveDevice,
|
|
15
|
-
addPendingApproval,
|
|
16
|
-
removePendingApproval,
|
|
17
|
-
getPendingApproval,
|
|
18
|
-
markDeviceRejected,
|
|
19
|
-
isDeviceRejected,
|
|
20
|
-
updateRejectedSocket,
|
|
21
|
-
clearRejectedDevice
|
|
22
|
-
} from "./deviceApproval.js";
|
|
23
|
-
|
|
24
|
-
function loadApiKey() {
|
|
25
|
-
try {
|
|
26
|
-
const keysFile = join(homedir(), ".9remote", "keys.json");
|
|
27
|
-
const data = JSON.parse(readFileSync(keysFile, "utf8"));
|
|
28
|
-
return data.key || null;
|
|
29
|
-
} catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let ioInstance = null;
|
|
35
|
-
|
|
36
|
-
export function getIO() {
|
|
37
|
-
return ioInstance;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Setup features on an approved socket */
|
|
41
|
-
function setupSocketFeatures(socket) {
|
|
42
|
-
// Clear one-time key if used
|
|
43
|
-
if (socket.handshake.auth?.tempKey) {
|
|
44
|
-
pushUiLog("One-time key used \u2014 clearing from UI");
|
|
45
|
-
clearOneTimeKey();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Approve a pending socket by socketId */
|
|
50
|
-
export function approveSocketDevice(socketId) {
|
|
51
|
-
const io = ioInstance;
|
|
52
|
-
if (!io) return false;
|
|
53
|
-
|
|
54
|
-
const socket = io.sockets.sockets.get(socketId);
|
|
55
|
-
const pending = getPendingApproval(socketId);
|
|
56
|
-
console.log(`[DEBUG-APPROVE] socketId=${socketId}, socketExists=${!!socket}, pendingExists=${!!pending}`);
|
|
57
|
-
if (!socket || !pending) return false;
|
|
58
|
-
|
|
59
|
-
// Save device as approved; clear any prior rejection
|
|
60
|
-
approveDevice(pending.deviceId);
|
|
61
|
-
removePendingApproval(socketId);
|
|
62
|
-
clearRejectedDevice(pending.deviceId);
|
|
63
|
-
|
|
64
|
-
// Unlock socket + notify client
|
|
65
|
-
socket.data.approved = true;
|
|
66
|
-
console.log(`[DEBUG-APPROVE] Emitting device:approved to ${socketId}`);
|
|
67
|
-
socket.emit("device:approved");
|
|
68
|
-
|
|
69
|
-
// Setup features
|
|
70
|
-
setupSocketFeatures(socket);
|
|
71
|
-
pushUiLog(`Device approved: ${pending.deviceId.slice(0, 8)}...`);
|
|
72
|
-
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Approve a previously-rejected device by deviceId (from Clients list) */
|
|
77
|
-
export function approveRejectedDevice(deviceId) {
|
|
78
|
-
const io = ioInstance;
|
|
79
|
-
if (!io || !deviceId) return false;
|
|
80
|
-
|
|
81
|
-
approveDevice(deviceId);
|
|
82
|
-
clearRejectedDevice(deviceId);
|
|
83
|
-
|
|
84
|
-
// Notify any active socket for this device
|
|
85
|
-
for (const socket of io.sockets.sockets.values()) {
|
|
86
|
-
if (socket.handshake.auth?.deviceId === deviceId) {
|
|
87
|
-
socket.data.approved = true;
|
|
88
|
-
socket.emit("device:approved");
|
|
89
|
-
setupSocketFeatures(socket);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
pushUiLog(`Device approved from pending: ${deviceId.slice(0, 8)}...`);
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** Disconnect all active sockets belonging to a deviceId (device stays approved) */
|
|
97
|
-
export function disconnectDeviceSockets(deviceId) {
|
|
98
|
-
const io = ioInstance;
|
|
99
|
-
if (!io || !deviceId) return 0;
|
|
100
|
-
let count = 0;
|
|
101
|
-
for (const socket of io.sockets.sockets.values()) {
|
|
102
|
-
if (socket.handshake.auth?.deviceId === deviceId) {
|
|
103
|
-
socket.disconnect(true);
|
|
104
|
-
count++;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (count) pushUiLog(`Disconnected ${count} socket(s) for device ${deviceId.slice(0, 8)}...`);
|
|
108
|
-
return count;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** Reject a pending socket by socketId (remember deviceId in RAM as pending) */
|
|
112
|
-
export function rejectSocketDevice(socketId) {
|
|
113
|
-
const io = ioInstance;
|
|
114
|
-
if (!io) return false;
|
|
115
|
-
|
|
116
|
-
const pending = getPendingApproval(socketId);
|
|
117
|
-
const socket = io.sockets.sockets.get(socketId);
|
|
118
|
-
removePendingApproval(socketId);
|
|
119
|
-
|
|
120
|
-
// Remember rejection in RAM so it shows up in Clients list as pending
|
|
121
|
-
if (pending?.deviceId) {
|
|
122
|
-
markDeviceRejected(pending.deviceId, { ip: pending.ip, socketId });
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (socket) {
|
|
126
|
-
socket.emit("device:rejected");
|
|
127
|
-
socket.disconnect(true);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Notify UI to refresh pending/approved list
|
|
131
|
-
pushUiEvent("deviceApproval", { action: "refresh" });
|
|
132
|
-
pushUiLog(`Device rejected: ${pending?.deviceId?.slice(0, 8) || "unknown"}...`);
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export async function setupSocketIO(server) {
|
|
137
|
-
// Load approved devices from disk
|
|
138
|
-
loadApprovedDevices();
|
|
139
|
-
|
|
140
|
-
const io = new Server(server, {
|
|
141
|
-
cors: {
|
|
142
|
-
origin: "*",
|
|
143
|
-
methods: ["GET", "POST"],
|
|
144
|
-
credentials: true,
|
|
145
|
-
allowedHeaders: ["*"]
|
|
146
|
-
},
|
|
147
|
-
transports: ["websocket", "polling"],
|
|
148
|
-
allowEIO3: true,
|
|
149
|
-
allowUpgrades: true,
|
|
150
|
-
pingTimeout: 60000,
|
|
151
|
-
pingInterval: 25000,
|
|
152
|
-
maxHttpBufferSize: 1e8
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Check remote availability at startup
|
|
156
|
-
const hasRemote = await checkRemoteAvailable();
|
|
157
|
-
setRemoteAvailable(hasRemote);
|
|
158
|
-
|
|
159
|
-
// Track connections + device approval
|
|
160
|
-
io.on("connection", (socket) => {
|
|
161
|
-
const ip = socket.handshake.headers["x-forwarded-for"] || socket.handshake.address || "unknown";
|
|
162
|
-
const deviceId = socket.handshake.auth?.deviceId || null;
|
|
163
|
-
|
|
164
|
-
// Block all events from unapproved sockets (except device:clientReady)
|
|
165
|
-
socket.data.approved = false;
|
|
166
|
-
socket.use((packet, next) => {
|
|
167
|
-
if (socket.data.approved) return next();
|
|
168
|
-
const event = packet[0];
|
|
169
|
-
if (event === "device:clientReady" || event === "disconnect") return next();
|
|
170
|
-
return next(new Error("Device not approved"));
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
trackConnection(socket.id, ip, deviceId);
|
|
174
|
-
pushUiLog(`Client connected: ${ip} (device: ${deviceId?.slice(0, 8) || "none"})`);
|
|
175
|
-
|
|
176
|
-
socket.on("disconnect", (reason) => {
|
|
177
|
-
untrackConnection(socket.id);
|
|
178
|
-
removePendingApproval(socket.id);
|
|
179
|
-
pushUiLog(`Client disconnected: ${ip} (${reason})`);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// Check device approval
|
|
183
|
-
if (deviceId && isDeviceApproved(deviceId)) {
|
|
184
|
-
// Known device — allow immediately
|
|
185
|
-
pushUiLog(`Device recognized: ${deviceId.slice(0, 8)}...`);
|
|
186
|
-
socket.data.approved = true;
|
|
187
|
-
setupSocketFeatures(socket);
|
|
188
|
-
} else if (deviceId && isDeviceRejected(deviceId)) {
|
|
189
|
-
// Previously rejected — keep socket unapproved, no modal, update socketId for later approve
|
|
190
|
-
updateRejectedSocket(deviceId, socket.id, ip);
|
|
191
|
-
pushUiLog(`Rejected device reconnected: ${deviceId.slice(0, 8)} — waiting in Clients list`);
|
|
192
|
-
socket.emit("device:rejected");
|
|
193
|
-
pushUiEvent("deviceApproval", { action: "refresh" });
|
|
194
|
-
} else {
|
|
195
|
-
// Unknown device — hold and request approval
|
|
196
|
-
pushUiLog(`Unknown device: ${deviceId?.slice(0, 8) || "no-id"} — waiting for approval`);
|
|
197
|
-
// Skip if same deviceId already pending (client reconnected)
|
|
198
|
-
if (isDevicePending(deviceId)) {
|
|
199
|
-
pushUiLog(`Device ${deviceId?.slice(0, 8)} already pending, ignoring duplicate`);
|
|
200
|
-
socket.disconnect(true);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
addPendingApproval(socket.id, { deviceId, ip });
|
|
205
|
-
|
|
206
|
-
// Wait for client to signal ready before emitting approval request
|
|
207
|
-
socket.once("device:clientReady", () => {
|
|
208
|
-
socket.emit("device:pendingApproval");
|
|
209
|
-
pushUiEvent("deviceApproval", {
|
|
210
|
-
socketId: socket.id,
|
|
211
|
-
deviceId,
|
|
212
|
-
ip,
|
|
213
|
-
action: "pending"
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// Setup Terminal + Remote on same root namespace
|
|
220
|
-
setupTerminalSocket(io, loadApiKey());
|
|
221
|
-
|
|
222
|
-
// Setup File Explorer (uses default namespace)
|
|
223
|
-
setupFileExplorerSocket(io);
|
|
224
|
-
|
|
225
|
-
ioInstance = io;
|
|
226
|
-
return io;
|
|
227
|
-
}
|