feat: add ADMIN_PWD and ALLOWED_GUILD_IDS support

- Add ADMIN_PWD and ALLOWED_GUILD_IDS env vars to config
- Extend PluginContext with adminPwd and allowedGuildIds
- Add adminAuth and guildFilter middleware for plugins
- Add /api/admin/login endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel 2026-03-05 23:48:23 +01:00
parent 1669af1e91
commit 1df780fe60
3 changed files with 58 additions and 1 deletions

View file

@ -0,0 +1,41 @@
import { Request, Response, NextFunction } from 'express';
import type { PluginContext } from './plugin.js';
/**
* Admin authentication middleware.
* Checks `x-admin-password` header against ADMIN_PWD env var.
*/
export function adminAuth(ctx: PluginContext) {
return (req: Request, res: Response, next: NextFunction): void => {
if (!ctx.adminPwd) {
res.status(503).json({ error: 'ADMIN_PWD not configured' });
return;
}
const pwd = req.headers['x-admin-password'] as string | undefined;
if (pwd !== ctx.adminPwd) {
res.status(401).json({ error: 'Unauthorized' });
return;
}
next();
};
}
/**
* Guild filter middleware.
* If ALLOWED_GUILD_IDS is set, only allows requests for those guilds.
* Reads guildId from req.params.guildId or req.body.guildId or req.query.guildId.
*/
export function guildFilter(ctx: PluginContext) {
return (req: Request, res: Response, next: NextFunction): void => {
if (ctx.allowedGuildIds.length === 0) { next(); return; }
const guildId = req.params.guildId ?? req.body?.guildId ?? req.query.guildId;
if (!guildId) { next(); return; }
if (!ctx.allowedGuildIds.includes(String(guildId))) {
res.status(403).json({ error: 'Guild not allowed' });
return;
}
next();
};
}

View file

@ -25,6 +25,8 @@ export interface Plugin {
export interface PluginContext {
client: Client;
dataDir: string;
adminPwd: string;
allowedGuildIds: string[];
}
const loadedPlugins: Plugin[] = [];