mirror of
https://github.com/supabase/supabase.git
synced 2026-05-06 08:56:46 -04:00
Add warning in SQL editor when running alter db commands which prevents connections to the DB (#43584)
## Context Adds a warning if running an `ALTER DATABASE` command that prevents connections to the database. This would lock the dashboard out of the database, and re-configuring the setting will require a direct connection to the DB <img width="623" height="535" alt="image" src="https://github.com/user-attachments/assets/4c388f4a-753b-4fd6-89c5-89dfaa52c859" /> ## To test - Could try running the following command in the SQL editor to check the warning, this will show all the warnings ``` ALTER TABLE colors2 drop column sss; update colors set name = 'test'; alter database postgres connection limit 0; ```
This commit is contained in:
@@ -167,6 +167,161 @@ test.describe('SQL Editor', () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('should block execution for alter database connection limit 0', async ({ ref }) => {
|
||||
await expect(page.getByText('Loading...')).not.toBeVisible()
|
||||
await page.locator('.view-lines').click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`alter database postgres connection limit 0;`)
|
||||
|
||||
// Track whether the SQL editor dispatches this specific query to pg-meta
|
||||
let queryDispatched = false
|
||||
const listener = (request: any) => {
|
||||
if (
|
||||
request.url().includes('query?key=') &&
|
||||
request.method() === 'POST' &&
|
||||
request.postData()?.includes('connection limit 0')
|
||||
) {
|
||||
queryDispatched = true
|
||||
}
|
||||
}
|
||||
page.on('request', listener)
|
||||
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
// verify warning modal blocks execution
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Potential issue detected with' })
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
page.getByText('Query will prevent connections to your database')
|
||||
).toBeVisible()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
// cancel should dismiss without executing
|
||||
await page.getByRole('button', { name: 'Cancel' }).click()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
page.removeListener('request', listener)
|
||||
|
||||
// clear SQL snippet
|
||||
if (!isCLI()) {
|
||||
await deleteSqlSnippet(page, ref, newSqlSnippetName)
|
||||
} else {
|
||||
await page.reload()
|
||||
}
|
||||
})
|
||||
|
||||
test('should block execution for alter database allow_connections false', async ({ ref }) => {
|
||||
await expect(page.getByText('Loading...')).not.toBeVisible()
|
||||
await page.locator('.view-lines').click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`ALTER DATABASE postgres ALLOW_CONNECTIONS false;`)
|
||||
|
||||
// Track whether the SQL editor dispatches this specific query to pg-meta
|
||||
let queryDispatched = false
|
||||
const listener = (request: any) => {
|
||||
if (
|
||||
request.url().includes('query?key=') &&
|
||||
request.method() === 'POST' &&
|
||||
request.postData()?.includes('ALLOW_CONNECTIONS false')
|
||||
) {
|
||||
queryDispatched = true
|
||||
}
|
||||
}
|
||||
page.on('request', listener)
|
||||
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
// verify warning modal blocks execution
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Potential issue detected with' })
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
page.getByText('Query will prevent connections to your database')
|
||||
).toBeVisible()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
// cancel should dismiss without executing
|
||||
await page.getByRole('button', { name: 'Cancel' }).click()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
page.removeListener('request', listener)
|
||||
|
||||
// clear SQL snippet
|
||||
if (!isCLI()) {
|
||||
await deleteSqlSnippet(page, ref, newSqlSnippetName)
|
||||
} else {
|
||||
await page.reload()
|
||||
}
|
||||
})
|
||||
|
||||
test('should block execution for update without where clause', async ({ ref }) => {
|
||||
await expect(page.getByText('Loading...')).not.toBeVisible()
|
||||
await page.locator('.view-lines').click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`update countries set name = 'test';`)
|
||||
|
||||
// Track whether the SQL editor dispatches this specific query to pg-meta
|
||||
let queryDispatched = false
|
||||
const listener = (request: any) => {
|
||||
if (
|
||||
request.url().includes('query?key=') &&
|
||||
request.method() === 'POST' &&
|
||||
request.postData()?.includes("set name = 'test'")
|
||||
) {
|
||||
queryDispatched = true
|
||||
}
|
||||
}
|
||||
page.on('request', listener)
|
||||
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
// verify warning modal blocks execution
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Potential issue detected with' })
|
||||
).toBeVisible()
|
||||
await expect(page.getByText('Query uses update without a where clause')).toBeVisible()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
// cancel should dismiss without executing
|
||||
await page.getByRole('button', { name: 'Cancel' }).click()
|
||||
expect(queryDispatched).toBe(false)
|
||||
|
||||
page.removeListener('request', listener)
|
||||
|
||||
// clear SQL snippet
|
||||
if (!isCLI()) {
|
||||
await deleteSqlSnippet(page, ref, newSqlSnippetName)
|
||||
} else {
|
||||
await page.reload()
|
||||
}
|
||||
})
|
||||
|
||||
test('should not show warning modal for safe alter database statement', async ({ ref }) => {
|
||||
await expect(page.getByText('Loading...')).not.toBeVisible()
|
||||
await page.locator('.view-lines').click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`alter database postgres set statement_timeout = 60000;`)
|
||||
|
||||
const sqlMutationPromise = waitForApiResponse(page, 'pg-meta', ref, 'query?key=', {
|
||||
method: 'POST',
|
||||
})
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
await sqlMutationPromise
|
||||
|
||||
// verify warning modal is NOT visible - query should execute directly
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Potential issue detected with' })
|
||||
).not.toBeVisible()
|
||||
|
||||
// clear SQL snippet
|
||||
if (!isCLI()) {
|
||||
await deleteSqlSnippet(page, ref, newSqlSnippetName)
|
||||
} else {
|
||||
await page.reload()
|
||||
}
|
||||
})
|
||||
|
||||
test('exporting works as expected', async ({ ref }) => {
|
||||
await expect(page.getByText('Loading...')).not.toBeVisible()
|
||||
await page.locator('.view-lines').click()
|
||||
|
||||
Reference in New Issue
Block a user