fix: allow booking rejection via GET for email clients that do not support forms (#28029)
* fix: allow booking rejection via GET for email clients that do not support forms Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * Refactor test cases for GET handler in route.test.ts --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
anik@cal.com
Devin AI
parent
a78a3ffe39
commit
8908a66c23
@@ -179,7 +179,22 @@ describe("verify-booking-token route", () => {
|
||||
});
|
||||
|
||||
describe("GET handler", () => {
|
||||
it("should redirect to booking page with error when action is reject (requires POST)", async () => {
|
||||
it("should process rejection via GET (for email clients that don't support POST)", async () => {
|
||||
createMockBooking({
|
||||
id: 1,
|
||||
uid: "abc123",
|
||||
oneTimePassword: "test-token",
|
||||
recurringEventId: null,
|
||||
});
|
||||
createMockUser({
|
||||
id: 42,
|
||||
uuid: "user-uuid",
|
||||
email: "test@example.com",
|
||||
username: "testuser",
|
||||
role: "USER",
|
||||
destinationCalendar: null,
|
||||
});
|
||||
|
||||
const baseUrl =
|
||||
"https://app.example.com/api/verify-booking-token?action=reject&token=test-token&bookingUid=abc123&userId=42";
|
||||
const req = createMockRequest(baseUrl, "GET");
|
||||
@@ -191,7 +206,16 @@ describe("verify-booking-token route", () => {
|
||||
|
||||
expect(redirectUrl.origin).toBe("https://app.example.com");
|
||||
expect(redirectUrl.pathname).toBe("/booking/abc123");
|
||||
expect(redirectUrl.searchParams.get("error")).toBe("Rejection requires POST method");
|
||||
expect(redirectUrl.searchParams.get("error")).toBeNull();
|
||||
expect(mockConfirmHandler).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
input: expect.objectContaining({
|
||||
bookingId: 1,
|
||||
confirmed: false,
|
||||
actionSource: "MAGIC_LINK",
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("should redirect with error when query params are invalid (missing action)", async () => {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { makeUserActor } from "@calcom/features/booking-audit/lib/makeActor";
|
||||
import { distributedTracing } from "@calcom/lib/tracing/factory";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { confirmHandler } from "@calcom/trpc/server/routers/viewer/bookings/confirm.handler";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
|
||||
import { parseRequestData } from "app/api/parseRequestData";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
import { distributedTracing } from "@calcom/lib/tracing/factory";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { confirmHandler } from "@calcom/trpc/server/routers/viewer/bookings/confirm.handler";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { makeUserActor } from "@calcom/features/booking-audit/lib/makeActor";
|
||||
|
||||
enum DirectAction {
|
||||
ACCEPT = "accept",
|
||||
REJECT = "reject",
|
||||
@@ -28,16 +27,6 @@ async function getHandler(request: NextRequest) {
|
||||
try {
|
||||
const { action, token, bookingUid, userId } = querySchema.parse(queryParams);
|
||||
|
||||
if (action === DirectAction.REJECT) {
|
||||
// Rejections should use POST method
|
||||
return NextResponse.redirect(
|
||||
new URL(
|
||||
`/booking/${bookingUid}?error=${encodeURIComponent("Rejection requires POST method")}`,
|
||||
request.url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return await handleBookingAction(action, token, bookingUid, userId, request, undefined);
|
||||
} catch {
|
||||
const bookingUid = queryParams.bookingUid || "";
|
||||
|
||||
Reference in New Issue
Block a user