feat: security and auditing

This commit is contained in:
2026-02-04 16:48:08 -08:00
parent 11be34cd21
commit 0a654f423a
42 changed files with 2195 additions and 160 deletions
+85
View File
@@ -0,0 +1,85 @@
/**
* @copyright 2026 NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { FastifyPluginAsync } from "fastify";
import { AuditService } from "../../services/audit.service";
import { adminGuard } from "../../middleware/admin-guard";
import type { AuditAction, AuditCategory } from "@library/shared-types";
interface AuditLogQuery {
action?: AuditAction;
category?: AuditCategory;
userId?: string;
success?: string;
startDate?: string;
endDate?: string;
page?: string;
limit?: string;
}
const auditRoutes: FastifyPluginAsync = async (app) => {
/**
* Get audit logs (admin only).
*/
app.get<{ Querystring: AuditLogQuery }>(
"/",
{
preValidation: [app.authenticate, adminGuard],
},
async (request) => {
const { action, category, userId, success, startDate, endDate, page, limit } = request.query;
return AuditService.getLogs({
action: action as AuditAction | undefined,
category: category as AuditCategory | undefined,
userId,
success: success === undefined ? undefined : success === "true",
startDate: startDate ? new Date(startDate) : undefined,
endDate: endDate ? new Date(endDate) : undefined,
page: page ? parseInt(page, 10) : 1,
limit: limit ? parseInt(limit, 10) : 50,
});
}
);
/**
* Get security logs (admin only).
*/
app.get<{ Querystring: { page?: string; limit?: string } }>(
"/security",
{
preValidation: [app.authenticate, adminGuard],
},
async (request) => {
const { page, limit } = request.query;
return AuditService.getSecurityLogs(
page ? parseInt(page, 10) : 1,
limit ? parseInt(limit, 10) : 50
);
}
);
/**
* Get logs for a specific user (admin only).
*/
app.get<{ Params: { userId: string }; Querystring: { page?: string; limit?: string } }>(
"/user/:userId",
{
preValidation: [app.authenticate, adminGuard],
},
async (request) => {
const { userId } = request.params;
const { page, limit } = request.query;
return AuditService.getLogsByUser(
userId,
page ? parseInt(page, 10) : 1,
limit ? parseInt(limit, 10) : 50
);
}
);
};
export default auditRoutes;