179 lines
12 KiB
JavaScript
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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
|