insert copyright headers for images
Sonarqube Scanner / Prepare environment (push) Successful in 7s
Sonarqube Scanner / Build and test (push) Successful in 30s
Sonarqube Scanner / SonarQube analysis (push) Successful in 1m6s
Sonarqube Scanner / Deploy to Server (push) Successful in 6s

This commit is contained in:
Florian Zumpe
2026-10-04 10:14:40 +02:00
parent 3a682f2b30
commit d3311cce06
18 changed files with 382 additions and 12 deletions
+57
View File
@@ -1,4 +1,5 @@
import { parseGpx } from '../src/services/gpx.js';
import { UPLOAD_COPYRIGHT_NOTICE, APP_IMAGE_COPYRIGHT_NOTICE, GROUP_SYMBOL_COPYRIGHT_NOTICE, COPYRIGHT_HEADER_LIMITS, ENVATO_SYMBOL_SOURCE } from '../src/services/copyright.js';
import { SAMPLE_GPX } from '../test-support/gpx-fixtures.js';
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
@@ -144,6 +145,7 @@ test('the npm-started local API is exercised through a write-auth proxy on loopb
const indexResponse = await fetch(`${baseUrl}/`);
const indexHtml = await indexResponse.text();
assert.equal(indexResponse.headers.get('x-copyright'), null);
assert.equal(indexResponse.status, 200);
assert.match(indexResponse.headers.get('cache-control') || '', /no-store/);
assert.match(indexHtml, /css\/app\.css\?v=0\.12\.14/);
@@ -164,6 +166,35 @@ test('the npm-started local API is exercised through a write-auth proxy on loopb
assert.match(appStyleResponse.headers.get('cache-control') || '', /no-store/);
await appStyleResponse.arrayBuffer();
assert.equal(appStyleResponse.headers.get('x-copyright'), null);
const iconResponse = await fetch(`${baseUrl}/images/icons/play.svg`);
assert.equal(iconResponse.status, 200);
assert.equal(iconResponse.headers.get('x-copyright'), APP_IMAGE_COPYRIGHT_NOTICE);
assert.equal(iconResponse.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(iconResponse.headers.get('x-copyright-source'), null);
await iconResponse.arrayBuffer();
const symbols = await fs.readdir(path.join(root, 'public/images/group-symbols'));
for (const name of symbols.filter(name => name.endsWith('.png'))) {
const symbolUrl = `${baseUrl}/images/group-symbols/${encodeURIComponent(name)}`;
const symbol = await fetch(symbolUrl);
assert.equal(symbol.status, 200, name);
assert.equal(symbol.headers.get('x-copyright'), GROUP_SYMBOL_COPYRIGHT_NOTICE, name);
assert.equal(symbol.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(symbol.headers.get('x-copyright-source'), ENVATO_SYMBOL_SOURCE);
const etag = symbol.headers.get('etag');
await symbol.arrayBuffer();
const symbolHead = await fetch(symbolUrl, { method: 'HEAD' });
assert.equal(symbolHead.status, 200);
assert.equal(symbolHead.headers.get('x-copyright'), GROUP_SYMBOL_COPYRIGHT_NOTICE);
assert.equal(symbolHead.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(symbolHead.headers.get('x-copyright-source'), ENVATO_SYMBOL_SOURCE);
const symbolCached = await fetch(symbolUrl, { headers: { 'If-None-Match': etag, 'Cache-Control': 'max-age=0' } });
assert.equal(symbolCached.status, 304);
assert.equal(symbolCached.headers.get('x-copyright'), GROUP_SYMBOL_COPYRIGHT_NOTICE);
assert.equal(symbolCached.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(symbolCached.headers.get('x-copyright-source'), ENVATO_SYMBOL_SOURCE);
}
const pythonHealthCheck = await runProcess('python3', ['-c', `
from common import ApiClient
result = ApiClient('${LOCAL_API_URL}').request('GET', '/api/health')
@@ -328,6 +359,32 @@ assert result['ok'] is True
const { response: pictureFileResponse, body: pictureFile } = await requestBuffer(`${baseUrl}${picture.url}`);
assert.match(pictureFileResponse.headers.get('content-type') || '', /image\/png/);
assert.deepEqual(pictureFile, PNG_FILE);
assert.equal(pictureFileResponse.headers.get('x-copyright'), UPLOAD_COPYRIGHT_NOTICE);
assert.equal(pictureFileResponse.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(pictureFileResponse.headers.get('x-copyright-source'), null);
const pictureHead = await fetch(`${baseUrl}${picture.url}`, { method: 'HEAD' });
assert.equal(pictureHead.status, 200);
assert.equal(pictureHead.headers.get('x-copyright'), UPLOAD_COPYRIGHT_NOTICE);
assert.equal(pictureHead.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(pictureHead.headers.get('x-copyright-source'), null);
const pictureRange = await fetch(`${baseUrl}${picture.url}`, { headers: { Range: 'bytes=0-7' } });
assert.equal(pictureRange.status, 206);
assert.equal(pictureRange.headers.get('x-copyright'), UPLOAD_COPYRIGHT_NOTICE);
assert.equal(pictureRange.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(pictureRange.headers.get('x-copyright-source'), null);
assert.deepEqual(Buffer.from(await pictureRange.arrayBuffer()), PNG_FILE.subarray(0, 8));
const pictureCached = await fetch(`${baseUrl}${picture.url}`, { headers: { 'If-None-Match': pictureFileResponse.headers.get('etag'), 'Cache-Control': 'max-age=0' } });
assert.equal(pictureCached.status, 304);
assert.equal(pictureCached.headers.get('x-copyright'), UPLOAD_COPYRIGHT_NOTICE);
assert.equal(pictureCached.headers.get('x-copyright-notice'), COPYRIGHT_HEADER_LIMITS);
assert.equal(pictureCached.headers.get('x-copyright-source'), null);
const wrongPicture = await fetch(`${baseUrl}/api/routes/${route.id}/pois/${poi.id}/pictures/999999`);
assert.equal(wrongPicture.status, 404);
assert.equal(wrongPicture.headers.get('x-copyright'), null);
await wrongPicture.arrayBuffer();
const metadataHeaders = await fetch(`${baseUrl}${picture.url}?metadata=true`);
assert.equal(metadataHeaders.headers.get('x-copyright'), null);
await metadataHeaders.arrayBuffer();
const { body: pictureMetadata } = await requestJson(`${baseUrl}${picture.url}?metadata=true`);
assert.equal(pictureMetadata.caption, 'Erste Bildbeschreibung');
assert.equal(pictureMetadata.poiId, poi.id);