diff --git a/src/api/apiService.ts b/src/api/apiService.ts index 0ab9874..9597179 100644 --- a/src/api/apiService.ts +++ b/src/api/apiService.ts @@ -18,7 +18,7 @@ async function fetchAPI(endpoint: string, method: string = 'GET', body?: object, }); if (!response.ok) { - if (endpoint != '/api' && response.status == 401) { + if (response.status == 401) { authStore.set({ username: undefined, password: undefined, @@ -40,11 +40,15 @@ export async function fetchAPIEvent( method: string = 'GET', body?: object ) { - const { - data: { token } - } = await redisSessionManager.getSession(event.cookies); + if (!event.cookies) { + redirect(308, '/login'); + } + const session = await redisSessionManager.getSession(event.cookies); + if (!session?.data?.token) { + redirect(308, '/login'); + } - return fetchAPI(endpoint, method, body, { Authorization: `Bearer ${token}` }); + return fetchAPI(endpoint, method, body, { Authorization: `Bearer ${session.data.token}` }); } export default fetchAPI; diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 4984e15..09be455 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -3,6 +3,14 @@ import { redisSessionManager } from '$stores/redisSessionManager'; import { env } from '$env/dynamic/private'; import type Redis from 'ioredis'; +const USER_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes + +interface SessionData { + token?: string; + user?: any; + userFetchedAt?: number; +} + export const handle: Handle = async ({ event, resolve }) => { // Ensure redis is connected const redisClient: Redis = redisSessionManager['redisClient']; @@ -11,36 +19,50 @@ export const handle: Handle = async ({ event, resolve }) => { await redisClient.connect(); } catch (err) { console.error('Redis connection failed', err); - // We can still continue without a user session, but log the error. } } // Get session from cookie const session = await redisSessionManager.getSession(event.cookies); + const sessionData: SessionData = session?.data || {}; - if (session && session.data && session.data.token) { - try { - // Fetch user data from /api/me - const response = await fetch(`${env.API_BASE_URL}/auth/me`, { - headers: { - Authorization: `Bearer ${session.data.token}` - } - }); + if (!sessionData.token) { + event.locals.user = null; + return resolve(event); + } - if (response.ok) { - const user = await response.json(); - event.locals.user = user; - } else { - console.log(await response.text(), response.status); - // Token might be invalid/expired, clear it - event.locals.user = null; - await redisSessionManager.deleteCookie(event.cookies); - } - } catch (error) { - console.error('Failed to fetch user:', error); - event.locals.user = null; + // Check if cached user data is still valid + if (sessionData.user && sessionData.userFetchedAt) { + const isExpired = Date.now() - sessionData.userFetchedAt > USER_CACHE_DURATION; + if (!isExpired) { + event.locals.user = sessionData.user; + return resolve(event); } - } else { + } + + // Fetch fresh user data + try { + const response = await fetch(`${env.API_BASE_URL}/auth/me`, { + headers: { + Authorization: `Bearer ${sessionData.token}` + } + }); + + if (response.ok) { + const user = await response.json(); + event.locals.user = user; + + // Cache user data in session + sessionData.user = user; + sessionData.userFetchedAt = Date.now(); + await redisSessionManager.createSession(event.cookies, sessionData, user.id); + } else { + // Token invalid, clear session + event.locals.user = null; + await redisSessionManager.deleteCookie(event.cookies); + } + } catch (error) { + console.error('Failed to fetch user:', error); event.locals.user = null; } diff --git a/src/routes/dashboard/+page.server.ts b/src/routes/dashboard/+page.server.ts index 4cc40a4..5a170f3 100644 --- a/src/routes/dashboard/+page.server.ts +++ b/src/routes/dashboard/+page.server.ts @@ -3,8 +3,6 @@ import { getServers, restartService, startService, stopService } from '$api/serv import { fail, redirect, type Actions, type RequestEvent } from '@sveltejs/kit'; export const load = async (event: RequestEvent) => { - const isAuth = await checkAuth(event); - if (!isAuth) return redirect(308, '/login'); const servers = await getServers(event); return { servers }; }; diff --git a/src/routes/dashboard/server/[id]/+page.server.ts b/src/routes/dashboard/server/[id]/+page.server.ts index 7e4afc4..1c63935 100644 --- a/src/routes/dashboard/server/[id]/+page.server.ts +++ b/src/routes/dashboard/server/[id]/+page.server.ts @@ -15,8 +15,6 @@ import { subDays, formatISO } from 'date-fns'; import { UTCDate } from '@date-fns/utc'; export const load = async (event: RequestEvent) => { - const isAuth = await checkAuth(event); - if (!isAuth) return redirect(308, '/login'); if (!event.params.id) return redirect(308, '/dashboard'); const today = new UTCDate(); const endDate = formatISO(today);