import type { PostgresTable, PostgresTrigger } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import Image from 'next/legacy/image' import { MutableRefObject, useEffect } from 'react' import { useParams } from 'common' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { Checkbox, Input, Listbox, Radio, SidePanel } from 'ui' import { HTTPArgument, isEdgeFunction } from './EditHookPanel' import HTTPRequestFields from './HTTPRequestFields' import { AVAILABLE_WEBHOOK_TYPES, HOOK_EVENTS } from './Hooks.constants' export interface FormContentsProps { values: any resetForm: any errors: any selectedHook?: PostgresTrigger tables: PostgresTable[] events: string[] eventsError?: string onUpdateSelectedEvents: (event: string) => void httpHeaders: HTTPArgument[] httpParameters: HTTPArgument[] setHttpHeaders: (arr: HTTPArgument[]) => void setHttpParameters: (arr: HTTPArgument[]) => void submitRef: MutableRefObject } export const FormContents = ({ values, resetForm, errors, selectedHook, tables, events, eventsError, onUpdateSelectedEvents, httpHeaders, httpParameters, setHttpHeaders, setHttpParameters, submitRef, }: FormContentsProps) => { const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const restUrl = project?.restUrl const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co' const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*') const { data: keys = [] } = useAPIKeysQuery( { projectRef: ref, reveal: true }, { enabled: canReadAPIKeys } ) const { data: functions = [], isSuccess: isSuccessEdgeFunctions } = useEdgeFunctionsQuery({ projectRef: ref, }) const legacyServiceRole = keys.find((x) => x.name === 'service_role')?.api_key ?? '[YOUR API KEY]' useEffect(() => { if (values.function_type === 'http_request') { if (selectedHook !== undefined) { const [url, method] = selectedHook.function_args const updatedValues = { ...values, http_url: url, http_method: method } resetForm({ values: updatedValues, initialValues: updatedValues }) } else { const updatedValues = { ...values, http_url: '' } resetForm({ values: updatedValues, initialValues: updatedValues }) } } else if (values.function_type === 'supabase_function') { // Default to first edge function in the list const fnSlug = functions[0]?.slug const defaultFunctionUrl = `https://${ref}.supabase.${restUrlTld}/functions/v1/${fnSlug}` const updatedValues = { ...values, http_url: isEdgeFunction({ ref, restUrlTld, url: values.http_url }) ? values.http_url : defaultFunctionUrl, } resetForm({ values: updatedValues, initialValues: updatedValues }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [values.function_type]) useEffect(() => { if (!isSuccessEdgeFunctions) return const isEdgeFunctionSelected = isEdgeFunction({ ref, restUrlTld, url: values.http_url }) if (values.http_url && isEdgeFunctionSelected) { const fnSlug = values.http_url.split('/').at(-1) const fn = functions.find((x) => x.slug === fnSlug) const authorizationHeader = httpHeaders.find((x) => x.name === 'Authorization') const edgeFunctionAuthHeaderVal = `Bearer ${legacyServiceRole}` if (fn?.verify_jwt && authorizationHeader == null) { const authorizationHeader = { id: uuidv4(), name: 'Authorization', value: edgeFunctionAuthHeaderVal, } setHttpHeaders([...httpHeaders, authorizationHeader]) } else if (fn?.verify_jwt && authorizationHeader?.value !== edgeFunctionAuthHeaderVal) { const updatedHttpHeaders = httpHeaders.map((x) => { if (x.name === 'Authorization') return { ...x, value: edgeFunctionAuthHeaderVal } else return x }) setHttpHeaders(updatedHttpHeaders) } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [values.http_url, isSuccessEdgeFunctions]) return (
General}> Select which table and events will trigger your webhook

} > Conditions to fire webhook } > --- {tables.map((table) => (

{table.schema}

{table.name}

))}
{HOOK_EVENTS.map((event) => ( onUpdateSelectedEvents(event.value)} /> ))}
Webhook configuration } > {AVAILABLE_WEBHOOK_TYPES.map((webhook) => ( {webhook.label}

{webhook.label}

{webhook.description}

} /> ))} { if (headers) setHttpHeaders(httpHeaders.concat(headers)) else setHttpHeaders(httpHeaders.concat({ id: uuidv4(), name: '', value: '' })) }} onUpdateHeader={(idx, property, value) => setHttpHeaders( httpHeaders.map((header, i) => { if (idx === i) return { ...header, [property]: value } else return header }) ) } onRemoveHeader={(idx) => setHttpHeaders(httpHeaders.filter((_, i) => idx !== i))} onAddParameter={() => setHttpParameters(httpParameters.concat({ id: uuidv4(), name: '', value: '' })) } onUpdateParameter={(idx, property, value) => setHttpParameters( httpParameters.map((param, i) => { if (idx === i) return { ...param, [property]: value } else return param }) ) } onRemoveParameter={(idx) => setHttpParameters(httpParameters.filter((_, i) => idx !== i))} />