dashboard: add authentication middleware
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9910548c65a11f2c83dfeb4fef3c93f06a6a6964
This commit is contained in:
parent
1bf4bc335c
commit
2db5fa502f
1 changed files with 41 additions and 5 deletions
|
|
@ -9,6 +9,43 @@ export function createDashboardRouter(config: Config): express.Router {
|
||||||
|
|
||||||
router.use(express.json());
|
router.use(express.json());
|
||||||
|
|
||||||
|
// Authentication middleware
|
||||||
|
if (config.dashboard?.auth) {
|
||||||
|
router.use((req, res, next) => {
|
||||||
|
const auth = config.dashboard!.auth!;
|
||||||
|
|
||||||
|
if (auth.type === 'basic') {
|
||||||
|
const authHeader = req.headers.authorization;
|
||||||
|
if (!authHeader || !authHeader.startsWith('Basic ')) {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Troutbot Dashboard"');
|
||||||
|
res.status(401).json({ error: 'Authentication required' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const credentials = Buffer.from(authHeader.slice(6), 'base64').toString('utf8');
|
||||||
|
const [username, password] = credentials.split(':');
|
||||||
|
|
||||||
|
if (username !== auth.username || password !== auth.password) {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Troutbot Dashboard"');
|
||||||
|
res.status(401).json({ error: 'Invalid credentials' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (auth.type === 'token') {
|
||||||
|
const authHeader = req.headers.authorization;
|
||||||
|
const token = req.query.token as string | undefined;
|
||||||
|
|
||||||
|
const providedToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : token;
|
||||||
|
|
||||||
|
if (!providedToken || providedToken !== auth.token) {
|
||||||
|
res.status(401).json({ error: 'Invalid or missing token' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// API routes
|
// API routes
|
||||||
router.get('/api/status', (_req, res) => {
|
router.get('/api/status', (_req, res) => {
|
||||||
const enabledBackends = Object.entries(config.engine.backends)
|
const enabledBackends = Object.entries(config.engine.backends)
|
||||||
|
|
@ -41,9 +78,9 @@ export function createDashboardRouter(config: Config): express.Router {
|
||||||
try {
|
try {
|
||||||
const partial = req.body as Partial<Config>;
|
const partial = req.body as Partial<Config>;
|
||||||
const merged = deepMerge(
|
const merged = deepMerge(
|
||||||
config as Record<string, unknown>,
|
config as unknown as Record<string, unknown>,
|
||||||
partial as Record<string, unknown>
|
partial as unknown as Record<string, unknown>
|
||||||
) as Config;
|
) as unknown as Config;
|
||||||
validate(merged);
|
validate(merged);
|
||||||
|
|
||||||
// Apply in-place
|
// Apply in-place
|
||||||
|
|
@ -55,8 +92,7 @@ export function createDashboardRouter(config: Config): express.Router {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Dashboard HTML ---
|
// Dashboard HTML
|
||||||
|
|
||||||
router.get('/dashboard', (_req, res) => {
|
router.get('/dashboard', (_req, res) => {
|
||||||
res.type('html').send(dashboardHTML());
|
res.type('html').send(dashboardHTML());
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue