Remove admin panel: strip admin startup, dependencies, and docs; keep minimal placeholder file
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
# Port the server listens on (client must connect to this)
|
# Port the server listens on (client must connect to this)
|
||||||
PORT=5055
|
PORT=5055
|
||||||
ADMIN_PORT=5056
|
|
||||||
|
|
||||||
# Logging: error, warn, info, verbose, debug, silly
|
# Logging: error, warn, info, verbose, debug, silly
|
||||||
LOG_LEVEL=info
|
LOG_LEVEL=info
|
||||||
@@ -13,7 +12,3 @@ RECNET_VERIFY_URL=
|
|||||||
|
|
||||||
# SQLite DB file
|
# SQLite DB file
|
||||||
SQLITE_FILE=./helium.db
|
SQLITE_FILE=./helium.db
|
||||||
|
|
||||||
# Admin basic auth (optional)
|
|
||||||
ADMIN_USER=admin
|
|
||||||
ADMIN_PASS=changeme
|
|
||||||
|
|||||||
@@ -7,28 +7,24 @@ What I added in this commit:
|
|||||||
- Protocol stub (src/protocol.js) — where Rec Room / Photon packet parsing should be implemented
|
- Protocol stub (src/protocol.js) — where Rec Room / Photon packet parsing should be implemented
|
||||||
- Auth helpers (src/auth.js) for Steam/RecNet token verification (placeholders that call configured endpoints)
|
- Auth helpers (src/auth.js) for Steam/RecNet token verification (placeholders that call configured endpoints)
|
||||||
- SQLite persistence (src/storage.js)
|
- SQLite persistence (src/storage.js)
|
||||||
- Admin console (src/admin.js) with basic auth and endpoints to list connections and broadcast messages
|
|
||||||
- Logger and test client
|
- Logger and test client
|
||||||
- package.json with dependencies
|
- package.json with dependencies
|
||||||
|
|
||||||
Environment variables (set in .env):
|
Environment variables (set in .env):
|
||||||
- PORT (default 5055) — WebSocket server port
|
- PORT (default 5055) — WebSocket server port
|
||||||
- ADMIN_PORT (default 5056) — Admin HTTP server port
|
|
||||||
- LOG_LEVEL — winston log level (info/debug/...)
|
- LOG_LEVEL — winston log level (info/debug/...)
|
||||||
- STEAM_WEB_API_KEY — Steam Web API key (if you plan to use Steam verification)
|
- STEAM_WEB_API_KEY — Steam Web API key (if you plan to use Steam verification)
|
||||||
- RECNET_VERIFY_URL — RecNet verification endpoint to POST { token }
|
- RECNET_VERIFY_URL — RecNet verification endpoint to POST { token }
|
||||||
- SQLITE_FILE — path for the SQLite DB file (default ./helium.db)
|
- SQLITE_FILE — path for the SQLite DB file (default ./helium.db)
|
||||||
- ADMIN_USER / ADMIN_PASS — optional Basic auth for admin console
|
|
||||||
|
|
||||||
How to run:
|
How to run:
|
||||||
1. Copy `.env.example` to `.env` and fill in the variables you need.
|
1. Copy `.env.example` to `.env` and fill in the variables you need.
|
||||||
2. npm install
|
2. npm install
|
||||||
3. npm start
|
3. npm start
|
||||||
4. Admin console: http://localhost:5056 (use basic auth if ADMIN_USER/ADMIN_PASS set)
|
|
||||||
|
|
||||||
Notes about Photon & Rec Room:
|
Notes about Photon & Rec Room:
|
||||||
- The client uses Photon; this skeleton provides a WebSocket entry point you can use for reverse engineering and testing. Photon traffic is binary and has its own framing — you'll need to implement Photon protocol handling inside src/protocol.js (or add a UDP/TCP transport if Photon expects that).
|
- The client uses Photon; this skeleton provides a WebSocket entry point you can use for reverse engineering and testing. Photon traffic is binary and has its own framing — you'll need to implement Photon protocol handling inside src/protocol.js (or add a UDP/TCP transport if Photon expects that).
|
||||||
- You said you can replace Photon keys and localhost yourself — good. Put the Photon server host/port to point to this process and replace any required AppId/AppVersion in the client.
|
- You said you can replace Photon keys & localhost yourself — point the client at this process and replace any required AppId/AppVersion in the client.
|
||||||
|
|
||||||
Next steps I can take after you confirm:
|
Next steps I can take after you confirm:
|
||||||
- Implement Photon framing and basic handshake to accept a 2023 Rec Room client (requires packet captures or protocol docs).
|
- Implement Photon framing and basic handshake to accept a 2023 Rec Room client (requires packet captures or protocol docs).
|
||||||
|
|||||||
+2
-5
@@ -5,16 +5,13 @@
|
|||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node src/index.js",
|
"start": "node src/index.js",
|
||||||
"dev": "nodemon src/index.js",
|
"dev": "nodemon src/index.js"
|
||||||
"admin": "node src/admin.js"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"dotenv": "^16.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"winston": "^3.8.0",
|
"winston": "^3.8.0",
|
||||||
"express": "^4.18.2",
|
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6"
|
||||||
"basic-auth": "^2.0.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-49
@@ -1,50 +1,5 @@
|
|||||||
const express = require('express');
|
// The admin console was intentionally removed from the project per repository owner request.
|
||||||
const basicAuth = require('basic-auth');
|
// If you need to restore it later, re-add an admin HTTP server (e.g., using express) and
|
||||||
const logger = require('./logger');
|
// provide ADMIN_USER / ADMIN_PASS environment variables for basic auth.
|
||||||
|
|
||||||
let serverInstance;
|
module.exports = {};
|
||||||
|
|
||||||
function ensureAuth(req, res, next) {
|
|
||||||
if (!process.env.ADMIN_USER || !process.env.ADMIN_PASS) return next();
|
|
||||||
const user = basicAuth(req);
|
|
||||||
if (!user || user.name !== process.env.ADMIN_USER || user.pass !== process.env.ADMIN_PASS) {
|
|
||||||
res.set('WWW-Authenticate', 'Basic realm="HeliumRecAdmin"');
|
|
||||||
return res.status(401).send('Authentication required');
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function start({ port = 5056, getConnections }) {
|
|
||||||
const app = express();
|
|
||||||
app.use(express.json());
|
|
||||||
|
|
||||||
app.get('/health', (req, res) => res.json({ ok: true }));
|
|
||||||
|
|
||||||
app.use(ensureAuth);
|
|
||||||
|
|
||||||
app.get('/connections', (req, res) => {
|
|
||||||
const conns = [];
|
|
||||||
const map = getConnections();
|
|
||||||
map.forEach((v, k) => {
|
|
||||||
conns.push({ id: k, user: v.user, connectedAt: v.connectedAt, remote: v.ws?._meta?.remote });
|
|
||||||
});
|
|
||||||
res.json(conns);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/broadcast', (req, res) => {
|
|
||||||
const { message } = req.body || {};
|
|
||||||
if (!message) return res.status(400).json({ error: 'message required' });
|
|
||||||
const map = getConnections();
|
|
||||||
let sent = 0;
|
|
||||||
map.forEach((v) => {
|
|
||||||
try { v.ws.send(typeof message === 'string' ? message : JSON.stringify(message)); sent++; } catch (e) { logger.warn('broadcast failed', e.message); }
|
|
||||||
});
|
|
||||||
res.json({ sent });
|
|
||||||
});
|
|
||||||
|
|
||||||
serverInstance = app.listen(port, () => logger.info(`Admin console listening on http://0.0.0.0:${port}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
function stop() { if (serverInstance) serverInstance.close(); }
|
|
||||||
|
|
||||||
module.exports = { start, stop };
|
|
||||||
|
|||||||
+15
-6
@@ -8,16 +8,28 @@ const logger = require('./logger');
|
|||||||
const protocol = require('./protocol');
|
const protocol = require('./protocol');
|
||||||
const auth = require('./auth');
|
const auth = require('./auth');
|
||||||
const storage = require('./storage');
|
const storage = require('./storage');
|
||||||
const admin = require('./admin');
|
|
||||||
|
|
||||||
const PORT = process.env.PORT || 5055;
|
const PORT = process.env.PORT || 5055;
|
||||||
const ADMIN_PORT = process.env.ADMIN_PORT || 5056;
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
await storage.init();
|
await storage.init();
|
||||||
|
|
||||||
// Start WebSocket server on its own HTTP server so we can inspect req.url
|
// Start WebSocket server on its own HTTP server so we can inspect req.url
|
||||||
const server = http.createServer();
|
const server = http.createServer((req, res) => {
|
||||||
|
// Provide a minimal informational page for HTTP GETs so browsers don't see "Cannot GET /"
|
||||||
|
if (req.method === 'GET' && (req.url === '/' || req.url === '/index.html')) {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||||
|
res.end(`<html><body>
|
||||||
|
<h1>HeliumRecServer</h1>
|
||||||
|
<p>This port is a WebSocket endpoint. Connect using a WebSocket client.</p>
|
||||||
|
<p>Server listens on ws://0.0.0.0:${PORT}</p>
|
||||||
|
</body></html>`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// leave other requests to return 404
|
||||||
|
res.writeHead(404); res.end('Not Found');
|
||||||
|
});
|
||||||
|
|
||||||
const wss = new WebSocket.Server({ noServer: true });
|
const wss = new WebSocket.Server({ noServer: true });
|
||||||
|
|
||||||
const connections = new Map(); // key -> { ws, user }
|
const connections = new Map(); // key -> { ws, user }
|
||||||
@@ -79,7 +91,4 @@ const ADMIN_PORT = process.env.ADMIN_PORT || 5056;
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.listen(PORT, () => logger.info(`HeliumRecServer WebSocket listening on ws://0.0.0.0:${PORT}`));
|
server.listen(PORT, () => logger.info(`HeliumRecServer WebSocket listening on ws://0.0.0.0:${PORT}`));
|
||||||
|
|
||||||
// Start admin console (HTTP) bound to ADMIN_PORT
|
|
||||||
admin.start({ port: ADMIN_PORT, getConnections: () => connections });
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user