feat: secure React dashboard cutover

This commit is contained in:
jjbrunton committed 2026-08-08 15:51:06 +01:00
1 parent a51e0b6b31
commit ad770a792a
9 files changed
+477 -73

No files matched your search

-60
View File
@@ -2,11 +2,6 @@ import { Router } from 'express';
import path from 'path';
import fs from 'fs';
import type { WebContext } from '../context.js';
import {
MatrixClient,
saveCredentials,
type MatrixCredentials,
} from '../../services/chat/index.js';
export function createDebugRouter(ctx: WebContext): Router {
const router = Router();
@@ -41,7 +36,6 @@ export function createDebugRouter(ctx: WebContext): Router {
return;
}
try {
const reveal = req.query.reveal === '1';
const urls = ['https://www.reddit.com', 'https://chat.reddit.com', 'https://matrix.redditspace.com'];
const out: Record<string, unknown> = {};
for (const u of urls) {
@@ -55,7 +49,6 @@ export function createDebugRouter(ctx: WebContext): Router {
sameSite: c.sameSite,
expires: c.expires,
valueLen: c.value.length,
value: reveal ? c.value : undefined,
}));
}
res.json(out);
@@ -65,59 +58,6 @@ export function createDebugRouter(ctx: WebContext): Router {
}
});
// Accepts a Matrix credentials JSON body, persists it to the cache file,
// and swaps it into the running ChatService. Lets us seed the deployed bot
// from a sniff run on a developer's machine when the in-container sniff
// can't reach an authed /chat/ surface and noVNC isn't an option.
//
// Body shape: { homeserver, accessToken, userId?, capturedAt? }
router.post('/debug/matrix-credentials', (req, res) => {
const body = (req.body ?? {}) as Partial<MatrixCredentials>;
if (!body.homeserver || !body.accessToken) {
res.status(400).json({ error: 'homeserver and accessToken are required' });
return;
}
const creds: MatrixCredentials = {
homeserver: body.homeserver,
accessToken: body.accessToken,
userId: body.userId ?? '',
capturedAt: body.capturedAt ?? Date.now(),
};
try {
saveCredentials(creds);
ctx.logger.info(
`[matrix] credentials uploaded via /api/debug/matrix-credentials (user=${creds.userId || 'unknown'})`,
);
if (ctx.services.chat) {
ctx.services.chat.setMatrixClient(new MatrixClient(creds, ctx.logger));
ctx.logger.info('[matrix] uploaded credentials swapped into running ChatService');
}
res.json({ success: true, homeserver: creds.homeserver, userId: creds.userId });
} catch (error) {
ctx.logger.error('Matrix credential upload failed:', error);
res.status(500).json({ error: String(error) });
}
});
router.post('/debug/inspect-dom', async (req, res) => {
if (!ctx.services.chat) {
res.status(500).json({ error: 'Chat service not initialized' });
return;
}
try {
const chatUrl = req.body?.url;
if (!chatUrl) {
res.status(400).json({ error: 'url is required' });
return;
}
const result = await ctx.services.chat.debugInspectDom(chatUrl);
res.json(result);
} catch (error) {
ctx.logger.error('DOM inspection failed:', error);
res.status(500).json({ error: String(error) });
}
});
router.post('/debug/check-responses', async (_req, res) => {
if (!ctx.services.responseChecker) {
res.status(500).json({ error: 'Response checker not initialized' });