106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
/**
|
|
* @fileoverview Route registration module for Aurora API.
|
|
* Aggregates all route handlers and provides a unified request handler.
|
|
*/
|
|
|
|
import type { RouteContext, RouteModule } from "./types";
|
|
import { authRoutes, isAuthenticated, getSession } from "./auth.routes";
|
|
import { healthRoutes } from "./health.routes";
|
|
import { statsRoutes } from "./stats.routes";
|
|
import { actionsRoutes } from "./actions.routes";
|
|
import { questsRoutes } from "./quests.routes";
|
|
import { settingsRoutes } from "./settings.routes";
|
|
import { guildSettingsRoutes } from "./guild-settings.routes";
|
|
import { itemsRoutes } from "./items.routes";
|
|
import { usersRoutes } from "./users.routes";
|
|
import { classesRoutes } from "./classes.routes";
|
|
import { moderationRoutes } from "./moderation.routes";
|
|
import { transactionsRoutes } from "./transactions.routes";
|
|
import { lootdropsRoutes } from "./lootdrops.routes";
|
|
import { assetsRoutes } from "./assets.routes";
|
|
import { errorResponse } from "./utils";
|
|
|
|
/** Routes that do NOT require authentication */
|
|
const publicRoutes: RouteModule[] = [
|
|
authRoutes,
|
|
healthRoutes,
|
|
];
|
|
|
|
/** Routes that require an authenticated admin session */
|
|
const protectedRoutes: RouteModule[] = [
|
|
statsRoutes,
|
|
actionsRoutes,
|
|
questsRoutes,
|
|
settingsRoutes,
|
|
guildSettingsRoutes,
|
|
itemsRoutes,
|
|
usersRoutes,
|
|
classesRoutes,
|
|
moderationRoutes,
|
|
transactionsRoutes,
|
|
lootdropsRoutes,
|
|
assetsRoutes,
|
|
];
|
|
|
|
/**
|
|
* Main request handler that routes requests to appropriate handlers.
|
|
*
|
|
* @param req - The incoming HTTP request
|
|
* @param url - Parsed URL object
|
|
* @returns Response from matching route handler, or null if no match
|
|
*
|
|
* @example
|
|
* const response = await handleRequest(req, url);
|
|
* if (response) return response;
|
|
* return new Response("Not Found", { status: 404 });
|
|
*/
|
|
export async function handleRequest(req: Request, url: URL): Promise<Response | null> {
|
|
const ctx: RouteContext = {
|
|
req,
|
|
url,
|
|
method: req.method,
|
|
pathname: url.pathname,
|
|
};
|
|
|
|
// Try public routes first (auth, health)
|
|
for (const module of publicRoutes) {
|
|
const response = await module.handler(ctx);
|
|
if (response !== null) return response;
|
|
}
|
|
|
|
// For API routes, enforce authentication
|
|
if (ctx.pathname.startsWith("/api/")) {
|
|
const session = getSession(req);
|
|
if (!session) {
|
|
return errorResponse("Unauthorized", 401);
|
|
}
|
|
|
|
// Admin-only routes: everything except stats and own user data
|
|
const playerAllowedPrefixes = ["/api/stats", "/api/health"];
|
|
const isPlayerAllowed = playerAllowedPrefixes.some(p => ctx.pathname.startsWith(p));
|
|
|
|
// Players can access their own user data
|
|
const isOwnUserRoute = ctx.pathname.match(/^\/api\/users\/\d+/) && session.role === "player";
|
|
|
|
if (session.role === "player" && !isPlayerAllowed && !isOwnUserRoute) {
|
|
return errorResponse("Admin access required", 403);
|
|
}
|
|
}
|
|
|
|
// Try protected routes
|
|
for (const module of protectedRoutes) {
|
|
const response = await module.handler(ctx);
|
|
if (response !== null) return response;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get list of all registered route module names.
|
|
* Useful for debugging and documentation.
|
|
*/
|
|
export function getRegisteredRoutes(): string[] {
|
|
return [...publicRoutes, ...protectedRoutes].map(m => m.name);
|
|
}
|