mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
**Changes:**
- Add function exposure controls to Data API settings
- Adds a per-function GRANT/REVOKE UI to the Data API settings page,
alongside the existing table selector.
- Empty state: shows "No tables/functions available" instead of "0 of 0
X exposed" when there's nothing to show
- Renamed update-exposed-tables-mutation →
update-exposed-entities-mutation to handle both tables and functions in
one save
**Decisions of note:**
- Functions are grouped by schema.name across overloads — toggling one
entry grants/revokes `EXECUTE` on all overloads
- Only normal and window functions are shown (`prokind in ('f', 'w')`) —
triggers and aggregates are excluded
---
**To test:**
- Table and schema selectors still works end-to-end
- Toggling a function and saving updates the count label and applies the
grant (check via SQL Editor: select * from
information_schema.role_routine_grants where routine_schema = 'public')
- Functions in unexposed schemas are dimmed and unclickable
- With no functions in the selected schemas, the selector label reads
"No functions available" and the dropdown shows the same
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import { queryOptions } from '@tanstack/react-query'
|
|
import { executeSql } from 'data/sql/execute-sql-query'
|
|
import type { ResponseError } from 'types'
|
|
|
|
import { privilegeKeys } from './keys'
|
|
import { getExposedFunctionCountsSql } from './privileges.sql'
|
|
|
|
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 })
|
|
|
|
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',
|
|
})
|
|
}
|