Files
supabase/apps/studio/components/interfaces/Settings/API/DataApiEnableSwitch.utils.ts
Joshen Lim 98b1b79909 Chore/shift manual queries into pg meta 04 (#43956)
## Context

Shifts all remaining dashboard queries into pg-meta so that we
centralize all manually written queries in one place
Having them in packages/pg-meta also allows us to write tests for them

## To test

Just needs a smoke test on
- Role Impersonation
- Lints
- Data API
- Database
  - Enumerated Types
- Integrations
  - Foreign Data Wrappers
  - Vault
2026-03-24 16:23:13 +08:00

69 lines
2.0 KiB
TypeScript

import { getUnsafeEntitiesInApiSql } from '@supabase/pg-meta'
import type { EnableCheckAction, EnableCheckState } from './DataApiEnableSwitch.types'
import { executeSql } from '@/data/sql/execute-sql-query'
export type ExposedEntity = {
schema: string
name: string
type: 'table' | 'foreign table' | 'materialized view' | 'view'
}
/**
* Queries for entities that would be exposed through the Data API with
* potential security issues: tables without RLS, foreign tables, materialized
* views, and views without SECURITY INVOKER.
*
* This checks against the _target_ schemas rather than the currently active
* PostgREST config, so it works correctly when enabling the Data API.
*/
export async function queryUnsafeEntitiesInApi({
projectRef,
connectionString,
schemas,
}: {
projectRef: string
connectionString?: string | null
schemas: Array<string>
}): Promise<Array<ExposedEntity>> {
if (schemas.length === 0) return []
const { result } = await executeSql<Array<ExposedEntity>>({
projectRef,
connectionString,
sql: getUnsafeEntitiesInApiSql({ schemas }),
queryKey: ['unsafe-entities-in-api'],
})
return result ?? []
}
export const getDefaultSchemas = (dbSchema: string | null | undefined) => {
const schemas =
dbSchema
?.split(',')
.map((schema) => schema.trim())
.filter((schema) => schema.length > 0) ?? []
return schemas.length > 0 ? schemas : ['public']
}
export function enableCheckReducer(
state: EnableCheckState,
action: EnableCheckAction
): EnableCheckState {
switch (state.status) {
case 'idle':
if (action.type === 'START_CHECK') return { status: 'checking' }
return state
case 'checking':
if (action.type === 'ENTITIES_FOUND')
return { status: 'confirming', unsafeEntities: action.unsafeEntities }
if (action.type === 'DISMISS') return { status: 'idle' }
return state
case 'confirming':
if (action.type === 'DISMISS') return { status: 'idle' }
return state
}
}