Runner: Analyse null erlaubt, Adresse optional (R10)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7de9f1aaa3
commit
18d37d1e01
4 files changed
+20
-4
No files matched your search
@@ -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;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<p class="entwurf"><strong>Vorläufiger Entwurf:</strong> Dieser Text wird vor der Veröffentlichung noch redaktionell und rechtlich überarbeitet.</p>
|
||||
|
||||
<h2>Verantwortlicher</h2>
|
||||
<p>{{company}}<br>{{address}}<br>E-Mail: <a href="mailto:{{email}}">{{email}}</a></p>
|
||||
<p>{{company}}<br>{{#address}}{{address}}<br>{{/address}}E-Mail: <a href="mailto:{{email}}">{{email}}</a></p>
|
||||
|
||||
<h2>Zweck</h2>
|
||||
<p>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.</p>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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'), '<html><head></head><body>NEU</body></html>');
|
||||
assert.ok(!existsSync(join(workDir, 'datenschutz-analyse.html')));
|
||||
});
|
||||
|
||||
test('leere Adresse: keine leere Zeile, kein Platzhalterrest', async () => {
|
||||
const d = dir(); put(d, 'index.html', '<head></head>');
|
||||
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<br>E-Mail:'));
|
||||
assert.ok(!p.includes('{{') && !p.includes('<br><br>'));
|
||||
});
|
||||
Reference in new issue
Block a user