This commit is contained in:
2026-03-19 18:27:09 +07:00
parent 791b46a21e
commit b4e89d644c
4 changed files with 60 additions and 2 deletions

View File

@@ -11,7 +11,7 @@ import { usersRouter } from "../modules/users/users.routes.js";
import { rolesRouter } from "../modules/roles/roles.routes.js"; import { rolesRouter } from "../modules/roles/roles.routes.js";
import { permissionsRouter } from "../modules/permissions/permissions.routes.js"; import { permissionsRouter } from "../modules/permissions/permissions.routes.js";
import { connectionsRouter } from "../modules/connections/connections.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"; import { requireAuth } from "../middleware/auth.js";
export const apiRouter = Router(); export const apiRouter = Router();
@@ -30,4 +30,4 @@ apiRouter.use("/users", usersRouter);
apiRouter.use("/roles", rolesRouter); apiRouter.use("/roles", rolesRouter);
apiRouter.use("/permissions", permissionsRouter); apiRouter.use("/permissions", permissionsRouter);
apiRouter.use("/connections", connectionsRouter); apiRouter.use("/connections", connectionsRouter);
apiRouter.use("/logs", logsRouter); apiRouter.use("/logs", logViewerRouter);

View 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);
}
}
);

View 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)
});

View 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
};
}