import { convexAuthNextjsMiddleware, createRouteMatcher, nextjsMiddlewareRedirect } from "@convex-dev/auth/nextjs/server"; import { isDevAuthEnabled } from "@/lib/auth/devUser"; // 说明: // - 这里启用 Convex Auth 的 Next.js 中间件,负责: // 1) 代理 /api/auth 到 Convex(用于 signIn / signOut 等动作) // 2) 刷新/同步 auth cookies // 3) 对需要登录的页面做统一拦截 // - 默认将未登录用户重定向到 /auth(Convex Auth 登录页)。 const isPublicRoute = createRouteMatcher([ "/auth", "/login", // 说明:仅用于本地/联调的页面选项回归入口(Playwright 会用它验证页面选项是否真正生效)。 // 该路由不写入后端数据,放行可避免 E2E 因鉴权/数据初始化问题被阻塞。 "/dev/page-options-playground", "/api/auth(.*)", // 说明:ONLYOFFICE 文档服务器(容器/远端)拉取文件与回调保存不携带用户态,必须放行。 "/api/onlyoffice/proxy(.*)", "/api/onlyoffice/callback(.*)", // 说明:/onlyoffice-server 与 /cache 主要承载 ONLYOFFICE 静态资源与二进制缓存。 // 这些资源不依赖用户态,且需要浏览器强缓存;若经过 Auth middleware 可能被追加 no-store,导致每次都重下几十 MB。 "/onlyoffice-server(.*)", // 说明:本地自定义 ONLYOFFICE 插件页面运行在同源 /onlyoffice/plugins/* 下,由文档编辑器 iframe 直接加载。 // 若被鉴权重定向到 /auth,会导致插件桥永远收不到 ready。 "/onlyoffice/plugins(.*)", "/cache(.*)", "/api/health(.*)", "/_next(.*)", "/favicon.ico", ]); export default convexAuthNextjsMiddleware(async (request, ctx) => { // 公共路由不做拦截(但 middleware 仍会处理 token 刷新/代理等)。 if (isPublicRoute(request)) return; // 只在启用 Convex 模式时做鉴权拦截;否则走 Supabase 逻辑(页面内部自行处理)。 // 注意:middleware 运行在 Edge/Node 环境中,读取到的是运行期环境变量。 if (process.env.NEXT_PUBLIC_USE_CONVEX !== "1") return; // 开发用户模式下允许“免登录”访问(主要用于迁移/联调与 E2E 回归)。 // 注意:生产环境请勿开启 MNOTE_DEV_AUTH。 if (isDevAuthEnabled()) return; const authed = await ctx.convexAuth.isAuthenticated(); if (!authed) { return nextjsMiddlewareRedirect(request, "/auth"); } }); export const config = { // 说明:排除静态资源,避免无意义的中间件开销。 matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"], };