( sessionManager: SessionManager, userStore: UserStore, )
| 24 | } |
| 25 | |
| 26 | export function createAdminRouter( |
| 27 | sessionManager: SessionManager, |
| 28 | userStore: UserStore, |
| 29 | ): Router { |
| 30 | const router = Router(); |
| 31 | |
| 32 | // All admin routes require admin role. |
| 33 | router.use(requireAdmin); |
| 34 | |
| 35 | // ── Dashboard UI ────────────────────────────────────────────────────────── |
| 36 | |
| 37 | router.get("/", (_req, res) => { |
| 38 | try { |
| 39 | const p = join(import.meta.dirname, "public/admin.html"); |
| 40 | res.setHeader("Content-Type", "text/html"); |
| 41 | res.send(readFileSync(p, "utf8")); |
| 42 | } catch { |
| 43 | res.setHeader("Content-Type", "text/html"); |
| 44 | res.send(INLINE_ADMIN_HTML); |
| 45 | } |
| 46 | }); |
| 47 | |
| 48 | // ── API: all active sessions ────────────────────────────────────────────── |
| 49 | |
| 50 | /** |
| 51 | * GET /admin/sessions |
| 52 | * Returns all active sessions across all users. |
| 53 | */ |
| 54 | router.get("/sessions", (_req, res) => { |
| 55 | const sessions = sessionManager.getAllSessions().map((s) => ({ |
| 56 | id: s.token, |
| 57 | userId: s.userId, |
| 58 | createdAt: s.created, |
| 59 | ageMs: Date.now() - new Date(s.created).getTime(), |
| 60 | alive: s.alive, |
| 61 | })); |
| 62 | res.json({ sessions }); |
| 63 | }); |
| 64 | |
| 65 | // ── API: all connected users ────────────────────────────────────────────── |
| 66 | |
| 67 | /** |
| 68 | * GET /admin/users |
| 69 | * Returns all users that currently have at least one active session. |
| 70 | */ |
| 71 | router.get("/users", (_req, res) => { |
| 72 | res.json({ users: userStore.list() }); |
| 73 | }); |
| 74 | |
| 75 | // ── API: force-kill a session ───────────────────────────────────────────── |
| 76 | |
| 77 | /** |
| 78 | * DELETE /admin/sessions/:token |
| 79 | * Force-kills the specified session regardless of which user owns it. |
| 80 | */ |
| 81 | router.delete("/sessions/:token", (req, res) => { |
| 82 | const { token } = req.params; |
| 83 | const session = sessionManager.getSession(token); |
no test coverage detected