From 22167d28b8b2b8382fabc75f079c998b5c0e5d83 Mon Sep 17 00:00:00 2001 From: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Date: Sat, 7 Feb 2026 17:57:16 +0530 Subject: [PATCH] fix: prevent auto-install for OAuth apps in installation flow (#27567) * fix: resolve organizer default conferencing app credential for location update - Fix Google Meet credential lookup in EventManager to properly map 'google:meet' to 'google_video' type - Add automatic credential ID resolution when selecting 'Organizer Default App' as location - Fixes 'Location update failed' error when editing round-robin team event location to organizer default app (Google Meet) with multiple Google Calendar connections Co-Authored-By: anik@cal.com * fix update --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../installation/[[...step]]/getServerSideProps.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts b/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts index 01138d3d66..41635230fa 100644 --- a/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts +++ b/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts @@ -259,8 +259,8 @@ const getEventTypeGroupsForStep = async (user: MinimalUser, userTeams: MinimalTe return groups; }; -const getInitialStep = (parsedStepParam: string | undefined, hasTeams: boolean, showEventTypesStep: boolean, parsedAppSlug: string): { step: string | undefined; redirect?: RedirectResult } => { - if (!hasTeams && parsedStepParam === AppOnboardingSteps.ACCOUNTS_STEP && showEventTypesStep) { +const getInitialStep = (parsedStepParam: string | undefined, hasTeams: boolean, showEventTypesStep: boolean, parsedAppSlug: string, isOAuth: boolean): { step: string | undefined; redirect?: RedirectResult } => { + if (!hasTeams && parsedStepParam === AppOnboardingSteps.ACCOUNTS_STEP && showEventTypesStep && !isOAuth) { return { step: parsedStepParam, redirect: { redirect: { permanent: false, destination: `/apps/installation/event-types?slug=${parsedAppSlug}` } } @@ -271,7 +271,7 @@ const getInitialStep = (parsedStepParam: string | undefined, hasTeams: boolean, if (hasTeams) { step = AppOnboardingSteps.ACCOUNTS_STEP; } else { - step = AppOnboardingSteps.EVENT_TYPES_STEP; + step = isOAuth ? AppOnboardingSteps.ACCOUNTS_STEP : AppOnboardingSteps.EVENT_TYPES_STEP; } } return { step }; @@ -308,7 +308,7 @@ const prepareUserTeams = async (user: MinimalUser & { teams: MinimalTeam[] }, pa const getCredential = async (parsedTeamIdParam: number | undefined, appInstalls: Prisma.CredentialGetPayload>[], user: MinimalUser & { teams: MinimalTeam[] }, initialStep: string, appMetadata: import("@calcom/types/App").AppMeta, parsedAppSlug: string): Promise<{ credentialId: number | null; redirect?: RedirectResult }> => { let credentialId = getCredentialId(parsedTeamIdParam, appInstalls, user.id); - if (!credentialId && !user.teams.length && initialStep === AppOnboardingSteps.EVENT_TYPES_STEP) { + if (!credentialId && !user.teams.length && initialStep === AppOnboardingSteps.EVENT_TYPES_STEP && !appMetadata.isOAuth) { credentialId = await handleAutoInstall(user, appMetadata, parsedAppSlug); if (!credentialId) return { credentialId: null, redirect: { redirect: { permanent: false, destination: "/apps" } } }; } @@ -351,8 +351,11 @@ export const getServerSideProps = async (context: GetServerSidePropsContext): Pr const showEventTypesStep = appMetadataFinal.extendsFeature === "EventType" || isConferencingApp(appMetadataFinal.categories); const { userTeams, isOrg, redirect: teamRedirect } = await prepareUserTeams(user, parsedTeamIdParam); if (teamRedirect) return teamRedirect; - const { step: initialStep, redirect: stepRedirect } = getInitialStep(parsedStepParam, !!userTeams.length, showEventTypesStep, parsedAppSlug); + const { step: initialStep, redirect: stepRedirect } = getInitialStep(parsedStepParam, !!userTeams.length, showEventTypesStep, parsedAppSlug, !!appMetadataFinal.isOAuth); if (stepRedirect) return stepRedirect; + if (!initialStep) { + return { redirect: { permanent: false, destination: "/apps" } }; + } let initialStepValidated: (typeof STEPS)[number]; try {