import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { ExternalLink } from 'lucide-react' import Link from 'next/link' import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Button, Card, CardContent, CardFooter, Form, FormControl, FormField, Switch, WarningIcon, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { PageSection, PageSectionContent, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns/PageSection' import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' import * as z from 'zod' import { NO_REQUIRED_CHARACTERS } from './Auth.constants' import AlertError from '@/components/ui/AlertError' import { InlineLink } from '@/components/ui/InlineLink' import NoPermission from '@/components/ui/NoPermission' import { useAuthConfigQuery } from '@/data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from '@/data/auth/auth-config-update-mutation' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled' import { DOCS_URL } from '@/lib/constants' const schema = z.object({ DISABLE_SIGNUP: z.boolean(), EXTERNAL_ANONYMOUS_USERS_ENABLED: z.boolean(), SECURITY_MANUAL_LINKING_ENABLED: z.boolean(), MAILER_AUTOCONFIRM: z.boolean(), SITE_URL: z.string().min(1, 'Must have a Site URL'), }) export const BasicAuthSettingsForm = () => { const { ref: projectRef } = useParams() const showManualLinking = useIsFeatureEnabled('authentication:show_manual_linking') const { data: authConfig, error: authConfigError, isError, isSuccess, isPending: isLoading, } = useAuthConfigQuery({ projectRef }) const { mutate: updateAuthConfig, isPending: isUpdatingConfig } = useAuthConfigUpdateMutation() const { can: canReadConfig, isSuccess: isPermissionsLoaded } = useAsyncCheckPermissions( PermissionAction.READ, 'custom_config_gotrue' ) const { can: canUpdateConfig } = useAsyncCheckPermissions( PermissionAction.UPDATE, 'custom_config_gotrue' ) const form = useForm({ resolver: zodResolver(schema), defaultValues: { DISABLE_SIGNUP: true, EXTERNAL_ANONYMOUS_USERS_ENABLED: false, SECURITY_MANUAL_LINKING_ENABLED: false, MAILER_AUTOCONFIRM: true, SITE_URL: '', }, }) const { isDirty } = form.formState useEffect(() => { if (authConfig) { form.reset({ DISABLE_SIGNUP: !authConfig.DISABLE_SIGNUP, EXTERNAL_ANONYMOUS_USERS_ENABLED: authConfig.EXTERNAL_ANONYMOUS_USERS_ENABLED, SECURITY_MANUAL_LINKING_ENABLED: authConfig.SECURITY_MANUAL_LINKING_ENABLED, // The backend uses false to represent that email confirmation is required MAILER_AUTOCONFIRM: !authConfig.MAILER_AUTOCONFIRM, SITE_URL: authConfig.SITE_URL, }) } }, [authConfig]) const onSubmit = (values: any) => { const payload = { ...values } payload.DISABLE_SIGNUP = !values.DISABLE_SIGNUP // The backend uses empty string to represent no required characters in the password if (payload.PASSWORD_REQUIRED_CHARACTERS === NO_REQUIRED_CHARACTERS) { payload.PASSWORD_REQUIRED_CHARACTERS = '' } // The backend uses false to represent that email confirmation is required payload.MAILER_AUTOCONFIRM = !values.MAILER_AUTOCONFIRM updateAuthConfig( { projectRef: projectRef!, config: payload }, { onError: (error) => { toast.error(`Failed to update settings: ${error?.message}`) }, onSuccess: () => { toast.success('Successfully updated settings') }, } ) } return ( User Signups {isError && ( )} {isPermissionsLoaded && !canReadConfig && (
)} {isLoading && ( )} {isSuccess && (
( )} /> {showManualLinking && ( ( Enable{' '} manual linking APIs {' '} for your project } > )} /> )} ( Enable{' '} anonymous sign-ins {' '} for your project } > )} /> {form.watch('EXTERNAL_ANONYMOUS_USERS_ENABLED') && (
Anonymous users will use the{' '} authenticated role when signing in

As a result, anonymous users will be subjected to RLS policies that apply to the public and{' '} authenticated roles. We strongly advise{' '} reviewing your RLS policies {' '} to ensure that access to your data is restricted where required.

)} {!authConfig?.SECURITY_CAPTCHA_ENABLED && form.watch('EXTERNAL_ANONYMOUS_USERS_ENABLED') && ( We highly recommend{' '} enabling captcha {' '} for anonymous sign-ins This will prevent potential abuse on sign-ins which may bloat your database and incur costs for monthly active users (MAU) )}
( )} /> {isDirty && ( )}
)}
) }