diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 53465995b1..6aea996be9 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -15,6 +15,7 @@ import { ImmutableStore } from "../src/Logic/UIEventSource" import * as crypto from "crypto" import * as eli from "../src/assets/editor-layer-index.json" import * as eli_global from "../src/assets/global-raster-layers.json" +import ValidationUtils from "../src/Models/ThemeConfig/Conversion/ValidationUtils" const sharp = require("sharp") const template = readFileSync("theme.html", "utf8") @@ -264,6 +265,7 @@ async function eliUrls(): Promise { async function generateCsp( layout: LayoutConfig, + layoutJson: LayoutConfigJson, options: { scriptSrcs: string[] } @@ -275,9 +277,20 @@ async function generateCsp( Constants.nominatimEndpoint, "https://api.openstreetmap.org", "https://pietervdvn.goatcounter.com", - ] - .concat(...SpecialVisualizations.specialVisualizations.map((sv) => sv.needsUrls)) - .concat(...(await eliUrls())) + ].concat(...(await eliUrls())) + + const usedSpecialVisualisations = ValidationUtils.getSpecialVisualisationsWithArgs(layoutJson) + for (const usedSpecialVisualisation of usedSpecialVisualisations) { + if (typeof usedSpecialVisualisation === "string") { + continue + } + const neededUrls = usedSpecialVisualisation.func.needsUrls + if (typeof neededUrls === "function") { + apiUrls.push(...neededUrls(usedSpecialVisualisation.args)) + } else { + apiUrls.push(...neededUrls) + } + } const geojsonSources: string[] = layout.layers.map((l) => l.source?.geojsonSource) const hosts = new Set() @@ -299,6 +312,10 @@ async function generateCsp( } } + if (hosts.has("*")) { + throw "* is not allowed as connect-src" + } + const connectSrc = Array.from(hosts).sort() const newSrcs = connectSrc.filter((newItem) => !previousSrc.has(newItem)) @@ -317,7 +334,7 @@ async function generateCsp( "default-src": "'self'", "child-src": "'self' blob: ", "img-src": "* data:", // maplibre depends on 'data:' to load - "connect-src": connectSrc.join(" "), + "connect-src": onnectSrc.join(" "), "report-to": "https://report.mapcomplete.org/csp", "worker-src": "'self' blob:", // Vite somehow loads the worker via a 'blob' "style-src": "'self' 'unsafe-inline'", // unsafe-inline is needed to change the default background pin colours @@ -344,7 +361,13 @@ const removeOtherLanguagesHash = crypto .update(removeOtherLanguages) .digest("base64") -async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alreadyWritten) { +async function createLandingPage( + layout: LayoutConfig, + layoutJson: LayoutConfigJson, + manifest, + whiteIcons, + alreadyWritten +) { Locale.language.setData(layout.language[0]) const targetLanguage = layout.language[0] const ogTitle = Translations.T(layout.title).textFor(targetLanguage).replace(/"/g, '\\"') @@ -428,7 +451,7 @@ async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alr .replace(/.*/s, themeSpecific) .replace( //, - await generateCsp(layout, { + await generateCsp(layout, layoutJson, { scriptSrcs: [`'sha256-${removeOtherLanguagesHash}'`], }) ) @@ -518,7 +541,13 @@ async function main(): Promise { writeFile("public/" + manifestLocation, manif, err) // Create a landing page for the given theme - const landing = await createLandingPage(layout, manifest, whiteIcons, alreadyWritten) + const landing = await createLandingPage( + layout, + layoutConfigJson, + manifest, + whiteIcons, + alreadyWritten + ) writeFile(enc(layout.id) + ".html", landing, err) await createIndexFor(layout) diff --git a/src/UI/SpecialVisualization.ts b/src/UI/SpecialVisualization.ts index 28125837cd..be3ffee159 100644 --- a/src/UI/SpecialVisualization.ts +++ b/src/UI/SpecialVisualization.ts @@ -88,7 +88,7 @@ export interface SpecialVisualization { readonly funcName: string readonly docs: string | BaseUIElement readonly example?: string - readonly needsUrls: string[] + readonly needsUrls: string[] | ((args: string[]) => string) /** * Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index f32f28d9e8..c0720293ad 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -1454,7 +1454,7 @@ export default class SpecialVisualizations { }, ], docs: "Shows events that are happening based on a Giggity URL", - needsUrls: ["*"], + needsUrls: (args) => args[0], constr( state: SpecialVisualizationState, tagSource: UIEventSource>,