Skip to content

Conversation

@joeauyeung
Copy link
Contributor

What does this PR do?

Allows conferencing apps to be installed on a team when the concurrentMeeting property is true in the app's metadata

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  • Add concurrentMeetings to a conferencing app's metadata
  • When installing the app it should bring you to the account selection on the install page

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

Client-side handlers in AppPage.tsx and AppCard.tsx now require both isConferencing(categories) and !concurrentMeetings to trigger the Event Types onboarding step; if concurrentMeetings is true (or the app is not conferencing) the flow falls back to the existing install mutation or the Accounts onboarding path based on team availability. On the server (getServerSideProps), installableOnTeams is computed as !!appMetadata?.concurrentMeetings || !isConferencing — i.e., conferencing apps are installable on teams only when appMetadata.concurrentMeetings is truthy, while non-conferencing apps remain installable. No exported/public declarations changed.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch make-concurrent-video-app-install-on-team

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 @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit 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:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit 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 @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @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.

@graphite-app graphite-app bot requested a review from a team August 28, 2025 16:47
@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Aug 28, 2025
@dosubot dosubot bot added the teams area: teams, round robin, collective, managed event-types label Aug 28, 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: 1

Caution

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

⚠️ Outside diff range comments (3)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (3)

179-197: OR with {} matches everything; also over-fetches credentials (potentially sensitive)

The empty object inside OR will return all credentials. Also, only id/teamId/userId are needed—avoid fetching other fields.

-const getAppInstallsBySlug = async (appSlug: string, userId: number, teamIds?: number[]) => {
-  const appInstalls = await prisma.credential.findMany({
-    where: {
-      OR: [
-        {
-          appId: appSlug,
-          userId: userId,
-        },
-        teamIds && Boolean(teamIds.length)
-          ? {
-              appId: appSlug,
-              teamId: { in: teamIds },
-            }
-          : {},
-      ],
-    },
-  });
-  return appInstalls;
-};
+const getAppInstallsBySlug = async (appSlug: string, userId: number, teamIds?: number[]) => {
+  const or: Prisma.CredentialWhereInput[] = [{ appId: appSlug, userId }];
+  if (teamIds?.length) {
+    or.push({ appId: appSlug, teamId: { in: teamIds } });
+  }
+  return prisma.credential.findMany({
+    where: { OR: or },
+    select: { id: true, teamId: true, userId: true }, // minimal set; never fetch credential.key
+  });
+};

68-74: Avoid sending app.keys to the client

app.keys is selected and the whole app object is returned via props. Remove keys from the select to prevent leaking metadata/secrets.

 const getAppBySlug = async (appSlug: string) => {
   const app = await prisma.app.findUnique({
     where: { slug: appSlug, enabled: true },
-    select: { slug: true, keys: true, enabled: true, dirName: true },
+    select: { slug: true, enabled: true, dirName: true },
   });
   return app;
 };

Also applies to: 306-309


216-218: Gate Event Types step for concurrent-meeting apps
In apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (around line 217), update the showEventTypesStep assignment to skip conferencing apps that support concurrent meetings:

-  const showEventTypesStep = extendsEventType || isConferencing;
+  const showEventTypesStep =
+    extendsEventType ||
+    (isConferencing && !appMetadata.concurrentMeetings);
+  // Skip Event Types step for conferencing apps with concurrentMeetings support
🧹 Nitpick comments (4)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (3)

213-218: Null-safety on appMetadata.categories

Guard against undefined metadata to avoid runtime crashes.

-  const isConferencing = isConferencingApp(appMetadata.categories);
+  const isConferencing = isConferencingApp(appMetadata?.categories ?? []);

300-301: Fix typo in comment

-  // dont allow app installation without cretendialId
+  // don't allow app installation without credentialId

199-323: Add test coverage for new team-install behavior

Please add SSR tests for:

  • conferencing + concurrentMeetings=true → installableOnTeams=true
  • conferencing + concurrentMeetings=false → installableOnTeams=false
  • non-conferencing → installableOnTeams=true

I can draft Playwright/SSR tests targeting getServerSideProps and the Accounts/Event Types routing if helpful.

packages/features/apps/components/AppCard.tsx (1)

59-81: Correct gating for Event Types; avoid recomputing doesAppSupportTeamInstall

Condition aligns with the new flow (skip Event Types when concurrentMeetings=true). Reuse enabledOnTeams instead of recomputing.

-    } else if (
-      !doesAppSupportTeamInstall({
-        appCategories: app.categories,
-        concurrentMeetings: app.concurrentMeetings,
-        isPaid: !!app.paid,
-      })
-    ) {
+    } else if (!enabledOnTeams) {

Note: This depends on the SSR fix to allow team installs when concurrentMeetings=true.

📜 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 464e5f1 and c64f198.

📒 Files selected for processing (3)
  • apps/web/components/apps/AppPage.tsx (1 hunks)
  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1 hunks)
  • packages/features/apps/components/AppCard.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:

  • apps/web/components/apps/AppPage.tsx
  • packages/features/apps/components/AppCard.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:

  • apps/web/components/apps/AppPage.tsx
  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts
  • packages/features/apps/components/AppCard.tsx
**/*.{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:

  • apps/web/components/apps/AppPage.tsx
  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts
  • packages/features/apps/components/AppCard.tsx
**/*.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/lib/apps/installation/[[...step]]/getServerSideProps.ts
🧬 Code graph analysis (3)
apps/web/components/apps/AppPage.tsx (1)
packages/app-store/utils.ts (1)
  • isConferencing (168-170)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1)
packages/app-store/utils.ts (1)
  • isConferencing (168-170)
packages/features/apps/components/AppCard.tsx (1)
packages/app-store/utils.ts (1)
  • isConferencing (168-170)
⏰ 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). (3)
  • GitHub Check: Type check / check-types
  • GitHub Check: Tests / Unit
  • GitHub Check: Linters / lint
🔇 Additional comments (1)
apps/web/components/apps/AppPage.tsx (1)

114-133: Gating looks right; ensure server-side installability matches

This correctly routes conferencing apps with concurrent meetings to Accounts. Ensure SSR sets installableOnTeams=true for that case (currently inverted in getServerSideProps).

Consider adding a component test covering both branches (concurrentMeetings true/false) to verify navigation targets.

@vercel
Copy link

vercel bot commented Aug 28, 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 28, 2025 5:11pm
cal-eu Ignored Ignored Aug 28, 2025 5:11pm

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

Caution

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

⚠️ Outside diff range comments (4)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (4)

216-218: Align server gating with client: skip Event Types for conferencing apps with concurrentMeetings=true

Client handlers only show Event Types when isConferencing && !concurrentMeetings. Server still uses extendsEventType || isConferencing, enabling manual navigation to the step. Align to avoid inconsistent flows.

Apply:

-  const showEventTypesStep = extendsEventType || isConferencing;
+  const showEventTypesStep =
+    extendsEventType || (isConferencing && !appMetadata?.concurrentMeetings);

179-197: Bug: {} inside OR broadens query to all credentials; also overfetches sensitive fields

When teamIds is falsy/empty, the {} branch makes OR: [{...}, {}] which matches everything. Additionally, no select is used, risking retrieval of credential.key. Build OR conditionally and select only needed fields.

-const getAppInstallsBySlug = async (appSlug: string, userId: number, teamIds?: number[]) => {
-  const appInstalls = await prisma.credential.findMany({
-    where: {
-      OR: [
-        {
-          appId: appSlug,
-          userId: userId,
-        },
-        teamIds && Boolean(teamIds.length)
-          ? {
-              appId: appSlug,
-              teamId: { in: teamIds },
-            }
-          : {},
-      ],
-    },
-  });
-  return appInstalls;
-};
+const getAppInstallsBySlug = async (appSlug: string, userId: number, teamIds?: number[]) => {
+  const orFilters: Prisma.CredentialWhereInput[] = [{ appId: appSlug, userId }];
+  if (teamIds && teamIds.length) {
+    orFilters.push({ appId: appSlug, teamId: { in: teamIds } });
+  }
+  return prisma.credential.findMany({
+    where: { OR: orFilters },
+    // Avoid fetching credential.key and other unused fields
+    select: { id: true, teamId: true, userId: true },
+  });
+};

254-260: Limit destinationCalendar fields to the minimum required

Currently fetches the full record and later ships it in props via eventTypeGroups, which may include credentialId. Select only needed fields.

-      const destinationCalendar = await prisma.destinationCalendar.findFirst({
+      const destinationCalendar = await prisma.destinationCalendar.findFirst({
         where: {
           userId: user.id,
           eventTypeId: null,
-        },
+        },
+        select: { id: true }, // expand if UI needs more, but avoid credentialId
       });

76-99: Constrain EventType.destinationCalendar selection to avoid leaking credential linkage

destinationCalendar: true pulls the full relation, potentially including credentialId. Select a safe subset.

-    destinationCalendar: true,
+    destinationCalendar: { select: { id: true } },
♻️ Duplicate comments (1)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1)

319-320: Update stale comment to match logic

Comment says conferencing apps don’t support team install; logic now allows it when concurrentMeetings is true.

-      // conferencing apps dont support team install
+      // Conferencing apps are installable on teams only when appMetadata.concurrentMeetings is true
🧹 Nitpick comments (2)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (2)

300-301: Fix typos in comment

Minor polish.

-  // dont allow app installation without cretendialId
+  // Don't allow app installation without credentialId

204-208: Be strict with [[...step]] parsing

params.step can be string|string[]. z.coerce.string() on an array yields a comma-joined string and may fail stepsEnum.parse. Normalize first element.

-  const parsedStepParam = z.coerce.string().parse(params?.step);
-  const _ = stepsEnum.parse(parsedStepParam);
+  const rawStep = params?.step;
+  const parsedStepParam = Array.isArray(rawStep) ? rawStep[0] : rawStep ?? "";
+  stepsEnum.parse(parsedStepParam);
📜 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 c64f198 and 9d5bd28.

📒 Files selected for processing (1)
  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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/lib/apps/installation/[[...step]]/getServerSideProps.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:

  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.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:

  • apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts
🧬 Code graph analysis (1)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1)
packages/app-store/utils.ts (1)
  • isConferencing (168-170)
🔇 Additional comments (1)
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1)

320-321: LGTM: installableOnTeams logic matches PR objective

!!appMetadata?.concurrentMeetings || !isConferencing correctly enables team installs for conferencing apps only when concurrent meetings are supported; non‑conferencing apps remain installable.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 28, 2025

E2E results are ready!

@joeauyeung joeauyeung merged commit 1fd1202 into main Aug 29, 2025
62 of 65 checks passed
@joeauyeung joeauyeung deleted the make-concurrent-video-app-install-on-team branch August 29, 2025 13:59
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 enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e teams area: teams, round robin, collective, managed event-types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants