google-labs-jules[bot] 589e146ecc feat(routes): decompose admin and auth monolith routes
Extracted domain-specific sub-routers from monolithic `server/routes/admin.ts` and `server/routes/auth.ts` into isolated modules within `server/routes/admin/` and `server/routes/auth/` respectively. The original entry routers were updated to import and assemble these sub-routers without breaking their current HTTP interface or rate limiting/authorization middleware. Testing and linting were run ensuring perfect functionality and 100% test passing score.

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-26 04:37:26 +00:00

158 lines
4.6 KiB
TypeScript

import { Hono } from "jsr:@hono/hono@4";
import { encodeBase64Url } from "jsr:@std/encoding@1/base64url";
import { sqlWrapper } from "../../db.ts";
import { auditWrapper } from "../../audit.ts";
import { getAuthenticatedUser } from "../../auth-session.ts";
import { getClientIp } from "../../middleware.ts";
export const invitesAdminRoutes = new Hono();
invitesAdminRoutes.get("/", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const invites = await sqlWrapper.sql`
SELECT i.id, i.code, i.role, i.max_uses, i.uses_count, i.auto_activate, i.expires_at, i.created_at, i.used_at,
a.name AS app_name, a.id AS app_id,
u.username AS used_by_username
FROM invites i
LEFT JOIN apps a ON i.app_id = a.id
LEFT JOIN users u ON i.used_by = u.id
ORDER BY i.created_at DESC
`;
return c.json({ invites });
});
invitesAdminRoutes.post("/create", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const {
appId,
role,
expiresInDays,
customCode,
usageLimitType,
maxUses,
autoActivate,
} = await c.req.json();
const assignedRole = (typeof role === "string" && role.trim())
? role.trim()
: "user";
let validatedAppId = null;
if (appId) {
const uuidRegex =
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
if (typeof appId !== "string" || !uuidRegex.test(appId)) {
return c.json({ error: "appId must be a valid UUID string" }, 400);
}
const appExists = await sqlWrapper
.sql`SELECT id FROM apps WHERE id = ${appId}`.then(
(res: any) => res[0],
);
if (!appExists) {
return c.json({ error: "Target application does not exist" }, 404);
}
validatedAppId = appId;
}
let parsedMaxUses: number | null = 1;
if (usageLimitType === "unlimited") {
parsedMaxUses = null;
} else if (usageLimitType === "limited") {
const n = parseInt(maxUses);
parsedMaxUses = (!isNaN(n) && n > 0) ? n : 5;
} else {
parsedMaxUses = 1; // single-use default
}
const shouldAutoActivate = autoActivate !== false;
const inviteCode =
(customCode && typeof customCode === "string" && customCode.trim())
? customCode.trim()
: encodeBase64Url(crypto.getRandomValues(new Uint8Array(24)));
const days = Number(expiresInDays) || 7;
if (!Number.isInteger(days) || days < 1 || days > 30) {
return c.json({
error: "expiresInDays must be an integer between 1 and 30",
}, 400);
}
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + days);
try {
await sqlWrapper.sql`
INSERT INTO invites (code, app_id, role, created_by, max_uses, uses_count, auto_activate, expires_at)
VALUES (${inviteCode}, ${validatedAppId}, ${assignedRole}, ${auth.userId}, ${parsedMaxUses}, 0, ${shouldAutoActivate}, ${expiresAt})
`;
} catch (err: any) {
if (err.code === "23505") {
return c.json({ error: "An invite with this code already exists" }, 409);
}
return c.json({ error: "Failed to generate invite" }, 500);
}
auditWrapper.auditLog(
auth.userId,
"invite_created",
validatedAppId,
{
code: inviteCode,
role: assignedRole,
max_uses: parsedMaxUses,
auto_activate: shouldAutoActivate,
expiresInDays: days,
},
getClientIp(c),
);
return c.json({
success: true,
inviteCode,
expiresAt,
maxUses: parsedMaxUses,
autoActivate: shouldAutoActivate,
});
});
invitesAdminRoutes.get("/:id/redemptions", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const inviteId = c.req.param("id");
const redemptions = await sqlWrapper.sql`
SELECT ir.id, ir.redeemed_at, u.id AS user_id, u.username, u.display_name, u.account_status
FROM invite_redemptions ir
JOIN users u ON ir.user_id = u.id
WHERE ir.invite_id = ${inviteId}
ORDER BY ir.redeemed_at DESC
`;
return c.json({ redemptions });
});
invitesAdminRoutes.delete("/:id", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const inviteId = c.req.param("id");
const invite = await sqlWrapper
.sql`DELETE FROM invites WHERE id = ${inviteId} RETURNING id, code`
.then((res: any) => res[0]);
if (invite) {
auditWrapper.auditLog(
auth.userId,
"invite_revoked",
inviteId,
{ code: invite.code },
getClientIp(c),
);
return c.json({ success: true });
}
return c.json({ error: "Invite not found" }, 404);
});