agent-smith/dist-in/endpoints/admin.js
2026-02-26 19:41:09 +01:00

179 lines
12 KiB
JavaScript

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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