import { PermissionAction } from '@supabase/shared-types/out/constants' import { template } from 'lodash' import { Download, Loader2 } from 'lucide-react' import { useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' import { SupportLink } from 'components/interfaces/Support/SupportLink' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' import { FormHeader } from 'components/ui/Forms/FormHeader' import { FormPanel } from 'components/ui/Forms/FormPanel' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { InlineLinkClassName } from 'components/ui/InlineLink' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useSSLEnforcementQuery } from 'data/ssl-enforcement/ssl-enforcement-query' import { useSSLEnforcementUpdateMutation } from 'data/ssl-enforcement/ssl-enforcement-update-mutation' import { useCustomContent } from 'hooks/custom-content/useCustomContent' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DOCS_URL } from 'lib/constants' import { Alert, Button, Switch, Tooltip, TooltipContent, TooltipTrigger } from 'ui' const SSLConfiguration = () => { const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const [isEnforced, setIsEnforced] = useState(false) const { data: settings } = useProjectSettingsV2Query({ projectRef: ref }) const { data: sslEnforcementConfiguration, isLoading, isSuccess, } = useSSLEnforcementQuery({ projectRef: ref, }) const { mutate: updateSSLEnforcement, isPending: isSubmitting } = useSSLEnforcementUpdateMutation( { onSuccess: () => { toast.success('Successfully updated SSL configuration') }, onError: (error) => { setIsEnforced(initialIsEnforced) toast.error(`Failed to update SSL enforcement: ${error.message}`) }, } ) const { can: canUpdateSSLEnforcement } = useAsyncCheckPermissions( PermissionAction.UPDATE, 'projects', { resource: { project_id: project?.id, }, } ) const initialIsEnforced = isSuccess ? sslEnforcementConfiguration.appliedSuccessfully && sslEnforcementConfiguration.currentConfig.database : false const hasAccessToSSLEnforcement = !( sslEnforcementConfiguration !== undefined && 'isNotAllowed' in sslEnforcementConfiguration && sslEnforcementConfiguration.isNotAllowed ) const env = process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' ? 'prod' : 'staging' const hasSSLCertificate = settings?.inserted_at !== undefined && new Date(settings.inserted_at) >= new Date('2021-04-30') const { sslCertificateUrl: sslCertificateUrlTemplate } = useCustomContent(['ssl:certificate_url']) const sslCertificateUrl = useMemo( () => template(sslCertificateUrlTemplate ?? '')({ env }), [sslCertificateUrlTemplate, env] ) useEffect(() => { if (!isLoading && sslEnforcementConfiguration) { setIsEnforced(initialIsEnforced) } }, [isLoading]) const toggleSSLEnforcement = async () => { if (!ref) return console.error('Project ref is required') setIsEnforced(!isEnforced) updateSSLEnforcement({ projectRef: ref, requestedConfig: { database: !isEnforced } }) } return (
Reject non-SSL connections to your database
{isSuccess && !sslEnforcementConfiguration?.appliedSuccessfully && (SSL Certificate
Use this certificate when connecting to your database to prevent snooping and man-in-the-middle attacks.