public
anord
read
Ledger
Why work hard when you can work easier?
Languages
Repository composition by tracked source files.
TypeScript
86%
CSS
10%
SQL
3%
Shell
1%
HTML
0%
Trace
apps/api/src/http/routes/admin.ts
Trace helps you understand code history line by line. See who changed each line, when it changed, and which commit introduced it.
Author
Date
Commit
Line
Code
1
import { Router } from "express";
2
import { requireAdmin } from "../middleware/auth.js";
3
import { pool } from "../../db/pool.js";
5
export const adminRouter = Router();
6
adminRouter.use(requireAdmin);
8
adminRouter.get("/users", async (_req, res) => {
9
const result = await pool.query(
10
`
11
SELECT u.id, u.email, u.display_name, r.key AS role_key
12
FROM users u
13
JOIN roles r ON r.id = u.primary_role_id
14
ORDER BY u.created_at ASC
15
`
16
);
17
return res.json({ users: result.rows });
18
});
20
adminRouter.get("/groups", async (_req, res) => {
21
const result = await pool.query(`SELECT * FROM groups ORDER BY name ASC`);
22
return res.json({ groups: result.rows });
23
});
25
adminRouter.get("/feedback", async (_req, res) => {
26
const result = await pool.query(
27
`
28
SELECT f.*, p.title AS page_title
29
FROM feedback f
30
JOIN pages p ON p.id = f.page_id
31
ORDER BY f.created_at DESC
32
LIMIT 100
33
`
34
);
35
return res.json({ feedback: result.rows });
36
});
38
adminRouter.get("/search-analytics", async (_req, res) => {
39
const topSearches = await pool.query(
40
`
41
SELECT query, COUNT(*)::int AS count
42
FROM searches
43
GROUP BY query
44
ORDER BY count DESC, query ASC
45
LIMIT 10
46
`
47
);
49
const noResults = await pool.query(
50
`
51
SELECT query, COUNT(*)::int AS count
52
FROM searches
53
WHERE results_count = 0
54
GROUP BY query
55
ORDER BY count DESC, query ASC
56
LIMIT 10
57
`
58
);
60
return res.json({
61
topSearches: topSearches.rows,
62
noResults: noResults.rows
63
});
64
});
66
adminRouter.get("/activity", async (_req, res) => {
67
const result = await pool.query(
68
`
69
SELECT
70
al.id,
71
al.action,
72
al.resource_type,
73
al.resource_id,
74
al.metadata,
75
al.created_at,
76
COALESCE(u.display_name, 'System') AS actor_name
77
FROM audit_logs al
78
LEFT JOIN users u ON u.id = al.actor_user_id
79
ORDER BY al.created_at DESC
80
LIMIT 100
81
`
82
);
84
return res.json({ activity: result.rows });
85
});