import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { Check, ChevronUp } from 'lucide-react' import { useState } from 'react' import toast from 'react-hot-toast' import ReactMarkdown from 'react-markdown' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import type { components } from 'data/api' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useProjectApiQuery } from 'data/config/project-api-query' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { BASE_PATH } from 'lib/constants' import { Alert, Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Button, Collapsible, Form, Input, WarningIcon, } from 'ui' import { ProviderCollapsibleClasses } from './AuthProvidersForm.constants' import type { Provider } from './AuthProvidersForm.types' import FormField from './FormField' export interface ProviderFormProps { config: components['schemas']['GoTrueConfigResponse'] provider: Provider } const ProviderForm = ({ config, provider }: ProviderFormProps) => { const [open, setOpen] = useState(false) const { ref: projectRef } = useParams() const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation() const doubleNegativeKeys = ['MAILER_AUTOCONFIRM', 'SMS_AUTOCONFIRM'] const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const { data: settings } = useProjectApiQuery({ projectRef }) const apiUrl = `${settings?.autoApiService.protocol}://${settings?.autoApiService.endpoint}` const { data: customDomainData } = useCustomDomainsQuery({ projectRef }) const generateInitialValues = () => { const initialValues: { [x: string]: string | boolean } = {} // the config is already loaded through the parent component Object.keys(provider.properties).forEach((key) => { // When the key is a 'double negative' key, we must reverse the boolean before adding it to the form const isDoubleNegative = doubleNegativeKeys.includes(key) if (provider.title === 'SAML 2.0') { const configValue = (config as any)[key] initialValues[key] = configValue || (provider.properties[key].type === 'boolean' ? false : '') } else { if (isDoubleNegative) { initialValues[key] = !(config as any)[key] } else { const configValue = (config as any)[key] initialValues[key] = configValue ? configValue : provider.properties[key].type === 'boolean' ? false : '' } } }) return initialValues } const isSAMLEnabled: boolean = provider.title === 'SAML 2.0' && config && (config as any)['SAML_ENABLED'] // [Joel] Introduced as the new LinkedIn provider has a corresponding config var of LINKEDIN_OIDC const isLinkedInOIDCEnabled: boolean = provider.title === 'LinkedIn (OIDC)' && config && (config as any)['EXTERNAL_LINKEDIN_OIDC_ENABLED'] const isSlackOIDCEnabled = provider.title === 'Slack (OIDC)' && config['EXTERNAL_SLACK_OIDC_ENABLED'] const isExternalProviderAndEnabled: boolean = config && (config as any)[`EXTERNAL_${provider?.title?.toUpperCase()}_ENABLED`] // [Joshen] Doing this check as SAML doesn't follow the same naming structure as the other provider options const isActive: boolean = isSAMLEnabled || isExternalProviderAndEnabled || isLinkedInOIDCEnabled || isSlackOIDCEnabled const INITIAL_VALUES = generateInitialValues() const onSubmit = (values: any, { resetForm }: any) => { const payload = { ...values } // Format payload for the following checks: // 1. Convert all empty string values to null // 2. When the key is a 'double negative' key, we must reverse the boolean before the payload can be sent Object.keys(values).map((x: string) => { if (doubleNegativeKeys.includes(x)) payload[x] = !values[x] if (payload[x] === '') payload[x] = null }) updateAuthConfig( { projectRef: projectRef!, config: payload }, { onSuccess: () => { resetForm({ values: { ...values }, initialValues: { ...values } }) setOpen(false) toast.success('Successfully updated settings') }, } ) } return (
{({ handleReset, initialValues, values }: any) => { const noChanges = JSON.stringify(initialValues) === JSON.stringify(values) return (
{provider.title === 'Slack (Deprecated)' && ( Slack (Deprecated) Provider Recently, Slack has updated their OAuth API. Please use the new Slack (OIDC) provider below. Developers using this provider should move over to the new provider. Please refer to our{' '} documentation {' '} for more details. )}
{Object.keys(provider.properties).map((x: string) => ( ))} {provider?.misc?.alert && ( {provider.misc.alert.description} )} {provider.misc.requiresRedirect && ( <> {provider.misc.helper} } /> )}
Save
) }}
) } export default ProviderForm