From 221e9d1f53f1e871dd81cccc00cb5724fcb9a297 Mon Sep 17 00:00:00 2001 From: aewing Date: Sat, 10 Jan 2026 19:39:57 +0000 Subject: [PATCH] fixed request for reauth on clicking show folder --- backend/server.ts | 13 +++++-------- frontend/index.html | 7 ++++--- frontend/signin.html | 26 ++++++++++++++++++++++++++ frontend/token-manager.js | 33 +++++++++------------------------ 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/backend/server.ts b/backend/server.ts index 08e3357..e2c6575 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -34,9 +34,9 @@ const getGraphToken = (c?: any) => { const headerToken = c?.req?.header ? c.req.header('x-graph-token') : ''; const envToken = process.env.GRAPH_TOKEN || process.env.MS_GRAPH_TOKEN || ''; const token = headerToken || envToken; - console.log('[getGraphToken] Header token:', headerToken ? headerToken.substring(0, 20) + '...' : 'NONE'); - console.log('[getGraphToken] Env token:', envToken ? 'SET' : 'NOT SET'); - console.log('[getGraphToken] Using:', token ? token.substring(0, 20) + '...' : 'NONE'); + if (!headerToken && !envToken) { + console.warn('[getGraphToken] No token available in header or environment'); + } return token; }; @@ -120,18 +120,15 @@ const filterByCategory = (items: DriveItem[], category?: string) => { // List/search job files via Graph using a shared folder link app.get('/api/job-files', async (c) => { try { - console.log('[job-files] Request received'); const token = getGraphToken(c); if (!token) { - console.log('[job-files] No token found'); - return c.json({ error: 'GRAPH_TOKEN missing' }, 500); + console.error('[job-files] No Graph token available (not in header or env)'); + return c.json({ error: 'Graph access token required. Please sign in again.' }, 401); } - console.log('[job-files] Token found:', token.substring(0, 20) + '...'); const link = c.req.query('link'); const q = c.req.query('q') || ''; const category = c.req.query('category') || ''; if (!link) return c.json({ error: 'link required' }, 400); - console.log('[job-files] Link:', link); const { driveId, itemId } = await resolveShareLink(link, token); diff --git a/frontend/index.html b/frontend/index.html index 2a38afd..a5cbcf8 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -880,7 +880,6 @@ const iframeViewerModal = document.getElementById('iframeViewerModal'); const iframeViewer = document.getElementById('iframeViewer'); const iframeLoader = document.getElementById('iframeLoader'); - iframeLoader.style.display = 'none'; // disable loader overlay entirely const iframeTitle = document.getElementById('iframeTitle'); const iframeBackBtn = document.getElementById('iframeBackBtn'); const iframeCloseBtn = document.getElementById('iframeCloseBtn'); @@ -1354,12 +1353,14 @@ iframeTitle.textContent = job.Job_Number ? `Job# ${job.Job_Number}` : 'Job Files'; fileListContainer.classList.remove('hidden'); iframeViewer.classList.add('hidden'); + pdfViewer.classList.add('hidden'); // Check if we have cached files const cached = fileCache.get(link); if (cached) { console.log('Using cached files for job', job.Job_Number); fileListState.items = cached.items; + iframeLoader.classList.add('hidden'); renderFileGroups(link); return; } @@ -1393,8 +1394,8 @@ } } - // If still unauthorized or server missing token, prefer stale cache or open-in-new-tab without forcing reauth - if (resp.status === 401 || resp.status === 500) { + // If still unauthorized, prefer stale cache or open-in-new-tab without forcing reauth + if (resp.status === 401) { const cachedAgain = fileCache.get(link); if (cachedAgain) { fileListState.items = cachedAgain.items; diff --git a/frontend/signin.html b/frontend/signin.html index bc074b3..25a21d1 100644 --- a/frontend/signin.html +++ b/frontend/signin.html @@ -58,9 +58,35 @@ errorEl.classList.add('hidden'); try { + // Step 1: Authenticate with PocketBase via Microsoft OAuth const authData = await pb.collection('users').authWithOAuth2({ provider: 'microsoft', }); + + // Step 2: Try to get Graph token from PB response + let graphToken = ( + authData?.meta?.graphAccessToken || + authData?.meta?.graph_token || + authData?.meta?.graphToken || + authData?.meta?.accessToken || + authData?.meta?.access_token || + authData?.meta?.token || + '' + ); + + // Step 3: If no Graph token from PB, use the OAuth token as the Graph token + // (PB's Microsoft OAuth should return a token that works with Graph API) + if (!graphToken && authData?.meta?.rawUser) { + // The OAuth token from Microsoft should work for Graph API calls + graphToken = authData?.token || authData?.meta?.accessToken || ''; + } + + if (graphToken) { + const expiresAt = authData?.meta?.graphTokenExpiresAt || new Date(Date.now() + 3600000).toISOString(); + await tokenManager.setToken(graphToken, expiresAt); + console.log('[Login] Graph token stored successfully'); + } + displayUserInfo(authData); } catch (error) { console.error('Login failed:', error); diff --git a/frontend/token-manager.js b/frontend/token-manager.js index 9f014be..90c75f8 100644 --- a/frontend/token-manager.js +++ b/frontend/token-manager.js @@ -136,18 +136,15 @@ class TokenManager { */ async refreshToken() { if (this.isRefreshing) { - console.log('[TokenManager] Refresh already in progress'); return this.token; // Return existing token while refresh ongoing } if (!this.pb?.authStore?.isValid) { - console.log('[TokenManager] PB session invalid, cannot refresh'); return null; } this.isRefreshing = true; try { - console.log('[TokenManager] Refreshing token...'); const authData = await this.pb.collection('users').authRefresh(); const meta = authData?.meta || {}; @@ -156,17 +153,16 @@ class TokenManager { if (newToken) { await this.setToken(newToken, newExpiry); - console.log('[TokenManager] Token refreshed successfully'); - this.retryAttempts = 0; // Reset retry counter on success + this.retryAttempts = 0; return newToken; } else { - console.warn('[TokenManager] No token in refresh response'); - return null; + // PB authRefresh doesn't return Graph tokens - this is expected + // Token must be obtained during initial OAuth flow + return this.token; // Return existing token if we have one } } catch (err) { - console.error('[TokenManager] Refresh failed:', err.message); - this.queueRefreshRetry(); - return this.token; // Return stale token while retrying + console.error('[TokenManager] PB authRefresh failed:', err.message); + return this.token; // Return stale token on error } finally { this.isRefreshing = false; } @@ -176,20 +172,9 @@ class TokenManager { * Queue retry with exponential backoff */ queueRefreshRetry() { - if (this.retryAttempts >= this.maxRetries) { - console.error('[TokenManager] Max refresh retries reached'); - return; - } - - this.retryAttempts++; - const backoffMs = Math.pow(2, this.retryAttempts - 1) * 1000; // 1s, 2s, 4s, 8s, 16s - console.log(`[TokenManager] Retry ${this.retryAttempts}/${this.maxRetries} in ${backoffMs}ms`); - - setTimeout(() => { - this.refreshToken().catch(err => { - console.error('[TokenManager] Retry failed:', err.message); - }); - }, backoffMs); + // Disable retry queue since PB authRefresh won't return Graph tokens + // Graph tokens must be obtained through the initial OAuth flow + return; } /**