mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 12:25:05 +03:00
When the `tableEditorApiAccessToggle` feature flag is enabled, project creation now appends SQL to revoke default privileges for `anon`, `authenticated`, and `service_role` on the `public` schema. This runs after the base image init script's default grants. This is temporary while we're still using a feature flag. Eventually it'll be moved into the base image. Applies to both the main project creation flow and the Vercel deploy button flow. Part of the "Secure by Default" initiative – new projects created under this flag won't automatically expose tables/functions/sequences to the Data API via default privileges. Users can still opt in at a table level. ## Notes Reusing the existing `useDataApiGrantTogglesEnabled()` flag here rather than creating a new one – it's the same feature surface area and avoids unnecessary flag proliferation. ## To test 1. **With flag enabled:** - Enable the `tableEditorApiAccessToggle` flag in PostHog for your user - Create a new project via the dashboard - Create a new table - Confirm in `/project/_/integrations/data_api/settings` that the new table is not exposed by default 2. **With flag disabled:** - Disable the flag (or use a different user without it) - Create a new project - Verify default privileges are intact and tables are accessible via the Data API as usual 3. **With RLS event trigger enabled too:** - Enable both the feature flag and the "enable RLS event trigger" checkbox during project creation - Verify both SQL statements run correctly on the new project --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { getExposedFunctionCountsSql } from '@supabase/pg-meta'
|
|
import { queryOptions } from '@tanstack/react-query'
|
|
import { executeSql } from 'data/sql/execute-sql-query'
|
|
import type { ResponseError } from 'types'
|
|
|
|
import { privilegeKeys } from './keys'
|
|
import { INTERNAL_SCHEMAS } from '@/hooks/useProtectedSchemas'
|
|
|
|
const IGNORED_SCHEMAS = [...INTERNAL_SCHEMAS, 'pg_catalog']
|
|
|
|
export type ExposedFunctionCountsVariables = {
|
|
projectRef?: string
|
|
connectionString?: string | null
|
|
selectedSchemas: string[]
|
|
}
|
|
|
|
export type ExposedFunctionCountsResponse = {
|
|
total_count: number
|
|
grants_count: number
|
|
}
|
|
|
|
export async function getExposedFunctionCounts(
|
|
{ projectRef, connectionString, selectedSchemas }: ExposedFunctionCountsVariables,
|
|
signal?: AbortSignal
|
|
): Promise<ExposedFunctionCountsResponse> {
|
|
if (!projectRef) throw new Error('projectRef is required')
|
|
if (!selectedSchemas) throw new Error('selectedSchemas is required')
|
|
|
|
const sql = getExposedFunctionCountsSql({ selectedSchemas, ignoredSchemas: IGNORED_SCHEMAS })
|
|
|
|
const { result } = await executeSql(
|
|
{
|
|
projectRef,
|
|
connectionString,
|
|
sql,
|
|
queryKey: ['exposed-function-counts', selectedSchemas],
|
|
},
|
|
signal
|
|
)
|
|
|
|
return result[0] as ExposedFunctionCountsResponse
|
|
}
|
|
|
|
export type ExposedFunctionCountsData = Awaited<ReturnType<typeof getExposedFunctionCounts>>
|
|
export type ExposedFunctionCountsError = ResponseError
|
|
|
|
export const exposedFunctionCountsQueryOptions = (
|
|
{ projectRef, connectionString, selectedSchemas }: ExposedFunctionCountsVariables,
|
|
{ enabled = true }: { enabled?: boolean } = {}
|
|
) => {
|
|
return queryOptions({
|
|
// eslint-disable-next-line @tanstack/query/exhaustive-deps -- connection string doesn't change the result of the query
|
|
queryKey: privilegeKeys.exposedFunctionCounts(projectRef, selectedSchemas),
|
|
queryFn: ({ signal }) =>
|
|
getExposedFunctionCounts(
|
|
{
|
|
projectRef,
|
|
connectionString,
|
|
selectedSchemas,
|
|
},
|
|
signal
|
|
),
|
|
enabled: enabled && typeof projectRef !== 'undefined',
|
|
})
|
|
}
|