From 6b805289c7701d47f1dac0df3402cf481804220d Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:18:53 -0500 Subject: [PATCH] chore(studio): remove feature flag for dataApiExposedBadge (#42563) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup / chore — removing a feature flag that has been at 100% rollout with no issues. ## What is the current behavior? The `dataApiExposedBadge` feature flag is checked at runtime via ConfigCat, even though it has been set to 100% for a while with no issues. ## What is the new behavior? The feature flag check is removed and the gated behavior is now unconditionally enabled. A reminder has been set to delete the flag from ConfigCat in a month. ## Summary by CodeRabbit **Refactor** * Simplified API access status indicators in the studio editor, ensuring security-related tooltips now display consistently based on actual access conditions. * Updated component interfaces and consolidated internal hook dependencies for improved code maintainability and organization. --- .../TableEditorLayout/EntityListItem.tsx | 55 ++++++++++--------- .../misc/useDataApiGrantTogglesEnabled.ts | 6 +- e2e/studio/features/table-editor.spec.ts | 19 ++++--- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index 86007254e06..1e33bfeb284 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -1,31 +1,13 @@ -import { useFlag, useParams } from 'common' -import { buildTableEditorUrl } from 'components/grid/SupabaseGrid.utils' -import { useTableFilter } from 'components/grid/hooks/useTableFilter' -import { getEntityLintDetails } from 'components/interfaces/TableGridEditor/TableEntity.utils' -import { EntityTypeIcon } from 'components/ui/EntityTypeIcon' -import { InlineLink } from 'components/ui/InlineLink' -import { getTableDefinition } from 'data/database/table-definition-query' -import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' -import { Entity } from 'data/entity-types/entity-types-infinite-query' -import { useProjectLintsQuery } from 'data/lint/lint-query' -import { EditorTablePageLink } from 'data/prefetchers/project.$ref.editor.$id' -import type { TableApiAccessData, TableApiAccessMap } from 'data/privileges/table-api-access-query' -import { useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query' -import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' -import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { useParams } from 'common' import { Copy, Download, Edit, Globe, Lock, MoreVertical, Trash } from 'lucide-react' import Link from 'next/link' import { type CSSProperties } from 'react' import { toast } from 'sonner' -import { - type RoleImpersonationState, - useRoleImpersonationStateSnapshot, -} from 'state/role-impersonation-state' -import { useTableEditorStateSnapshot } from 'state/table-editor' -import { createTabId, useTabsStateSnapshot } from 'state/tabs' import { Badge, Button, + cn, + copyToClipboard, DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -38,12 +20,33 @@ import { TooltipContent, TooltipTrigger, TreeViewItemVariant, - cn, - copyToClipboard, } from 'ui' import { useExportAllRowsAsCsv, useExportAllRowsAsSql } from './ExportAllRows' +import { useTableFilter } from '@/components/grid/hooks/useTableFilter' +import { buildTableEditorUrl } from '@/components/grid/SupabaseGrid.utils' +import { getEntityLintDetails } from '@/components/interfaces/TableGridEditor/TableEntity.utils' +import { EntityTypeIcon } from '@/components/ui/EntityTypeIcon' +import { InlineLink } from '@/components/ui/InlineLink' +import { getTableDefinition } from '@/data/database/table-definition-query' +import { ENTITY_TYPE } from '@/data/entity-types/entity-type-constants' +import { Entity } from '@/data/entity-types/entity-types-infinite-query' +import { useProjectLintsQuery } from '@/data/lint/lint-query' +import { EditorTablePageLink } from '@/data/prefetchers/project.$ref.editor.$id' +import type { + TableApiAccessData, + TableApiAccessMap, +} from '@/data/privileges/table-api-access-query' +import { useTableRowsCountQuery } from '@/data/table-rows/table-rows-count-query' +import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { formatSql } from '@/lib/formatSql' +import { + useRoleImpersonationStateSnapshot, + type RoleImpersonationState, +} from '@/state/role-impersonation-state' +import { useTableEditorStateSnapshot } from '@/state/table-editor' +import { createTabId, useTabsStateSnapshot } from '@/state/tabs' export interface EntityListItemProps { id: number | string @@ -79,7 +82,6 @@ export const EntityListItem = ({ const tabs = useTabsStateSnapshot() const isPreview = tabs.previewTabId === tabId - const isOpened = Object.values(tabs.tabsMap).some((tab) => tab.metadata?.tableId === entity.id) const isActive = Number(id) === entity.id const canEdit = isActive && !isLocked @@ -405,7 +407,6 @@ const EntityTooltipTrigger = ({ apiAccessData?: TableApiAccessData }) => { const { ref } = useParams() - const isDataApiExposedBadgeEnabled = useFlag('dataApiExposedBadge') let tooltipContent = null const accessWarning = 'Data is publicly accessible via API' @@ -476,7 +477,7 @@ const EntityTooltipTrigger = ({ entity.type === ENTITY_TYPE.TABLE && apiAccessData?.apiAccessType === 'access' && tableHasRlsEnabledNoPolicyLint - if (isDataApiExposedBadgeEnabled && isRlsEnabledNoPolicies) { + if (isRlsEnabledNoPolicies) { return ( @@ -492,7 +493,7 @@ const EntityTooltipTrigger = ({ const isApiExposedWithRlsAndPolicies = apiAccessData?.apiAccessType === 'access' && !tableHasRlsEnabledNoPolicyLint - if (isDataApiExposedBadgeEnabled && isApiExposedWithRlsAndPolicies) { + if (isApiExposedWithRlsAndPolicies) { return ( diff --git a/apps/studio/hooks/misc/useDataApiGrantTogglesEnabled.ts b/apps/studio/hooks/misc/useDataApiGrantTogglesEnabled.ts index e79771a3118..fdd1f92e807 100644 --- a/apps/studio/hooks/misc/useDataApiGrantTogglesEnabled.ts +++ b/apps/studio/hooks/misc/useDataApiGrantTogglesEnabled.ts @@ -1,6 +1,5 @@ -import { useFlag } from 'common' -import { IS_TEST_ENV } from 'lib/constants' import { usePHFlag } from '../ui/useFlag' +import { IS_TEST_ENV } from '@/lib/constants' /** * Determine whether a user has access to Data API grant toggles. @@ -12,7 +11,6 @@ import { usePHFlag } from '../ui/useFlag' * without requiring the feature flag infrastructure. */ export const useDataApiGrantTogglesEnabled = (): boolean => { - const isDataApiBadgesEnabled = useFlag('dataApiExposedBadge') const isTableEditorApiAccessEnabled = usePHFlag('tableEditorApiAccessToggle') // In test environment, enable the feature for E2E testing @@ -20,5 +18,5 @@ export const useDataApiGrantTogglesEnabled = (): boolean => { return true } - return isDataApiBadgesEnabled && !!isTableEditorApiAccessEnabled + return !!isTableEditorApiAccessEnabled } diff --git a/e2e/studio/features/table-editor.spec.ts b/e2e/studio/features/table-editor.spec.ts index 61933ed6b56..7cc237fc4fd 100644 --- a/e2e/studio/features/table-editor.spec.ts +++ b/e2e/studio/features/table-editor.spec.ts @@ -1,8 +1,9 @@ -import { expect, Page } from '@playwright/test' import fs from 'fs' import path from 'path' -import { createTable as dbCreateTable, dropTable } from '../utils/db/index.js' +import { expect, Page } from '@playwright/test' + import { env } from '../env.config.js' +import { createTable as dbCreateTable, dropTable } from '../utils/db/index.js' import { releaseFileOnceCleanup, withFileOnceSetup } from '../utils/once-per-file.js' import { resetLocalStorage } from '../utils/reset-local-storage.js' import { test } from '../utils/test.js' @@ -165,7 +166,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameActions}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() await page.getByRole('menuitem', { name: 'Copy name' }).click() await page.waitForTimeout(500) @@ -176,7 +177,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameActions}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() await page.getByRole('menuitem', { name: 'Copy table schema' }).click() await waitForApiResponse(page, 'pg-meta', ref, 'query?key=table-definition-') // wait for endpoint to generate schema @@ -193,7 +194,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameActions}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() await page.getByRole('menuitem', { name: 'Duplicate table' }).click() await page.getByRole('button', { name: 'Save' }).click() @@ -367,7 +368,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameGridEditor}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() await page.getByRole('menuitem', { name: 'Edit table' }).click() await page.getByTestId('table-name-input').fill(tableNameUpdated) @@ -386,7 +387,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameUpdated}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() // Open nested export submenu via keyboard (more stable than hover in headless) const exportDataItemCsv = page.getByRole('menuitem', { name: 'Export data' }) @@ -425,7 +426,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameUpdated}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() // Open nested export submenu via keyboard (more stable than hover in headless) const exportDataItemSql = page.getByRole('menuitem', { name: 'Export data' }) @@ -459,7 +460,7 @@ testRunner('table editor', () => { await page .getByRole('button', { name: `View ${tableNameUpdated}`, exact: true }) .getByRole('button') - .nth(1) + .nth(2) .click() const exportDataItemCli = page.getByRole('menuitem', { name: 'Export data' })