fix(auth): prevent unexpected logout during file upload#48
Merged
Conversation
… tasks Add new test modules for management commands (assign_owners, create_api_key, create_test_users), project service, and user service. Extend existing tests for authentication (scope permissions, ambiguous prefix), data upload (preview endpoint, cross-owner access), event views (API key access control, slot/project mismatch), serializers, schedule service, and Celery tasks (training, tuning, scheduled retraining, error handling). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ctively - Add ensureFreshToken() to auth store: checks token expiry and refreshes if within 60 seconds of expiry, preventing stale-token upload failures - Add visibilitychange listener: re-schedules proactive refresh when the tab regains focus, covering tokens that expired in background tabs - Add 401 retry in DataUploadPage: if the XHR returns 401 (token expired mid-upload), refresh the token and retry the upload once automatically - Attach .status to XHR errors so the 401 can be detected in catch blocks - Update tests: switch nextTick → flushPromises for async ensureFreshToken, add 23 new tests covering all new behaviours Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Users were being unexpectedly "logged out" while uploading files. The root cause:
DataUploadPageuses rawXMLHttpRequestwhich bypasses the API client's automatic token refresh. If the access token expired between page load and upload completion, the XHR returned 401 — which surfaced as an upload error that looked like a logout.Changes Made
frontend/src/stores/auth.tsensureFreshToken(): New exported method that checks if the access token expires within 60 seconds and proactively refreshes it. Returnstrueif a valid token is available after the check,falseif not authenticated.visibilitychangelistener: When a browser tab regains focus, re-invokesscheduleProactiveRefresh(). SincescheduleProactiveRefreshalready handlesdelay <= 0by refreshing immediately, this naturally handles tokens that expired while the tab was backgrounded (wheresetTimeoutwas throttled by the browser).frontend/src/pages/DataUploadPage.vueauthStore.ensureFreshToken()before starting the XHR, ensuring the token is fresh at upload time..statusto XHR errors so the retry logic can identify 401s specifically (vs. 400, 403, 500, etc.).frontend/src/__tests__/stores/auth.test.ts&DataUploadPage.test.tsnextTick→flushPromisesafteremitUploadercalls (needed becauseensureFreshTokenis now async)ensureFreshToken(8 cases),visibilitychange(3 cases), pre-upload refresh (2 cases), 401 retry (8 cases), error status property (2 cases)Testing
npm run test:unit)vue-tsc --noEmitpasses with no type errorsACCESS_TOKEN_LIFETIME=60, login, wait ~55s, upload a file → upload succeeds instead of showing a 401 errorBreaking Changes
None.
ensureFreshTokenis additive; existing behaviour ofrefreshAccessTokenandscheduleProactiveRefreshis unchanged.Additional Notes
visibilitychangelistener is registered once per store instance; since the auth store is a singleton via Pinia, there's no risk of duplicate listeners