import { createRoute, z } from '@hono/zod-openapi'; import { logger } from '../commons/logger.js'; import { getBanList, unbanIP, unbanUser, getViolationStats } from '../middleware/autoBan.js'; export const restartRoute = createRoute({ method: 'post', path: '/api/admin/system/restart', tags: ['Admin'], summary: 'Restart the server', description: 'Exits the process with code 0, relying on systemd to restart it.', responses: { 200: { description: 'Restart initiated', content: { 'application/json': { schema: z.object({ message: z.string(), pid: z.number() }) } } } } }); export const restartHandler = async (c) => { const pid = process.pid; // Use a slight delay to allow the response to be sent setTimeout(() => { logger.info('Exiting process for restart...'); process.exit(0); }, 1000); return c.json({ message: 'Server is restarting...', pid }); }; // Ban List Routes export const getBanListRoute = createRoute({ method: 'get', path: '/api/admin/bans', tags: ['Admin'], summary: 'Get current ban list', description: 'Returns all auto-banned IPs, users, and tokens', responses: { 200: { description: 'Ban list retrieved', content: { 'application/json': { schema: z.object({ bannedIPs: z.array(z.string()), bannedUserIds: z.array(z.string()), bannedTokens: z.array(z.string()) }) } } } } }); export const getBanListHandler = async (c) => { const banList = getBanList(); logger.info({ user: c.get('user') }, 'Admin retrieved ban list'); return c.json(banList); }; export const unbanIPRoute = createRoute({ method: 'post', path: '/api/admin/bans/unban-ip', tags: ['Admin'], summary: 'Unban an IP address', description: 'Removes an IP from the auto-ban list', request: { body: { content: { 'application/json': { schema: z.object({ ip: z.string() }) } } } }, responses: { 200: { description: 'IP unbanned successfully', content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } } } } }); export const unbanIPHandler = async (c) => { const { ip } = await c.req.json(); const success = unbanIP(ip); logger.info({ user: c.get('user'), ip, success }, 'Admin attempted to unban IP'); return c.json({ success, message: success ? `IP ${ip} has been unbanned` : `IP ${ip} was not found in ban list` }); }; export const unbanUserRoute = createRoute({ method: 'post', path: '/api/admin/bans/unban-user', tags: ['Admin'], summary: 'Unban a user', description: 'Removes a user from the auto-ban list', request: { body: { content: { 'application/json': { schema: z.object({ userId: z.string() }) } } } }, responses: { 200: { description: 'User unbanned successfully', content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } } } } }); export const unbanUserHandler = async (c) => { const { userId } = await c.req.json(); const success = unbanUser(userId); logger.info({ user: c.get('user'), userId, success }, 'Admin attempted to unban user'); return c.json({ success, message: success ? `User ${userId} has been unbanned` : `User ${userId} was not found in ban list` }); }; export const getViolationStatsRoute = createRoute({ method: 'get', path: '/api/admin/bans/violations', tags: ['Admin'], summary: 'Get violation statistics', description: 'Returns current violation tracking data', responses: { 200: { description: 'Violation stats retrieved', content: { 'application/json': { schema: z.object({ totalViolations: z.number(), violations: z.array(z.object({ key: z.string(), count: z.number(), firstViolation: z.number(), lastViolation: z.number() })) }) } } } } }); export const getViolationStatsHandler = async (c) => { const stats = getViolationStats(); return c.json(stats); }; export const registerAdminRoutes = (app) => { app.openapi(restartRoute, restartHandler); app.openapi(getBanListRoute, getBanListHandler); app.openapi(unbanIPRoute, unbanIPHandler); app.openapi(unbanUserRoute, unbanUserHandler); app.openapi(getViolationStatsRoute, getViolationStatsHandler); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRtaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZW5kcG9pbnRzL2FkbWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBZSxXQUFXLEVBQUUsQ0FBQyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDL0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQzdDLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDBCQUEwQixDQUFBO0FBRTVGLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxXQUFXLENBQUM7SUFDcEMsTUFBTSxFQUFFLE1BQU07SUFDZCxJQUFJLEVBQUUsMkJBQTJCO0lBQ2pDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQztJQUNmLE9BQU8sRUFBRSxvQkFBb0I7SUFDN0IsV0FBVyxFQUFFLGtFQUFrRTtJQUMvRSxTQUFTLEVBQUU7UUFDUCxHQUFHLEVBQUU7WUFDRCxXQUFXLEVBQUUsbUJBQW1CO1lBQ2hDLE9BQU8sRUFBRTtnQkFDTCxrQkFBa0IsRUFBRTtvQkFDaEIsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUM7d0JBQ2IsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUU7d0JBQ25CLEdBQUcsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFO3FCQUNsQixDQUFDO2lCQUNMO2FBQ0o7U0FDSjtLQUNKO0NBQ0osQ0FBQyxDQUFBO0FBRUYsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBRSxDQUFNLEVBQUUsRUFBRTtJQUMzQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFBO0lBQ3ZCLHNEQUFzRDtJQUN0RCxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ1osTUFBTSxDQUFDLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFBO1FBQzdDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFD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