From 8de7876f72fc002159b769a06a7c692cd6fae4f5 Mon Sep 17 00:00:00 2001 From: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Date: Wed, 12 Mar 2025 18:24:50 +0200 Subject: [PATCH] chore: add CalendarService Exception Filter api v2 (#20021) --- apps/api/v2/package.json | 2 +- apps/api/v2/src/app.ts | 2 + .../calendar-service-exception.filter.ts | 57 +++++++++++++++++++ apps/api/v2/src/lib/filterReqHeaders.ts | 19 ++++--- packages/platform/libraries/app-store.ts | 8 +++ 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 apps/api/v2/src/filters/calendar-service-exception.filter.ts diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index b0c81135bc..c7cd299fbc 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -38,7 +38,7 @@ "@axiomhq/winston": "^1.2.0", "@calcom/platform-constants": "*", "@calcom/platform-enums": "*", - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.149", + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.150", "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", diff --git a/apps/api/v2/src/app.ts b/apps/api/v2/src/app.ts index cbcff9b57b..17c08ce131 100644 --- a/apps/api/v2/src/app.ts +++ b/apps/api/v2/src/app.ts @@ -21,6 +21,7 @@ import { X_CAL_PLATFORM_EMBED, } from "@calcom/platform-constants"; +import { CalendarServiceExceptionFilter } from "./filters/calendar-service-exception.filter"; import { TRPCExceptionFilter } from "./filters/trpc-exception.filter"; export const bootstrap = (app: NestExpressApplication): NestExpressApplication => { @@ -76,6 +77,7 @@ export const bootstrap = (app: NestExpressApplication): NestExpressApplication = app.useGlobalFilters(new ZodExceptionFilter()); app.useGlobalFilters(new HttpExceptionFilter()); app.useGlobalFilters(new TRPCExceptionFilter()); + app.useGlobalFilters(new CalendarServiceExceptionFilter()); app.use(cookieParser()); diff --git a/apps/api/v2/src/filters/calendar-service-exception.filter.ts b/apps/api/v2/src/filters/calendar-service-exception.filter.ts new file mode 100644 index 0000000000..a4915f8b48 --- /dev/null +++ b/apps/api/v2/src/filters/calendar-service-exception.filter.ts @@ -0,0 +1,57 @@ +import { filterReqHeaders } from "@/lib/filterReqHeaders"; +import { ArgumentsHost, Catch, ExceptionFilter, Logger } from "@nestjs/common"; +import { Request } from "express"; + +import { ERROR_STATUS } from "@calcom/platform-constants"; +import { + CalendarAppError, + CalendarAppDelegationCredentialInvalidGrantError, + CalendarAppDelegationCredentialError, + CalendarAppDelegationCredentialConfigurationError, + CalendarAppDelegationCredentialClientIdNotAuthorizedError, + CalendarAppDelegationCredentialNotSetupError, +} from "@calcom/platform-libraries/app-store"; +import { Response } from "@calcom/platform-types"; + +type CalendarError = + | CalendarAppError + | CalendarAppDelegationCredentialInvalidGrantError + | CalendarAppDelegationCredentialError + | CalendarAppDelegationCredentialConfigurationError + | CalendarAppDelegationCredentialNotSetupError + | CalendarAppDelegationCredentialClientIdNotAuthorizedError; +@Catch( + CalendarAppError, + CalendarAppDelegationCredentialInvalidGrantError, + CalendarAppDelegationCredentialError, + CalendarAppDelegationCredentialConfigurationError, + CalendarAppDelegationCredentialClientIdNotAuthorizedError, + CalendarAppDelegationCredentialNotSetupError +) +export class CalendarServiceExceptionFilter implements ExceptionFilter { + private readonly logger = new Logger("CalendarServiceExceptionFilter"); + + catch(exception: CalendarError, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + + const requestId = request.headers["X-Request-Id"]; + + this.logger.error(`Calendar Service Exception Filter: ${exception?.message}`, { + exception, + body: request.body, + headers: filterReqHeaders(request.headers), + url: request.url, + method: request.method, + requestId, + }); + + response.status(400).json({ + status: ERROR_STATUS, + timestamp: new Date().toISOString(), + path: request.url, + error: { code: exception.name, message: exception.message }, + }); + } +} diff --git a/apps/api/v2/src/lib/filterReqHeaders.ts b/apps/api/v2/src/lib/filterReqHeaders.ts index e99d6fa779..2e6e12b234 100644 --- a/apps/api/v2/src/lib/filterReqHeaders.ts +++ b/apps/api/v2/src/lib/filterReqHeaders.ts @@ -2,19 +2,20 @@ import { IncomingHttpHeaders } from "http"; export function filterReqHeaders(headers: IncomingHttpHeaders): Partial { return { - "Content-Type": headers["content-type"], - "User-Agent": headers["user-agent"], + "Content-Type": headers["Content-Type"] ?? headers["content-type"], + Authorization: headers["Authorization"] ?? headers["authorization"], + "X-Cal-Client-Id": headers["X-Cal-Client-Id"] ?? headers["x-cal-client-id"], + "Cal-Api-Version": headers["Cal-Api-Version"] ?? headers["cal-api-version"], "X-Request-Id": headers["X-Request-Id"] ?? headers["x-request-id"], - // IP-related headers + "User-Agent": headers["User-agent"] ?? headers["user-agent"], "X-Forwarded-For": headers["x-forwarded-for"], "X-Forwarded-Host": headers["x-forwarded-host"], "CF-Connecting-IP": headers["cf-connecting-ip"], "CloudFront-Viewer-Address": headers["cloudfront-viewer-address"], - // Vercel headers - "x-vercel-id": headers["x-vercel-id"], - "x-vercel-deployment-url": headers["x-vercel-deployment-url"], - "x-vercel-country": headers["x-vercel-country"], - "x-vercel-region": headers["x-vercel-region"], - Host: headers["host"], + "X-Vercel-Id": headers["x-vercel-id"], + "X-Vercel-Deployment-Url": headers["x-vercel-deployment-url"], + "X-Vercel-Country": headers["x-vercel-country"], + "X-Vercel-Region": headers["x-vercel-region"], + Host: headers["Host"] ?? headers["host"], }; } diff --git a/packages/platform/libraries/app-store.ts b/packages/platform/libraries/app-store.ts index 60ed69b691..325264e902 100644 --- a/packages/platform/libraries/app-store.ts +++ b/packages/platform/libraries/app-store.ts @@ -32,3 +32,11 @@ export { addDelegationCredential }; export { enrichUserWithDelegationConferencingCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server"; export { toggleDelegationCredentialEnabled } from "@calcom/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler"; +export { + CalendarAppError, + CalendarAppDelegationCredentialInvalidGrantError, + CalendarAppDelegationCredentialError, + CalendarAppDelegationCredentialConfigurationError, + CalendarAppDelegationCredentialClientIdNotAuthorizedError, + CalendarAppDelegationCredentialNotSetupError, +} from "@calcom/lib/CalendarAppError";