From 7cf5df7b3eb3dcae24ec137e13ab3d3cf82c70fd Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Wed, 1 Apr 2026 16:13:38 +0800 Subject: [PATCH] chore(studio): remove Fly.io integration code (#44336) The Fly login/auth endpoints were removed from the management API (supabase/platform#30987). This cleans up the associated studio code and regenerates the API types. Note: existing Fly projects are still running, so all `cloud_provider` guards and Fly-specific UI (disk management, billing, pg_cron warnings, etc.) are intentionally kept in place. **Removed:** - `sign-in-fly-tos.tsx` page - `organization-by-fly-organization-id-mutation.ts` - `project-by-fly-extension-id-mutation.ts` **Other:** - Regenerated API types to reflect removed endpoints - Removed stale Fly-related comments in `InstanceConfiguration`, `ObservabilityMenu`, `ReportsMenu` - Fixed unrelated optional chaining bug in `SSOConfig.tsx` ## To test - Check project creation flow still works - Verify `/sign-in-fly-tos` no longer resolves --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../studio/.github/eslint-rule-baselines.json | 1 - .../interfaces/Organization/SSO/SSOConfig.tsx | 2 +- .../InstanceConfiguration.tsx | 2 - .../ObservabilityLayout/ObservabilityMenu.tsx | 1 - .../layouts/ReportsLayout/ReportsMenu.tsx | 1 - ...ization-by-fly-organization-id-mutation.ts | 52 ------ .../project-by-fly-extension-id-mutation.ts | 52 ------ apps/studio/pages/new/[slug].tsx | 1 + apps/studio/pages/sign-in-fly-tos.tsx | 135 -------------- packages/api-types/types/api.d.ts | 12 +- packages/api-types/types/platform.d.ts | 171 +++--------------- 11 files changed, 29 insertions(+), 401 deletions(-) delete mode 100644 apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts delete mode 100644 apps/studio/data/projects/project-by-fly-extension-id-mutation.ts delete mode 100644 apps/studio/pages/sign-in-fly-tos.tsx diff --git a/apps/studio/.github/eslint-rule-baselines.json b/apps/studio/.github/eslint-rule-baselines.json index 01b1cb68f19..bfd770c282f 100644 --- a/apps/studio/.github/eslint-rule-baselines.json +++ b/apps/studio/.github/eslint-rule-baselines.json @@ -150,7 +150,6 @@ "pages/project/[ref]/settings/jwt/legacy.tsx": 1, "pages/project/[ref]/sql/quickstarts.tsx": 1, "pages/project/[ref]/sql/templates.tsx": 1, - "pages/sign-in-fly-tos.tsx": 1, "pages/sign-in-mfa.tsx": 1, "state/role-impersonation-state.tsx": 1, "state/sidebar-manager-state.tsx": 1, diff --git a/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx b/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx index c39784c9bf6..3b4b9c39c33 100644 --- a/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx +++ b/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx @@ -164,7 +164,7 @@ export const SSOConfig = () => { if (ssoConfig) { form.reset({ enabled: ssoConfig.enabled, - domains: ssoConfig.domains.map((domain) => ({ value: domain })), + domains: ssoConfig.domains?.map((domain) => ({ value: domain })) ?? [], metadataXmlUrl: ssoConfig.metadata_xml_url, metadataXmlFile: ssoConfig.metadata_xml_file, emailMapping: ssoConfig.email_mapping.map((email) => ({ value: email })), diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx index 27e2f58a363..b8954694f83 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx @@ -236,8 +236,6 @@ const InstanceConfigurationUI = ({ diagramOnly = false }: InstanceConfigurationU isSuccessReplicas && !isLoadingProject ? '' : 'flex items-center justify-center px-28' }`} > - {/* Sometimes the read replicas are loaded before the project info and causes read replicas to be shown on Fly deploys. - You can replicate this to going to this page and refresh. This isLoadingProject flag fixes that. */} {(isLoading || isLoadingProject) && ( )} diff --git a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.tsx b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.tsx index 2a31a162dd2..78004bf305d 100644 --- a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.tsx +++ b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.tsx @@ -33,7 +33,6 @@ const ObservabilityMenu = () => { const showOverview = useFlag('observabilityOverview') const { isSupamonitorEnabled } = useSupamonitorStatus() - // b/c fly doesn't support storage const storageSupported = useIsFeatureEnabled('project_storage:all') const { can: canCreateCustomReport } = useAsyncCheckPermissions( diff --git a/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx b/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx index 312840a4ea8..89cf5c437b3 100644 --- a/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx +++ b/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx @@ -26,7 +26,6 @@ const ReportsMenu = () => { const { ref, id } = useParams() const pageKey = (id || router.pathname.split('/')[4]) as string - // b/c fly doesn't support storage const storageSupported = useIsFeatureEnabled('project_storage:all') const { can: canCreateCustomReport } = useAsyncCheckPermissions( diff --git a/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts b/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts deleted file mode 100644 index a93098c48d7..00000000000 --- a/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { useMutation } from '@tanstack/react-query' -import { toast } from 'sonner' - -import { get, handleError } from 'data/fetchers' -import type { ResponseError, UseCustomMutationOptions } from 'types' - -export type OrganizationByFlyOrgIdVariables = { - flyOrganizationId: string -} - -// [Joshen] Should be converted into a query instead of a mutation -// Will need to update sign-in-fly-tos.tsx as well - -export async function getOrganizationByFlyOrgId({ - flyOrganizationId, -}: OrganizationByFlyOrgIdVariables) { - const { data, error } = await get('/platform/organizations/fly/{fly_organization_id}', { - params: { path: { fly_organization_id: flyOrganizationId } }, - }) - if (error) handleError(error) - return data as { slug: string } -} - -type OrganizationByFlyOrgIdData = Awaited> - -export const useOrganizationByFlyOrgIdMutation = ({ - onSuccess, - onError, - ...options -}: Omit< - UseCustomMutationOptions< - OrganizationByFlyOrgIdData, - ResponseError, - OrganizationByFlyOrgIdVariables - >, - 'mutationFn' -> = {}) => { - return useMutation({ - mutationFn: (vars) => getOrganizationByFlyOrgId(vars), - async onSuccess(data, variables, context) { - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to get organization: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - }) -} diff --git a/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts b/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts deleted file mode 100644 index 8c29d8c8cb7..00000000000 --- a/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { useMutation } from '@tanstack/react-query' -import { toast } from 'sonner' - -import { get, handleError } from 'data/fetchers' -import type { ResponseError, UseCustomMutationOptions } from 'types' - -export type ProjectByFlyExtensionIdVariables = { - flyExtensionId: string -} - -// [Joshen] Should be converted into a query instead of a mutation -// Will need to update sign-in-fly-tos.tsx as well - -export async function getProjectByFlyExtensionId({ - flyExtensionId, -}: ProjectByFlyExtensionIdVariables) { - const { data, error } = await get('/platform/projects/fly/{fly_extension_id}', { - params: { path: { fly_extension_id: flyExtensionId } }, - }) - if (error) handleError(error) - return data as { ref: string } -} - -type ProjectByFlyExtensionIdData = Awaited> - -export const useProjectByFlyExtensionIdMutation = ({ - onSuccess, - onError, - ...options -}: Omit< - UseCustomMutationOptions< - ProjectByFlyExtensionIdData, - ResponseError, - ProjectByFlyExtensionIdVariables - >, - 'mutationFn' -> = {}) => { - return useMutation({ - mutationFn: (vars) => getProjectByFlyExtensionId(vars), - async onSuccess(data, variables, context) { - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to get project: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - }) -} diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx index 18ad85561f3..958139f9dab 100644 --- a/apps/studio/pages/new/[slug].tsx +++ b/apps/studio/pages/new/[slug].tsx @@ -96,6 +96,7 @@ const Wizard: NextPageWithLayout = () => { const projectCreationDisabled = useFlag('disableProjectCreationAndUpdate') const showPostgresVersionSelector = useFlag('showPostgresVersionSelector') const cloudProviderEnabled = useFlag('enableFlyCloudProvider') + const isDataApiGrantTogglesEnabled = useDataApiGrantTogglesEnabled() // Read the raw flag for telemetry — useDataApiGrantTogglesEnabled coerces undefined→false, // which would record false for users whose flags haven't loaded yet. The raw value preserves diff --git a/apps/studio/pages/sign-in-fly-tos.tsx b/apps/studio/pages/sign-in-fly-tos.tsx deleted file mode 100644 index d700355fb78..00000000000 --- a/apps/studio/pages/sign-in-fly-tos.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { useTheme } from 'next-themes' -import Image from 'next/image' -import Link from 'next/link' -import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' - -import { useIsLoggedIn } from 'common' -import { useOrganizationByFlyOrgIdMutation } from 'data/organizations/organization-by-fly-organization-id-mutation' -import { useProjectByFlyExtensionIdMutation } from 'data/projects/project-by-fly-extension-id-mutation' -import { API_URL, BASE_PATH } from 'lib/constants' -import { Button } from 'ui' - -const SignInFlyTos = () => { - const [loading, setLoading] = useState(true) - const isLoggedIn = useIsLoggedIn() - const router = useRouter() - const { - isReady, - query: { fly_extension_id, fly_organization_id }, - } = router - const { resolvedTheme } = useTheme() - const { mutateAsync: getProjectByFlyExtensionId } = useProjectByFlyExtensionIdMutation({ - onSuccess: (res) => { - router.replace(`/project/${res.ref}`) - }, - onError: () => { - setLoading(false) - }, - }) - const { mutateAsync: getOrgByFlyOrgId } = useOrganizationByFlyOrgIdMutation({ - onSuccess: () => { - router.replace('/organizations') - }, - onError: () => { - setLoading(false) - }, - }) - - useEffect(() => { - if (!isReady) { - return - } - if (!isLoggedIn) { - setLoading(false) - return - } - - fly_extension_id - ? getProjectByFlyExtensionId({ flyExtensionId: fly_extension_id as string }) - : fly_organization_id - ? getOrgByFlyOrgId({ flyOrganizationId: fly_organization_id as string }) - : setLoading(false) - }, [isReady]) - - const [isRedirecting, setIsRedirecting] = useState(false) - - const onSignInWithFly = async () => { - setIsRedirecting(true) - - try { - window.location.href = fly_extension_id - ? `${API_URL}/tos/fly?extension_id=${fly_extension_id}` - : `${API_URL}/tos/fly?organization_id=${fly_organization_id}` - } catch (error) { - setIsRedirecting(false) - throw error - } - } - - return ( -
-
- -
-
-

Continue to Supabase Dashboard

-
- {loading ? ( -

Checking your access rights...

- ) : ( -
- - {isReady && !fly_extension_id && !fly_organization_id && ( -

- A fly extension ID or organization ID is required to login -

- )} -
- )} -
-

- By continuing, you agree to Supabase’s{' '} - - Terms of Service - {' '} - and{' '} - - Privacy Policy - - , and to receive periodic emails with updates. -

-
-
- ) -} - -export default SignInFlyTos diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index da48a60ad1c..89a5b3916fc 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -1267,22 +1267,22 @@ export interface paths { cookie?: never } /** - * [Beta] List applied migration versions + * List applied migration versions * @description Only available to selected partner OAuth apps */ get: operations['v1-list-migration-history'] /** - * [Beta] Upsert a database migration without applying + * Upsert a database migration without applying * @description Only available to selected partner OAuth apps */ put: operations['v1-upsert-a-migration'] /** - * [Beta] Apply a database migration + * Apply a database migration * @description Only available to selected partner OAuth apps */ post: operations['v1-apply-a-migration'] /** - * [Beta] Rollback database migrations and remove them from history table + * Rollback database migrations and remove them from history table * @description Only available to selected partner OAuth apps */ delete: operations['v1-rollback-migrations'] @@ -1299,7 +1299,7 @@ export interface paths { cookie?: never } /** - * [Beta] Fetch an existing entry from migration history + * Fetch an existing entry from migration history * @description Only available to selected partner OAuth apps */ get: operations['v1-get-a-migration'] @@ -1309,7 +1309,7 @@ export interface paths { options?: never head?: never /** - * [Beta] Patch an existing entry in migration history + * Patch an existing entry in migration history * @description Only available to selected partner OAuth apps */ patch: operations['v1-patch-a-migration'] diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index 5d3a7fe59e5..6a6523ffa37 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -1834,23 +1834,6 @@ export interface paths { patch?: never trace?: never } - '/platform/organizations/fly/{fly_organization_id}': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Gets organization linked to fly organization id */ - get: operations['OrganizationsController_getOrganizationByFlyOrganizationId'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } '/platform/pg-meta/{ref}/column-privileges': { parameters: { query?: never @@ -3343,23 +3326,6 @@ export interface paths { patch?: never trace?: never } - '/platform/projects/fly/{fly_extension_id}': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Gets project linked to fly extension id */ - get: operations['ProjectsController_getProjectByFlyExtensionId'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } '/platform/replication/{ref}/destinations': { parameters: { query?: never @@ -4458,23 +4424,6 @@ export interface paths { patch?: never trace?: never } - '/platform/tos/fly': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Redirects to Fly sso flow */ - get: operations['TermsOfServiceController_flyTosAccepted'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } '/platform/update-email': { parameters: { query?: never @@ -5746,7 +5695,8 @@ export interface components { } CreateSSOProviderBody: | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -5760,7 +5710,8 @@ export interface components { user_name_mapping?: string[] } | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -5774,7 +5725,8 @@ export interface components { } CreateSSOProviderResponse: | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -5788,7 +5740,8 @@ export interface components { user_name_mapping?: string[] } | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -6315,9 +6268,6 @@ export interface components { } with_delimiter?: boolean } - GetOrganizationByFlyOrganizationIdResponse: { - slug: string - } GetOrganizationIntegrationResponse: { added_by: { primary_email: string @@ -6410,9 +6360,6 @@ export interface components { | 'DELETING' }[] } - GetProjectByFlyExtensionIdResponse: { - ref: string - } GetProjectLintsResponse: { cache_key: string categories: ('PERFORMANCE' | 'SECURITY')[] @@ -6597,7 +6544,8 @@ export interface components { } GetSSOProviderResponse: | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -6611,7 +6559,8 @@ export interface components { user_name_mapping?: string[] } | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -8408,6 +8357,7 @@ export interface components { connectionString?: string | null db_host: string dbVersion?: string + high_availability: boolean id: number /** @enum {string} */ infra_compute_size?: @@ -10754,7 +10704,8 @@ export interface components { } UpdateSSOProviderBody: | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -10768,7 +10719,8 @@ export interface components { user_name_mapping?: string[] } | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -10782,7 +10734,8 @@ export interface components { } UpdateSSOProviderResponse: | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -10796,7 +10749,8 @@ export interface components { user_name_mapping?: string[] } | { - domains: string[] + /** @default [] */ + domains?: string[] email_mapping: string[] enabled: boolean first_name_mapping?: string[] @@ -17068,27 +17022,6 @@ export interface operations { } } } - OrganizationsController_getOrganizationByFlyOrganizationId: { - parameters: { - query?: never - header?: never - path: { - fly_organization_id: string - } - cookie?: never - } - requestBody?: never - responses: { - 200: { - headers: { - [name: string]: unknown - } - content: { - 'application/json': components['schemas']['GetOrganizationByFlyOrganizationIdResponse'] - } - } - } - } ColumnPrivilegesController_getColumnPrivileges: { parameters: { query?: never @@ -22632,48 +22565,6 @@ export interface operations { } } } - ProjectsController_getProjectByFlyExtensionId: { - parameters: { - query?: never - header?: never - path: { - fly_extension_id: string - } - cookie?: never - } - requestBody?: never - responses: { - 200: { - headers: { - [name: string]: unknown - } - content: { - 'application/json': components['schemas']['GetProjectByFlyExtensionIdResponse'] - } - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } ReplicationDestinationsController_getDestinations: { parameters: { query?: never @@ -26510,26 +26401,6 @@ export interface operations { } } } - TermsOfServiceController_flyTosAccepted: { - parameters: { - query: { - extension_id: string - organization_id: string - } - header?: never - path?: never - cookie?: never - } - requestBody?: never - responses: { - 200: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } UpdateEmailController_updateEmail: { parameters: { query?: never