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 (