From c6e7f6bb784f80030341dead63038ed45e4c8258 Mon Sep 17 00:00:00 2001 From: sudipnext Date: Wed, 22 Apr 2026 12:43:17 +0545 Subject: [PATCH] refactor: streamline authentication handling and remove deprecated components, enhancing session management in Next.js middleware --- .../app/(presentation-generator)/layout.tsx | 13 +-- servers/nextjs/app/layout.tsx | 11 +- servers/nextjs/app/not-found.tsx | 84 ++++++++------ servers/nextjs/app/schema/layout.tsx | 11 ++ servers/nextjs/components/Auth/AuthGate.tsx | 23 ++-- .../components/Auth/ProtectedRouteGuard.tsx | 77 ------------- servers/nextjs/middleware.ts | 107 ++++-------------- servers/nextjs/utils/serverAuth.ts | 78 +++++++++++++ 8 files changed, 173 insertions(+), 231 deletions(-) create mode 100644 servers/nextjs/app/schema/layout.tsx delete mode 100644 servers/nextjs/components/Auth/ProtectedRouteGuard.tsx create mode 100644 servers/nextjs/utils/serverAuth.ts diff --git a/servers/nextjs/app/(presentation-generator)/layout.tsx b/servers/nextjs/app/(presentation-generator)/layout.tsx index d05021cc..35d8ec3f 100644 --- a/servers/nextjs/app/(presentation-generator)/layout.tsx +++ b/servers/nextjs/app/(presentation-generator)/layout.tsx @@ -1,16 +1,13 @@ import React from "react"; -import ProtectedRouteGuard from "@/components/Auth/ProtectedRouteGuard"; +import { requireAppSession } from "@/utils/serverAuth"; import { ConfigurationInitializer } from "../ConfigurationInitializer"; -const layout = ({ children }: { children: React.ReactNode }) => { +export default async function Layout({ children }: { children: React.ReactNode }) { + await requireAppSession(); return (
- - {children} - + {children}
); -}; - -export default layout; +} diff --git a/servers/nextjs/app/layout.tsx b/servers/nextjs/app/layout.tsx index 7a70334b..3ff8b3ef 100644 --- a/servers/nextjs/app/layout.tsx +++ b/servers/nextjs/app/layout.tsx @@ -1,6 +1,6 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; -import { Syne, Unbounded } from "next/font/google"; +import { Syne } from "next/font/google"; import "./globals.css"; import { Providers } from "./providers"; import MixpanelInitializer from "./MixpanelInitializer"; @@ -22,13 +22,6 @@ const syne = Syne({ variable: "--font-syne", }); -const unbounded = Unbounded({ - subsets: ["latin"], - weight: ["400", "500", "600", "700", "800"], - variable: "--font-unbounded", -}); - - export const metadata: Metadata = { metadataBase: new URL("https://presenton.ai"), title: "Presenton - Open Source AI presentation generator", @@ -82,7 +75,7 @@ export default function RootLayout({ return ( diff --git a/servers/nextjs/app/not-found.tsx b/servers/nextjs/app/not-found.tsx index 869552eb..831cdb66 100644 --- a/servers/nextjs/app/not-found.tsx +++ b/servers/nextjs/app/not-found.tsx @@ -1,39 +1,51 @@ -import React from 'react'; -import Link from 'next/link'; -import { Button } from '@/components/ui/button'; +import type { Metadata } from "next"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; -const NotFound = () => { - return ( -
-
- Page not found -

- Oops! Page Not Found -

-

- It seems you've found a page that doesn't exist. But don't worry, every great presentation starts with a blank slide! -

- -
- - - - - - -
- -
-
- ); +export const metadata: Metadata = { + title: "Page not found | Presenton", }; -export default NotFound; \ No newline at end of file +/** + * Unknown routes only. Keep the 404.svg inside a fixed max height + object-contain + * so the illustration never scales to full-viewport (the old w-3/4-only layout could). + */ +export default function NotFound() { + return ( +
+
+
+ Page not found +
+

+ Oops! Page Not Found +

+

+ It seems you've found a page that doesn't exist. But don't worry, every + great presentation starts with a blank slide! +

+ +
+ + + + + + +
+
+
+ ); +} diff --git a/servers/nextjs/app/schema/layout.tsx b/servers/nextjs/app/schema/layout.tsx new file mode 100644 index 00000000..23afd152 --- /dev/null +++ b/servers/nextjs/app/schema/layout.tsx @@ -0,0 +1,11 @@ +import type { ReactNode } from "react"; + +import { requireAppSession } from "@/utils/serverAuth"; + +/** + * /schema is outside the (presentation-generator) group; same session gate as the main app. + */ +export default async function SchemaLayout({ children }: { children: ReactNode }) { + await requireAppSession(); + return <>{children}; +} diff --git a/servers/nextjs/components/Auth/AuthGate.tsx b/servers/nextjs/components/Auth/AuthGate.tsx index bc9be868..88b880d2 100644 --- a/servers/nextjs/components/Auth/AuthGate.tsx +++ b/servers/nextjs/components/Auth/AuthGate.tsx @@ -5,6 +5,7 @@ import { ConfigurationInitializer } from "@/app/ConfigurationInitializer"; import Home from "@/components/Home"; import { getApiUrl } from "@/utils/api"; import { formatFastApiDetail, UNAUTHORIZED_DETAIL } from "@/utils/authErrors"; +import { toast } from "sonner"; type AuthStatus = { configured: boolean; @@ -26,8 +27,6 @@ export default function AuthGate() { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); - const [blockedAccessMessage, setBlockedAccessMessage] = useState(null); - const isSetupMode = useMemo(() => !status.configured, [status.configured]); useEffect(() => { @@ -40,9 +39,12 @@ export default function AuthGate() { } const params = new URLSearchParams(window.location.search); if (params.get("reason") === "unauthorized") { - setBlockedAccessMessage(UNAUTHORIZED_DETAIL); - const clean = `${window.location.pathname}`; - window.history.replaceState({}, "", clean); + toast.error("Unauthorized", { + id: "auth-unauthorized-redirect", + description: "Sign in to view this page.", + duration: 5000, + }); + window.history.replaceState({}, "", window.location.pathname); } }, []); @@ -78,7 +80,6 @@ export default function AuthGate() { const handleSubmit = async (event: FormEvent) => { event.preventDefault(); setError(null); - setBlockedAccessMessage(null); const cleanedUsername = username.trim(); if (cleanedUsername.length < 3) { @@ -154,7 +155,7 @@ export default function AuthGate() {
Presenton
-

Presenton

+

Presenton

Preparing your workspace…

@@ -203,7 +204,7 @@ export default function AuthGate() {

Secure instance

-

+

{isSetupMode ? "Create your admin login" : "Sign in to continue"}

@@ -216,12 +217,6 @@ export default function AuthGate() { : "This deployment is protected. Enter your credentials to open the app."}

- {blockedAccessMessage ? ( -
- {blockedAccessMessage}. All other routes require a valid session. -
- ) : null} -