import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import * as z from 'zod' import { useParams } from 'common' import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, Card, CardContent, CardFooter, FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, Input_Shadcn_, PrePostTab, WarningIcon, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { StringNumberOrNull } from 'components/ui/Forms/Form.constants' const FormSchema = z.object({ API_MAX_REQUEST_DURATION: z.coerce .number() .min(5, 'Must be 5 or larger') .max(30, 'Must be a value no greater than 30'), DB_MAX_POOL_SIZE: StringNumberOrNull, }) export const AdvancedAuthSettingsForm = () => { const { ref: projectRef } = useParams() const organization = useSelectedOrganization() const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const [isUpdatingRequestDurationForm, setIsUpdatingRequestDurationForm] = useState(false) const [isUpdatingDatabaseForm, setIsUpdatingDatabaseForm] = useState(false) const { data: authConfig, error: authConfigError, isLoading, isError, } = useAuthConfigQuery({ projectRef }) const { mutate: updateAuthConfig } = useAuthConfigUpdateMutation() const isTeamsEnterprisePlan = organization?.plan.id !== 'free' && organization?.plan.id !== 'pro' const promptTeamsEnterpriseUpgrade = IS_PLATFORM && !isTeamsEnterprisePlan const requestDurationForm = useForm({ resolver: zodResolver( z.object({ API_MAX_REQUEST_DURATION: FormSchema.shape.API_MAX_REQUEST_DURATION, }) ), defaultValues: { API_MAX_REQUEST_DURATION: 10, }, }) const databaseForm = useForm({ resolver: zodResolver( z.object({ DB_MAX_POOL_SIZE: FormSchema.shape.DB_MAX_POOL_SIZE, }) ), defaultValues: { DB_MAX_POOL_SIZE: '', }, }) useEffect(() => { if (authConfig) { if (!isUpdatingRequestDurationForm) { requestDurationForm.reset({ API_MAX_REQUEST_DURATION: authConfig?.API_MAX_REQUEST_DURATION ?? 10, }) } if (!isUpdatingDatabaseForm) { databaseForm.reset({ DB_MAX_POOL_SIZE: authConfig?.DB_MAX_POOL_SIZE !== null ? String(authConfig?.DB_MAX_POOL_SIZE) : '', }) } } }, [authConfig, isUpdatingRequestDurationForm, isUpdatingDatabaseForm]) const onSubmitRequestDurationForm = (values: any) => { if (!projectRef) return console.error('Project ref is required') if (!isTeamsEnterprisePlan) return setIsUpdatingRequestDurationForm(true) updateAuthConfig( { projectRef: projectRef, config: values }, { onError: (error) => { toast.error(`Failed to update request duration settings: ${error?.message}`) setIsUpdatingRequestDurationForm(false) }, onSuccess: () => { toast.success('Successfully updated request duration settings') setIsUpdatingRequestDurationForm(false) }, } ) } const onSubmitDatabaseForm = (values: any) => { if (!projectRef) return console.error('Project ref is required') setIsUpdatingDatabaseForm(true) const config = { DB_MAX_POOL_SIZE: values.DB_MAX_POOL_SIZE, } updateAuthConfig( { projectRef: projectRef, config }, { onError: (error) => { toast.error(`Failed to update database connection settings: ${error?.message}`) setIsUpdatingDatabaseForm(false) }, onSuccess: () => { toast.success('Successfully updated database connection settings') setIsUpdatingDatabaseForm(false) }, } ) } if (isError) { return ( Failed to retrieve auth configuration {authConfigError.message} ) } if (!canReadConfig) { return } return ( <> {promptTeamsEnterpriseUpgrade && (
)} Request Duration
(
)} />
{requestDurationForm.formState.isDirty && ( )}
Auth Database Connections
( )} /> {databaseForm.formState.isDirty && ( )}
) }