| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- import { PermissionAction } from '@supabase/shared-types/out/constants'
- import { useParams } from 'common'
- import { useRouter } from 'next/router'
- import { cn } from 'ui'
- import { CodeBlock } from 'ui-patterns/CodeBlock'
- import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
- import {
- buildDirectPostgresConnectionUri,
- buildLogicalBackupShellScript,
- DB_PASSWORD_PLACEHOLDER,
- } from './LogicalBackupCliInstructions.utils'
- import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
- import { InlineLink } from '@/components/ui/InlineLink'
- import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
- import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
- import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
- import { DOCS_URL } from '@/lib/constants'
- export type LogicalBackupCliInstructionsProps = {
- enabled?: boolean
- className?: string
- showResetPassword?: boolean
- note?: string
- }
- export const LogicalBackupCliInstructions = ({
- enabled = true,
- className,
- showResetPassword = true,
- note,
- }: LogicalBackupCliInstructionsProps) => {
- const router = useRouter()
- const { ref } = useParams()
- const { data: project } = useSelectedProjectQuery()
- const { can: canResetDbPassword } = useAsyncCheckPermissions(
- PermissionAction.UPDATE,
- 'projects',
- {
- resource: {
- project_id: project?.id,
- },
- }
- )
- const {
- data: settings,
- isSuccess,
- isError,
- } = useProjectSettingsV2Query({ projectRef: ref }, { enabled: enabled && Boolean(ref) })
- const connectionUri =
- isSuccess && settings
- ? buildDirectPostgresConnectionUri({
- db_user: settings.db_user,
- db_host: settings.db_host,
- db_port: settings.db_port,
- db_name: settings.db_name,
- })
- : null
- const shellScript = connectionUri ? buildLogicalBackupShellScript(connectionUri) : ''
- const resetPasswordHref = ref ? `/project/${ref}/database/settings#database-password` : '#'
- const resetDisabled = !canResetDbPassword
- return (
- <div className={cn('space-y-3', className)}>
- <div className="space-y-1">
- <h4 className="text-sm font-medium">Back up your database with the Briven CLI</h4>
- <p className="text-sm text-foreground-light">
- Use your direct connection string — replace {DB_PASSWORD_PLACEHOLDER} with your database
- password.{' '}
- <InlineLink href={`${DOCS_URL}/guides/platform/backups`}>Backup documentation</InlineLink>
- .
- </p>
- <p className="text-sm text-foreground-light">
- Any reserved character in your password must be percent-encoded in the URL (e.g.{' '}
- <code>@</code> → <code>%40</code>, <code>:</code> → <code>%3A</code>,{' '}
- <code>/</code> → <code>%2F</code>, <code>#</code> → <code>%23</code>).
- Encode <code>%</code> as <code>%25</code> first.
- </p>
- </div>
- {showResetPassword && (
- <ButtonTooltip
- type="default"
- disabled={resetDisabled}
- onClick={() => {
- if (!resetDisabled && ref) {
- void router.push(`/project/${ref}/database/settings#database-password`)
- }
- }}
- tooltip={{
- content: {
- side: 'bottom',
- text: !canResetDbPassword
- ? 'You need additional permissions to reset the database password'
- : undefined,
- },
- }}
- >
- Reset database password
- </ButtonTooltip>
- )}
- {note && <p className="text-sm text-foreground-light">{note}</p>}
- {isError && (
- <p className="text-sm text-foreground-light">
- Could not load connection details. Open{' '}
- <InlineLink href={resetPasswordHref}>Database settings</InlineLink> to copy your
- connection string manually.
- </p>
- )}
- {!isError && !connectionUri && <ShimmeringLoader className="py-4" />}
- {connectionUri ? (
- <CodeBlock
- language="bash"
- value={shellScript}
- hideLineNumbers
- className="[&_code]:text-[12px] [&_code]:text-foreground"
- wrapperClassName="[&_pre]:px-4 [&_pre]:py-3"
- />
- ) : null}
- </div>
- )
- }
|