Skip to content

fix: platform confirmed/declined meeting attendee reschedule email url#23335

Merged
supalarry merged 8 commits intomainfrom
lauris/cal-6315-fix-platform-attendee-reschedule-email-after-confirmation
Aug 27, 2025
Merged

fix: platform confirmed/declined meeting attendee reschedule email url#23335
supalarry merged 8 commits intomainfrom
lauris/cal-6315-fix-platform-attendee-reschedule-email-after-confirmation

Conversation

@supalarry
Copy link
Contributor

Linear CAL-6315

@linear
Copy link

linear bot commented Aug 25, 2025

@graphite-app graphite-app bot requested a review from a team August 25, 2025 13:26
@vercel
Copy link

vercel bot commented Aug 25, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Aug 27, 2025 1:59pm
cal-eu Ignored Ignored Aug 27, 2025 1:59pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

Walkthrough

Updated apps/web/app/api/link/route.ts to parse four optional platform fields (platformClientId, platformRescheduleUrl, platformCancelUrl, platformBookingUrl) from the decrypted token, moved session getter logic to a top-level createSessionGetter(userId), and conditionally forwards platformClientParams when confirming a booking. packages/emails/src/templates/OrganizerRequestEmail.tsx now includes the same platform fields in the encrypted seedData token. apps/api/v2/package.json pins @calcom/platform-libraries to 0.0.335.

Assessment against linked issues

Objective Addressed Explanation
Include platform settings in OrganizerRequestEmail token for accept/decline links (CAL-6315)
Extract platform settings in /api/link route and pass to confirm handler similar to v2 implementation (CAL-6315)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Bump @calcom/platform-libraries from 0.0.333 to 0.0.335 (apps/api/v2/package.json) Dependency version bump unrelated to CAL-6315 objectives which focus on token payload and /api/link handling.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0f4832b and 9086c4a.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • apps/api/v2/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/v2/package.json
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lauris/cal-6315-fix-platform-attendee-reschedule-email-after-confirmation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@keithwillcode keithwillcode added core area: core, team members only platform Anything related to our platform plan labels Aug 25, 2025
@graphite-app graphite-app bot requested a review from a team August 25, 2025 13:26
@dosubot dosubot bot added the emails area: emails, cancellation email, reschedule email, inbox, spam folder, not getting email label Aug 25, 2025
@supalarry supalarry requested a review from a team as a code owner August 25, 2025 13:29
@graphite-app
Copy link

graphite-app bot commented Aug 25, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (08/25/25)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add platform team as reviewer" took an action on this PR • (08/25/25)

1 reviewer was added to this PR based on Keith Williams's automation.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
packages/emails/src/templates/OrganizerRequestEmail.tsx (1)

8-15: Seed now includes platform fields — good. Minor nit to compact payload and avoid nulls.

If any of these props can be null, they’ll be serialized as "key": null. You can drop empty values to shrink the token and avoid downstream null checks.

-  const seedData = {
-    bookingUid: props.calEvent.uid,
-    userId: props.calEvent.organizer.id,
-    platformClientId: props.calEvent.platformClientId,
-    platformRescheduleUrl: props.calEvent.platformRescheduleUrl,
-    platformCancelUrl: props.calEvent.platformCancelUrl,
-    platformBookingUrl: props.calEvent.platformBookingUrl,
-  };
+  const seedData = {
+    bookingUid: props.calEvent.uid,
+    userId: props.calEvent.organizer.id,
+    ...(props.calEvent.platformClientId && { platformClientId: props.calEvent.platformClientId }),
+    ...(props.calEvent.platformRescheduleUrl && { platformRescheduleUrl: props.calEvent.platformRescheduleUrl }),
+    ...(props.calEvent.platformCancelUrl && { platformCancelUrl: props.calEvent.platformCancelUrl }),
+    ...(props.calEvent.platformBookingUrl && { platformBookingUrl: props.calEvent.platformBookingUrl }),
+  };
apps/web/app/api/link/route.ts (5)

33-37: Strengthen schema: validate URLs and bound size to prevent garbage inputs

These are used to influence downstream behavior. Add URL validation and reasonable size limits to reduce risk of malformed/oversized inputs.

-  platformClientId: z.string().optional(),
-  platformRescheduleUrl: z.string().optional(),
-  platformCancelUrl: z.string().optional(),
-  platformBookingUrl: z.string().optional(),
+  platformClientId: z.string().trim().max(200).optional(),
+  platformRescheduleUrl: z.string().trim().url().max(2048).optional(),
+  platformCancelUrl: z.string().trim().url().max(2048).optional(),
+  platformBookingUrl: z.string().trim().url().max(2048).optional(),

111-118: Gate on any provided platform field, not only platformClientId

If a platform integration supplies only URLs (and not an ID), we’ll currently drop platformClientParams. Consider forwarding the object when any of the fields exist.

-      platformClientParams: platformClientId
-        ? {
-            platformClientId,
-            platformRescheduleUrl,
-            platformCancelUrl,
-            platformBookingUrl,
-          }
-        : undefined,
+      platformClientParams:
+        platformClientId || platformRescheduleUrl || platformCancelUrl || platformBookingUrl
+          ? {
+              ...(platformClientId && { platformClientId }),
+              ...(platformRescheduleUrl && { platformRescheduleUrl }),
+              ...(platformCancelUrl && { platformCancelUrl }),
+              ...(platformBookingUrl && { platformBookingUrl }),
+            }
+          : undefined,

Please confirm how confirm.handler.ts behaves when only URLs are present. If it strictly requires platformClientId, then keeping the current guard is fine.


68-69: Avoid empty-string fallback for encryption key

Using "" may mask misconfiguration and lead to decryption failures that look like token corruption. Fail fast with a clear error if the key is missing.

-  const decryptedData = JSON.parse(
-    symmetricDecrypt(decodeURIComponent(token), process.env.CALENDSO_ENCRYPTION_KEY || "")
-  );
+  const encryptionKey = process.env.CALENDSO_ENCRYPTION_KEY;
+  if (!encryptionKey) {
+    throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Missing encryption key" });
+  }
+  const decryptedData = JSON.parse(
+    symmetricDecrypt(decodeURIComponent(token), encryptionKey)
+  );

126-126: Optional: consider redirecting to platformBookingUrl when present (with allowlisting)

If the desired UX is to land the organizer back on the platform app, conditionally redirect there. Be careful to prevent open-redirects; validate against an allowlist or trusted origin from server-side config instead of trusting the token.

-  return NextResponse.redirect(`${url.origin}/booking/${bookingUid}`);
+  // Optional: only enable if you enforce an allowlist of trusted hosts
+  return NextResponse.redirect(
+    platformBookingUrl && new URL(platformBookingUrl).protocol.startsWith("http")
+      ? platformBookingUrl
+      : `${url.origin}/booking/${bookingUid}`
+  );

80-86: Select only necessary booking fields and verify organizer binding

We’ve confirmed that the Booking model defines userId (not ownerId) as the relation back to User (see schema, lines 762–763) – so the refactor below correctly targets the organizer field. Applying this optional change will:

  • Limit data fetched from the database to only what’s needed
  • Defensively ensure the token’s userId matches the booking’s organizer to prevent cross-token misuse

File: apps/web/app/api/link/route.ts (around lines 80–86)

-  const booking = await prisma.booking.findUniqueOrThrow({
-    where: { uid: bookingUid },
-  });
+  const booking = await prisma.booking.findUniqueOrThrow({
+    where: { uid: bookingUid },
+    select: { id: true, uid: true, recurringEventId: true, userId: true },
+  });
+
+  // Ensure the token’s userId matches the booking’s organizer
+  if (booking.userId !== userId) {
+    return NextResponse.redirect(
+      `${url.origin}/booking/${bookingUid}?error=${encodeURIComponent("Invalid token context")}`
+    );
+  }

If you still need additional Booking or User fields downstream, you can fetch them in a separate query or extend the select accordingly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 489d56d and ed11fbd.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • apps/api/v2/package.json (1 hunks)
  • apps/web/app/api/link/route.ts (3 hunks)
  • packages/emails/src/templates/OrganizerRequestEmail.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/emails/src/templates/OrganizerRequestEmail.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/emails/src/templates/OrganizerRequestEmail.tsx
  • apps/web/app/api/link/route.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/emails/src/templates/OrganizerRequestEmail.tsx
  • apps/web/app/api/link/route.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/web/app/api/link/route.ts
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (2)
apps/api/v2/package.json (1)

41-41: 0.0.331 is published, lockfile updated, and no peer conflicts
Version 0.0.331 is confirmed on npm, and lockfile entries for @calcom/platform-libraries@0.0.331 exist at lines 2496 and 3556 in yarn.lock, with no peerDependencies reported. This bump is safe to merge.

  • yarn.lock entries at yarn.lock:2496 and yarn.lock:3556 confirm the version is locked in
  • npm view @calcom/platform-libraries@0.0.331 version → 0.0.331
  • npm view @calcom/platform-libraries@0.0.331 peerDependencies → (no peers)
apps/web/app/api/link/route.ts (1)

71-78: Extraction matches the schema and PR goal

Destructuring the new platform fields from the decrypted payload is correct and aligns with the objective to forward platform settings to the confirm handler.

Ryukemeister
Ryukemeister previously approved these changes Aug 25, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Aug 25, 2025

E2E results are ready!

Ryukemeister
Ryukemeister previously approved these changes Aug 26, 2025
@supalarry supalarry merged commit d0e59f1 into main Aug 27, 2025
39 checks passed
@supalarry supalarry deleted the lauris/cal-6315-fix-platform-attendee-reschedule-email-after-confirmation branch August 27, 2025 14:35
@coderabbitai coderabbitai bot mentioned this pull request Oct 10, 2025
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only emails area: emails, cancellation email, reschedule email, inbox, spam folder, not getting email platform Anything related to our platform plan ready-for-e2e

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants