mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-02 21:32:10 +03:00
- Rename 254 .js files to .ts (domain, lib, services, stores, API routes, etc.) - Rename 133 .js files to .tsx (components, pages, layouts) - Fix ~230 import references (remove .js extensions from internal imports) - Fix 10 open-sse cross-references to @/lib/ and ../../src/ paths - Add TypeScript interfaces to Card, Modal, Button, and notificationStore - Install tsx for test runner (handles extensionless .ts imports in Node ESM) - Update test:unit script to use tsx/esm loader - Update test imports from .js to .ts (20 files) - Add typescript.ignoreBuildErrors in next.config.mjs for gradual migration - Create src/types/global.d.ts for env vars and untyped modules - Update tsconfig.json (jsx: preserve, forceConsistentCasingInFileNames) Results: - Build: ✓ compiles in ~40s - Tests: ✓ 368/368 pass (100%) - Zero .js files remain in src/
79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { jwtVerify } from "jose";
|
|
import { generateRequestId } from "./shared/utils/requestId";
|
|
import { getSettings } from "./lib/localDb";
|
|
|
|
// FASE-01: Fail-fast — no hardcoded fallback. Server must have JWT_SECRET configured.
|
|
if (!process.env.JWT_SECRET) {
|
|
console.error("[SECURITY] JWT_SECRET is not set. Authentication will fail.");
|
|
}
|
|
|
|
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
|
|
|
|
export async function proxy(request) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// Pipeline: Add request ID header for end-to-end tracing
|
|
const requestId = generateRequestId();
|
|
const response = NextResponse.next();
|
|
response.headers.set("X-Request-Id", requestId);
|
|
|
|
// Protect all dashboard routes (except onboarding)
|
|
if (pathname.startsWith("/dashboard")) {
|
|
// Always allow onboarding — it has its own setupComplete guard
|
|
if (pathname.startsWith("/dashboard/onboarding")) {
|
|
return response;
|
|
}
|
|
|
|
const token = request.cookies.get("auth_token")?.value;
|
|
|
|
if (token) {
|
|
try {
|
|
await jwtVerify(token, SECRET);
|
|
return response;
|
|
} catch (err) {
|
|
// FASE-01: Log auth errors instead of silently redirecting
|
|
console.error("[Middleware] auth_error: JWT verification failed:", err.message, {
|
|
path: pathname,
|
|
tokenPresent: true,
|
|
requestId,
|
|
});
|
|
return NextResponse.redirect(new URL("/login", request.url));
|
|
}
|
|
}
|
|
|
|
try {
|
|
// Direct import — no HTTP self-fetch overhead
|
|
const settings = await getSettings();
|
|
// Skip auth if login is not required
|
|
if (settings.requireLogin === false) {
|
|
return response;
|
|
}
|
|
// Skip auth if no password has been set yet (fresh install with no env override)
|
|
// This prevents an unresolvable loop where requireLogin=true but no password exists
|
|
if (!settings.password && !process.env.INITIAL_PASSWORD) {
|
|
return response;
|
|
}
|
|
} catch (err) {
|
|
// FASE-01: Log settings fetch errors instead of silencing them
|
|
console.error("[Middleware] settings_error: Settings read failed:", err.message, {
|
|
path: pathname,
|
|
requestId,
|
|
});
|
|
// On error, require login
|
|
}
|
|
return NextResponse.redirect(new URL("/login", request.url));
|
|
}
|
|
|
|
// Redirect / to /dashboard if logged in, or /dashboard if it's the root
|
|
if (pathname === "/") {
|
|
return NextResponse.redirect(new URL("/dashboard", request.url));
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ["/", "/dashboard/:path*"],
|
|
};
|