From 7d83b1feb4ca215124d123bc3126b705b6cd4236 Mon Sep 17 00:00:00 2001 From: Simon Emanuelsson Date: Wed, 27 Mar 2024 09:33:31 +0100 Subject: [PATCH] fix: split middleware in two, authed and public --- middleware.ts | 128 +++++++++++++++++++++++++++-------------------- routes/public.ts | 2 - types/auth.d.ts | 9 ++++ 3 files changed, 82 insertions(+), 57 deletions(-) delete mode 100644 routes/public.ts diff --git a/middleware.ts b/middleware.ts index 217269d2e..83457883c 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,4 +1,4 @@ -import { NextResponse } from "next/server" +import { NextRequest, NextResponse } from "next/server" import { auth } from "@/auth" @@ -6,12 +6,68 @@ import { findLocale } from "@/constants/locales" import { pageNames } from "@/constants/myPages" import { apiAuthPrefix } from "@/routes/api" -// import { publicRoutes } from "@/routes/public" import { protectedRoutes } from "@/routes/protected" -export default auth(async function middleware(request) { +import type { NextAuthRequest } from "next-auth" + +export async function publiceMiddleware(request: NextRequest) { const { nextUrl } = request + const locale = findLocale(nextUrl.pathname) + + if (nextUrl.pathname.startsWith(`/${locale}/login`)) { + return NextResponse.next() + } + + const contentType = "currentContentPage" + const pathNameWithoutLocale = nextUrl.pathname.replace(`/${locale}`, "") + const searchParams = new URLSearchParams(request.nextUrl.searchParams) + + if (request.nextUrl.pathname.includes("preview")) { + searchParams.set("uri", pathNameWithoutLocale.replace("/preview", "")) + return NextResponse.rewrite( + new URL(`/${locale}/preview-current?${searchParams.toString()}`, nextUrl) + ) + } + + searchParams.set("uri", pathNameWithoutLocale) + switch (contentType) { + case "currentContentPage": + return NextResponse.rewrite( + new URL( + `/${locale}/current-content-page?${searchParams.toString()}`, + nextUrl + ) + ) + } + + // Unreachable atm + return NextResponse.next() +} + +async function authedMiddlewareFunction(request: NextAuthRequest) { + const { nextUrl } = request + const locale = findLocale(nextUrl.pathname)! const isLoggedIn = !!request.auth + if (isLoggedIn) { + /** + * Temporary hard rewrite to my pages + */ + return NextResponse.rewrite( + new URL(`/${locale}/${pageNames[locale]}`, nextUrl) + ) + } else { + /** + * Redirect to Loginpage + * (Loginpage most likely to be removed) + */ + return NextResponse.redirect(new URL(`/${locale}/login`, nextUrl)) + } +} + +const authedMiddleware = auth(authedMiddlewareFunction) + +export async function middleware(request: NextRequest) { + const { nextUrl } = request const isApiRoute = nextUrl.pathname.startsWith(apiAuthPrefix) if (isApiRoute) { @@ -26,59 +82,21 @@ export default auth(async function middleware(request) { const isProtectedRoute = protectedRoutes.includes(nextUrl.pathname) if (isProtectedRoute) { - if (isLoggedIn) { - /** - * Temporary hard rewrite to my pages - */ - return NextResponse.rewrite( - new URL(`/${locale}/${pageNames[locale]}`, nextUrl) - ) - } else { - /** - * Redirect to Loginpage - * (Loginpage most likely to be removed) - */ - return NextResponse.redirect(new URL(`/${locale}/login`, nextUrl)) - } + /** + * AppRouteHandlerFnContext is the context that is passed to the handler as the + * second argument. + * + * type AppRouteHandlerFnContext = { + * params?: Record + * } + * + * We don't need it so just pass an empty object + */ + return authedMiddleware(request, {}) + } else { + return publiceMiddleware(request) } - - if (nextUrl.pathname.startsWith(`/${locale}/login`)) { - return NextResponse.next() - } - - // const isPublicRoute = publicRoutes.includes(nextUrl.pathname) - // if (!isLoggedIn && !isPublicRoute) { - // return NextResponse.redirect(new URL(`/${locale}/login`, nextUrl)) - // } - - //const contentType = data.response.meta.contentType; - const contentType = "currentContentPage" - const pathNameWithoutLocale = nextUrl.pathname.replace(`/${locale}`, "") - const searchParams = new URLSearchParams(request.nextUrl.searchParams) - - if (request.nextUrl.pathname.includes("preview")) { - searchParams.set("uri", pathNameWithoutLocale.replace("/preview", "")) - return NextResponse.rewrite( - new URL( - `/${locale}/preview-current?${searchParams.toString()}`, - request.url - ) - ) - } - - searchParams.set("uri", pathNameWithoutLocale) - switch (contentType) { - case "currentContentPage": - return NextResponse.rewrite( - new URL( - `/${locale}/current-content-page?${searchParams.toString()}`, - request.url - ) - ) - } - - return NextResponse.next() -}) +} // See "Matching Paths" below to learn more export const config = { diff --git a/routes/public.ts b/routes/public.ts deleted file mode 100644 index fc91de55d..000000000 --- a/routes/public.ts +++ /dev/null @@ -1,2 +0,0 @@ -/* Unauthenticated routes */ -export const publicRoutes: string[] = ["/"] diff --git a/types/auth.d.ts b/types/auth.d.ts index 1b6db41a6..13a946865 100644 --- a/types/auth.d.ts +++ b/types/auth.d.ts @@ -1,4 +1,5 @@ import "next-auth" +import type { NextRequest } from "next/server" // Module augmentation // https://authjs.dev/getting-started/typescript#popular-interfaces-to-augment @@ -21,6 +22,14 @@ declare module "next-auth" { * Returned by `useSession`, `auth`, contains information about the active session. */ interface Session {} + + /** + * NextAuthRequest isn't exported by next-auth so we declare a copy + * of how they do it to support or switch in middleware.ts + */ + interface NextAuthRequest extends NextRequest { + auth: Session | null + } } declare module "next-auth/jwt" {