diff --git a/apps/studio/data/database-extensions/database-extensions-query.ts b/apps/studio/data/database-extensions/database-extensions-query.ts index e9eb3ae42a5..76133e1dc17 100644 --- a/apps/studio/data/database-extensions/database-extensions-query.ts +++ b/apps/studio/data/database-extensions/database-extensions-query.ts @@ -5,6 +5,7 @@ import { databaseExtensionsKeys } from './keys' import { components } from 'api-types' import { useSelectedProject } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabaseExtension = components['schemas']['PostgresExtension'] @@ -27,6 +28,7 @@ export async function getDatabaseExtensions( params: { header: { 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, }, path: { ref: projectRef, diff --git a/apps/studio/data/database-policies/database-policies-query.ts b/apps/studio/data/database-policies/database-policies-query.ts index a2602491f46..291a263526e 100644 --- a/apps/studio/data/database-policies/database-policies-query.ts +++ b/apps/studio/data/database-policies/database-policies-query.ts @@ -5,6 +5,7 @@ import { useSelectedProject } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabasePoliciesVariables = { projectRef?: string @@ -24,7 +25,10 @@ export async function getDatabasePolicies( const { data, error } = await get('/platform/pg-meta/{ref}/policies', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: { included_schemas: schema || '', diff --git a/apps/studio/data/database-publications/database-publications-query.ts b/apps/studio/data/database-publications/database-publications-query.ts index f8e20b269f7..616efce3692 100644 --- a/apps/studio/data/database-publications/database-publications-query.ts +++ b/apps/studio/data/database-publications/database-publications-query.ts @@ -2,6 +2,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { databasePublicationsKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabasePublicationsVariables = { projectRef?: string @@ -21,6 +22,7 @@ export async function getDatabasePublications( params: { header: { 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, }, path: { ref: projectRef, diff --git a/apps/studio/data/database-triggers/database-triggers-query.ts b/apps/studio/data/database-triggers/database-triggers-query.ts index 997d077c469..faa78e23fc2 100644 --- a/apps/studio/data/database-triggers/database-triggers-query.ts +++ b/apps/studio/data/database-triggers/database-triggers-query.ts @@ -2,6 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { databaseTriggerKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabaseTriggersVariables = { projectRef?: string @@ -19,7 +20,10 @@ export async function getDatabaseTriggers( const { data, error } = await get('/platform/pg-meta/{ref}/triggers', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: undefined as any, }, diff --git a/apps/studio/data/enumerated-types/enumerated-types-query.ts b/apps/studio/data/enumerated-types/enumerated-types-query.ts index e7b541f0f77..ed61ae2291d 100644 --- a/apps/studio/data/enumerated-types/enumerated-types-query.ts +++ b/apps/studio/data/enumerated-types/enumerated-types-query.ts @@ -4,6 +4,7 @@ import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { enumeratedTypesKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type EnumeratedTypesVariables = { projectRef?: string @@ -23,7 +24,10 @@ export async function getEnumeratedTypes( const { data, error } = await get('/platform/pg-meta/{ref}/types', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, }, headers: Object.fromEntries(headers), diff --git a/apps/studio/data/fetchers.ts b/apps/studio/data/fetchers.ts index 7b8bb0ef7de..4cafb546dee 100644 --- a/apps/studio/data/fetchers.ts +++ b/apps/studio/data/fetchers.ts @@ -6,8 +6,8 @@ import { API_URL } from 'lib/constants' import { getAccessToken } from 'lib/gotrue' import { uuidv4 } from 'lib/helpers' import { ResponseError } from 'types' -// generated from openapi-typescript -import type { paths } from './api' +import type { paths } from './api' // generated from openapi-typescript +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' const DEFAULT_HEADERS = { Accept: 'application/json' } @@ -73,6 +73,9 @@ function pgMetaGuard(request: Request) { retryAfterHeader ? parseInt(retryAfterHeader) : undefined ) } + if (!request.headers.get('x-pg-application-name')) { + request.headers.set('x-pg-application-name', DEFAULT_PLATFORM_APPLICATION_NAME) + } } return request } diff --git a/apps/studio/data/foreign-tables/foreign-tables-query.ts b/apps/studio/data/foreign-tables/foreign-tables-query.ts index 3c2f3157122..bffbb857aaa 100644 --- a/apps/studio/data/foreign-tables/foreign-tables-query.ts +++ b/apps/studio/data/foreign-tables/foreign-tables-query.ts @@ -4,6 +4,7 @@ import { PostgresView } from '@supabase/postgres-meta' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { foreignTableKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type ForeignTablesVariables = { projectRef?: string @@ -22,7 +23,10 @@ export async function getForeignTables( const { data, error } = await get('/platform/pg-meta/{ref}/foreign-tables', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: { included_schemas: schema || '', diff --git a/apps/studio/data/materialized-views/materialized-views-query.ts b/apps/studio/data/materialized-views/materialized-views-query.ts index a8a7eab23dd..052a3dc3377 100644 --- a/apps/studio/data/materialized-views/materialized-views-query.ts +++ b/apps/studio/data/materialized-views/materialized-views-query.ts @@ -4,6 +4,7 @@ import { PostgresMaterializedView } from '@supabase/postgres-meta' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { materializedViewKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type MaterializedViewsVariables = { projectRef?: string @@ -22,7 +23,10 @@ export async function getMaterializedViews( const { data, error } = await get('/platform/pg-meta/{ref}/materialized-views', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: { included_schemas: schema || '', diff --git a/apps/studio/data/privileges/column-privileges-query.ts b/apps/studio/data/privileges/column-privileges-query.ts index 01bda4ce1f3..249a7c028ff 100644 --- a/apps/studio/data/privileges/column-privileges-query.ts +++ b/apps/studio/data/privileges/column-privileges-query.ts @@ -4,6 +4,7 @@ import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { privilegeKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type ColumnPrivilegesVariables = { projectRef?: string @@ -25,7 +26,10 @@ export async function getColumnPrivileges( params: { path: { ref: projectRef }, // this is needed to satisfy the typescript, but it doesn't pass the actual header - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, }, signal, headers, diff --git a/apps/studio/data/sql/execute-sql-query.ts b/apps/studio/data/sql/execute-sql-query.ts index a7fe145fc9e..65fe32a565b 100644 --- a/apps/studio/data/sql/execute-sql-query.ts +++ b/apps/studio/data/sql/execute-sql-query.ts @@ -9,6 +9,7 @@ import { } from 'lib/role-impersonation' import type { ResponseError } from 'types' import { sqlKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type ExecuteSqlVariables = { projectRef?: string @@ -73,7 +74,12 @@ export async function executeSql( const result = await post('/platform/pg-meta/{ref}/query', { signal, params: { - header: { 'x-connection-encrypted': connectionString ?? '' }, + header: { + 'x-connection-encrypted': connectionString ?? '', + 'x-pg-application-name': isStatementTimeoutDisabled + ? 'supabase/dashboard-query-editor' + : DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, // @ts-expect-error: This is just a client side thing to identify queries better query: { diff --git a/apps/studio/data/tables/tables-query.ts b/apps/studio/data/tables/tables-query.ts index 02ce5a5c625..b7da827a5bb 100644 --- a/apps/studio/data/tables/tables-query.ts +++ b/apps/studio/data/tables/tables-query.ts @@ -6,6 +6,7 @@ import { useCallback } from 'react' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { tableKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type TablesVariables = { projectRef?: string @@ -45,7 +46,10 @@ export async function getTables( const { data, error } = await get('/platform/pg-meta/{ref}/tables', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: queryParams as any, }, diff --git a/apps/studio/data/views/views-query.ts b/apps/studio/data/views/views-query.ts index 4903c28323f..884dda527e9 100644 --- a/apps/studio/data/views/views-query.ts +++ b/apps/studio/data/views/views-query.ts @@ -4,6 +4,7 @@ import { PostgresView } from '@supabase/postgres-meta' import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { viewKeys } from './keys' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type ViewsVariables = { projectRef?: string @@ -22,7 +23,10 @@ export async function getViews( const { data, error } = await get('/platform/pg-meta/{ref}/views', { params: { - header: { 'x-connection-encrypted': connectionString! }, + header: { + 'x-connection-encrypted': connectionString!, + 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, + }, path: { ref: projectRef }, query: { included_schemas: schema || '', diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index 090d53fbbd8..00a3b169b1a 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -7835,7 +7835,6 @@ export interface components { organization_id: number region: string status: string - subscription_id: string } UpcomingInvoice: { amount_projected?: number @@ -11308,6 +11307,12 @@ export interface operations { 'application/json': components['schemas']['CustomerResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve the Billing customer */ 500: { headers: { @@ -11422,6 +11427,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get daily organization stats */ 500: { headers: { @@ -11453,6 +11464,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get daily organization stats for compute */ 500: { headers: { @@ -11893,6 +11910,12 @@ export interface operations { 'application/json': components['schemas']['MemberWithFreeProjectLimit'][] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve organization members who have reached their free project limit */ 500: { headers: { @@ -12541,6 +12564,12 @@ export interface operations { 'application/json': components['schemas']['OrgUsageResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get usage stats */ 500: { headers: { @@ -12606,6 +12635,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12643,6 +12673,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12684,6 +12715,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12728,6 +12760,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12765,6 +12798,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12810,6 +12844,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12849,6 +12884,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12890,6 +12926,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12927,6 +12964,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -12970,6 +13008,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13012,6 +13051,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13052,6 +13092,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13089,6 +13130,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13132,6 +13174,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13171,6 +13214,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13220,6 +13264,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13260,6 +13305,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13297,6 +13343,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13340,6 +13387,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13379,6 +13427,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13420,6 +13469,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13457,6 +13507,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13500,6 +13551,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13539,6 +13591,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13580,6 +13633,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13683,6 +13737,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13720,6 +13775,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13763,6 +13819,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13802,6 +13859,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13851,6 +13909,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13888,6 +13947,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13933,6 +13993,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -13972,6 +14033,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14016,6 +14078,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14053,6 +14116,7 @@ export interface operations { query?: never header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14096,6 +14160,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14135,6 +14200,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14179,6 +14245,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -14224,6 +14291,7 @@ export interface operations { } header: { 'x-connection-encrypted': string + 'x-pg-application-name': string } path: { /** @description Project ref */ @@ -16858,6 +16926,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get daily project stats */ 500: { headers: { diff --git a/packages/pg-meta/src/constants.ts b/packages/pg-meta/src/constants.ts index c28ea770cc0..bb9513080a9 100644 --- a/packages/pg-meta/src/constants.ts +++ b/packages/pg-meta/src/constants.ts @@ -1 +1,2 @@ export const DEFAULT_SYSTEM_SCHEMAS = ['information_schema', 'pg_catalog', 'pg_toast'] +export const DEFAULT_PLATFORM_APPLICATION_NAME = 'supabase/dashboard'