mirror of
https://github.com/supabase/supabase.git
synced 2026-05-07 06:27:16 +08:00
The link builders in `apps/studio/components/interfaces/Linter/Linter.utils.tsx` interpolate `metadata.schema` and `metadata.name` directly into URL query strings. A schema or table name with `&`, `=`, `+`, or `#` breaks the destination filter on the linked page because `URLSearchParams` stops at the bare `&` and decodes `+` to a space. The `public_bucket_allows_listing` lint at line 338 already wraps `bucket_id` in `encodeURIComponent`. The other 15 builders did not. This wraps each `metadata?.schema` and `metadata?.name` interpolation with `encodeURIComponent(value ?? '')` to match. Added `Linter.utils.test.tsx` that constructs links with a schema `a&b=c` and a name `d e+f` and asserts `URLSearchParams` round-trips them. The bucket precedent is also covered. Closes #45384 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved URL encoding for navigation links in the linter interface to ensure proper handling of special characters in database, schema, and table names. * **Tests** * Added test coverage for URL generation functionality in the linter utility. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
69 lines
2.7 KiB
TypeScript
69 lines
2.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { lintInfoMap } from './Linter.utils'
|
|
import { Lint } from '@/data/lint/lint-query'
|
|
|
|
const projectRef = 'abc'
|
|
const trickySchema = 'a&b=c'
|
|
const trickyName = 'd e+f'
|
|
|
|
describe('Linter.utils lintInfoMap link encoding', () => {
|
|
const cases: Array<{ name: string; nameParam?: string; hasSchema: boolean }> = [
|
|
{ name: 'unindexed_foreign_keys', hasSchema: true },
|
|
{ name: 'unused_index', nameParam: 'table', hasSchema: true },
|
|
{ name: 'multiple_permissive_policies', nameParam: 'search', hasSchema: true },
|
|
{ name: 'policy_exists_rls_disabled', nameParam: 'search', hasSchema: true },
|
|
{ name: 'rls_enabled_no_policy', nameParam: 'search', hasSchema: true },
|
|
{ name: 'duplicate_index', nameParam: 'table', hasSchema: true },
|
|
{ name: 'function_search_path_mutable', nameParam: 'search', hasSchema: true },
|
|
{ name: 'rls_disabled_in_public', nameParam: 'search', hasSchema: true },
|
|
{ name: 'extension_in_public', nameParam: 'filter', hasSchema: false },
|
|
{ name: 'sensitive_columns_exposed', nameParam: 'table', hasSchema: true },
|
|
{ name: 'rls_policy_always_true', nameParam: 'search', hasSchema: true },
|
|
{ name: 'pg_graphql_anon_table_exposed', nameParam: 'table', hasSchema: true },
|
|
{ name: 'pg_graphql_authenticated_table_exposed', nameParam: 'table', hasSchema: true },
|
|
{ name: 'anon_security_definer_function_executable', nameParam: 'search', hasSchema: true },
|
|
{
|
|
name: 'authenticated_security_definer_function_executable',
|
|
nameParam: 'search',
|
|
hasSchema: true,
|
|
},
|
|
]
|
|
|
|
for (const { name, nameParam, hasSchema } of cases) {
|
|
it(`preserves special characters in metadata for ${name}`, () => {
|
|
const info = lintInfoMap.find((entry) => entry.name === name)
|
|
expect(info, `expected ${name} in lintInfoMap`).toBeDefined()
|
|
|
|
const url = info!.link({
|
|
projectRef,
|
|
metadata: {
|
|
schema: trickySchema,
|
|
name: trickyName,
|
|
} as unknown as Lint['metadata'],
|
|
})
|
|
|
|
const parsed = new URL(url, 'http://example.com')
|
|
|
|
if (hasSchema) {
|
|
expect(parsed.searchParams.get('schema')).toBe(trickySchema)
|
|
}
|
|
if (nameParam) {
|
|
expect(parsed.searchParams.get(nameParam)).toBe(trickyName)
|
|
}
|
|
})
|
|
}
|
|
|
|
it('preserves slash and space in bucket_id for public_bucket_allows_listing', () => {
|
|
const info = lintInfoMap.find((entry) => entry.name === 'public_bucket_allows_listing')
|
|
expect(info).toBeDefined()
|
|
const url = info!.link({
|
|
projectRef,
|
|
metadata: {
|
|
bucket_id: 'a/b c',
|
|
} as unknown as Lint['metadata'],
|
|
})
|
|
expect(url).toBe('/project/abc/storage/files/buckets/a%2Fb%20c')
|
|
})
|
|
})
|