diff --git a/runner/src/analytics-inject.js b/runner/src/analytics-inject.js index d1a41ab..bc92d3d 100644 --- a/runner/src/analytics-inject.js +++ b/runner/src/analytics-inject.js @@ -52,7 +52,8 @@ export async function injectAnalytics(dir, analytics, { baseUrl, onLine, fs = no const tag = scriptTag(analytics, baseUrl); const p = analytics.privacy || {}; const template = await fs.readFile(TEMPLATE_URL, 'utf8'); - const page = template.replace(/\{\{(company|address|email)\}\}/g, (_, k) => esc(p[k] ?? '')); + const withAddr = p.address ? template.replace(/\{\{#address\}\}|\{\{\/address\}\}/g, '') : template.replace(/\{\{#address\}\}[\s\S]*?\{\{\/address\}\}/g, ''); + const page = withAddr.replace(/\{\{(company|address|email)\}\}/g, (_, k) => esc(p[k] ?? '')); await fs.writeFile(join(dir, PAGE), page, 'utf8'); await fs.chmod(join(dir, PAGE), 0o644); let n = 0; diff --git a/runner/src/templates/datenschutz-analyse.html b/runner/src/templates/datenschutz-analyse.html index 448312a..675b112 100644 --- a/runner/src/templates/datenschutz-analyse.html +++ b/runner/src/templates/datenschutz-analyse.html @@ -17,7 +17,7 @@

Vorläufiger Entwurf: Dieser Text wird vor der Veröffentlichung noch redaktionell und rechtlich überarbeitet.

Verantwortlicher

-

{{company}}
{{address}}
E-Mail: {{email}}

+

{{company}}
{{#address}}{{address}}
{{/address}}E-Mail: {{email}}

Zweck

Wir möchten verstehen, wie diese Website genutzt wird, um sie zu verbessern (zum Beispiel welche Seiten gelesen werden und wo Besucher hängen bleiben). Es gibt keine Werbung und kein Profiling.

diff --git a/runner/src/validate.js b/runner/src/validate.js index 15671d0..a64a08e 100644 --- a/runner/src/validate.js +++ b/runner/src/validate.js @@ -48,7 +48,7 @@ export function validateJob(body) { } } let analytics; - if (body.analytics !== undefined) { + if (body.analytics !== undefined && body.analytics !== null) { const a = body.analytics; if (!a || typeof a !== 'object' || Array.isArray(a)) return { ok: false, error: 'Ungültige Analyse-Angaben' }; if (typeof a.siteKey !== 'string' || !RE_SITE_KEY.test(a.siteKey)) return { ok: false, error: 'Ungültiger Analyse-Schlüssel' }; @@ -59,6 +59,7 @@ export function validateJob(body) { for (const [k, max] of [['company', 200], ['address', 300], ['email', 200]]) { const v = pr[k]; // eslint-disable-next-line no-control-regex + if (k === 'address' && (v === undefined || v === '')) { privacy[k] = ''; continue; } if (typeof v !== 'string' || !v.trim() || v.length > max || /[\x00-\x1f\x7f]/.test(v)) return { ok: false, error: `Ungültige Analyse-Datenschutzangabe: ${k}` }; privacy[k] = v; } diff --git a/runner/test/analytics-inject.test.js b/runner/test/analytics-inject.test.js index 04bb280..284eb88 100644 --- a/runner/test/analytics-inject.test.js +++ b/runner/test/analytics-inject.test.js @@ -107,11 +107,17 @@ test('validateJob: analytics streng, Weiterreichen in den Job', () => { assert.equal(ok.ok, true); assert.deepEqual(ok.job.analytics, A()); assert.equal(validateJob(base).job.analytics, undefined); + const nul = validateJob({ ...base, analytics: null }); + assert.equal(nul.ok, true); assert.equal(nul.job.analytics, undefined); + const noAddr = validateJob({ ...base, analytics: A({ privacy: { company: 'F', email: 'e@x.de' } }) }); + assert.equal(noAddr.ok, true); assert.equal(noAddr.job.analytics.privacy.address, ''); + assert.equal(validateJob({ ...base, analytics: A({ privacy: { company: 'F', email: '' } }) }).ok, false); + assert.equal(validateJob({ ...base, analytics: A({ privacy: { email: 'e@x.de' } }) }).ok, false); const bad = [ A({ siteKey: 'kurz' }), A({ siteKey: 'A'.repeat(20) }), A({ color: '#ABCDEF' }), A({ color: '#abc' }), A({ privacy: undefined }), A({ privacy: { ...A().privacy, company: 'x'.repeat(201) } }), A({ privacy: { ...A().privacy, address: 'x'.repeat(301) } }), A({ privacy: { ...A().privacy, email: 'x'.repeat(201) } }), - A({ privacy: { ...A().privacy, company: 'a\nb' } }), A({ privacy: { ...A().privacy, email: 5 } }), 'x', [], null, + A({ privacy: { ...A().privacy, company: 'a\nb' } }), A({ privacy: { ...A().privacy, email: 5 } }), 'x', [], ]; for (const a of bad) { const r = validateJob({ ...base, analytics: a }); assert.equal(r.ok, false, JSON.stringify(a)); assert.match(r.error, /Analyse/); } }); @@ -171,3 +177,11 @@ test('Dev-Modus (prepareWorkspace) fasst Dateien nicht an', async () => { assert.equal(get(workDir, 'index.html'), 'NEU'); assert.ok(!existsSync(join(workDir, 'datenschutz-analyse.html'))); }); + +test('leere Adresse: keine leere Zeile, kein Platzhalterrest', async () => { + const d = dir(); put(d, 'index.html', ''); + await injectAnalytics(d, A({ privacy: { company: 'Muster GmbH', address: '', email: 'info@muster.de' } }), { baseUrl: BASE }); + const p = get(d, 'datenschutz-analyse.html'); + assert.ok(p.includes('Muster GmbH
E-Mail:')); + assert.ok(!p.includes('{{') && !p.includes('

')); +});