26 lines
1.2 KiB
TypeScript
26 lines
1.2 KiB
TypeScript
import { createRedisNamedEventResponse } from "@/lib/events/redis-stream";
|
|
import { authorizeTicket } from "@/lib/commission/tickets";
|
|
import { requireCommissionUser } from "@/lib/commission/server";
|
|
import { errorResponse, HttpError } from "@/lib/security/http";
|
|
import { limitRequest, trustedClientAddress } from "@/lib/security/rate-limit";
|
|
|
|
export async function GET(request: Request) {
|
|
try {
|
|
const user = await requireCommissionUser();
|
|
await limitRequest("stream-open", trustedClientAddress(request.headers), 60);
|
|
const url = new URL(request.url);
|
|
const ticketId = url.searchParams.get("ticketId");
|
|
const scope = url.searchParams.get("scope");
|
|
let topic: string;
|
|
if (ticketId) {
|
|
if (!/^[a-f0-9-]{36}$/i.test(ticketId)) throw new HttpError(400, "invalid-ticket-id");
|
|
await authorizeTicket(ticketId);
|
|
topic = `commission:ticket:${ticketId}`;
|
|
} else if (scope === "admin") {
|
|
if (user.role !== "admin" || !user.emailVerified) throw new HttpError(403, "forbidden");
|
|
topic = "commission:admin";
|
|
} else topic = `commission:user:${user.id}`;
|
|
return await createRedisNamedEventResponse(topic, "changed", request.signal);
|
|
} catch (cause) { return errorResponse(cause); }
|
|
}
|