mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 09:32:15 +08:00
Chore/update local lints (#28421)
* Update lints * Add new lint type, update api types * Update lints again * Update types
This commit is contained in:
@@ -178,6 +178,16 @@ export const lintInfoMap: LintInfo[] = [
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api',
|
||||
},
|
||||
{
|
||||
name: 'unsupported_reg_types',
|
||||
title: 'Unsupported reg types',
|
||||
icon: <Table2 className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: () =>
|
||||
`https://supabase.com/docs/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`,
|
||||
linkText: 'View docs',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint',
|
||||
},
|
||||
]
|
||||
|
||||
export const LintCTA = ({
|
||||
|
||||
@@ -41,6 +41,7 @@ ${query}
|
||||
`
|
||||
|
||||
export const LINT_SQL = /* SQL */ `set local search_path = '';
|
||||
|
||||
(
|
||||
with foreign_keys as (
|
||||
select
|
||||
@@ -131,7 +132,6 @@ select
|
||||
'schema', n.nspname,
|
||||
'name', c.relname,
|
||||
'type', 'view',
|
||||
|
||||
'exposed_to', array_remove(array_agg(DISTINCT case when pg_catalog.has_table_privilege('anon', c.oid, 'SELECT') then 'anon' when pg_catalog.has_table_privilege('authenticated', c.oid, 'SELECT') then 'authenticated' end), null)
|
||||
) as metadata,
|
||||
format('auth_users_exposed_%s_%s', n.nspname, c.relname) as cache_key
|
||||
@@ -257,8 +257,9 @@ from
|
||||
policies
|
||||
where
|
||||
is_rls_active
|
||||
-- NOTE: does not include realtime in support of monitoring policies on realtime.messages
|
||||
and schema_name not in (
|
||||
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
|
||||
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
|
||||
)
|
||||
and (
|
||||
-- Example: auth.uid()
|
||||
@@ -368,6 +369,7 @@ select
|
||||
psui.relname,
|
||||
psui.indexrelname
|
||||
) as cache_key
|
||||
|
||||
from
|
||||
pg_catalog.pg_stat_user_indexes psui
|
||||
join pg_catalog.pg_index pi
|
||||
@@ -410,7 +412,6 @@ select
|
||||
'multiple_permissive_policies_%s_%s_%s_%s',
|
||||
n.nspname,
|
||||
c.relname,
|
||||
|
||||
r.rolname,
|
||||
act.cmd
|
||||
) as cache_key
|
||||
@@ -458,7 +459,6 @@ group by
|
||||
having
|
||||
count(1) > 1)
|
||||
union all
|
||||
|
||||
(
|
||||
select
|
||||
'policy_exists_rls_disabled' as name,
|
||||
@@ -470,12 +470,12 @@ select
|
||||
format(
|
||||
'Table \`%s.%s\` has RLS policies but RLS is not enabled on the table. Policies include %s.',
|
||||
n.nspname,
|
||||
|
||||
c.relname,
|
||||
array_agg(p.polname order by p.polname)
|
||||
) as detail,
|
||||
'https://supabase.com/docs/guides/database/database-linter?lint=0007_policy_exists_rls_disabled' as remediation,
|
||||
jsonb_build_object(
|
||||
'schema', n.nspname,
|
||||
'name', c.relname,
|
||||
'type', 'table'
|
||||
) as metadata,
|
||||
@@ -602,10 +602,8 @@ group by
|
||||
n.nspname,
|
||||
c.relkind,
|
||||
c.relname,
|
||||
|
||||
replace(pi.indexdef, pi.indexname, '')
|
||||
having
|
||||
|
||||
count(*) > 1)
|
||||
union all
|
||||
(
|
||||
@@ -645,6 +643,7 @@ where
|
||||
pg_catalog.has_table_privilege('anon', c.oid, 'SELECT')
|
||||
or pg_catalog.has_table_privilege('authenticated', c.oid, 'SELECT')
|
||||
)
|
||||
and substring(pg_catalog.version() from 'PostgreSQL ([0-9]+)') >= '15' -- security invoker was added in pg15
|
||||
and n.nspname = any(array(select trim(unnest(string_to_array(current_setting('pgrst.db_schemas', 't'), ',')))))
|
||||
and n.nspname not in (
|
||||
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
|
||||
@@ -667,7 +666,7 @@ select
|
||||
'WARN' as level,
|
||||
'EXTERNAL' as facing,
|
||||
array['SECURITY'] as categories,
|
||||
'Detects functions with a mutable search_path parameter which could fail to execute successfully for some roles.' as description,
|
||||
'Detects functions where the search_path parameter is not set to an empty string.' as description,
|
||||
format(
|
||||
'Function \`%s.%s\` has a role mutable search_path',
|
||||
n.nspname,
|
||||
@@ -738,9 +737,7 @@ where
|
||||
)
|
||||
and n.nspname = any(array(select trim(unnest(string_to_array(current_setting('pgrst.db_schemas', 't'), ',')))))
|
||||
and n.nspname not in (
|
||||
|
||||
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
|
||||
|
||||
))
|
||||
union all
|
||||
(
|
||||
@@ -753,13 +750,11 @@ select
|
||||
'Detects extensions installed in the \`public\` schema.' as description,
|
||||
format(
|
||||
'Extension \`%s\` is installed in the public schema. Move it to another schema.',
|
||||
|
||||
pe.extname
|
||||
) as detail,
|
||||
'https://supabase.com/docs/guides/database/database-linter?lint=0014_extension_in_public' as remediation,
|
||||
jsonb_build_object(
|
||||
'schema', pe.extnamespace::regnamespace,
|
||||
|
||||
'name', pe.extname,
|
||||
'type', 'extension'
|
||||
) as metadata,
|
||||
@@ -777,11 +772,9 @@ where
|
||||
-- search path. That currently isn't available via SQL. In other lints
|
||||
-- we have used has_schema_privilege('anon', 'extensions', 'USAGE') but that
|
||||
-- is not appropriate here as it would evaluate true for the extensions schema
|
||||
|
||||
and pe.extnamespace::regnamespace::text = 'public')
|
||||
union all
|
||||
(
|
||||
|
||||
with policies as (
|
||||
select
|
||||
nsp.nspname as schema_name,
|
||||
@@ -817,12 +810,9 @@ select
|
||||
jsonb_build_object(
|
||||
'schema', schema_name,
|
||||
'name', table_name,
|
||||
|
||||
'type', 'table'
|
||||
) as metadata,
|
||||
|
||||
format('rls_references_user_metadata_%s_%s_%s', schema_name, table_name, policy_name) as cache_key
|
||||
|
||||
from
|
||||
policies
|
||||
where
|
||||
@@ -841,11 +831,9 @@ where
|
||||
union all
|
||||
(
|
||||
select
|
||||
|
||||
'materialized_view_in_api' as name,
|
||||
'Materialized View in API' as title,
|
||||
'WARN' as level,
|
||||
|
||||
'EXTERNAL' as facing,
|
||||
array['SECURITY'] as categories,
|
||||
'Detects materialized views that are accessible over the Data APIs.' as description,
|
||||
@@ -925,4 +913,47 @@ where
|
||||
and n.nspname not in (
|
||||
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
|
||||
)
|
||||
and dep.objid is null)`.trim()
|
||||
and dep.objid is null)
|
||||
union all
|
||||
(
|
||||
select
|
||||
'unsupported_reg_types' as name,
|
||||
'Unsupported reg types' as title,
|
||||
'WARN' as level,
|
||||
'EXTERNAL' as facing,
|
||||
array['SECURITY'] as categories,
|
||||
'Identifies columns using unsupported reg* types outside pg_catalog schema, which prevents database upgrades using pg_upgrade.' as description,
|
||||
format(
|
||||
'Table \`%s.%s\` has a column \`%s\` with unsupported reg* type \`%s\`.',
|
||||
n.nspname,
|
||||
c.relname,
|
||||
a.attname,
|
||||
t.typname
|
||||
) as detail,
|
||||
'https://supabase.com/docs/guides/database/database-linter?lint=unsupported_reg_types' as remediation,
|
||||
jsonb_build_object(
|
||||
'schema', n.nspname,
|
||||
'name', c.relname,
|
||||
'column', a.attname,
|
||||
'type', 'table'
|
||||
) as metadata,
|
||||
format(
|
||||
'unsupported_reg_types_%s_%s_%s',
|
||||
n.nspname,
|
||||
c.relname,
|
||||
a.attname
|
||||
) AS cache_key
|
||||
from
|
||||
pg_catalog.pg_attribute a
|
||||
join pg_catalog.pg_class c
|
||||
on a.attrelid = c.oid
|
||||
join pg_catalog.pg_namespace n
|
||||
on c.relnamespace = n.oid
|
||||
join pg_catalog.pg_type t
|
||||
on a.atttypid = t.oid
|
||||
join pg_catalog.pg_namespace tn
|
||||
on t.typnamespace = tn.oid
|
||||
where
|
||||
tn.nspname = 'pg_catalog'
|
||||
and t.typname in ('regcollation', 'regconfig', 'regdictionary', 'regnamespace', 'regoper', 'regoperator', 'regproc', 'regprocedure')
|
||||
and n.nspname not in ('pg_catalog', 'information_schema', 'pgsodium'))`.trim()
|
||||
|
||||
56
packages/api-types/types/api.d.ts
vendored
56
packages/api-types/types/api.d.ts
vendored
@@ -2131,6 +2131,7 @@ export interface components {
|
||||
| 'pitr_14'
|
||||
| 'pitr_28'
|
||||
| 'ipv4_default'
|
||||
| 'auth_mfa_phone_default'
|
||||
AmiSearchOptions: {
|
||||
search_tags?: Record<string, never>
|
||||
}
|
||||
@@ -2291,6 +2292,11 @@ export interface components {
|
||||
mailer_templates_reauthentication_content: string | null
|
||||
mailer_templates_recovery_content: string | null
|
||||
mfa_max_enrolled_factors: number | null
|
||||
mfa_phone_enroll_enabled: boolean | null
|
||||
mfa_phone_max_frequency: number | null
|
||||
mfa_phone_otp_length: number
|
||||
mfa_phone_template: string | null
|
||||
mfa_phone_verify_enabled: boolean | null
|
||||
mfa_totp_enroll_enabled: boolean | null
|
||||
mfa_totp_verify_enabled: boolean | null
|
||||
password_hibp_enabled: boolean | null
|
||||
@@ -2692,10 +2698,15 @@ export interface components {
|
||||
data_api_use_api_schema?: boolean
|
||||
db_pass: string
|
||||
db_pricing_tier_id?: string
|
||||
/**
|
||||
* @description Provider region description
|
||||
* @example Southeast Asia (Singapore)
|
||||
*/
|
||||
db_region: string
|
||||
db_sql?: string
|
||||
desired_instance_size?: components['schemas']['DesiredInstanceSize']
|
||||
name: string
|
||||
/** @deprecated */
|
||||
org_id?: number
|
||||
organization_slug?: string
|
||||
}
|
||||
@@ -3465,6 +3476,11 @@ export interface components {
|
||||
MAILER_TEMPLATES_REAUTHENTICATION_CONTENT: string
|
||||
MAILER_TEMPLATES_RECOVERY_CONTENT: string
|
||||
MFA_MAX_ENROLLED_FACTORS: number
|
||||
MFA_PHONE_ENROLL_ENABLED: boolean
|
||||
MFA_PHONE_MAX_FREQUENCY: number
|
||||
MFA_PHONE_OTP_LENGTH: number
|
||||
MFA_PHONE_TEMPLATE: string
|
||||
MFA_PHONE_VERIFY_ENABLED: boolean
|
||||
MFA_TOTP_ENROLL_ENABLED: boolean
|
||||
MFA_TOTP_VERIFY_ENABLED: boolean
|
||||
PASSWORD_HIBP_ENABLED: boolean
|
||||
@@ -3614,11 +3630,11 @@ export interface components {
|
||||
id: string
|
||||
invoice_pdf: string
|
||||
number: string
|
||||
payment_attempted: boolean
|
||||
period_end: number
|
||||
status: string
|
||||
subscription: string | null
|
||||
subtotal: number
|
||||
payment_attempted: boolean
|
||||
}
|
||||
JoinResponse: {
|
||||
billing_email: string
|
||||
@@ -3956,7 +3972,14 @@ export interface components {
|
||||
| 'STORAGE_IMAGES_TRANSFORMED'
|
||||
| 'REALTIME_MESSAGE_COUNT'
|
||||
| 'REALTIME_PEAK_CONNECTIONS'
|
||||
| 'DISK_SIZE_GB_HOURS'
|
||||
| 'DISK_SIZE_GB_HOURS_GP3'
|
||||
| 'DISK_SIZE_GB_HOURS_IO2'
|
||||
| 'AUTH_MFA_PHONE'
|
||||
| 'LOG_DRAIN_EVENTS'
|
||||
| 'MONTHLY_ACTIVE_THIRD_PARTY_USERS'
|
||||
| 'DISK_THROUGHPUT_GP3'
|
||||
| 'DISK_IOPS_GP3'
|
||||
| 'DISK_IOPS_IO2'
|
||||
| 'COMPUTE_HOURS_BRANCH'
|
||||
| 'COMPUTE_HOURS_XS'
|
||||
| 'COMPUTE_HOURS_SM'
|
||||
@@ -3973,12 +3996,13 @@ export interface components {
|
||||
| 'PITR_14'
|
||||
| 'PITR_28'
|
||||
| 'IPV4'
|
||||
| 'LOG_DRAIN'
|
||||
pricing_free_units?: number
|
||||
pricing_package_price?: number
|
||||
pricing_package_size?: number
|
||||
pricing_per_unit_price?: number
|
||||
/** @enum {string} */
|
||||
pricing_strategy: 'UNIT' | 'PACKAGE' | 'NONE'
|
||||
pricing_strategy: 'UNIT' | 'PACKAGE' | 'TIERED' | 'NONE'
|
||||
project_allocations: components['schemas']['ProjectAllocation'][]
|
||||
unit_price_desc: string
|
||||
unlimited: boolean
|
||||
@@ -4338,7 +4362,7 @@ export interface components {
|
||||
selected_addons: components['schemas']['SelectedAddonResponse'][]
|
||||
}
|
||||
/** @enum {string} */
|
||||
ProjectAddonType: 'custom_domain' | 'compute_instance' | 'pitr' | 'ipv4'
|
||||
ProjectAddonType: 'custom_domain' | 'compute_instance' | 'pitr' | 'ipv4' | 'auth_mfa_phone'
|
||||
/** @enum {string} */
|
||||
ProjectAddonVariantPricingType: 'fixed' | 'usage'
|
||||
ProjectAddonVariantResponse: {
|
||||
@@ -5424,6 +5448,11 @@ export interface components {
|
||||
mailer_templates_reauthentication_content?: string
|
||||
mailer_templates_recovery_content?: string
|
||||
mfa_max_enrolled_factors?: number
|
||||
mfa_phone_enroll_enabled?: boolean
|
||||
mfa_phone_max_frequency?: number
|
||||
mfa_phone_otp_length?: number
|
||||
mfa_phone_template?: string
|
||||
mfa_phone_verify_enabled?: boolean
|
||||
mfa_totp_enroll_enabled?: boolean
|
||||
mfa_totp_verify_enabled?: boolean
|
||||
password_hibp_enabled?: boolean
|
||||
@@ -5666,6 +5695,11 @@ export interface components {
|
||||
MAILER_TEMPLATES_REAUTHENTICATION_CONTENT?: string
|
||||
MAILER_TEMPLATES_RECOVERY_CONTENT?: string
|
||||
MFA_MAX_ENROLLED_FACTORS?: number
|
||||
MFA_PHONE_ENROLL_ENABLED?: boolean
|
||||
MFA_PHONE_MAX_FREQUENCY?: number
|
||||
MFA_PHONE_OTP_LENGTH?: number
|
||||
MFA_PHONE_TEMPLATE?: string
|
||||
MFA_PHONE_VERIFY_ENABLED?: boolean
|
||||
MFA_TOTP_ENROLL_ENABLED?: boolean
|
||||
MFA_TOTP_VERIFY_ENABLED?: boolean
|
||||
PASSWORD_HIBP_ENABLED?: boolean
|
||||
@@ -7848,7 +7882,14 @@ export interface operations {
|
||||
| 'STORAGE_IMAGES_TRANSFORMED'
|
||||
| 'REALTIME_MESSAGE_COUNT'
|
||||
| 'REALTIME_PEAK_CONNECTIONS'
|
||||
| 'DISK_SIZE_GB_HOURS'
|
||||
| 'DISK_SIZE_GB_HOURS_GP3'
|
||||
| 'DISK_SIZE_GB_HOURS_IO2'
|
||||
| 'AUTH_MFA_PHONE'
|
||||
| 'LOG_DRAIN_EVENTS'
|
||||
| 'MONTHLY_ACTIVE_THIRD_PARTY_USERS'
|
||||
| 'DISK_THROUGHPUT_GP3'
|
||||
| 'DISK_IOPS_GP3'
|
||||
| 'DISK_IOPS_IO2'
|
||||
| 'COMPUTE_HOURS_BRANCH'
|
||||
| 'COMPUTE_HOURS_XS'
|
||||
| 'COMPUTE_HOURS_SM'
|
||||
@@ -7865,6 +7906,7 @@ export interface operations {
|
||||
| 'PITR_14'
|
||||
| 'PITR_28'
|
||||
| 'IPV4'
|
||||
| 'LOG_DRAIN'
|
||||
interval: string
|
||||
endDate: string
|
||||
startDate: string
|
||||
@@ -11673,8 +11715,8 @@ export interface operations {
|
||||
/** Gets the count of a user's content by type */
|
||||
ContentController_getContentCount: {
|
||||
parameters: {
|
||||
query: {
|
||||
type: string
|
||||
query?: {
|
||||
type?: string
|
||||
}
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
|
||||
Reference in New Issue
Block a user