diff --git a/src/app.js b/src/app.js index 93019c29..9233d7b8 100644 --- a/src/app.js +++ b/src/app.js @@ -1650,7 +1650,17 @@ function normalizeSiteApiSecurityPolicy(securityConfig = null) { return 'public'; } if (Object.prototype.hasOwnProperty.call(requirement, 'siteTokenHeader')) { - return 'authenticated-site'; + // siteTokenHeader paired with bearerAuth (in the same requirement) is + // 'authenticated-site' (bearer JWT + site token, e.g. provider-search, + // site API mutations). siteTokenHeader alone is 'site-token-only' — + // the site token is validated against the server-side active user by + // the handler (e.g. generateAppStore), no bearer JWT required. This + // mirrors the original handler-validated behavior and avoids requiring + // a bearer JWT the front-end appStore fetch does not send. + if (Object.prototype.hasOwnProperty.call(requirement, 'bearerAuth')) { + return 'authenticated-site'; + } + return 'site-token-only'; } if (Object.prototype.hasOwnProperty.call(requirement, 'userTokenHeader')) { requiresUserToken = true; diff --git a/src/systemRoutes/v1/routes/connectionSettings.js b/src/systemRoutes/v1/routes/connectionSettings.js index f1382e93..776a21bf 100644 --- a/src/systemRoutes/v1/routes/connectionSettings.js +++ b/src/systemRoutes/v1/routes/connectionSettings.js @@ -142,20 +142,24 @@ async function connectionSettings(req, res) { res.setHeader('Expires', '0'); res.setHeader('Surrogate-Control', 'no-store'); res.setHeader('Content-Type', 'application/javascript'); - const isDashboardRequest = ( - HAXCMS && - HAXCMS.operatingContext !== 'single' && - req.headers && - req.headers.referer && - !req.headers.referer.includes(`/${HAXCMS.sitesDirectory}/`) - ); - // default to relative API paths so calls in site context resolve correctly - // and mirror PHP behavior for appStore-generated endpoint paths. - let baseAPIPath = HAXCMS.systemRequestBase; - // in non-root installs, preserve basePath for site-context API routing. - if (!isDashboardRequest && HAXCMS.basePath && HAXCMS.basePath !== '/') { - baseAPIPath = `${HAXCMS.basePath}${HAXCMS.systemRequestBase}`; + // System API base path is always absolute (root-level), mirroring PHP + // (HAXCMS.php appJWTConnectionSettings forces a leading slash). System + // routes are not site-scoped; both backends serve them at + // /system/api/v1/ so calls resolve identically whether the page is a + // site context (/_sites//) or the system dashboard. A relative + // path would resolve against the current page URL and produce a + // site-scoped system endpoint (/_sites//system/api/v1/...) which + // works on Node but is not standardized with PHP. + let systemNormalizedBasePath = String(HAXCMS.basePath || '/'); + if (systemNormalizedBasePath.charAt(0) !== '/') { + systemNormalizedBasePath = '/' + systemNormalizedBasePath; + } + if ( + systemNormalizedBasePath.charAt(systemNormalizedBasePath.length - 1) !== '/' + ) { + systemNormalizedBasePath += '/'; } + let baseAPIPath = `${systemNormalizedBasePath}${HAXCMS.systemRequestBase}`; var sitename = ''; // name parsed from a multisite site-context URL (/_sites//...). // tracked separately because it must drive the site API base path, whereas