Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Couple fixes to improve error reporting #16895

Merged
merged 6 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/api/v1/pages/api/bookings/[id]/_delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { NextApiRequest } from "next";

import handleCancelBooking from "@calcom/features/bookings/lib/handleCancelBooking";
import { defaultResponder } from "@calcom/lib/server";
import { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
import { bookingCancelSchema } from "@calcom/prisma/zod-utils";

import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";

Expand Down Expand Up @@ -65,7 +65,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
*/
async function handler(req: NextApiRequest) {
const { id, allRemainingBookings, cancellationReason } = schemaQueryIdParseInt
.merge(schemaBookingCancelParams.pick({ allRemainingBookings: true, cancellationReason: true }))
.merge(bookingCancelSchema.pick({ allRemainingBookings: true, cancellationReason: true }))
.parse({
...req.query,
allRemainingBookings: req.query.allRemainingBookings === "true",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type z from "zod";

import type { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
import type { bookingCancelSchema } from "@calcom/prisma/zod-utils";

export function getMockRequestDataForCancelBooking(data: z.infer<typeof schemaBookingCancelParams>) {
export function getMockRequestDataForCancelBooking(data: z.infer<typeof bookingCancelSchema>) {
return data;
}
16 changes: 4 additions & 12 deletions packages/features/bookings/lib/handleCancelBooking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ import prisma, { bookingMinimalSelect } from "@calcom/prisma";
import type { WebhookTriggerEvents } from "@calcom/prisma/enums";
import { BookingStatus } from "@calcom/prisma/enums";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
import {
bookingMetadataSchema,
EventTypeMetaDataSchema,
schemaBookingCancelParams,
} from "@calcom/prisma/zod-utils";
import { bookingMetadataSchema, EventTypeMetaDataSchema, bookingCancelInput } from "@calcom/prisma/zod-utils";
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
import { getAllWorkflowsFromEventType } from "@calcom/trpc/server/routers/viewer/workflows/util";
import type { CalendarEvent } from "@calcom/types/Calendar";
Expand All @@ -43,7 +39,7 @@ import cancelAttendeeSeat from "./handleSeats/cancel/cancelAttendeeSeat";
const log = logger.getSubLogger({ prefix: ["handleCancelBooking"] });

async function getBookingToDelete(id: number | undefined, uid: string | undefined) {
return await prisma.booking.findUnique({
return await prisma.booking.findUniqueOrThrow({
where: {
id,
uid,
Expand Down Expand Up @@ -160,7 +156,7 @@ export type HandleCancelBookingResponse = {

async function handler(req: CustomRequest) {
const { id, uid, allRemainingBookings, cancellationReason, seatReferenceUid, cancelledBy } =
schemaBookingCancelParams.parse(req.body);
bookingCancelInput.parse(req.body);
req.bookingToDelete = await getBookingToDelete(id, uid);
const {
bookingToDelete,
Expand All @@ -172,11 +168,7 @@ async function handler(req: CustomRequest) {
arePlatformEmailsEnabled,
} = req;

if (!bookingToDelete || !bookingToDelete.user) {
throw new HttpError({ statusCode: 400, message: "Booking not found" });
}

if (!bookingToDelete.userId) {
if (!bookingToDelete.userId || !bookingToDelete.user) {
throw new HttpError({ statusCode: 400, message: "User not found" });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { WorkflowRepository } from "@calcom/lib/server/repository/workflow";
import prisma from "@calcom/prisma";
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
import { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
import { bookingCancelAttendeeSeatSchema } from "@calcom/prisma/zod-utils";
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
import type { CalendarEvent } from "@calcom/types/Calendar";

Expand All @@ -32,9 +32,10 @@ async function cancelAttendeeSeat(
},
eventTypeMetadata: EventTypeMetadata
) {
const { seatReferenceUid } = schemaBookingCancelParams.parse(req.body);
const input = bookingCancelAttendeeSeatSchema.safeParse(req.body);
const { webhooks, evt, eventTypeInfo } = dataForWebhooks;
if (!seatReferenceUid) return;
if (!input.success) return;
const { seatReferenceUid } = input.data;
const bookingToDelete = req.bookingToDelete;
if (!bookingToDelete?.attendees.length || bookingToDelete.attendees.length < 2) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2664,6 +2664,7 @@ describe("handleSeats", () => {

const mockBookingData = getMockRequestDataForBooking({
data: {
id: firstBookingId,
eventTypeId: 1,
responses: {
email: booker.email,
Expand Down
11 changes: 6 additions & 5 deletions packages/lib/server/defaultResponder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ export function defaultResponder<T>(f: Handle<T>) {
return res.json(result);
}
} catch (err) {
console.error(err);
const error = getServerErrorFromUnknown(err);
// dynamic import of Sentry so it's only loaded when something goes wrong.
const captureException = (await import("@sentry/nextjs")).captureException;
captureException(err);
// return API route response
// we don't want to report Bad Request errors to Sentry / console
if (!(error.statusCode >= 400 && error.statusCode < 500)) {
console.error(err);
const captureException = (await import("@sentry/nextjs")).captureException;
captureException(err);
}
return res
.status(error.statusCode)
.json({ message: error.message, url: error.url, method: error.method });
Expand Down
1 change: 0 additions & 1 deletion packages/lib/server/getServerErrorFromUnknown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ function parseZodErrorIssues(issues: ZodIssue[]): string {

export function getServerErrorFromUnknown(cause: unknown): HttpError {
if (isZodError(cause)) {
console.log("cause", cause);
return new HttpError({
statusCode: 400,
message: parseZodErrorIssues(cause.issues),
Expand Down
4 changes: 2 additions & 2 deletions packages/platform/atoms/hooks/useCancelBooking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { z } from "zod";

import { SUCCESS_STATUS } from "@calcom/platform-constants";
import type { ApiResponse, ApiErrorResponse } from "@calcom/platform-types";
import type { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
import type { bookingCancelSchema } from "@calcom/prisma/zod-utils";

import http from "../lib/http";

Expand All @@ -12,7 +12,7 @@ interface IUseCancelBooking {
onError?: (err: ApiErrorResponse | Error) => void;
}

type inputParams = z.infer<typeof schemaBookingCancelParams>;
type inputParams = z.infer<typeof bookingCancelSchema>;

export const useCancelBooking = (
{ onSuccess, onError }: IUseCancelBooking = {
Expand Down
11 changes: 10 additions & 1 deletion packages/prisma/zod-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export const bookingCreateBodySchemaForApi = extendedBookingCreateBody.merge(
bookingCreateSchemaLegacyPropsForApi.partial()
);

export const schemaBookingCancelParams = z.object({
export const bookingCancelSchema = z.object({
id: z.number().optional(),
uid: z.string().optional(),
allRemainingBookings: z.boolean().optional(),
Expand All @@ -323,6 +323,15 @@ export const schemaBookingCancelParams = z.object({
cancelledBy: z.string().email({ message: "Invalid email" }).optional(),
});

export const bookingCancelAttendeeSeatSchema = z.object({
seatReferenceUid: z.string(),
});

export const bookingCancelInput = bookingCancelSchema.refine(
(data) => !!data.id || !!data.uid,
"At least one of the following required: 'id', 'uid'."
);

export const vitalSettingsUpdateSchema = z.object({
connected: z.boolean().optional(),
selectedParam: z.string().optional(),
Expand Down
Loading