fix: guard body null su PUT contenuti, formato tag e suffisso random su upload immagine

This commit is contained in:
2026-07-05 17:22:23 +02:00
parent eda4d73aac
commit bf19cba4d3
2 changed files with 8 additions and 1 deletions
+1
View File
@@ -10,6 +10,7 @@ const json = (status: number, body: object) =>
export const PUT: APIRoute = async ({ params, request, locals }) => {
let data: Record<string, unknown>;
try { data = await request.json(); } catch { return json(400, { error: 'Dati non validi.' }); }
if (typeof data !== 'object' || data === null) return json(400, { error: 'Dati non validi.' });
const r = applyContentUpdate(getDb(), params.tag ?? '', data, locals.user!.username);
if (!r.ok) return json(r.status, { error: r.error });
invalidateContentCache();
+7 -1
View File
@@ -1,6 +1,7 @@
import type { APIRoute } from 'astro';
import { writeFile, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import { randomBytes } from 'node:crypto';
import { getDb } from '../../../../../lib/db';
import { getEnv } from '../../../../../lib/env';
import { invalidateContentCache } from '../../../../../lib/content';
@@ -10,7 +11,12 @@ export const prerender = false;
const json = (status: number, body: object) =>
new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
// Difesa in profondità: oggi i tag arrivano solo dal seed, ma il nome file deriva
// dal tag — vincolarne il formato evita sorprese se in futuro i tag diventano dinamici.
const TAG_RE = /^[a-z0-9][a-z0-9.-]*$/;
function findImageTag(tag: string): { ok: true } | { ok: false; status: number; error: string } {
if (!TAG_RE.test(tag)) return { ok: false, status: 400, error: 'Tag non valido.' };
const row = getDb().prepare('SELECT type FROM content_blocks WHERE tag = ?').get(tag) as { type: string } | undefined;
if (!row) return { ok: false, status: 404, error: 'Tag inesistente.' };
if (row.type !== 'image') return { ok: false, status: 400, error: 'Il tag non è di tipo immagine.' };
@@ -26,7 +32,7 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
if (!checked.ok) return json(400, { error: checked.error });
const dir = join(getEnv('UPLOADS_DIR', 'uploads'), 'content');
await mkdir(dir, { recursive: true });
const name = `${tag.replaceAll('.', '-')}-${Date.now()}${checked.ext}`;
const name = `${tag.replaceAll('.', '-')}-${Date.now()}-${randomBytes(4).toString('hex')}${checked.ext}`;
await writeFile(join(dir, name), Buffer.from(await checked.file.arrayBuffer()));
getDb().prepare(
`UPDATE content_blocks SET value = ?, updated_at = datetime('now'), updated_by = ? WHERE tag = ?`