-
Notifications
You must be signed in to change notification settings - Fork 0
fix: handle collective multiple host on destinationCalendar #8
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
base: enhance-collective-scheduling-foundation
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,7 +104,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) | |
| }); | ||
|
|
||
| const attendeesList = await Promise.all(attendeesListPromises); | ||
|
|
||
| const selectedDestinationCalendar = booking.destinationCalendar || user.destinationCalendar; | ||
| const evt: CalendarEvent = { | ||
| type: booking.title, | ||
| title: booking.title, | ||
|
|
@@ -127,7 +127,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) | |
| attendees: attendeesList, | ||
| uid: booking.uid, | ||
| recurringEvent: parseRecurringEvent(booking.eventType?.recurringEvent), | ||
| destinationCalendar: booking.destinationCalendar || user.destinationCalendar, | ||
| destinationCalendar: selectedDestinationCalendar ? [selectedDestinationCalendar] : [], | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/apps/web/pages/api/cron/bookingReminder.ts
+++ b/apps/web/pages/api/cron/bookingReminder.ts
@@ -1,5 +1,6 @@
+import crypto from "crypto";
+
import type { NextApiRequest, NextApiResponse } from "next";
import dayjs from "@calcom/dayjs";
import { sendOrganizerRequestReminderEmail } from "@calcom/emails";
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
@@ -8,18 +9,30 @@ import { getTranslation } from "@calcom/lib/server/i18n";
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
import { BookingStatus, ReminderType } from "@calcom/prisma/enums";
import type { CalendarEvent } from "@calcom/types/Calendar";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
- const apiKey = req.headers.authorization || req.query.apiKey;
- if (process.env.CRON_API_KEY !== apiKey) {
- res.status(401).json({ message: "Not authenticated" });
- return;
+ if (req.method !== "POST") {
+ res.status(405).json({ message: "Method not allowed" });
+ return;
}
- if (req.method !== "POST") {
- res.status(405).json({ message: "Not authenticated" });
+ const expectedApiKey = process.env.CRON_API_KEY;
+ if (!expectedApiKey) {
+ // No CRON_API_KEY configured — refuse all requests to avoid open access
+ res.status(500).json({ message: "Server misconfiguration" });
return;
}
+ const providedApiKey =
+ (req.headers.authorization ?? "").replace(/^Bearer\s+/i, "") ||
+ (typeof req.query.apiKey === "string" ? req.query.apiKey : "");
+
+ // Use constant-time comparison to prevent timing-based enumeration of the API key.
+ // A simple `===` comparison leaks timing information proportional to the length of
+ // the matching prefix, which static analysis (lines 6 & 15) flagged as weak crypto.
+ const expected = Buffer.from(expectedApiKey, "utf8");
+ const provided = Buffer.from(providedApiKey, "utf8");
+ const keysMatch =
+ expected.length === provided.length &&
+ crypto.timingSafeEqual(expected, provided);
+
+ if (!keysMatch) {
+ res.status(401).json({ message: "Not authenticated" });
+ return;
+ }🤖 Grapple PR auto-fix • minor • Review this diff before applying |
||
|
|
||
| await sendOrganizerRequestReminderEmail(evt); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -246,7 +246,7 @@ test.describe("BOOKING_REJECTED", async () => { | |||||||||||||||||
| }, | ||||||||||||||||||
| ], | ||||||||||||||||||
| location: "[redacted/dynamic]", | ||||||||||||||||||
| destinationCalendar: null, | ||||||||||||||||||
| destinationCalendar: [], | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 MINOR — Webhook Contract Change (confidence: 89%) The webhook payload contract changed Evidence:
Agent: architecture There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✅
Suggested change
🤖 Grapple PR auto-fix • minor • confidence: 89% |
||||||||||||||||||
| // hideCalendarNotes: false, | ||||||||||||||||||
| requiresConfirmation: "[redacted/dynamic]", | ||||||||||||||||||
| eventTypeId: "[redacted/dynamic]", | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -84,7 +84,7 @@ export default class GoogleCalendarService implements Calendar { | |||||
| }; | ||||||
| }; | ||||||
|
|
||||||
| async createEvent(calEventRaw: CalendarEvent): Promise<NewCalendarEventType> { | ||||||
| async createEvent(calEventRaw: CalendarEvent, credentialId: number): Promise<NewCalendarEventType> { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 MAJOR — Missing Credential for Google Calendar createEvent (confidence: 100%) The Evidence:
Agent: logic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 MINOR — Code Patterns (confidence: 93%) Method signature changed to add Evidence:
Agent: style There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✅
Suggested change
🤖 Grapple PR auto-fix • minor • confidence: 93% There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/larkcalendar/lib/CalendarService.ts
+++ b/packages/app-store/larkcalendar/lib/CalendarService.ts
@@ -122,7 +122,7 @@ export default class LarkCalendarService implements Calendar {
};
}
- async createEvent(event: CalendarEvent): Promise<NewCalendarEventType> {
+ async createEvent(event: CalendarEvent, credentialId: number): Promise<NewCalendarEventType> {
let eventId = "";
let eventRespData;
const mainHostDestinationCalendar = event.destinationCalendar
--- a/packages/app-store/office365calendar/lib/CalendarService.ts
+++ b/packages/app-store/office365calendar/lib/CalendarService.ts
@@ -69,7 +69,7 @@ export default class Office365CalendarService implements Calendar {
};
}
- async createEvent(event: CalendarEvent): Promise<NewCalendarEventType> {
+ async createEvent(event: CalendarEvent, credentialId: number): Promise<NewCalendarEventType> {
const calendarId = event.destinationCalendar?.find(
(cal) => cal.integration === "office365_calendar"
)?.externalId;
--- a/packages/lib/CalendarService.ts
+++ b/packages/lib/CalendarService.ts
@@ -1,6 +1,7 @@
import type {
Calendar,
CalendarEvent,
+ NewCalendarEventType,
} from "@calcom/types/Calendar";
// Ensure any abstract/base createEvent signature matches the interface🤖 Grapple PR auto-fix • major • Review this diff before applying |
||||||
| const eventAttendees = calEventRaw.attendees.map(({ id: _id, ...rest }) => ({ | ||||||
| ...rest, | ||||||
| responseStatus: "accepted", | ||||||
|
|
@@ -97,6 +97,10 @@ export default class GoogleCalendarService implements Calendar { | |||||
| responseStatus: "accepted", | ||||||
| })) || []; | ||||||
| return new Promise(async (resolve, reject) => { | ||||||
| const [mainHostDestinationCalendar] = | ||||||
| calEventRaw?.destinationCalendar && calEventRaw?.destinationCalendar.length > 0 | ||||||
| ? calEventRaw.destinationCalendar | ||||||
| : []; | ||||||
| const myGoogleAuth = await this.auth.getToken(); | ||||||
| const payload: calendar_v3.Schema$Event = { | ||||||
| summary: calEventRaw.title, | ||||||
|
|
@@ -115,8 +119,8 @@ export default class GoogleCalendarService implements Calendar { | |||||
| id: String(calEventRaw.organizer.id), | ||||||
| responseStatus: "accepted", | ||||||
| organizer: true, | ||||||
| email: calEventRaw.destinationCalendar?.externalId | ||||||
| ? calEventRaw.destinationCalendar.externalId | ||||||
| email: mainHostDestinationCalendar?.externalId | ||||||
| ? mainHostDestinationCalendar.externalId | ||||||
| : calEventRaw.organizer.email, | ||||||
| }, | ||||||
| ...eventAttendees, | ||||||
|
|
@@ -138,13 +142,16 @@ export default class GoogleCalendarService implements Calendar { | |||||
| const calendar = google.calendar({ | ||||||
| version: "v3", | ||||||
| }); | ||||||
| const selectedCalendar = calEventRaw.destinationCalendar?.externalId | ||||||
| ? calEventRaw.destinationCalendar.externalId | ||||||
| : "primary"; | ||||||
| // Find in calEventRaw.destinationCalendar the one with the same credentialId | ||||||
|
|
||||||
| const selectedCalendar = calEventRaw.destinationCalendar?.find( | ||||||
| (cal) => cal.credentialId === credentialId | ||||||
| )?.externalId; | ||||||
|
|
||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 INFO — Code Organization (confidence: 86%) Incomplete TODO comment added during refactoring. Lines 146-147 contain a TODO comment 'Find in calEventRaw.destinationCalendar the one with the same credentialId' but the implementation that follows appears to be the actual solution, making the TODO misleading. Evidence:
Agent: style |
||||||
| calendar.events.insert( | ||||||
| { | ||||||
| auth: myGoogleAuth, | ||||||
| calendarId: selectedCalendar, | ||||||
| calendarId: selectedCalendar || "primary", | ||||||
| requestBody: payload, | ||||||
| conferenceDataVersion: 1, | ||||||
| sendUpdates: "none", | ||||||
|
|
@@ -188,6 +195,8 @@ export default class GoogleCalendarService implements Calendar { | |||||
|
|
||||||
| async updateEvent(uid: string, event: CalendarEvent, externalCalendarId: string): Promise<any> { | ||||||
| return new Promise(async (resolve, reject) => { | ||||||
| const [mainHostDestinationCalendar] = | ||||||
| event?.destinationCalendar && event?.destinationCalendar.length > 0 ? event.destinationCalendar : []; | ||||||
| const myGoogleAuth = await this.auth.getToken(); | ||||||
| const eventAttendees = event.attendees.map(({ ...rest }) => ({ | ||||||
| ...rest, | ||||||
|
|
@@ -216,8 +225,8 @@ export default class GoogleCalendarService implements Calendar { | |||||
| id: String(event.organizer.id), | ||||||
| organizer: true, | ||||||
| responseStatus: "accepted", | ||||||
| email: event.destinationCalendar?.externalId | ||||||
| ? event.destinationCalendar.externalId | ||||||
| email: mainHostDestinationCalendar?.externalId | ||||||
| ? mainHostDestinationCalendar.externalId | ||||||
| : event.organizer.email, | ||||||
| }, | ||||||
| ...(eventAttendees as any), | ||||||
|
|
@@ -244,7 +253,7 @@ export default class GoogleCalendarService implements Calendar { | |||||
|
|
||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 CRITICAL — Logic Error / Silent Data Loss (confidence: 100%) In Evidence:
Agent: architecture There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • critical • Review this diff before applying |
||||||
| const selectedCalendar = externalCalendarId | ||||||
| ? externalCalendarId | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 CRITICAL — Logic Bug - Dead Code / Always Falsy (confidence: 100%) In Evidence:
Agent: logic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • critical • Review this diff before applying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 MAJOR — Logic Error — Tautological Condition Breaks Calendar Fallback (confidence: 100%) In Evidence:
Agent: security There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • major • Review this diff before applying |
||||||
| : event.destinationCalendar?.externalId; | ||||||
| : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 MINOR — Unnecessary work (confidence: 100%) In Evidence:
Agent: performance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • minor • Review this diff before applying |
||||||
|
|
||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 MAJOR — Unnecessary work (confidence: 100%) Dead-code logic in Evidence:
Agent: performance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • major • Review this diff before applying |
||||||
| calendar.events.update( | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 MAJOR — Input validation (confidence: 100%) In Evidence:
Agent: security There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -253,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : event.destinationCalendar?.find((cal) => cal.credentialId === this.credential.id)?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : event.destinationCalendar?.find((cal) => cal.credentialId === this.credential.id)?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • major • Review this diff before applying |
||||||
| { | ||||||
|
|
@@ -303,7 +312,9 @@ export default class GoogleCalendarService implements Calendar { | |||||
| }); | ||||||
|
|
||||||
| const defaultCalendarId = "primary"; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 CRITICAL — Logic Bug - Dead Code / Always Falsy (confidence: 100%) In Evidence:
Agent: logic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -250,7 +250,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.update(
{
@@ -309,6 +309,9 @@ export default class GoogleCalendarService implements Calendar {
async deleteEvent(uid: string, event: CalendarEvent, externalCalendarId?: string | null): Promise<void> {
return new Promise(async (resolve, reject) => {
const myGoogleAuth = await this.auth.getToken();
+ const [mainHostDestinationCalendar] =
+ event?.destinationCalendar && event?.destinationCalendar.length > 0
+ ? event.destinationCalendar
+ : [];
const calendar = google.calendar({
version: "v3",
auth: myGoogleAuth,
@@ -316,7 +319,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : mainHostDestinationCalendar?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • critical • Review this diff before applying |
||||||
| const calendarId = externalCalendarId ? externalCalendarId : event.destinationCalendar?.externalId; | ||||||
| const calendarId = externalCalendarId | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 MINOR — Unnecessary work (confidence: 93%) Same no-op fallback pattern in Evidence:
Agent: performance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
--- a/packages/app-store/googlecalendar/lib/CalendarService.ts
+++ b/packages/app-store/googlecalendar/lib/CalendarService.ts
@@ -250,7 +250,7 @@ export default class GoogleCalendarService implements Calendar {
const selectedCalendar = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : event.destinationCalendar?.[0]?.externalId;
calendar.events.update(
{
@@ -312,7 +312,7 @@ export default class GoogleCalendarService implements Calendar {
const defaultCalendarId = "primary";
const calendarId = externalCalendarId
? externalCalendarId
- : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
+ : event.destinationCalendar?.[0]?.externalId;
calendar.events.delete(
{🤖 Grapple PR auto-fix • minor • Review this diff before applying |
||||||
| ? externalCalendarId | ||||||
| : event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId; | ||||||
|
|
||||||
| calendar.events.delete( | ||||||
| { | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -217,7 +217,8 @@ export const getBusyCalendarTimes = async ( | |||||
|
|
||||||
| export const createEvent = async ( | ||||||
| credential: CredentialWithAppName, | ||||||
| calEvent: CalendarEvent | ||||||
| calEvent: CalendarEvent, | ||||||
| externalId?: string | ||||||
| ): Promise<EventResult<NewCalendarEventType>> => { | ||||||
| const uid: string = getUid(calEvent); | ||||||
| const calendar = await getCalendar(credential); | ||||||
|
|
@@ -226,29 +227,31 @@ export const createEvent = async ( | |||||
|
|
||||||
| // Check if the disabledNotes flag is set to true | ||||||
| if (calEvent.hideCalendarNotes) { | ||||||
| calEvent.additionalNotes = "Notes have been hidden by the organiser"; // TODO: i18n this string? | ||||||
| calEvent.additionalNotes = "Notes have been hidden by the organizer"; // TODO: i18n this string? | ||||||
| } | ||||||
|
|
||||||
| // TODO: Surface success/error messages coming from apps to improve end user visibility | ||||||
| const creationResult = calendar | ||||||
| ? await calendar.createEvent(calEvent).catch(async (error: { code: number; calError: string }) => { | ||||||
| success = false; | ||||||
| /** | ||||||
| * There is a time when selectedCalendar externalId doesn't match witch certain credential | ||||||
| * so google returns 404. | ||||||
| * */ | ||||||
| if (error?.code === 404) { | ||||||
| ? await calendar | ||||||
| .createEvent(calEvent, credential.id) | ||||||
| .catch(async (error: { code: number; calError: string }) => { | ||||||
| success = false; | ||||||
| /** | ||||||
| * There is a time when selectedCalendar externalId doesn't match witch certain credential | ||||||
| * so google returns 404. | ||||||
| * */ | ||||||
| if (error?.code === 404) { | ||||||
| return undefined; | ||||||
| } | ||||||
| if (error?.calError) { | ||||||
| calError = error.calError; | ||||||
| } | ||||||
| log.error("createEvent failed", JSON.stringify(error), calEvent); | ||||||
| // @TODO: This code will be off till we can investigate an error with it | ||||||
| //https://github.com/calcom/cal.com/issues/3949 | ||||||
| // await sendBrokenIntegrationEmail(calEvent, "calendar"); | ||||||
| return undefined; | ||||||
| } | ||||||
| if (error?.calError) { | ||||||
| calError = error.calError; | ||||||
| } | ||||||
| log.error("createEvent failed", JSON.stringify(error), calEvent); | ||||||
| // @TODO: This code will be off till we can investigate an error with it | ||||||
| //https://github.com/calcom/cal.com/issues/3949 | ||||||
| // await sendBrokenIntegrationEmail(calEvent, "calendar"); | ||||||
| return undefined; | ||||||
| }) | ||||||
| }) | ||||||
| : undefined; | ||||||
|
|
||||||
| return { | ||||||
|
|
@@ -261,6 +264,8 @@ export const createEvent = async ( | |||||
| originalEvent: calEvent, | ||||||
| calError, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 MAJOR — Incorrect externalId Passing (confidence: 100%) The Evidence:
Agent: logic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✅
Suggested change
🤖 Grapple PR auto-fix • major • confidence: 100% |
||||||
| calWarnings: creationResult?.additionalInfo?.calWarnings || [], | ||||||
| externalId, | ||||||
| credentialId: credential.id, | ||||||
| }; | ||||||
| }; | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 MINOR — Data exposure (confidence: 73%)
The cron endpoint now wraps
destinationCalendarin an array ([selectedDestinationCalendar]) or empty array. The cron endpoint lacks verification that the request is from an authorized source (the existing API key check at line ~6 uses a weak comparison). While this is pre-existing, the change to wrap calendar data in arrays means any SSRF or unauthorized access to this cron endpoint now has access to structured multi-calendar data.Evidence:
destinationCalendararrayAgent: security