From b8961b85c504fbdf295cbf19945f391115eac33d Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sat, 28 Feb 2026 22:18:55 +0100 Subject: [PATCH] fix: reduce unauthenticated log noise and add request path context --- src/app/layout.tsx | 47 ++++++++++++++++----------- src/lib/services/favorites.service.ts | 25 +++++++++++--- src/middleware.ts | 9 +++-- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7e79296..3ac0314 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,7 +7,7 @@ import { PreferencesService } from "@/lib/services/preferences.service"; import { PreferencesProvider } from "@/contexts/PreferencesContext"; import { I18nProvider } from "@/components/providers/I18nProvider"; import { AuthProvider } from "@/components/providers/AuthProvider"; -import { cookies } from "next/headers"; +import { cookies, headers } from "next/headers"; import { defaultPreferences } from "@/types/preferences"; import type { UserPreferences } from "@/types/preferences"; import type { KomgaLibrary, KomgaSeries } from "@/types/komga"; @@ -70,7 +70,10 @@ export const metadata: Metadata = { export default async function RootLayout({ children }: { children: React.ReactNode }) { const cookieStore = await cookies(); + const requestHeaders = await headers(); const locale = cookieStore.get("NEXT_LOCALE")?.value || "fr"; + const requestPath = requestHeaders.get("x-request-path") || "unknown"; + const requestPathname = requestHeaders.get("x-request-pathname") || "unknown"; let preferences: UserPreferences = defaultPreferences; let userIsAdmin = false; @@ -78,30 +81,36 @@ export default async function RootLayout({ children }: { children: React.ReactNo let favorites: KomgaSeries[] = []; try { - const [preferencesData, isAdminCheck, librariesData, favoritesData] = await Promise.allSettled([ - PreferencesService.getPreferences(), - import("@/lib/auth-utils").then((m) => m.isAdmin()), - import("@/lib/services/library.service").then((m) => m.LibraryService.getLibraries()), - import("@/lib/services/favorites.service").then((m) => m.FavoritesService.getFavorites()), - ]); + const currentUser = await import("@/lib/auth-utils").then((m) => m.getCurrentUser()); - if (preferencesData.status === "fulfilled") { - preferences = preferencesData.value; - } + if (currentUser) { + const [preferencesData, librariesData, favoritesData] = await Promise.allSettled([ + PreferencesService.getPreferences(), + import("@/lib/services/library.service").then((m) => m.LibraryService.getLibraries()), + import("@/lib/services/favorites.service").then((m) => + m.FavoritesService.getFavorites({ requestPath, requestPathname }) + ), + ]); - if (isAdminCheck.status === "fulfilled") { - userIsAdmin = isAdminCheck.value; - } + userIsAdmin = currentUser.roles.includes("ROLE_ADMIN"); - if (librariesData.status === "fulfilled") { - libraries = librariesData.value || []; - } + if (preferencesData.status === "fulfilled") { + preferences = preferencesData.value; + } - if (favoritesData.status === "fulfilled") { - favorites = favoritesData.value; + if (librariesData.status === "fulfilled") { + libraries = librariesData.value || []; + } + + if (favoritesData.status === "fulfilled") { + favorites = favoritesData.value; + } } } catch (error) { - logger.error({ err: error }, "Erreur lors du chargement des données initiales:"); + logger.error( + { err: error, requestPath, requestPathname }, + "Erreur lors du chargement des données initiales:" + ); } return ( diff --git a/src/lib/services/favorites.service.ts b/src/lib/services/favorites.service.ts index 2fc3912..cc7f0e8 100644 --- a/src/lib/services/favorites.service.ts +++ b/src/lib/services/favorites.service.ts @@ -4,7 +4,10 @@ import type { KomgaSeries } from "@/types/komga"; import logger from "@/lib/logger"; export class FavoritesService { - static async getFavorites(): Promise { + static async getFavorites(context?: { + requestPath?: string; + requestPathname?: string; + }): Promise { try { const favoriteIds = await FavoriteService.getAllFavoriteIds(); @@ -17,7 +20,15 @@ export class FavoritesService { try { return await SeriesService.getSeries(id); } catch (error) { - logger.error({ err: error, seriesId: id }, "Error fetching favorite series"); + logger.error( + { + err: error, + seriesId: id, + requestPath: context?.requestPath, + requestPathname: context?.requestPathname, + }, + "Error fetching favorite series" + ); // Si la série n'existe plus, la retirer des favoris try { await FavoriteService.removeFromFavorites(id); @@ -31,9 +42,15 @@ export class FavoritesService { const results = await Promise.all(promises); return results.filter((series): series is KomgaSeries => series !== null); } catch (error) { - logger.error({ err: error }, "Error fetching favorites"); + logger.error( + { + err: error, + requestPath: context?.requestPath, + requestPathname: context?.requestPathname, + }, + "Error fetching favorites" + ); return []; } } } - diff --git a/src/middleware.ts b/src/middleware.ts index bfc27fe..b82f7c4 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -13,6 +13,11 @@ const defaultLocale = "fr"; export default async function middleware(request: NextRequest) { const { pathname } = request.nextUrl; + const requestPath = `${pathname}${request.nextUrl.search}`; + const forwardedHeaders = new Headers(request.headers); + forwardedHeaders.set("x-request-pathname", pathname); + forwardedHeaders.set("x-request-path", requestPath); + const createNextResponse = () => NextResponse.next({ request: { headers: forwardedHeaders } }); // Gestion de la langue let locale = request.headers.get("cookie")?.match(/NEXT_LOCALE=([^;]+)/)?.[1]; @@ -34,7 +39,7 @@ export default async function middleware(request: NextRequest) { pathname === "/favicon.svg" || pathname === "/favicon.ico" ) { - return NextResponse.next(); + return createNextResponse(); } // Vérifier l'authentification avec NextAuth v5 @@ -59,7 +64,7 @@ export default async function middleware(request: NextRequest) { } // Définir le cookie de langue si nécessaire - const response = NextResponse.next(); + const response = createNextResponse(); if (!request.headers.get("cookie")?.includes("NEXT_LOCALE") && locale) { response.cookies.set("NEXT_LOCALE", locale, { path: "/",