Git history was lost when the previous Gitea instance was wiped and reinstalled due to an unresolved corruption bug — this commit is the last known-good file content, exported before the reinstall. Prior commit history is not recoverable through this path.
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
export const runtime = "nodejs";
|
|
|
|
import { NextResponse } from "next/server";
|
|
import { getCustomerByPortalToken, appendCustomerReply } from "@/lib/tickets/service";
|
|
import { saveAttachment, AttachmentTooLargeError, MAX_ATTACHMENT_BYTES } from "@/lib/attachments/storage";
|
|
|
|
export async function POST(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ ticketId: string }> },
|
|
) {
|
|
const { ticketId } = await params;
|
|
const formData = await request.formData().catch(() => null);
|
|
|
|
const token = formData?.get("token");
|
|
if (typeof token !== "string" || !token) {
|
|
return NextResponse.json({ error: "Missing token" }, { status: 400 });
|
|
}
|
|
|
|
const file = formData?.get("file");
|
|
if (!(file instanceof File)) {
|
|
return NextResponse.json({ error: "Missing file" }, { status: 400 });
|
|
}
|
|
if (file.size > MAX_ATTACHMENT_BYTES) {
|
|
return NextResponse.json({ error: "File too large" }, { status: 413 });
|
|
}
|
|
|
|
const customer = await getCustomerByPortalToken(token);
|
|
if (!customer) {
|
|
return NextResponse.json({ error: "Invalid token" }, { status: 404 });
|
|
}
|
|
|
|
const captionRaw = formData?.get("caption");
|
|
const caption = typeof captionRaw === "string" ? captionRaw.trim() : "";
|
|
|
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
let saved;
|
|
try {
|
|
saved = await saveAttachment(buffer);
|
|
} catch (err) {
|
|
if (err instanceof AttachmentTooLargeError) {
|
|
return NextResponse.json({ error: "File too large" }, { status: 413 });
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
try {
|
|
const result = await appendCustomerReply({
|
|
ticketId,
|
|
customerId: customer.id,
|
|
authorName: customer.displayName,
|
|
body: caption || file.name || "Вложение",
|
|
attachments: [
|
|
{
|
|
filename: file.name || "file",
|
|
mimeType: file.type || "application/octet-stream",
|
|
sizeBytes: saved.sizeBytes,
|
|
storageKey: saved.storageKey,
|
|
},
|
|
],
|
|
});
|
|
return NextResponse.json(result, { status: 201 });
|
|
} catch {
|
|
return NextResponse.json({ error: "Ticket not found" }, { status: 404 });
|
|
}
|
|
}
|