diff --git a/cache-bust.json b/cache-bust.json index 637b191d..38f4d645 100644 --- a/cache-bust.json +++ b/cache-bust.json @@ -1,5 +1,5 @@ { - "version": "969cdb8dc567be69", + "version": "5be459fb48f09ce6", "generatedBy": "scripts/updateCacheBusting.mjs", "assets": { "assets/app-icon-16.png": "6645731d86da1071", @@ -42,7 +42,7 @@ "src/core/domReady.js": "f385624460b061da", "src/core/dynamicFieldStorage.js": "1ff73616e74c57db", "src/core/fieldAccess.js": "2b23c13ba7c64dc6", - "src/core/fieldDefs.js": "d2591627fb51e4b4", + "src/core/fieldDefs.js": "b83155408257c564", "src/core/formatting/cellDisplayFormatting.js": "be7e1f92547161d8", "src/core/formatting/dataFormatters.js": "01cc0a530b21639c", "src/core/formatting/dateValues.js": "8346afd2fe520d11", @@ -158,7 +158,7 @@ "src/features/templates/data/queryTemplateRepository.js": "76b24ebd79844cf5", "src/features/templates/data/queryTemplateState.js": "cfea7d82eb831bfe", "src/features/templates/data/queryTemplateUiConfig.js": "89542ddf66e29e9f", - "src/features/templates/queryTemplates.js": "948b2105fb218318", + "src/features/templates/queryTemplates.js": "93c038712414291f", "src/features/templates/view/queryTemplateDetailView.js": "6e2a8355b61e2e79", "src/features/templates/view/queryTemplateElements.js": "1eeb873c56db8d39", "src/features/templates/view/queryTemplateListView.js": "2f4f1ac2cd5440d4", @@ -282,7 +282,7 @@ "src/ui/mobileTableControls.js": "7cdf395901b8c776", "src/ui/modalManager.js": "35da15fad2658581", "src/ui/queryAnimation.js": "a39c12407a8bb1d3", - "src/ui/queryBuilderShell.js": "fce746ac4656510c", + "src/ui/queryBuilderShell.js": "61b3e9bacc2468f1", "src/ui/queryTableView.js": "8ef5bf8101a16ffc", "src/ui/queryUI.js": "c82dc41c880a00b2", "src/ui/siteUpdate.js": "195b5eabf5a54404", diff --git a/src/core/fieldDefs.js b/src/core/fieldDefs.js index da604bc0..0fc3c562 100644 --- a/src/core/fieldDefs.js +++ b/src/core/fieldDefs.js @@ -4,6 +4,7 @@ * @module FieldDefs */ import { BackendApi } from './backendApi.js'; +import { getSession } from './authSession.js'; import { getFieldAccessState, isFieldAccessAuthorized, @@ -217,6 +218,8 @@ async function fetchFieldDefinitions() { } async function loadFieldDefinitions() { + const session = getSession(); + if (!session?.token && !session?.cookieSession) return fieldDefsArray; if (isFieldsLoaded) return fieldDefsArray; if (fieldDefinitionsLoadPromise) return fieldDefinitionsLoadPromise; diff --git a/src/features/templates/queryTemplates.js b/src/features/templates/queryTemplates.js index 23f2bc23..9c52acb1 100644 --- a/src/features/templates/queryTemplates.js +++ b/src/features/templates/queryTemplates.js @@ -1,4 +1,5 @@ import { BackendApi } from '../../core/backendApi.js'; +import { getSession } from '../../core/authSession.js'; import { onDOMReady } from '../../core/domReady.js'; import { showToastMessage } from '../../core/toast.js'; import { getClientErrorMessage } from '../../core/clientErrorMessages.js'; @@ -195,6 +196,10 @@ import { escapeHtml } from '../../core/formatting/html.js'; } async function refreshTemplates(options = {}) { + if (!getSession()?.token && !getSession()?.cookieSession) { + render(); + return; + } const force = options.force === true; if (state.loading) { return; diff --git a/src/ui/queryBuilderShell.js b/src/ui/queryBuilderShell.js index 5729ed43..60df7911 100644 --- a/src/ui/queryBuilderShell.js +++ b/src/ui/queryBuilderShell.js @@ -11,6 +11,7 @@ import { import { QueryChangeManager } from '../core/queryState.js'; import { appServices } from '../core/appServices.js'; import { appUiActions, registerAppUiActionDependencies } from '../core/appUiActions.js'; +import { getSession } from '../core/authSession.js'; import { DOM } from '../core/domCache.js'; import { StartupStatus } from './startupStatus.js'; @@ -37,6 +38,10 @@ let QueryBuilderShell; services.closeAllModals(); } + function hasAuthenticatedSession(session = getSession()) { + return Boolean(session?.token || session?.cookieSession); + } + async function initializeBuilderState() { try { console.log('Initializing application for live queries (test data disabled)'); @@ -99,7 +104,19 @@ let QueryBuilderShell; }); initializeBuilderState(); - loadDynamicFields(); + if (hasAuthenticatedSession()) { + loadDynamicFields(); + } else { + StartupStatus.update({ + title: 'Sign in to continue', + detail: 'Field controls will load after your account is verified.' + }); + StartupStatus.complete({ delay: 180 }); + } + + globalThis.addEventListener?.('query-auth:changed', event => { + if (hasAuthenticatedSession(event.detail) && !hasLoadedFieldDefinitions()) void loadDynamicFields(); + }); } QueryBuilderShell = Object.freeze({ diff --git a/tests/browser/browserSmoke.mjs b/tests/browser/browserSmoke.mjs index 49cf7a1a..4330c7d5 100644 --- a/tests/browser/browserSmoke.mjs +++ b/tests/browser/browserSmoke.mjs @@ -2110,6 +2110,9 @@ async function runSmokeTest() { throw new Error('Query History control must remain hidden until the user signs in'); } await signedOutPage.locator('#auth-session-dialog[open]').waitFor({ state: 'visible', timeout: 5000 }); + if (signedOutApiStub.countAction('get_fields') !== 0 || signedOutApiStub.countAction('list_templates') !== 0) { + throw new Error(`Signed-out startup must not request protected data before authentication: ${JSON.stringify(signedOutApiStub.getRequests())}`); + } const signedOutLockState = await signedOutPage.evaluate(() => ({ authRequired: document.body.classList.contains('query-auth-required'), appVisible: Boolean(document.querySelector('#query-app-shell')?.getBoundingClientRect().width),