132 lines
3.5 KiB
TypeScript
132 lines
3.5 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import {
|
|
createDirectus,
|
|
rest,
|
|
staticToken,
|
|
createItem,
|
|
readItems,
|
|
} from "@directus/sdk";
|
|
|
|
export interface CMSConfig {
|
|
url: string;
|
|
token: string;
|
|
}
|
|
|
|
export function createCMSClient(config: CMSConfig) {
|
|
return createDirectus(config.url)
|
|
.with(staticToken(config.token))
|
|
.with(rest());
|
|
}
|
|
|
|
export async function handleFeedbackRequest(
|
|
req: NextRequest,
|
|
config: CMSConfig,
|
|
) {
|
|
const client = createCMSClient(config);
|
|
|
|
if (req.method === "GET") {
|
|
try {
|
|
const items = await client.request(
|
|
readItems("visual_feedback", {
|
|
fields: ["*", { comments: ["*"] }],
|
|
sort: ["-date_created"],
|
|
}),
|
|
);
|
|
return NextResponse.json(items);
|
|
} catch (error: any) {
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
if (req.method === "POST") {
|
|
try {
|
|
const body = await req.json();
|
|
const { action, screenshot_base64, ...data } = body;
|
|
|
|
if (action === "reply") {
|
|
const reply = await client.request(
|
|
createItem("visual_feedback_comments", {
|
|
feedback_id: data.feedbackId,
|
|
user_name: data.userName,
|
|
text: data.text,
|
|
}),
|
|
);
|
|
return NextResponse.json(reply);
|
|
}
|
|
|
|
let screenshotId = null;
|
|
|
|
if (screenshot_base64) {
|
|
try {
|
|
const base64Data = screenshot_base64.split(";base64,").pop();
|
|
const buffer = Buffer.from(base64Data, "base64");
|
|
const formData = new FormData();
|
|
const blob = new Blob([buffer], { type: "image/png" });
|
|
formData.append("file", blob, `feedback-${Date.now()}.png`);
|
|
|
|
const fileRes = await fetch(`${config.url}/files`, {
|
|
method: "POST",
|
|
headers: { Authorization: `Bearer ${config.token}` },
|
|
body: formData,
|
|
});
|
|
|
|
if (fileRes.ok) {
|
|
const fileData = await fileRes.json();
|
|
screenshotId = fileData.data.id;
|
|
}
|
|
} catch (e) {
|
|
console.error("Failed to upload screenshot:", e);
|
|
}
|
|
}
|
|
|
|
const feedback = await client.request(
|
|
createItem("visual_feedback", {
|
|
project: data.project || req.headers.get("host") || "unknown",
|
|
url: data.url,
|
|
selector: data.selector,
|
|
x: data.x,
|
|
y: data.y,
|
|
type: data.type,
|
|
text: data.text,
|
|
user_name: data.userName,
|
|
user_identity: data.userIdentity,
|
|
status: "open",
|
|
screenshot: screenshotId,
|
|
company: data.companyId,
|
|
}),
|
|
);
|
|
|
|
return NextResponse.json(feedback);
|
|
} catch (error: any) {
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
}
|
|
|
|
export async function handleWhoAmIRequest(
|
|
req: NextRequest,
|
|
gatekeeperUrl: string,
|
|
) {
|
|
try {
|
|
const bypass = req.nextUrl.searchParams.get("gatekeeper_bypass");
|
|
const targetUrl = bypass
|
|
? `${gatekeeperUrl}/api/whoami?gatekeeper_bypass=${bypass}`
|
|
: `${gatekeeperUrl}/api/whoami`;
|
|
|
|
// Forward cookies
|
|
const cookieHeader = req.headers.get("cookie") || "";
|
|
const res = await fetch(targetUrl, {
|
|
headers: { Cookie: cookieHeader },
|
|
});
|
|
|
|
if (res.ok) {
|
|
return NextResponse.json(await res.json());
|
|
}
|
|
return NextResponse.json({ identity: "Guest" });
|
|
} catch (_e) {
|
|
return NextResponse.json({ identity: "Guest" });
|
|
}
|
|
}
|