From 08edd4f361972f7c91b74e28ad216ecbdc038bd2 Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Sun, 11 Jan 2026 00:04:02 -0500 Subject: [PATCH] chore: Add logging to `msteams` (#23684) * Add logging * fix: Add response status checking to MS Teams adapter error handling - Add response.ok checks before parsing JSON in createMeeting and updateMeeting - Remove console.log statements that could leak credential information - Ensure error handling matches original handleErrorsRaw behavior for tests Co-Authored-By: joe@cal.com * Fix logs * Revert "fix: Add response status checking to MS Teams adapter error handling" This reverts commit 35820d21e1a54d9e04d83fd5f53584d64a5459b6. * fix: Add response status checking to MS Teams adapter error handling - Check response.ok before parsing JSON in createMeeting and updateMeeting - Re-throw HttpError instances instead of wrapping them in catch blocks - This ensures HTTP errors (like 500) are properly propagated Co-Authored-By: unknown <> * fix: Correct log message in updateMeeting to say 'updating' instead of 'creating' Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> --- .../office365video/lib/VideoApiAdapter.ts | 95 +++++++++++++------ 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/packages/app-store/office365video/lib/VideoApiAdapter.ts b/packages/app-store/office365video/lib/VideoApiAdapter.ts index 9648acb2de..04bc6ad348 100644 --- a/packages/app-store/office365video/lib/VideoApiAdapter.ts +++ b/packages/app-store/office365video/lib/VideoApiAdapter.ts @@ -1,13 +1,12 @@ import { z } from "zod"; import { triggerDelegationCredentialErrorWebhook } from "@calcom/features/webhooks/lib/triggerDelegationCredentialErrorWebhook"; -import logger from "@calcom/lib/logger"; import { CalendarAppDelegationCredentialConfigurationError, CalendarAppDelegationCredentialInvalidGrantError, } from "@calcom/lib/CalendarAppError"; -import { handleErrorsRaw } from "@calcom/lib/errors"; import { HttpError } from "@calcom/lib/http-error"; +import logger from "@calcom/lib/logger"; import type { CalendarEvent } from "@calcom/types/Calendar"; import type { CredentialForCalendarServiceWithTenantId } from "@calcom/types/Credential"; import type { PartialReference } from "@calcom/types/EventManager"; @@ -39,6 +38,7 @@ const getO365VideoAppKeys = async () => { }; const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenantId): VideoApiAdapter => { + const log = logger.getSubLogger({ prefix: ["TeamsVideoApiAdapter"] }); let azureUserId: string | null; const tokenResponse = oAuthManagerHelper.getTokenObjectFromCredential(credential); @@ -228,57 +228,92 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant return Promise.resolve([]); }, updateMeeting: async (bookingRef: PartialReference, event: CalendarEvent) => { - const resultString = await auth - .requestRaw({ + try { + const response = await auth.requestRaw({ url: `${await getUserEndpoint()}/onlineMeetings`, options: { method: "POST", body: JSON.stringify(translateEvent(event)), }, - }) - .then(handleErrorsRaw); + }); - const resultObject = JSON.parse(resultString); + if (!response.ok) { + throw new HttpError({ + statusCode: response.status, + message: response.statusText, + }); + } - return Promise.resolve({ - type: "office365_video", - id: resultObject.id, - password: "", - url: resultObject.joinWebUrl || resultObject.joinUrl, - }); + const resultString = await response.text(); + const resultObject = JSON.parse(resultString); + + return Promise.resolve({ + type: "office365_video", + id: resultObject.id, + password: "", + url: resultObject.joinWebUrl || resultObject.joinUrl, + }); + } catch (error) { + log.error(`Error updating MS Teams meeting for booking ${event.uid}`, error); + if (error instanceof HttpError) { + throw error; + } + throw new HttpError({ + statusCode: 500, + message: `Error updating MS Teams meeting for booking ${event.uid}`, + }); + } }, - deleteMeeting: () => { + deleteMeeting:() => { return Promise.resolve([]); }, createMeeting: async (event: CalendarEvent): Promise => { const url = `${await getUserEndpoint()}/onlineMeetings`; - const resultString = await auth - .requestRaw({ + try { + const response = await auth.requestRaw({ url, options: { method: "POST", body: JSON.stringify(translateEvent(event)), }, - }) - .then(handleErrorsRaw); + }); - const resultObject = JSON.parse(resultString); + if (!response.ok) { + throw new HttpError({ + statusCode: response.status, + message: response.statusText, + }); + } - if (!resultObject.id || !resultObject.joinUrl || !resultObject.joinWebUrl) { + const resultString = await response.text(); + + const resultObject = JSON.parse(resultString); + + if (!resultObject.id || !resultObject.joinUrl || !resultObject.joinWebUrl) { + throw new HttpError({ + statusCode: 500, + message: `Error creating MS Teams meeting: ${resultObject.error?.message || "missing required fields in response"}`, + }); + } + + log.debug("Teams meeting created", { meetingId: resultObject.id }); + + return Promise.resolve({ + type: "office365_video", + id: resultObject.id, + password: "", + url: resultObject.joinWebUrl || resultObject.joinUrl, + }); + } catch (error) { + log.error(`Error creating MS Teams meeting for booking ${event.uid}`, error); + if (error instanceof HttpError) { + throw error; + } throw new HttpError({ statusCode: 500, - message: `Error creating MS Teams meeting: ${resultObject.error?.message || "missing required fields in response"}`, + message: `Error creating MS Teams meeting for booking ${event.uid}`, }); } - - logger.debug("Teams meeting created", { meetingId: resultObject.id }); - - return Promise.resolve({ - type: "office365_video", - id: resultObject.id, - password: "", - url: resultObject.joinWebUrl || resultObject.joinUrl, - }); }, }; };