fix: security hardening, UI fixes, and validation improvements

- Fix header nav overflow by switching to lg: breakpoint with tighter gaps
- Fix file upload path traversal by whitelisting allowed folders and extensions
- Fix BookingModal using hardcoded content instead of DB-backed data
- Add input length validation on public master-class registration API
- Add ID validation on team member and reorder API routes
- Fix BookingModal useCallback missing groupInfo/contact dependencies
- Improve admin news date field to use native date picker
- Add missing Мастер-классы and Новости cards to admin dashboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 17:37:29 +03:00
parent 26cb9a9772
commit 3ac6a4d840
8 changed files with 73 additions and 31 deletions

View File

@@ -4,9 +4,18 @@ import { revalidatePath } from "next/cache";
type Params = { params: Promise<{ id: string }> };
function parseId(raw: string): number | null {
const n = Number(raw);
return Number.isInteger(n) && n > 0 ? n : null;
}
export async function GET(_request: NextRequest, { params }: Params) {
const { id } = await params;
const member = getTeamMember(Number(id));
const numId = parseId(id);
if (!numId) {
return NextResponse.json({ error: "Invalid ID" }, { status: 400 });
}
const member = getTeamMember(numId);
if (!member) {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
@@ -15,15 +24,23 @@ export async function GET(_request: NextRequest, { params }: Params) {
export async function PUT(request: NextRequest, { params }: Params) {
const { id } = await params;
const numId = parseId(id);
if (!numId) {
return NextResponse.json({ error: "Invalid ID" }, { status: 400 });
}
const data = await request.json();
updateTeamMember(Number(id), data);
updateTeamMember(numId, data);
revalidatePath("/");
return NextResponse.json({ ok: true });
}
export async function DELETE(_request: NextRequest, { params }: Params) {
const { id } = await params;
deleteTeamMember(Number(id));
const numId = parseId(id);
if (!numId) {
return NextResponse.json({ error: "Invalid ID" }, { status: 400 });
}
deleteTeamMember(numId);
revalidatePath("/");
return NextResponse.json({ ok: true });
}