mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
Makes it possible to reset password from the connect sheet. Once reset the password is shown temporarily in the connection string for copy. The copy prompt action does not copy the password. <img width="1043" height="953" alt="image" src="https://github.com/user-attachments/assets/fe1a33bb-839f-47e3-b07f-7a5fa1df2b8d" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Session Pooler notice for direct connections on IPv4 networks * Option to show a temporary database password during direct-connection setup * **Improvements** * New password reset dialog with strength checks and generation * Connection-copy behavior now redacts temporary passwords and produces cleaner copy prompts * **Tests** * Added tests covering connection-string password insertion/replacement and copy-prompt behavior <!-- end of auto-generated comment: release notes by coderabbit.ai -->
118 lines
3.0 KiB
TypeScript
118 lines
3.0 KiB
TypeScript
import type { ConnectionStringMethod } from './Connect.constants'
|
|
import type { ConnectionStringPooler } from './Connect.types'
|
|
|
|
export const DEFAULT_PORT = '5432'
|
|
export const PASSWORD_PLACEHOLDER = '[YOUR-PASSWORD]'
|
|
|
|
export type ConnectionParams = {
|
|
host: string
|
|
port: string
|
|
user: string
|
|
database: string
|
|
}
|
|
|
|
export const resolveConnectionString = ({
|
|
connectionMethod,
|
|
useSharedPooler,
|
|
connectionStringPooler,
|
|
}: {
|
|
connectionMethod: ConnectionStringMethod
|
|
useSharedPooler: boolean
|
|
connectionStringPooler: ConnectionStringPooler | undefined
|
|
}) => {
|
|
if (!connectionStringPooler) return ''
|
|
|
|
if (connectionMethod === 'direct') {
|
|
return connectionStringPooler.direct ?? ''
|
|
}
|
|
|
|
if (connectionMethod === 'session') {
|
|
return connectionStringPooler.sessionShared ?? ''
|
|
}
|
|
|
|
if (useSharedPooler || !connectionStringPooler.transactionDedicated) {
|
|
return connectionStringPooler.transactionShared ?? ''
|
|
}
|
|
|
|
return connectionStringPooler.transactionDedicated ?? ''
|
|
}
|
|
|
|
export const parseConnectionParams = (connectionString: string): ConnectionParams => {
|
|
if (!connectionString) {
|
|
return {
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
}
|
|
}
|
|
|
|
try {
|
|
const parsed = new URL(connectionString)
|
|
// The URL parser percent-encodes characters that aren't valid in user-info
|
|
// (e.g. brackets in the self-hosted `postgres.[POOLER_TENANT_ID]` placeholder).
|
|
// Decode so the displayed string matches the literal we wrote.
|
|
const decode = (value: string) => {
|
|
try {
|
|
return decodeURIComponent(value)
|
|
} catch {
|
|
return value
|
|
}
|
|
}
|
|
return {
|
|
host: parsed.hostname || 'hidden',
|
|
port: parsed.port || DEFAULT_PORT,
|
|
user: parsed.username ? decode(parsed.username) : 'hidden',
|
|
database: parsed.pathname?.replace(/^\//, '') || 'hidden',
|
|
}
|
|
} catch (error) {
|
|
return {
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
}
|
|
}
|
|
}
|
|
|
|
export const buildSafeConnectionString = (
|
|
connectionString: string,
|
|
params: ConnectionParams
|
|
): string => {
|
|
if (!connectionString) return ''
|
|
|
|
const search = (() => {
|
|
try {
|
|
return new URL(connectionString).search
|
|
} catch (error) {
|
|
return ''
|
|
}
|
|
})()
|
|
|
|
return `postgresql://${params.user}:${PASSWORD_PLACEHOLDER}@${params.host}:${params.port}/${params.database}${search}`
|
|
}
|
|
|
|
export const buildConnectionStringWithPassword = (
|
|
connectionString: string,
|
|
password: string
|
|
): string => {
|
|
if (!connectionString || !password) return connectionString
|
|
|
|
const encodedPassword = (() => {
|
|
try {
|
|
return encodeURIComponent(password)
|
|
} catch {
|
|
return password
|
|
}
|
|
})()
|
|
|
|
return connectionString.split(PASSWORD_PLACEHOLDER).join(encodedPassword)
|
|
}
|
|
|
|
export const buildConnectionParameters = (params: ConnectionParams) => [
|
|
{ key: 'host', value: params.host },
|
|
{ key: 'port', value: params.port },
|
|
{ key: 'database', value: params.database },
|
|
{ key: 'user', value: params.user },
|
|
]
|