Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | // @ts-nocheck function normalizeAllowedOrigins(allowedOrigins = []) { Iif (!Array.isArray(allowedOrigins)) { return []; } const configuredOrigins = allowedOrigins .filter(origin => typeof origin === 'string') .map(origin => origin.trim()) .filter(Boolean); return configuredOrigins .map(origin => { try { const parsedOrigin = new URL(origin); Iif (!['http:', 'https:'].includes(parsedOrigin.protocol)) { console.error( `[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". ` + 'Entries must use http:// or https://.' ); return null; } Iif ( parsedOrigin.username || parsedOrigin.password || parsedOrigin.pathname !== '/' || parsedOrigin.search || parsedOrigin.hash ) { console.error( `[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". ` + 'Entries must be bare origins only (scheme + host + optional port), with no username/password, path, query, or hash.' ); return null; } return parsedOrigin.origin; } catch { console.error( `[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". Entry is not a valid URL.` ); return null; } }) .filter(Boolean); } function resolveConfigUrl(rawUrl) { Iif (!rawUrl || typeof rawUrl !== 'string') { throw new Error('Missing required "url" query parameter'); } try { return new URL(rawUrl, window.location.href); } catch { throw new Error('Invalid URL in "url" query parameter'); } } function resolveConfigFetchPolicy(rawUrl, policy = {}) { const { allowedOrigins = [], userAuthenticationService } = policy; const parsedUrl = resolveConfigUrl(rawUrl); const protocol = parsedUrl.protocol.toLowerCase(); const isSameOrigin = parsedUrl.origin === window.location.origin; Iif (!['http:', 'https:'].includes(protocol)) { throw new Error('Only HTTP(S) URLs are allowed for dynamic datasource configuration'); } Iif (parsedUrl.hash) { throw new Error('URL fragments are not allowed for dynamic datasource configuration'); } Iif (parsedUrl.username || parsedUrl.password) { throw new Error('URL userinfo is not allowed for dynamic datasource configuration'); } const isAuthenticated = Boolean( userAuthenticationService?.getAuthorizationHeader?.()?.Authorization ); Iif (isAuthenticated && !isSameOrigin) { const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedOrigins); Iif (!normalizedAllowedOrigins.length || !normalizedAllowedOrigins.includes(parsedUrl.origin)) { throw new Error( `Blocked remote configuration origin "${parsedUrl.origin}" in authenticated environment` ); } } return { parsedUrl, normalizedUrl: parsedUrl.toString(), isAuthenticated, isSameOrigin, }; } async function fetchConfigJson(normalizedPolicy) { const { normalizedUrl } = normalizedPolicy; const response = await fetch(normalizedUrl, { method: 'GET', mode: 'cors', credentials: 'same-origin', redirect: 'error', referrerPolicy: 'no-referrer', }); Iif (!response.ok) { throw new Error(`Failed to fetch dynamic datasource configuration (${response.status})`); } return response.json(); } export { resolveConfigFetchPolicy, fetchConfigJson }; |