Files
textbee/web/proxy.ts
isra el dbea68ab30 refactor: modernize nextauth wrapper and provider setup
- extract the provider tree into app/(app)/providers.tsx and create the
  QueryClient once via useState (it was rebuilt on every render, discarding
  the cache); remove the old layout-wrapper
- replace the per-navigation whoAmI session check with a global 401 response
  interceptor in httpBrowserClient that routes expired sessions to /logout
- rename middleware.ts -> proxy.ts (Next 16 convention), clearing the
  deprecation warning; auth guard verified by e2e
- fix .env.example: NEXTAUTH_SECRET (was mislabeled AUTH_SECRET) + NEXTAUTH_URL
- add an e2e assertion for the authenticated login -> dashboard redirect

Build, 19 unit tests, and 3 e2e all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 01:40:25 +03:00

67 lines
2.2 KiB
TypeScript

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { getToken } from 'next-auth/jwt'
import { Routes } from './config/routes'
// Next 16 renamed the "middleware" convention to "proxy". This guards the
// dashboard: authenticated routing based on the NextAuth session token.
export async function proxy(request: NextRequest) {
// Extract token using the secret for session-based authentication
const token = await getToken({
req: request,
secret: process.env.NEXTAUTH_SECRET,
})
const { pathname } = request.nextUrl
// if path is /app redirect to login or dashboard based on auth status
if (pathname === '/app') {
if (!token) {
const loginUrl = new URL(Routes.login, request.url)
return NextResponse.redirect(loginUrl)
}
const dashboardUrl = new URL(Routes.dashboard, request.url)
return NextResponse.redirect(dashboardUrl)
}
// Check if the path starts with /app/dashboard
if (pathname.startsWith(Routes.dashboard)) {
if (!token) {
// Redirect to login if not authenticated
const loginUrl = new URL(Routes.login, request.url)
return NextResponse.redirect(loginUrl)
}
}
// If user is authenticated and visiting /app/login or /app/register, redirect to /app/dashboard
if (token && (pathname === Routes.login || pathname === Routes.register)) {
const dashboardUrl = new URL(Routes.dashboard, request.url)
return NextResponse.redirect(dashboardUrl)
}
// Set the pathname in the response headers
const response = NextResponse.next()
response.headers.set('x-pathname', pathname)
request.headers?.set('x-current-url', request.nextUrl?.href ?? '')
return NextResponse.next({
request: {
headers: request.headers,
},
})
}
export const config = {
matcher: [
/*
* Match all request paths except:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - images - .svg, .png, .jpg, .jpeg, .gif, .webp
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
}