432
This commit is contained in:
@@ -11,7 +11,7 @@ import { usersRouter } from "../modules/users/users.routes.js";
|
||||
import { rolesRouter } from "../modules/roles/roles.routes.js";
|
||||
import { permissionsRouter } from "../modules/permissions/permissions.routes.js";
|
||||
import { connectionsRouter } from "../modules/connections/connections.routes.js";
|
||||
import { logsRouter } from "../modules/logs/logs.routes.js";
|
||||
import { logViewerRouter } from "../modules/log-viewer/log-viewer.routes.js";
|
||||
import { requireAuth } from "../middleware/auth.js";
|
||||
|
||||
export const apiRouter = Router();
|
||||
@@ -30,4 +30,4 @@ apiRouter.use("/users", usersRouter);
|
||||
apiRouter.use("/roles", rolesRouter);
|
||||
apiRouter.use("/permissions", permissionsRouter);
|
||||
apiRouter.use("/connections", connectionsRouter);
|
||||
apiRouter.use("/logs", logsRouter);
|
||||
apiRouter.use("/logs", logViewerRouter);
|
||||
|
||||
29
backend/src/modules/log-viewer/log-viewer.routes.ts
Normal file
29
backend/src/modules/log-viewer/log-viewer.routes.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Router } from "express";
|
||||
import { ok } from "../../lib/api-response.js";
|
||||
import { requirePermission } from "../../middleware/permission.js";
|
||||
import { validateQuery } from "../../middleware/validate.js";
|
||||
import { logViewerQuerySchema } from "./log-viewer.schemas.js";
|
||||
import { listLogEntries } from "./log-viewer.service.js";
|
||||
|
||||
export const logViewerRouter = Router();
|
||||
|
||||
logViewerRouter.get(
|
||||
"/",
|
||||
requirePermission("logs", "view_logs"),
|
||||
validateQuery(logViewerQuerySchema),
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
const query = req.query as unknown as { q: string; severity: string; page: number; limit: number };
|
||||
const result = await listLogEntries(query);
|
||||
res.json(
|
||||
ok(result.data, {
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
limit: result.limit
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
8
backend/src/modules/log-viewer/log-viewer.schemas.ts
Normal file
8
backend/src/modules/log-viewer/log-viewer.schemas.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const logViewerQuerySchema = z.object({
|
||||
q: z.string().optional().default(""),
|
||||
severity: z.string().optional().default(""),
|
||||
page: z.coerce.number().default(1),
|
||||
limit: z.coerce.number().default(100)
|
||||
});
|
||||
21
backend/src/modules/log-viewer/log-viewer.service.ts
Normal file
21
backend/src/modules/log-viewer/log-viewer.service.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { env } from "../../config/env.js";
|
||||
import { getPagination } from "../../lib/pagination.js";
|
||||
|
||||
export async function listLogEntries(query: { q: string; severity: string; page: number; limit: number }) {
|
||||
const raw = await readFile(env.LOG_SOURCE_PATH, "utf8").catch(() => "");
|
||||
const lines = raw.split(/\r?\n/).filter(Boolean);
|
||||
const filtered = lines.filter((line) => {
|
||||
const matchesText = !query.q || line.toLowerCase().includes(query.q.toLowerCase());
|
||||
const matchesSeverity = !query.severity || line.toLowerCase().includes(query.severity.toLowerCase());
|
||||
return matchesText && matchesSeverity;
|
||||
});
|
||||
const pagination = getPagination(query.page, query.limit);
|
||||
|
||||
return {
|
||||
data: filtered.slice(pagination.offset, pagination.offset + pagination.limit),
|
||||
total: filtered.length,
|
||||
page: pagination.page,
|
||||
limit: pagination.limit
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user