Skip to content

Conversation

anikdhabal
Copy link
Contributor

@anikdhabal anikdhabal commented Sep 26, 2025

What does this PR do?

This PR implements auto-accept functionality for team invitations sent to existing Cal.com users. When an existing user clicks the "Accept Invite" button in their invitation email, the invitation is automatically accepted and they are redirected to the /teams page, eliminating the need for manual acceptance.

- Change email button text from 'View Invitation' to 'Accept Invite'
- Implement auto-accept flow when clicking email CTA
- Update TeamService.inviteMemberByToken to support auto-acceptance
- Add new autoAcceptInvite tRPC endpoint for handling auto-acceptance
- Update invitation link generation to include autoAccept parameter
- Handle both team and organization invitation scenarios
- Maintain payment/billing flow integration with TeamBilling.updateQuantity
- Preserve backward compatibility with existing manual flow
- Update all locale files with new 'Accept Invite' button text

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
Copy link
Contributor

coderabbitai bot commented Sep 26, 2025

Walkthrough

Adds an autoAccept query parameter to team invitation flows and propagates it through login callback URLs. Server pages and TeamsListing accept an autoAccept flag; when true and a token is present the flow calls TeamService.acceptInvitationByToken to auto-accept invites. TeamService gains acceptOrLeaveTeamMembership and acceptInvitationByToken to centralize accept/remove logic and profile/event updates. Invitation utilities centralize verification token creation and adjust join link construction; resend-invitation now defaults to /teams?token=...&autoAccept=true. Email CTA keys and locale strings are added and E2E tests for auto-accept and wrong-user errors are included.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly and concisely summarizes the main feature of the changeset by stating that team invitations will be auto-accepted for existing users, matching the implementation details and following conventional commit style.
Description Check ✅ Passed The description directly outlines the new auto-accept functionality for team invitations and its user flow, aligning closely with the code changes and objectives of the PR.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1758863155-auto-accept-team-invitations

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 ec4ee4f and 667af8a.

📒 Files selected for processing (1)
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.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: Codacy Static Code Analysis

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

Comment @coderabbitai help to get the list of available commands and usage tips.

- Keep only English 'Accept Invite' translation
- Revert all other locale files to original 'View Invitation' translations
- Maintain core auto-accept invitation functionality

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
@pull-request-size pull-request-size bot added size/M and removed size/L labels Sep 26, 2025
Copy link

vercel bot commented Sep 26, 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 Sep 27, 2025 6:34am
cal-eu Ignored Ignored Sep 27, 2025 6:34am

- Remove autoAccept parameter from TeamService.inviteMemberByToken
- Always auto-accept invitations for existing users clicking email links
- Remove autoAccept logic from teams server-page.tsx
- Remove autoAccept=true from invitation URLs
- Delete autoAcceptInvite handler and schema files
- Remove autoAcceptInvite endpoint from tRPC router
- Simplify invitation flow to match new user pattern

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
- Change expectation from accepted: false to accepted: true
- Update test description to reflect auto-accept behavior
- Fix TypeScript type casting to use Pick<TeamRepository, 'deleteById'>
- Aligns with new default auto-acceptance for team invitations

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
anikdhabal and others added 4 commits September 26, 2025 17:32
- Fix duplicate property assignments in mock user objects
- Use proper email format (user@example.com) for email fields
- Use proper username format (testuser) for username fields
- Fix logic error in acceptInvitationByToken (|| to &&)
- Add autoAccept parameter to resendInvitation.handler.ts
- All 16 tests passing with proper TypeScript types

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
- Add test for existing user auto-accepting team invitation via email link
- Add test for error handling when wrong user tries to use invitation link
- Verify proper user identity validation and database state changes
- Follow existing e2e test patterns with browser context isolation
- Fix ESLint warnings: replace conditional with assertion and remove unused browser parameter

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
@anikdhabal anikdhabal marked this pull request as ready for review September 26, 2025 12:44
@graphite-app graphite-app bot requested a review from a team September 26, 2025 12:44
@calcom calcom deleted a comment from devin-ai-integration bot Sep 26, 2025
@dosubot dosubot bot added teams area: teams, round robin, collective, managed event-types ✨ feature New feature or request labels Sep 26, 2025
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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/features/ee/teams/components/TeamsListing.tsx (1)

91-110: Don’t show success toast if auto-accept failed.

This short-circuits on autoAccept regardless of server outcome, masking errors. Show error first, then success only if no error.

Apply this diff:

   useEffect(() => {
     if (!token) {
       return;
     }

-    if (autoAccept) {
-      showToast(t("successfully_joined"), "success");
-      return;
-    }
+    if (errorMsgFromInvite) {
+      showToast(errorMsgFromInvite, "error");
+      return;
+    }
+
+    if (autoAccept) {
+      showToast(t("successfully_joined"), "success");
+      return;
+    }

     if (teamNameFromInvite) {
       showToast(t("team_invite_received", { teamName: teamNameFromInvite }), "success");
       return;
     }
 
-    if (errorMsgFromInvite) {
-      showToast(errorMsgFromInvite, "error");
-      return;
-    }
-  }, []);
+  }, [token, autoAccept, teamNameFromInvite, errorMsgFromInvite, t]);
packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts (1)

505-516: Fix token mismatch in signup invite link

You generate a local token and also create a verification token, but the joinLink uses the local (unsaved) token, breaking signup flows. Use the token returned by createVerificationToken and remove the unused local token.

   try {
-    const token: string = randomBytes(32).toString("hex");
-
-    await createVerificationToken(usernameOrEmail, teamId);
+    const verificationToken = await createVerificationToken(usernameOrEmail, teamId);
     await sendTeamInviteEmail({
       language: translation,
       from: inviterName || `${team.name}'s admin`,
       to: usernameOrEmail,
       teamName: team.name,
-      joinLink: `${WEBAPP_URL}/signup?token=${token}&callbackUrl=/getting-started`,
+      joinLink: `${WEBAPP_URL}/signup?token=${verificationToken.token}&callbackUrl=/getting-started`,
       isCalcomMember: false,
       isOrg: isOrg,
       parentTeamName: team?.parent?.name,
       isAutoJoin: false,
       isExistingUserMovedToOrg: false,
🧹 Nitpick comments (8)
apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx (1)

26-27: Encode callbackUrl when embedding it into the login URL.

You build a safe callbackUrl (params encoded), but when passing it to /auth/login?callbackUrl=... it should be wrapped in encodeURIComponent to avoid parameter confusion.

Suggested change outside the shown range (Line 30):

redirect(callbackUrl ? `/auth/login?callbackUrl=${encodeURIComponent(callbackUrl)}` : "/auth/login");
apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx (1)

35-36: Auto-accept: surface success/failure explicitly to the UI.

Currently the service call returns void; UI infers success from autoAccept query. Prefer returning a success flag or team name from acceptInvitationByToken and pass it through, so the client can toast success only on actual acceptance. Also consider cache invalidation if you rely on tags elsewhere.

Also applies to: 43-47, 65-66

packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts (1)

721-736: Avoid reusing expired tokens when building invite links

When reusing an existing token, you don’t check its validity. If the token is expired, the auto-accept flow will fail. Filter by validity (expiry) and only reuse valid tokens; otherwise create a fresh one. Also, select only needed fields.

As per coding guidelines

-      } else if (!isAutoJoin) {
-        let verificationToken = await prisma.verificationToken.findFirst({
-          where: {
-            identifier: user.email,
-            teamId: teamId,
-          },
-        });
+      } else if (!isAutoJoin) {
+        let verificationToken = await prisma.verificationToken.findFirst({
+          where: {
+            identifier: user.email,
+            teamId: teamId,
+            OR: [{ expiresInDays: null }, { expires: { gte: new Date() } }],
+          },
+          select: { token: true },
+        });
         if (!verificationToken) {
           verificationToken = await createVerificationToken(user.email, teamId);
         }
         inviteTeamOptions.joinLink = `${WEBAPP_URL}/teams?token=${verificationToken.token}&autoAccept=true`;
       }
packages/lib/server/service/teamService.test.ts (2)

334-366: Add assertion that invite token is invalidated after acceptance

After a successful acceptance by token, we should delete the token. Add an expectation to ensure the service invalidates the token (see suggested change in TeamService).

Example assertion to add after calling acceptInvitationByToken:

expect(prismaMock.verificationToken.deleteMany).toHaveBeenCalledWith({
  where: { token: "valid-token" },
});

367-399: Also assert token invalidation for username-identifier path

Mirror the deletion assertion for the username match case to cover both identifier variants.

packages/lib/server/service/teamService.ts (3)

294-296: Replace console.log with structured logger

Use the existing logger with context; avoid console.log in server code.

-      } catch (e) {
-        console.log(e);
-      }
+      } catch (e) {
+        logger.error("Failed to delete membership(s) on invite rejection", { userId, teamId, error: e });
+      }

231-276: Consider wrapping acceptance operations in a transaction

Accepting child and parent memberships plus optional profile creation should be atomic to avoid partial state if one step fails.


343-350: Invalidate the verification token after successful acceptance

Prevent re-use of the invite link by deleting the token post-acceptance.

     await TeamService.acceptOrLeaveTeamMembership({
       accept: true,
       userId,
       teamId: verificationToken.teamId,
       userEmail: currentUser.email,
       username: currentUser.username,
     });
+    await prisma.verificationToken.deleteMany({ where: { token: acceptanceToken } });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 8b7947a and 1d8ab0a.

📒 Files selected for processing (11)
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx (1 hunks)
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx (2 hunks)
  • apps/web/playwright/team/team-invitation.e2e.ts (3 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/emails/src/templates/TeamInviteEmail.tsx (1 hunks)
  • packages/features/ee/teams/components/TeamsListing.tsx (3 hunks)
  • packages/lib/server/service/teamService.test.ts (5 hunks)
  • packages/lib/server/service/teamService.ts (2 hunks)
  • packages/trpc/server/routers/viewer/teams/acceptOrLeave.handler.ts (2 hunks)
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts (3 hunks)
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.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:

  • packages/trpc/server/routers/viewer/teams/acceptOrLeave.handler.ts
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
  • packages/lib/server/service/teamService.test.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
  • packages/lib/server/service/teamService.ts
**/*.{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/trpc/server/routers/viewer/teams/acceptOrLeave.handler.ts
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts
  • packages/emails/src/templates/TeamInviteEmail.tsx
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
  • packages/lib/server/service/teamService.test.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx
  • packages/features/ee/teams/components/TeamsListing.tsx
  • packages/lib/server/service/teamService.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/trpc/server/routers/viewer/teams/acceptOrLeave.handler.ts
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx
  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts
  • packages/emails/src/templates/TeamInviteEmail.tsx
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
  • packages/lib/server/service/teamService.test.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx
  • packages/features/ee/teams/components/TeamsListing.tsx
  • packages/lib/server/service/teamService.ts
**/*.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:

  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx
  • packages/emails/src/templates/TeamInviteEmail.tsx
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx
  • packages/features/ee/teams/components/TeamsListing.tsx
**/*Service.ts

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

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/lib/server/service/teamService.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.
📚 Learning: 2025-09-16T08:59:45.884Z
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-09-16T08:59:45.884Z
Learning: anglerfishlyy's PR #23467 demonstrates excellent software architecture with proper email validation (regex + zod), secure token generation using randomBytes, comprehensive host type system using discriminated unions (userId OR email), and smart reuse of existing team invitation infrastructure. The implementation includes robust error handling, type safety, and maintains backward compatibility while adding CreatableSelect-based email invitation functionality.

Applied to files:

  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
📚 Learning: 2025-08-27T16:39:38.192Z
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.

Applied to files:

  • packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts
  • packages/emails/src/templates/TeamInviteEmail.tsx
  • packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
  • apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx
  • packages/lib/server/service/teamService.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • packages/emails/src/templates/TeamInviteEmail.tsx
🧬 Code graph analysis (6)
packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts (1)
packages/lib/constants.ts (1)
  • WEBAPP_URL (12-18)
packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts (1)
packages/lib/constants.ts (1)
  • WEBAPP_URL (12-18)
packages/lib/server/service/teamService.test.ts (2)
packages/lib/server/service/teamService.ts (1)
  • TeamService (54-569)
packages/lib/createAProfileForAnExistingUser.ts (1)
  • createAProfileForAnExistingUser (13-104)
apps/web/playwright/team/team-invitation.e2e.ts (1)
apps/web/playwright/lib/localize.ts (1)
  • localize (4-11)
apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx (1)
packages/lib/server/service/teamService.ts (1)
  • TeamService (54-569)
packages/lib/server/service/teamService.ts (1)
packages/lib/createAProfileForAnExistingUser.ts (1)
  • createAProfileForAnExistingUser (13-104)
⏰ 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 (7)
packages/emails/src/templates/TeamInviteEmail.tsx (1)

64-65: CTA label logic looks correct and matches new i18n keys.

The conditional picks the intended keys (login/accept_invite/join_now). No issues spotted.

apps/web/public/static/locales/en/common.json (1)

2153-2156: New strings align with usage.

Keys accept_invite, join_now, and successfully_joined are added and referenced by the UI/email changes.

Please ensure these keys are added in other locales or that fallbacks are acceptable for this release.

packages/trpc/server/routers/viewer/teams/acceptOrLeave.handler.ts (1)

14-20: Good delegation to service.

Handler now cleanly delegates to TeamService with the necessary context. No issues.

packages/features/ee/teams/components/TeamsListing.tsx (1)

21-21: Prop addition is clear and typed.

Public surface updated to accept autoAccept: boolean. No issues.

apps/web/playwright/team/team-invitation.e2e.ts (3)

50-50: LGTM: assert invite link presence

This improves deterministic behavior over early returns.


195-257: LGTM: solid coverage of auto‑accept happy path

End-to-end verifies link shape, pre/post membership state, login gating, and success toast.


259-326: LGTM: negative path for wrong user is well covered

Validates error message and ensures no unauthorized membership changes.

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 (2)
apps/web/playwright/team/team-invitation.e2e.ts (2)

226-249: Narrow Prisma membership selects in this test

These lookups only need the accepted boolean, but they currently fetch the entire membership row. Please add explicit select clauses here (and to the similar lookup a few lines below) to comply with our Prisma query guidelines.

As per coding guidelines

-      const membership = await prisma.membership.findFirst({
-        where: {
-          userId: invitedUser.id,
-          teamId: team.id,
-        },
-      });
+      const membership = await prisma.membership.findFirst({
+        where: {
+          userId: invitedUser.id,
+          teamId: team.id,
+        },
+        select: { accepted: true },
+      });

301-315: Apply explicit selects when checking memberships

Same issue here: these assertions only require minimal fields (id and accepted), so let’s scope the selects accordingly to avoid pulling full membership records.

As per coding guidelines

-      const membership = await prisma.membership.findFirst({
+      const membership = await prisma.membership.findFirst({
         where: {
           userId: wrongUser.id,
           teamId: team.id,
         },
+        select: { id: true },
       });
 ...
-      const invitedMembership = await prisma.membership.findFirst({
+      const invitedMembership = await prisma.membership.findFirst({
         where: {
           userId: invitedUser.id,
           teamId: team.id,
         },
+        select: { accepted: true },
       });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 1d8ab0a and ec4ee4f.

📒 Files selected for processing (2)
  • apps/web/playwright/team/team-invitation.e2e.ts (3 hunks)
  • packages/lib/server/service/teamService.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*Service.ts

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

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/lib/server/service/teamService.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:

  • packages/lib/server/service/teamService.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
**/*.{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/lib/server/service/teamService.ts
  • apps/web/playwright/team/team-invitation.e2e.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/lib/server/service/teamService.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.
📚 Learning: 2025-08-27T16:39:38.192Z
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.

Applied to files:

  • packages/lib/server/service/teamService.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
📚 Learning: 2025-09-16T08:59:45.884Z
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-09-16T08:59:45.884Z
Learning: anglerfishlyy's PR #23467 demonstrates excellent software architecture with proper email validation (regex + zod), secure token generation using randomBytes, comprehensive host type system using discriminated unions (userId OR email), and smart reuse of existing team invitation infrastructure. The implementation includes robust error handling, type safety, and maintains backward compatibility while adding CreatableSelect-based email invitation functionality.

Applied to files:

  • packages/lib/server/service/teamService.ts
  • apps/web/playwright/team/team-invitation.e2e.ts
📚 Learning: 2025-07-28T11:50:23.946Z
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : For Prisma queries, only select data you need; never use `include`, always use `select`

Applied to files:

  • packages/lib/server/service/teamService.ts
📚 Learning: 2025-08-07T18:42:34.081Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/lib/server/repository/PrismaPhoneNumberRepository.ts:412-417
Timestamp: 2025-08-07T18:42:34.081Z
Learning: In Cal.com codebase, the coding guideline requiring explicit `select` clauses instead of `include` for Prisma queries applies to read operations but not to update operations. Update operations don't need explicit select clauses.

Applied to files:

  • packages/lib/server/service/teamService.ts
🧬 Code graph analysis (1)
apps/web/playwright/team/team-invitation.e2e.ts (1)
apps/web/playwright/lib/localize.ts (1)
  • localize (4-11)
⏰ 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)
packages/lib/server/service/teamService.ts (2)

241-246: Limit team fields returned when accepting membership

We still pull the full team object here. Please tighten the selection to the fields actually used (id, parentId, isOrganization) so we stay compliant with the Prisma query policy.

As per coding guidelines

-        select: {
-          team: true,
-        },
+        select: {
+          team: {
+            select: {
+              id: true,
+              parentId: true,
+              isOrganization: true,
+            },
+          },
+        },

281-284: Also narrow the team shape when deleting membership

Same concern in the removal path: only parentId and id are referenced later, so please trim this selection too.

As per coding guidelines

-        const membership = await prisma.membership.delete({
+        const membership = await prisma.membership.delete({
           where: {
             userId_teamId: { userId, teamId },
           },
           select: {
-            team: true,
+            team: {
+              select: {
+                id: true,
+                parentId: true,
+              },
+            },
           },
         });

Copy link
Contributor

github-actions bot commented Sep 26, 2025

E2E results are ready!

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 ✨ feature New feature or request ready-for-e2e size/XL teams area: teams, round robin, collective, managed event-types
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants