mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 04:15:04 +03:00
Mark provenance of SQL via the branded types SafeSqlFragment and UntrustedSqlFragment. Only SafeSqlFragment should be executed; UntrustedSqlFragments require some kind of implicit user approval (show on screen + user has to click something) before they are promoted to SafeSqlFragment. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Editor and RLS tester show loading states for inferred/generated SQL and include a dedicated user SQL editor for safer edits. * **Refactor** * Platform-wide SQL handling tightened: snippets and AI-generated SQL are treated as untrusted/display-only until promoted, improving safety and consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { untrustedSql } from '@supabase/pg-meta'
|
|
import { IS_PLATFORM } from 'common'
|
|
|
|
import type { SqlSnippets, UserContent } from '@/types'
|
|
|
|
const SQL_SNIPPET_SCHEMA_VERSION = '1.0'
|
|
|
|
export const NEW_SQL_SNIPPET_SKELETON: UserContent<SqlSnippets.Content> = {
|
|
name: 'New Query',
|
|
description: '',
|
|
type: 'sql',
|
|
visibility: 'user', // default to user scope
|
|
favorite: false,
|
|
content: {
|
|
schema_version: SQL_SNIPPET_SCHEMA_VERSION,
|
|
content_id: '',
|
|
unchecked_sql: untrustedSql(''),
|
|
},
|
|
}
|
|
|
|
export const sqlAiDisclaimerComment = `
|
|
-- Supabase AI is experimental and may produce incorrect answers
|
|
-- Always verify the output before executing
|
|
`.trim()
|
|
|
|
// Should only be used for comparisons. If you need a new title, use generateSnippetTitle()
|
|
export const untitledSnippetTitle = 'Untitled query'
|
|
|
|
/**
|
|
* Generates a snippet title. If the platform is self-hosted, it will return a random number to avoid conflicts.
|
|
*/
|
|
export const generateSnippetTitle = () => {
|
|
if (IS_PLATFORM) {
|
|
return untitledSnippetTitle
|
|
} else {
|
|
return `${untitledSnippetTitle} ${Math.floor(Math.random() * 900) + 100}`
|
|
}
|
|
}
|
|
|
|
export const destructiveSqlRegex = [
|
|
/^(.*;)?\s*(drop|delete|truncate|alter\s+table\s+.*\s+drop\s+column)\s/is,
|
|
]
|
|
|
|
// Matches `UPDATE <table> SET ...` where <table> is any combination of bareword
|
|
// or double-quoted identifiers, optionally schema-qualified. Quoted identifiers
|
|
// can contain any character (including spaces) and use `""` to escape an inner
|
|
// quote, mirroring Postgres syntax.
|
|
export const updateWithoutWhereRegex =
|
|
/(?:^|;)\s*update\s+(?:"(?:[^"]|"")+"|[\w]+)(?:\.(?:"(?:[^"]|"")+"|[\w]+))?\s+set\s+[\w\W]+?(?!\s*where\s)/is
|
|
|
|
export const alterDatabasePreventConnectionStatements = [
|
|
'alter database postgres connection limit 0',
|
|
'alter database postgres allow_connections false',
|
|
]
|
|
|
|
export const ASSISTANT_TEMPLATES = [
|
|
{
|
|
name: 'Twitter clone',
|
|
description: 'Simplified schema that mimics the Twitter application',
|
|
prompt: 'Create a twitter clone',
|
|
},
|
|
{
|
|
name: 'Chat application',
|
|
description: 'Send messages through channels or direct messages',
|
|
prompt:
|
|
'Create a chat application that supports sending messages either through channels or directly between users',
|
|
},
|
|
{
|
|
name: 'User management schema',
|
|
description: 'With role based access control',
|
|
prompt: 'Create a simple user management schema that supports role based access control',
|
|
},
|
|
{
|
|
name: 'Countries and Cities',
|
|
description: 'With each city belonging to a country',
|
|
prompt:
|
|
'Create a table of countries and a table of cities, with each city belonging to a country',
|
|
},
|
|
]
|
|
|
|
export const ROWS_PER_PAGE_OPTIONS = [
|
|
{ value: -1, label: 'No limit' },
|
|
{ value: 100, label: '100 rows' },
|
|
{ value: 500, label: '500 rows' },
|
|
{ value: 1000, label: '1,000 rows' },
|
|
]
|