From 0cbc6935db6058bb7726a99c7bd149c10dad5a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Mon, 22 Sep 2025 23:29:30 +0200 Subject: [PATCH] use login?expired=true for unauthorized logout --- src/app/login/page.tsx | 86 ++++-------------------------- src/components/login/LoginForm.tsx | 82 ++++++++++++++++++++++++++++ src/lib/api/client/base.ts | 2 +- src/lib/auth/server.ts | 2 +- 4 files changed, 95 insertions(+), 77 deletions(-) create mode 100644 src/components/login/LoginForm.tsx diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 8578791..2a1d25a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,79 +1,15 @@ -'use client'; +import { Suspense } from 'react'; +import LoginForm from '@/components/login/LoginForm'; +export const dynamic = 'force-dynamic'; -import { loginAction, LoginResult, clearExpiredSessionAction } from '@/lib/actions/auth'; -import { useActionState, useEffect } from 'react'; -import { useSearchParams } from 'next/navigation'; - -const initialState: LoginResult = { - message: '', - success: true -}; - -export default function LoginPage() { - const searchParams = useSearchParams(); - const expired = searchParams.get('expired') === 'true'; - const [state, formAction] = useActionState(loginAction, initialState); - - useEffect(() => { - if (expired) { - clearExpiredSessionAction(); - } - }, [expired]); +export default function LoginPage({ + searchParams +}: { + searchParams: Promise<{ expired: boolean | undefined }>; +}) { return ( -
-
-
-

ACC Server Manager

-

Sign in to manage your servers

-
- {expired && ( -
- Your session has expired. Please sign in again. -
- )} - {state?.success ? null : ( -
- {state?.message} -
- )} - -
-
- - -
- -
- - -
- - -
-
-
+ Loading...}> + + ); } diff --git a/src/components/login/LoginForm.tsx b/src/components/login/LoginForm.tsx new file mode 100644 index 0000000..cb0e6fe --- /dev/null +++ b/src/components/login/LoginForm.tsx @@ -0,0 +1,82 @@ +'use client'; + +import { clearExpiredSessionAction, loginAction, LoginResult } from '@/lib/actions/auth'; +import { use, useActionState, useEffect } from 'react'; + +const initialState: LoginResult = { + message: '', + success: true +}; + +export default function LoginForm({ + searchParams +}: { + searchParams: Promise<{ expired: boolean | undefined }>; +}) { + const params = use(searchParams); + const expired = params.expired; + + useEffect(() => { + if (expired) { + clearExpiredSessionAction(); + } + }, [expired]); + const [state, formAction] = useActionState(loginAction, initialState); + return ( +
+
+
+

ACC Server Manager

+

Sign in to manage your servers

+
+ {expired && ( +
+ Your session has expired. Please sign in again. +
+ )} + {state?.success ? null : ( +
+ {state?.message} +
+ )} + +
+
+ + +
+ +
+ + +
+ + +
+
+
+ ); +} diff --git a/src/lib/api/client/base.ts b/src/lib/api/client/base.ts index 2d75aaa..740121c 100644 --- a/src/lib/api/client/base.ts +++ b/src/lib/api/client/base.ts @@ -49,7 +49,7 @@ export async function fetchClientAPI( if (!response.ok) { if (response.status === 401) { - window.location.href = '/login'; + window.location.href = '/login?expired=true'; return { error: 'unauthorized' }; } throw new Error(`API Error: ${response.statusText} - ${method} - ${BASE_URL}${endpoint}`); diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index 5caa26f..7374ac2 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -12,7 +12,7 @@ export async function requireAuth(skipRedirect?: boolean) { const session = await getSession(); if (!skipRedirect && (!session.token || !session.user)) { - redirect('/login'); + redirect('/login?expired=true'); } return session;