From fa685e6ba9a6a788c203f7718f88de20e0d0ce3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Kr=C4=8Dek?= Date: Tue, 2 Sep 2025 18:18:58 +0200 Subject: [PATCH] Added loading indicator --- src/lib/components/GoogleAuthButton.svelte | 13 +++++-- src/lib/google/auth/manager.ts | 37 ++++++++++++++++--- .../private/api/google/auth/check/+server.ts | 32 ++++++++++++++++ 3 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 src/routes/private/api/google/auth/check/+server.ts diff --git a/src/lib/components/GoogleAuthButton.svelte b/src/lib/components/GoogleAuthButton.svelte index 928fcbd..da0ca5d 100644 --- a/src/lib/components/GoogleAuthButton.svelte +++ b/src/lib/components/GoogleAuthButton.svelte @@ -21,8 +21,8 @@ let authState = $state(createGoogleAuthState()); let authManager = new GoogleAuthManager(authState); - onMount(() => { - authManager.checkConnection(); + onMount(async () => { + await authManager.checkConnection(); }); async function handleConnect() { @@ -57,7 +57,14 @@ }; -{#if authState.isConnected} +{#if authState.checking} +
+
+
+ Checking connection... +
+
+{:else if authState.isConnected}
diff --git a/src/lib/google/auth/manager.ts b/src/lib/google/auth/manager.ts index f87901e..54d8a39 100644 --- a/src/lib/google/auth/manager.ts +++ b/src/lib/google/auth/manager.ts @@ -30,7 +30,7 @@ export class GoogleAuthManager { this.state = state; } - checkConnection(): void { + async checkConnection(): Promise { this.state.checking = true; this.state.error = null; @@ -38,12 +38,39 @@ export class GoogleAuthManager { const token = localStorage.getItem('google_refresh_token'); const email = localStorage.getItem('google_user_email'); - this.state.isConnected = !!token; - this.state.token = token; - this.state.userEmail = email; + if (!token) { + this.state.isConnected = false; + this.state.token = null; + this.state.userEmail = null; + return; + } + + // Verify the token by calling our backend endpoint + const response = await fetch('/private/api/google/auth/check', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ refreshToken: token }) + }); + + if (response.ok) { + this.state.isConnected = true; + this.state.token = token; + this.state.userEmail = email; + } else { + // Token is invalid or expired + await this.disconnectGoogle(); + if (response.status === 401) { + this.state.error = 'Google session expired. Please reconnect.'; + } else { + this.state.error = 'Failed to verify connection.'; + } + } } catch (error) { console.error('Error checking connection:', error); - this.state.error = 'Failed to check connection status'; + this.state.error = 'Failed to verify connection status'; + this.state.isConnected = false; } finally { this.state.checking = false; } diff --git a/src/routes/private/api/google/auth/check/+server.ts b/src/routes/private/api/google/auth/check/+server.ts new file mode 100644 index 0000000..9b832fe --- /dev/null +++ b/src/routes/private/api/google/auth/check/+server.ts @@ -0,0 +1,32 @@ +import { json } from '@sveltejs/kit'; +import { getAuthenticatedClient } from '$lib/google/auth/server'; + +/** + * @description Verify the validity of a Google refresh token + * @method POST + * @param {Request} request + * @returns {Response} + */ +export async function POST({ request }: { request: Request }): Promise { + try { + const { refreshToken } = await request.json(); + + if (!refreshToken) { + return json({ error: 'Refresh token is required' }, { status: 400 }); + } + + // Get an authenticated client. This will attempt to get a new access token, + // which effectively validates the refresh token. + const oauth2Client = getAuthenticatedClient(refreshToken); + + // Attempt to get a new access token + await oauth2Client.getAccessToken(); + + // If no error is thrown, the token is valid + return json({ success: true }); + } catch (error) { + console.error('Failed to verify Google refresh token:', error); + // The token is likely invalid or revoked + return json({ error: 'Invalid or expired refresh token' }, { status: 401 }); + } +}