From e53f3ae528ca189f6d6b29baee0e04da147614f2 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sat, 20 Dec 2025 11:11:46 +0000
Subject: fix: add authentication checks to settings layout (#2274)

The settings layout was missing authentication checks, causing server
errors when unauthenticated users tried to access any settings page.
This fix adds:

- Session verification via getServerAuthSession()
- Redirect to "/" if no session exists
- Proper error handling with tryCatch wrapper
- Redirect to "/logout" for NOT_FOUND or UNAUTHORIZED errors

This brings the settings layout in line with the auth patterns used
in dashboard, admin, and reader layouts.

Fixes #2242

Co-authored-by: Claude <noreply@anthropic.com>
---
 apps/web/app/settings/layout.tsx | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

(limited to 'apps/web/app/settings/layout.tsx')

diff --git a/apps/web/app/settings/layout.tsx b/apps/web/app/settings/layout.tsx
index 0124becf..8d211e53 100644
--- a/apps/web/app/settings/layout.tsx
+++ b/apps/web/app/settings/layout.tsx
@@ -1,9 +1,12 @@
+import { redirect } from "next/navigation";
 import MobileSidebar from "@/components/shared/sidebar/MobileSidebar";
 import Sidebar from "@/components/shared/sidebar/Sidebar";
 import SidebarLayout from "@/components/shared/sidebar/SidebarLayout";
 import { ReaderSettingsProvider } from "@/lib/readerSettings";
 import { UserSettingsContextProvider } from "@/lib/userSettings";
 import { api } from "@/server/api/client";
+import { getServerAuthSession } from "@/server/auth";
+import { TRPCError } from "@trpc/server";
 import { TFunction } from "i18next";
 import {
   ArrowLeft,
@@ -22,6 +25,7 @@ import {
 } from "lucide-react";
 
 import serverConfig from "@karakeep/shared/config";
+import { tryCatch } from "@karakeep/shared/tryCatch";
 
 const settingsSidebarItems = (
   t: TFunction,
@@ -112,9 +116,27 @@ export default async function SettingsLayout({
 }: Readonly<{
   children: React.ReactNode;
 }>) {
-  const userSettings = await api.users.settings();
+  const session = await getServerAuthSession();
+  if (!session) {
+    redirect("/");
+  }
+
+  const userSettings = await tryCatch(api.users.settings());
+
+  if (userSettings.error) {
+    if (userSettings.error instanceof TRPCError) {
+      if (
+        userSettings.error.code === "NOT_FOUND" ||
+        userSettings.error.code === "UNAUTHORIZED"
+      ) {
+        redirect("/logout");
+      }
+    }
+    throw userSettings.error;
+  }
+
   return (
-    <UserSettingsContextProvider userSettings={userSettings}>
+    <UserSettingsContextProvider userSettings={userSettings.data}>
       <ReaderSettingsProvider>
         <SidebarLayout
           sidebar={<Sidebar items={settingsSidebarItems} />}
-- 
cgit v1.2.3-70-g09d2

