Trigger82 commited on
Commit
b432d2b
Β·
verified Β·
1 Parent(s): f489a5c

Update public/script.js

Browse files
Files changed (1) hide show
  1. public/script.js +266 -129
public/script.js CHANGED
@@ -1,132 +1,269 @@
1
- document.addEventListener('DOMContentLoaded', () => {
2
- const socket = io();
3
- const outputEl = document.getElementById('output');
4
- const statusEl = document.getElementById('status');
5
- const commandInput = document.getElementById('commandInput');
6
- const fileListEl = document.getElementById('fileList');
7
- const fileEditor = document.getElementById('fileEditor');
8
- const currentFile = { path: null };
9
-
10
- // Update status indicator
11
- socket.on('connect', () => {
12
- statusEl.textContent = 'Connected';
13
- statusEl.className = 'status-indicator connected';
14
- });
15
-
16
- socket.on('disconnect', () => {
17
- statusEl.textContent = 'Disconnected';
18
- statusEl.className = 'status-indicator disconnected';
19
- });
20
-
21
- // Handle output from server
22
- socket.on('output', (data) => {
23
- outputEl.innerHTML += data + '\n';
24
- outputEl.scrollTop = outputEl.scrollHeight;
25
- });
26
-
27
- // Handle command input
28
- commandInput.addEventListener('keypress', (e) => {
29
- if (e.key === 'Enter') {
30
- const command = commandInput.value.trim();
31
- if (command) {
32
- outputEl.innerHTML += `$ ${command}\n`;
33
- socket.emit('command', command);
34
- commandInput.value = '';
35
- }
36
- }
37
- });
38
-
39
- // Clone repository
40
- document.getElementById('cloneBtn').addEventListener('click', () => {
41
- const repoUrl = document.getElementById('repoUrl').value.trim();
42
- if (repoUrl) {
43
- socket.emit('clone', repoUrl);
44
- }
45
- });
46
-
47
- // Install dependencies
48
- document.getElementById('installBtn').addEventListener('click', () => {
49
- const packageManager = document.getElementById('packageManager').value;
50
- socket.emit('install', packageManager);
51
- });
52
-
53
- // Start process
54
- document.getElementById('startBtn').addEventListener('click', () => {
55
- const command = document.getElementById('startCommand').value.trim();
56
- if (command) {
57
- socket.emit('start', command);
58
- }
59
- });
60
-
61
- // Stop process
62
- document.getElementById('stopBtn').addEventListener('click', () => {
63
- socket.emit('stop');
64
- });
65
-
66
- // PM2 commands
67
- document.getElementById('pm2Btn').addEventListener('click', () => {
68
- const command = document.getElementById('pm2Command').value;
69
- socket.emit('pm2', command);
70
- });
71
-
72
- // File browser functionality
73
- function loadFileList() {
74
- socket.emit('list-files', '', (response) => {
75
- if (response.error) {
76
- outputEl.innerHTML += `Error listing files: ${response.error}\n`;
77
- return;
78
- }
79
-
80
- fileListEl.innerHTML = '';
81
- response.files.forEach(file => {
82
- const fileEl = document.createElement('div');
83
- fileEl.className = 'file-item';
84
- fileEl.textContent = file;
85
- fileEl.addEventListener('click', () => {
86
- socket.emit('read-file', file, (fileResponse) => {
87
- if (fileResponse.error) {
88
- outputEl.innerHTML += `Error reading file: ${fileResponse.error}\n`;
89
- return;
90
- }
91
- currentFile.path = file;
92
- fileEditor.value = fileResponse.content;
93
- });
94
- });
95
- fileListEl.appendChild(fileEl);
96
- });
97
- });
98
  }
99
-
100
- // Save file
101
- document.getElementById('saveFileBtn').addEventListener('click', () => {
102
- if (!currentFile.path) return;
103
-
104
- socket.emit('write-file', {
105
- filePath: currentFile.path,
106
- content: fileEditor.value
107
- }, (response) => {
108
- if (response.error) {
109
- outputEl.innerHTML += `Error saving file: ${response.error}\n`;
110
- } else {
111
- outputEl.innerHTML += `File ${currentFile.path} saved successfully\n`;
112
- }
113
- });
114
- });
115
-
116
- // Admin controls
117
- document.getElementById('banBtn').addEventListener('click', () => {
118
- const password = document.getElementById('adminPassword').value;
119
- if (!password) return;
120
-
121
- socket.emit('admin', {
122
- password: password,
123
- command: 'ban'
124
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  });
126
-
127
- // Initial load
128
- loadFileList();
129
-
130
- // Focus command input on page load
131
- commandInput.focus();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  });
 
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // Frontend Logic
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+
5
+ const socket = io();
6
+ let currentUserId = null;
7
+ let isAdmin = false;
8
+
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ // 1) AUTHENTICATION (Register, Login, Logout)
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+
13
+ function doRegister() {
14
+ const username = document.getElementById('username').value.trim();
15
+ const password = document.getElementById('password').value.trim();
16
+ const clientId = document.getElementById('clientId').value.trim();
17
+ if (!username || !password || !clientId) {
18
+ showAuthMessage('All fields required for register.');
19
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
+ socket.emit('register', { username, password, clientId });
22
+ }
23
+
24
+ function doLogin() {
25
+ const username = document.getElementById('username').value.trim();
26
+ const password = document.getElementById('password').value.trim();
27
+ if (!username || !password) {
28
+ showAuthMessage('Username & password required.');
29
+ return;
30
+ }
31
+ socket.emit('login', { username, password });
32
+ }
33
+
34
+ function doLogout() {
35
+ location.reload(); // Full refresh to clear session
36
+ }
37
+
38
+ // Handle auth responses
39
+ socket.on('registerResponse', (res) => {
40
+ const msgEl = document.getElementById('authMessage');
41
+ if (res.success) {
42
+ msgEl.style.color = 'green';
43
+ msgEl.innerText = `Registered! Your ID: ${res.userId}`;
44
+ } else {
45
+ msgEl.style.color = 'red';
46
+ msgEl.innerText = res.message;
47
+ }
48
+ });
49
+
50
+ socket.on('loginResponse', (res) => {
51
+ const msgEl = document.getElementById('authMessage');
52
+ if (res.success) {
53
+ currentUserId = res.userId;
54
+ isAdmin = res.isAdmin;
55
+ msgEl.innerText = '';
56
+ showMainPanel();
57
+ } else {
58
+ msgEl.style.color = 'red';
59
+ msgEl.innerText = res.message;
60
+ }
61
+ });
62
+
63
+ // ─────────────────────────────────────────────────────────────────────────────
64
+ // 2) SHOW MAIN PANEL AFTER LOGIN
65
+ // ─────────────────────────────────────────────────────────────────────────────
66
+
67
+ function showMainPanel() {
68
+ document.getElementById('authCard').style.display = 'none';
69
+ document.getElementById('mainPanel').style.display = 'block';
70
+ document.getElementById('displayUserId').innerText = currentUserId;
71
+ if (isAdmin) {
72
+ document.getElementById('adminBadge').style.display = 'inline-block';
73
+ document.getElementById('adminPanel').style.display = 'block';
74
+ fetchUsers();
75
+ }
76
+ // Start periodic stats & keep-alive ping
77
+ requestLiveStats();
78
+ startPing();
79
+ }
80
+
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+ // 3) LIVE STATS (uptime, system status, user counts)
83
+ // ─────────────────────────────────────────────────────────────────────────────
84
+
85
+ socket.on('serverRuntime', (uptimeStr) => {
86
+ document.getElementById('uptime').innerText = uptimeStr;
87
+ });
88
+
89
+ socket.on('systemStatus', (stats) => {
90
+ document.getElementById('cpu').innerText = stats.cpu + '%';
91
+ document.getElementById('mem').innerText = stats.memory + '%';
92
+ document.getElementById('disk').innerText = stats.disk + '%';
93
+ });
94
+
95
+ socket.on('userStats', (uStats) => {
96
+ document.getElementById('totalUsers').innerText = uStats.total;
97
+ document.getElementById('activeUsers').innerText = uStats.active;
98
+ document.getElementById('bannedUsers').innerText = uStats.banned;
99
+ });
100
+
101
+ function requestLiveStats() {
102
+ socket.emit('getServerRuntime');
103
+ socket.emit('getSystemStatus');
104
+ socket.emit('getUserStats');
105
+ setTimeout(requestLiveStats, 5000);
106
+ }
107
+
108
+ // Keep-alive ping every 10 seconds to prevent HF from killing idle socket
109
+ function startPing() {
110
+ setInterval(() => {
111
+ socket.emit('ping');
112
+ }, 10000);
113
+ }
114
+
115
+ // ─────────────────────────────────────────────────────────────────────────────
116
+ // 4) ADMIN DASHBOARD (Fetch/list users, Ban/Unban/Delete/MakeAdmin/RemoveAdmin)
117
+ // ─────────────────────────────────────────────────────────────────────────────
118
+
119
+ function fetchUsers() {
120
+ socket.emit('adminGetUsers');
121
+ }
122
+
123
+ socket.on('adminUserList', (data) => {
124
+ const container = document.getElementById('adminUserList');
125
+ container.innerHTML = '';
126
+ if (!data.users.length) {
127
+ container.innerText = 'No users found.';
128
+ return;
129
+ }
130
+ data.users.forEach((u) => {
131
+ const row = document.createElement('div');
132
+ row.className = 'user-row';
133
+ row.innerHTML = `
134
+ <span><b>${u.username}</b> (ID: ${u.id}) ${u.isAdmin ? '[Admin]' : ''}</span>
135
+ <button onclick="adminBan('${u.id}')">Ban</button>
136
+ <button onclick="adminUnban('${u.id}')">Unban</button>
137
+ <button onclick="adminDelete('${u.id}')">Delete</button>
138
+ <button onclick="adminMakeAdmin('${u.id}')">Make Admin</button>
139
+ <button onclick="adminRemoveAdmin('${u.id}')">Remove Admin</button>
140
+ `;
141
+ container.appendChild(row);
142
  });
143
+ });
144
+
145
+ socket.on('adminBanResponse', (res) => {
146
+ showAdminMessage(res.message, res.success);
147
+ fetchUsers();
148
+ });
149
+ socket.on('adminUnbanResponse', (res) => {
150
+ showAdminMessage(res.message, res.success);
151
+ fetchUsers();
152
+ });
153
+ socket.on('adminDeleteUserResponse', (res) => {
154
+ showAdminMessage(res.message, res.success);
155
+ fetchUsers();
156
+ });
157
+ socket.on('adminMakeAdminResponse', (res) => {
158
+ showAdminMessage(res.message, res.success);
159
+ fetchUsers();
160
+ });
161
+ socket.on('adminRemoveAdminResponse', (res) => {
162
+ showAdminMessage(res.message, res.success);
163
+ fetchUsers();
164
+ });
165
+
166
+ function adminBan(userId) {
167
+ socket.emit('adminBanUser', userId);
168
+ }
169
+ function adminUnban(userId) {
170
+ socket.emit('adminUnbanUser', userId);
171
+ }
172
+ function adminDelete(userId) {
173
+ socket.emit('adminDeleteUser', userId);
174
+ }
175
+ function adminMakeAdmin(userId) {
176
+ socket.emit('adminMakeAdmin', userId);
177
+ }
178
+ function adminRemoveAdmin(userId) {
179
+ socket.emit('adminRemoveAdmin', userId);
180
+ }
181
+
182
+ function showAdminMessage(msg, success) {
183
+ const el = document.getElementById('adminMessage');
184
+ el.style.color = success ? 'green' : 'red';
185
+ el.innerText = msg;
186
+ }
187
+
188
+ // ─────────────────────────────────────────────────────────────────────────────
189
+ // 5) USER CONSOLE (Start session, send commands, display output)
190
+ // ─────────────────────────────────────────────────────────────────────────────
191
+
192
+ function startSession() {
193
+ if (!currentUserId) return;
194
+ socket.emit('start', currentUserId);
195
+ }
196
+
197
+ function sendCommand() {
198
+ const cmd = document.getElementById('commandInput').value.trim();
199
+ if (!cmd) return;
200
+ appendOutput(`> ${cmd}`);
201
+ socket.emit('command', { userId: currentUserId, message: cmd });
202
+ document.getElementById('commandInput').value = '';
203
+ }
204
+
205
+ socket.on('message', (data) => {
206
+ if (typeof data === 'string') {
207
+ appendOutput(data);
208
+ } else {
209
+ appendOutput(JSON.stringify(data, null, 2));
210
+ }
211
+ });
212
+
213
+ function appendOutput(text) {
214
+ const out = document.getElementById('consoleOutput');
215
+ out.innerText += text + '\n';
216
+ out.scrollTop = out.scrollHeight;
217
+ }
218
+
219
+ // ─────────────────────────────────────────────────────────────────────────────
220
+ // 6) PASSWORD RESET (Request token, submit reset)
221
+ // ─────────────────────────────────────────────────────────────────────────────
222
+
223
+ function requestReset() {
224
+ const clientId = document.getElementById('resetClientId').value.trim();
225
+ if (!clientId) {
226
+ showResetMessage('Enter your Device ID first.', false);
227
+ return;
228
+ }
229
+ socket.emit('forgotPassword', clientId);
230
+ }
231
+
232
+ socket.on('resetTokenGenerated', ({ username, resetToken }) => {
233
+ showResetMessage(`Token generated for ${username}: ${resetToken}`, true);
234
+ });
235
+
236
+ socket.on('resetTokenError', (msg) => {
237
+ showResetMessage(msg, false);
238
+ });
239
+
240
+ function submitReset() {
241
+ const token = document.getElementById('resetToken').value.trim();
242
+ const newPass = document.getElementById('newPassword').value.trim();
243
+ if (!token || !newPass) {
244
+ showResetMessage('Token & new password are required.', false);
245
+ return;
246
+ }
247
+ socket.emit('resetPassword', { resetToken: token, newPassword: newPass });
248
+ }
249
+
250
+ socket.on('passwordResetSuccess', (msg) => {
251
+ showResetMessage(msg, true);
252
+ });
253
+ socket.on('passwordResetError', (msg) => {
254
+ showResetMessage(msg, false);
255
+ });
256
+
257
+ function showResetMessage(msg, success) {
258
+ const el = document.getElementById('resetMessage');
259
+ el.style.color = success ? 'green' : 'red';
260
+ el.innerText = msg;
261
+ }
262
+
263
+ // ─────────────────────────────────────────────────────────────────────────────
264
+ // 7) HANDLE DISCONNECTS (optional cleanup)
265
+ // ─────────────────────────────────────────────────────────────────────────────
266
+
267
+ socket.on('disconnect', () => {
268
+ appendOutput('πŸ“΄ Disconnected from server.');
269
  });