Conversation
…dule-email-after-confirmation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
WalkthroughUpdated 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
Assessment against linked issues: Out-of-scope changes
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
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. |
There was a problem hiding this comment.
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 inputsThese 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 platformClientIdIf 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.tsbehaves when only URLs are present. If it strictly requiresplatformClientId, then keeping the current guard is fine.
68-69: Avoid empty-string fallback for encryption keyUsing
""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 bindingWe’ve confirmed that the
Bookingmodel definesuserId(notownerId) as the relation back toUser(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
userIdmatches the booking’s organizer to prevent cross-token misuseFile: 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
BookingorUserfields downstream, you can fetch them in a separate query or extend theselectaccordingly.
📜 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.
⛔ Files ignored due to path filters (1)
yarn.lockis 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.tsxapps/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.tsxapps/web/app/api/link/route.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield 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.331exist at lines 2496 and 3556 inyarn.lock, with no peerDependencies reported. This bump is safe to merge.
- yarn.lock entries at
yarn.lock:2496andyarn.lock:3556confirm the version is locked innpm view @calcom/platform-libraries@0.0.331 version→ 0.0.331npm 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 goalDestructuring the new platform fields from the decrypted payload is correct and aligns with the objective to forward platform settings to the confirm handler.
E2E results are ready! |
…dule-email-after-confirmation
…dule-email-after-confirmation
…dule-email-after-confirmation
Linear CAL-6315